lots of progress

This commit is contained in:
JISAUAY committed 2025-01-23 16:30:50 -06:00
1 parent 1d56b5efea
commit f8815964b5
8 files changed
+16549 -16

No files matched your search

+111 -6
View File
@@ -1,3 +1,4 @@
import time
import random
import string
import hashlib
@@ -12,6 +13,21 @@ import requests
logger = logging.getLogger(__name__)
class Playlist:
id: str
name: str
songCount: int
duration: str
owner: str
coverArtId: str
def __init__(self, info: dict):
self.id = info['id']
self.name = info['name']
self.songCount = int(info['songCount'])
self.duration = time.strftime('%H:%M:%S', time.gmtime(int(info['duration'])))
self.owner = info['owner']
self.coverArtId = info['coverArt']
class Album:
id: str
@@ -22,6 +38,9 @@ class Album:
duration: int
artistId: str
songCount: int
playCount: int
year: int | None
duration: str
def __init__(self, album_info: dict):
self.id = album_info['id']
@@ -32,6 +51,12 @@ class Album:
self.duration = int(album_info['duration'])
self.artistId = album_info['artistId']
self.songCount = int(album_info['songCount'])
self.playCount = int(album_info['playCount']) if 'playCount' in album_info else 0
self.year = int(album_info['year']) if 'year' in album_info else None
self.duration = self._secondToMinutes(int(album_info['duration']))
def _secondToMinutes(self, s: int) -> str:
return f'{s // 60}:{s % 60 if s % 60 > 9 else "0" + str(s % 60)}'
class Song:
id: str
@@ -50,13 +75,14 @@ class Song:
comment: str
channelCount: int
samplingRate: int
playCount: int | None
def __init__(self, song_info: dict):
self.id = song_info['id']
self.title = song_info['title']
self.album = song_info['album']
self.artist = song_info['artist']
self.trackNumber = int(song_info['track'])
self.trackNumber = int(song_info['track']) if 'track' in song_info else None
self.contentType = song_info['contentType']
self.suffix = song_info['suffix']
self.duration = int(song_info['duration'])
@@ -64,10 +90,11 @@ class Song:
self.path = song_info['path']
self.discNumber = int(song_info['discNumber']) if 'discNumber' in song_info else None
self.albumId = song_info['albumId']
self.artistId = song_info['artistId']
self.artistId = song_info['artistId'] if 'artistId' in song_info else None
self.comment = song_info['comment']
self.channelCount = int(song_info['channelCount'])
self.samplingRate = int(song_info['samplingRate'])
self.playCount = int(song_info['playCount']) if 'playCount' in song_info else None
class Artist:
id: str
@@ -230,17 +257,95 @@ class SubpyConn:
return artists
def getAlbums(self) -> list[Album]:
def getAlbums(self, size: int | None = 25, offset: int | None = 0) -> list[Album]:
url = self.base_url + '/rest/getAlbumList?'
payload = self._getBasePayload()
payload['type'] = 'alphabeticalByName'
payload['size'] = 20
payload['size'] = size
payload['offset'] = offset
payload['f'] = 'json'
r = requests.get(url + self._encodePayload(payload))
json_r = r.json()
albums: list[Album] = []
if 'album' not in json_r['subsonic-response']['albumList']:
return []
for album in json_r['subsonic-response']['albumList']['album']:
albums.append(Album(album))
return albums
def getAllAlbums(self) -> list[Album]:
all_albums: list[Album] = []
offset = 0
while albums := self.getAlbums(50, offset):
all_albums.extend(albums)
offset += 50
return all_albums
def getPlaylists(self) -> list[Playlist]:
url = self.base_url + "/rest/getPlaylists?"
payload = self._getBasePayload()
payload['f'] = 'json'
r = requests.get(url + self._encodePayload(payload))
with open("albumList.xml" , 'wb') as file:
file.write(r.content)
json_r = r.json()
playlists: list[Playlist] = []
for playlist in json_r['subsonic-response']['playlists']['playlist']:
playlists.append(Playlist(playlist))
return playlists
def getStarred(self) -> list[Album | Song | Artist]:
url = self.base_url + "/rest/getStarred?"
payload = self._getBasePayload()
payload['f'] = 'json'
r = requests.get(url + self._encodePayload(payload))
json_r = r.json()
starred: list[Album | Song | Artist] = []
for album in json_r['subsonic-response']['starred']['artist']:
starred.append(Album(album))
for artist in json_r['subsonic-response']['starred']['artist']:
starred.append(Artist(
artist['id'],
artist['name'],
artist['albumCount'],
artist['coverArt'],
artist['artistImageUrl']
))
for song in json_r['subsonic-response']['starred']['song']:
starred.append(Song(song))
return starred
def getStarredSongs(self) -> list[Song]:
url = self.base_url + "/rest/getStarred?"
payload = self._getBasePayload()
payload['f'] = 'json'
r = requests.get(url + self._encodePayload(payload))
json_r = r.json()
starred: list[Song] = []
for song in json_r['subsonic-response']['starred']['song']:
starred.append(Song(song))
return starred
# Returns a requests Response object, the data stream can be found in Response.content
def stream(self, song_id: str) -> requests.Response:
+8 -1
View File
@@ -91,7 +91,14 @@ class SubPyPlayer:
# player = SubPyPlayer(conn)
conn.getAlbums()
# for album in conn.getAllAlbums():
# print(album.name)
# for playlist in conn.getPlaylists():
# print(playlist.name, playlist.duration)
for song in conn.getStarredSongs():
print(song.title)
# player.play_song(echidna_id)
+544
View File
@@ -0,0 +1,544 @@
{
"subsonic-response": {
"status": "ok",
"version": "1.16.1",
"type": "navidrome",
"serverVersion": "0.54.3 (734eb30a)",
"openSubsonic": true,
"albumList": {
"album": [
{
"id": "47e9412a4c73816e0d8411fddf5ac071",
"parent": "5cd6da7549d3b2f7d486e823403179d9",
"isDir": true,
"title": "%NAME%",
"name": "%NAME%",
"album": "%NAME%",
"artist": "Madoi The Maid",
"year": 2022,
"coverArt": "al-47e9412a4c73816e0d8411fddf5ac071_677f0728",
"duration": 1034,
"playCount": 11,
"created": "2025-01-09T01:44:52.036289708Z",
"artistId": "5cd6da7549d3b2f7d486e823403179d9",
"songCount": 5,
"isVideo": false,
"played": "2025-01-22T17:30:25.733688541Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "46d39a2668849161633175dfb1109ebf",
"parent": "dc7bcc78207dc2cc8476da519fb9be62",
"isDir": true,
"title": "1000 gecs",
"name": "1000 gecs",
"album": "1000 gecs",
"artist": "100 gecs",
"year": 2019,
"genre": "Bubblegum Bass",
"coverArt": "al-46d39a2668849161633175dfb1109ebf_67869cab",
"duration": 1385,
"playCount": 1,
"created": "2025-01-14T17:51:48.047329609Z",
"artistId": "dc7bcc78207dc2cc8476da519fb9be62",
"songCount": 10,
"isVideo": false,
"played": "2025-01-15T14:13:39.450407291Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "6cddb1f1-d7c4-4932-b080-fe9a0968eb75",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "6413f9f9de4566a42a35820e0330c00e",
"parent": "5cd6da7549d3b2f7d486e823403179d9",
"isDir": true,
"title": "30355375",
"name": "30355375",
"album": "30355375",
"artist": "Madoi The Maid",
"year": 2021,
"coverArt": "al-6413f9f9de4566a42a35820e0330c00e_677f07ec",
"duration": 1061,
"created": "2025-01-09T01:53:52.055553494Z",
"artistId": "5cd6da7549d3b2f7d486e823403179d9",
"songCount": 4,
"isVideo": false,
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "d6f2e67009217f02d8478bb0b35d0c03",
"parent": "d1fb0b96a0a51a3f73fbf777ca44f6fb",
"isDir": true,
"title": "[Unknown Album]",
"name": "[Unknown Album]",
"album": "[Unknown Album]",
"artist": "[Unknown Artist]",
"coverArt": "al-d6f2e67009217f02d8478bb0b35d0c03_65afdea5",
"duration": 1090,
"created": "2025-01-09T00:29:52.080283967Z",
"artistId": "d1fb0b96a0a51a3f73fbf777ca44f6fb",
"songCount": 4,
"isVideo": false,
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "0e5b2f2a2e88f81f184d955225e807ce",
"parent": "db88716c9e3f99bee680fa2f09d3a341",
"isDir": true,
"title": "[Unknown Album]",
"name": "[Unknown Album]",
"album": "[Unknown Album]",
"artist": "Nfract",
"year": 2021,
"coverArt": "al-0e5b2f2a2e88f81f184d955225e807ce_65afe471",
"duration": 1211,
"created": "2025-01-13T16:07:49.056650918Z",
"artistId": "db88716c9e3f99bee680fa2f09d3a341",
"songCount": 4,
"isVideo": false,
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "d8c1f6207254951d1c93735623d6141f",
"parent": "c0dabaa054d44941aedfb1314ad0db0e",
"isDir": true,
"title": "And Justice For None [Deluxe]",
"name": "And Justice For None [Deluxe]",
"album": "And Justice For None [Deluxe]",
"artist": "Five Finger Death Punch",
"year": 2018,
"genre": "Metal",
"coverArt": "al-d8c1f6207254951d1c93735623d6141f_678fd3d2",
"duration": 3479,
"playCount": 2,
"created": "2025-01-21T17:59:53.055692164Z",
"artistId": "c0dabaa054d44941aedfb1314ad0db0e",
"songCount": 16,
"isVideo": false,
"played": "2025-01-22T20:35:45.509Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "ed00f28740a9c5216c2541cca1c06860",
"parent": "cd596686c16da5c34ebc2e26f5e81e67",
"isDir": true,
"title": "Another Light",
"name": "Another Light",
"album": "Another Light",
"artist": "Red Vox",
"year": 2017,
"coverArt": "al-ed00f28740a9c5216c2541cca1c06860_677cc436",
"duration": 2937,
"playCount": 5,
"created": "2025-01-07T06:21:03.118167048Z",
"artistId": "cd596686c16da5c34ebc2e26f5e81e67",
"songCount": 13,
"isVideo": false,
"played": "2025-01-13T18:48:10.232Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "b6b8cff3e0911c416e4c2a148998d267",
"parent": "0975b4f6e62c566fea75ee400e45ac7b",
"isDir": true,
"title": "ap2",
"name": "ap2",
"album": "ap2",
"artist": "goreshit",
"year": 2021,
"coverArt": "al-b6b8cff3e0911c416e4c2a148998d267_677f0b2f",
"duration": 3045,
"created": "2025-01-09T01:57:52.047375693Z",
"artistId": "0975b4f6e62c566fea75ee400e45ac7b",
"songCount": 8,
"isVideo": false,
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "2f435628fa8eb04c3a7a1be14f9f1af0",
"parent": "c9c92840fdb77d2e2dab9ae5fbd34d43",
"isDir": true,
"title": "Army of Mushrooms",
"name": "Army of Mushrooms",
"album": "Army of Mushrooms",
"artist": "Infected Mushroom",
"year": 2012,
"genre": "Psytrance",
"coverArt": "al-2f435628fa8eb04c3a7a1be14f9f1af0_677ccd0f",
"duration": 4796,
"playCount": 3,
"created": "2025-01-07T08:21:03.068117618Z",
"artistId": "c9c92840fdb77d2e2dab9ae5fbd34d43",
"songCount": 12,
"isVideo": false,
"played": "2025-01-22T20:39:34.814Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "47b6f635-d38b-434c-8cef-81e936d85920",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "0862b448d1af4f40602dea9d0e37894c",
"parent": "1bd222373c64674d749b318511a64bfd",
"isDir": true,
"title": "Atlanta Millionaires Club",
"name": "Atlanta Millionaires Club",
"album": "Atlanta Millionaires Club",
"artist": "Faye Webster",
"year": 2019,
"genre": "Alternative",
"coverArt": "al-0862b448d1af4f40602dea9d0e37894c_677f5a52",
"duration": 1909,
"created": "2025-01-09T06:04:52.190240048Z",
"artistId": "1bd222373c64674d749b318511a64bfd",
"songCount": 10,
"isVideo": false,
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "1d2749574810ce63fa1c47b57e8e3e73",
"parent": "0371f111b9d8391a4b669a4199809186",
"isDir": true,
"title": "Automated Refrains",
"name": "Automated Refrains",
"album": "Automated Refrains",
"artist": "Dan Terminus",
"year": 2017,
"genre": "Electronic",
"coverArt": "al-1d2749574810ce63fa1c47b57e8e3e73_678fdf31",
"duration": 1317,
"created": "2025-01-21T17:53:53.046342896Z",
"artistId": "0371f111b9d8391a4b669a4199809186",
"songCount": 4,
"isVideo": false,
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "1574db21-9e3c-4429-a64e-a46adb842931",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "06e75c5a2dadb55a9071f52196da3846",
"parent": "e3a642b6f67ac1f4683882ad9118312d",
"isDir": true,
"title": "Back To Earth",
"name": "Back To Earth",
"album": "Back To Earth",
"artist": "Golemm",
"year": 2023,
"coverArt": "al-06e75c5a2dadb55a9071f52196da3846_677cc2f8",
"duration": 165,
"playCount": 1,
"created": "2025-01-07T06:20:03.048260207Z",
"artistId": "e3a642b6f67ac1f4683882ad9118312d",
"songCount": 1,
"isVideo": false,
"played": "2025-01-09T17:27:34.978Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "48976a6cf6f6cac0a29772a4dce103fe",
"parent": "955a5787540a074d8732ad9962aefaca",
"isDir": true,
"title": "Basement Popstar",
"name": "Basement Popstar",
"album": "Basement Popstar",
"artist": "GNB CHILI",
"year": 2021,
"coverArt": "al-48976a6cf6f6cac0a29772a4dce103fe_677c7fc9",
"duration": 4197,
"playCount": 6,
"created": "2025-01-07T01:36:13.02318597Z",
"artistId": "955a5787540a074d8732ad9962aefaca",
"songCount": 26,
"isVideo": false,
"played": "2025-01-21T22:56:16.312531561Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "98e13ac9e58288efbd93a261225d1a5b",
"parent": "db88716c9e3f99bee680fa2f09d3a341",
"isDir": true,
"title": "Bleeding Reflection",
"name": "Bleeding Reflection",
"album": "Bleeding Reflection",
"artist": "Nfract",
"year": 2020,
"coverArt": "al-98e13ac9e58288efbd93a261225d1a5b_678675e6",
"duration": 412,
"created": "2025-01-13T16:07:49.08422529Z",
"artistId": "db88716c9e3f99bee680fa2f09d3a341",
"songCount": 1,
"isVideo": false,
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "85c79ce0-dbb8-4554-97a1-511798aa1f64",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "a880dcf07c4c886175cec0ffb4968ed6",
"parent": "0f51c7454c088cab6c7c965bbea9791d",
"isDir": true,
"title": "blight",
"name": "blight",
"album": "blight",
"artist": "purity://filter",
"year": 2021,
"coverArt": "al-a880dcf07c4c886175cec0ffb4968ed6_677f0a65",
"duration": 836,
"playCount": 2,
"created": "2025-01-09T01:48:52.04606921Z",
"artistId": "0f51c7454c088cab6c7c965bbea9791d",
"songCount": 6,
"isVideo": false,
"played": "2025-01-15T22:54:40.187Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "3d60ef6028532c45fd59554fe861397a",
"parent": "0975b4f6e62c566fea75ee400e45ac7b",
"isDir": true,
"title": "blue girl on sunday",
"name": "blue girl on sunday",
"album": "blue girl on sunday",
"artist": "goreshit",
"year": 2011,
"coverArt": "al-3d60ef6028532c45fd59554fe861397a_677f16f7",
"duration": 2471,
"created": "2025-01-09T01:57:52.069784029Z",
"artistId": "0975b4f6e62c566fea75ee400e45ac7b",
"songCount": 7,
"isVideo": false,
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "78f9621af89b8184278ef7821c6cff89",
"parent": "b56870783b82e1413af57d4cbde24f31",
"isDir": true,
"title": "BRAT",
"name": "BRAT",
"album": "BRAT",
"artist": "Charli xcx",
"year": 2024,
"genre": "Club",
"coverArt": "al-78f9621af89b8184278ef7821c6cff89_6786fdf5",
"starred": "2025-01-15T21:37:49.500009424Z",
"duration": 2490,
"playCount": 7,
"created": "2025-01-14T17:55:48.042982684Z",
"artistId": "b56870783b82e1413af57d4cbde24f31",
"songCount": 15,
"isVideo": false,
"played": "2025-01-22T17:23:55.631096876Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "97b69f53-5b37-4b94-856b-8fa32063310a",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "622532ca446558d45ce006e4264abf69",
"parent": "ab255ac1a3606a016e598f4f6674e51a",
"isDir": true,
"title": "Changes",
"name": "Changes",
"album": "Changes",
"artist": "King Gizzard \u0026 the Lizard Wizard",
"year": 2022,
"genre": "Psychedelic Rock",
"coverArt": "al-622532ca446558d45ce006e4264abf69_677c73b3",
"starred": "2025-01-07T20:15:02.583375374Z",
"duration": 2403,
"playCount": 3,
"created": "2025-01-07T00:41:13.214313142Z",
"artistId": "ab255ac1a3606a016e598f4f6674e51a",
"songCount": 7,
"isVideo": false,
"played": "2025-01-16T18:55:56.099535351Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "3fe553cd-5e38-4b55-8052-656821f6d113",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "d7f4db94acce29a5811d80cc1394f005",
"parent": "7decc729670767718e65266f1def027f",
"isDir": true,
"title": "chaotic solutions",
"name": "chaotic solutions",
"album": "chaotic solutions",
"artist": "Kobaryo",
"year": 2014,
"coverArt": "al-d7f4db94acce29a5811d80cc1394f005_678fd9c3",
"duration": 2849,
"created": "2025-01-21T18:11:53.264694258Z",
"artistId": "7decc729670767718e65266f1def027f",
"songCount": 14,
"isVideo": false,
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "64adb258-9c2e-4746-b994-3506d7b6840e",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
},
{
"id": "9c451436790418adbe4053e8acc4be1f",
"parent": "545d81e9329d136f3f25bc1e367fadd7",
"isDir": true,
"title": "CHASER",
"name": "CHASER",
"album": "CHASER",
"artist": "Femtanyl",
"year": 2023,
"genre": "Breakcore",
"coverArt": "al-9c451436790418adbe4053e8acc4be1f_677c80d7",
"duration": 824,
"playCount": 3,
"created": "2025-01-07T01:40:13.185825129Z",
"artistId": "545d81e9329d136f3f25bc1e367fadd7",
"songCount": 6,
"isVideo": false,
"played": "2025-01-19T23:04:45.888978139Z",
"bpm": 0,
"comment": "",
"sortName": "",
"mediaType": "album",
"musicBrainzId": "",
"genres": [],
"replayGain": {},
"channelCount": 0,
"samplingRate": 0
}
]
}
}
}
+1
View File
@@ -0,0 +1 @@
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.16.1" type="navidrome" serverVersion="0.54.3 (734eb30a)" openSubsonic="true"><albumList><album id="47e9412a4c73816e0d8411fddf5ac071" parent="5cd6da7549d3b2f7d486e823403179d9" isDir="true" title="%NAME%" name="%NAME%" album="%NAME%" artist="Madoi The Maid" year="2022" coverArt="al-47e9412a4c73816e0d8411fddf5ac071_677f0728" duration="1034" playCount="11" created="2025-01-09T01:44:52.036289708Z" artistId="5cd6da7549d3b2f7d486e823403179d9" songCount="5" isVideo="false" played="2025-01-22T17:30:25.733688541Z" bpm="0" comment="" sortName="" mediaType="album" musicBrainzId="" channelCount="0" samplingRate="0"><replayGain></replayGain></album><album id="46d39a2668849161633175dfb1109ebf" parent="dc7bcc78207dc2cc8476da519fb9be62" isDir="true" title="1000 gecs" name="1000 gecs" album="1000 gecs" artist="100 gecs" year="2019" genre="Bubblegum Bass" coverArt="al-46d39a2668849161633175dfb1109ebf_67869cab" duration="1385" playCount="1" created="2025-01-14T17:51:48.047329609Z" artistId="dc7bcc78207dc2cc8476da519fb9be62" songCount="10" isVideo="false" played="2025-01-15T14:13:39.450407291Z" bpm="0" comment="" sortName="" mediaType="album" musicBrainzId="6cddb1f1-d7c4-4932-b080-fe9a0968eb75" channelCount="0" samplingRate="0"><replayGain></replayGain></album><album id="6413f9f9de4566a42a35820e0330c00e" parent="5cd6da7549d3b2f7d486e823403179d9" isDir="true" title="30355375" name="30355375" album="30355375" artist="Madoi The Maid" year="2021" coverArt="al-6413f9f9de4566a42a35820e0330c00e_677f07ec" duration="1061" created="2025-01-09T01:53:52.055553494Z" artistId="5cd6da7549d3b2f7d486e823403179d9" songCount="4" isVideo="false" bpm="0" comment="" sortName="" mediaType="album" musicBrainzId="" channelCount="0" samplingRate="0"><replayGain></replayGain></album><album id="d6f2e67009217f02d8478bb0b35d0c03" parent="d1fb0b96a0a51a3f73fbf777ca44f6fb" isDir="true" title="[Unknown Album]" name="[Unknown Album]" album="[Unknown Album]" artist="[Unknown Artist]" coverArt="al-d6f2e67009217f02d8478bb0b35d0c03_65afdea5" duration="1090" created="2025-01-09T00:29:52.080283967Z" artistId="d1fb0b96a0a51a3f73fbf777ca44f6fb" songCount="4" isVideo="false" bpm="0" comment="" sortName="" mediaType="album" musicBrainzId="" channelCount="0" samplingRate="0"><replayGain></replayGain></album><album id="0e5b2f2a2e88f81f184d955225e807ce" parent="db88716c9e3f99bee680fa2f09d3a341" isDir="true" title="[Unknown Album]" name="[Unknown Album]" album="[Unknown Album]" artist="Nfract" year="2021" coverArt="al-0e5b2f2a2e88f81f184d955225e807ce_65afe471" duration="1211" created="2025-01-13T16:07:49.056650918Z" artistId="db88716c9e3f99bee680fa2f09d3a341" songCount="4" isVideo="false" bpm="0" comment="" sortName="" mediaType="album" musicBrainzId="" channelCount="0" samplingRate="0"><replayGain></replayGain></album><album id="d8c1f6207254951d1c93735623d6141f" parent="c0dabaa054d44941aedfb1314ad0db0e" isDir="true" title="And Justice For None [Deluxe]" name="And Justice For None [Deluxe]" album="And Justice For None [Deluxe]" artist="Five Finger Death Punch" year="2018" genre="Metal" coverArt="al-d8c1f6207254951d1c93735623d6141f_678fd3d2" duration="3479" playCount="2" created="2025-01-21T17:59:53.055692164Z" artistId="c0dabaa054d44941aedfb1314ad0db0e" songCount="16" isVideo="false" played="2025-01-22T20:35:45.509Z" bpm="0" comment="" sortName="" mediaType="album" musicBrainzId="" channelCount="0" samplingRate="0"><replayGain></replayGain></album><album id="ed00f28740a9c5216c2541cca1c06860" parent="cd596686c16da5c34ebc2e26f5e81e67" isDir="true" title="Another Light" name="Another Light" album="Another Light" artist="Red Vox" year="2017" coverArt="al-ed00f28740a9c5216c2541cca1c06860_677cc436" duration="2937" playCount="5" created="2025-01-07T06:21:03.118167048Z" artistId="cd596686c16da5c34ebc2e26f5e81e67" songCount="13" isVideo="false" played="2025-01-13T18:48:10.232Z" bpm="0" comment="" sortName="" mediaType="album" musicBrainzId="" channelCount="0" samplingRate="0"><replayGain></replayGain></album><album id="b6b8cff3e0911c416e4c2a148998d267" parent="0975b4f6e62c566fea75ee400e45ac7b" isDir="true" title="ap2" name="ap2" album="ap2" artist="goreshit" year="2021" coverArt="al-b6b8cff3e0911c416e4c2a148998d267_677f0b2f" duration="3045" created="2025-01-09T01:57:52.047375693Z" artistId="0975b4f6e62c566fea75ee400e45ac7b" songCount="8" isVideo="false" bpm="0" comment="" sortName="" mediaType="album" musicBrainzId="" channelCount="0" samplingRate="0"><replayGain></replayGain></album><album id="2f435628fa8eb04c3a7a1be14f9f1af0" parent="c9c92840fdb77d2e2dab9ae5fbd34d43" isDir="true" title="Army of Mushrooms" name="Army of Mushrooms" album="Army of Mushrooms" artist="Infected Mushroom" year="2012" genre="Psytrance" coverArt="al-2f435628fa8eb04c3a7a1be14f9f1af0_677ccd0f" duration="4796" playCount="3" created="2025-01-07T08:21:03.068117618Z" artistId="c9c92840fdb77d2e2dab9ae5fbd34d43" songCount="12" isVideo="fLine truncated
+59
View File
@@ -0,0 +1,59 @@
{
"subsonic-response": {
"status": "ok",
"version": "1.16.1",
"type": "navidrome",
"serverVersion": "0.54.3 (734eb30a)",
"openSubsonic": true,
"playlists": {
"playlist": [
{
"id": "a79d6039-cc24-40ce-9518-191b5dfc7909",
"name": "Disc 2",
"comment": "Auto-imported from 'Disc 2.m3u8'",
"songCount": 11,
"duration": 3157,
"public": false,
"owner": "pseudo",
"created": "2025-01-21T18:10:53.124749519Z",
"changed": "2025-01-21T18:10:53.126220207Z",
"coverArt": "pl-a79d6039-cc24-40ce-9518-191b5dfc7909_678fe32d"
},
{
"id": "e6e8ff27-2a60-4e33-8aa1-09586191166a",
"name": "King Gizzard \u0026 The Lizard Wizard I Like",
"songCount": 63,
"duration": 23786,
"public": true,
"owner": "pseudo",
"created": "2025-01-07T20:14:21.840994748Z",
"changed": "2025-01-21T17:53:53.194711932Z",
"coverArt": "pl-e6e8ff27-2a60-4e33-8aa1-09586191166a_678fdf31"
},
{
"id": "9d76a86b-901f-4727-a2ec-01210157ff01",
"name": "Maidcore",
"songCount": 43,
"duration": 11109,
"public": true,
"owner": "pseudo",
"created": "2025-01-08T16:32:46.021014672Z",
"changed": "2025-01-21T17:49:53.312033526Z",
"coverArt": "pl-9d76a86b-901f-4727-a2ec-01210157ff01_678fde41"
},
{
"id": "79f69dc0-1cbf-4d9b-850d-6562c10eb1ff",
"name": "NorthernJourneyOST",
"comment": "Auto-imported from 'NorthernJourneyOST.m3u'",
"songCount": 24,
"duration": 4269,
"public": false,
"owner": "pseudo",
"created": "2025-01-14T14:32:48.159884456Z",
"changed": "2025-01-14T14:32:48.161286475Z",
"coverArt": "pl-79f69dc0-1cbf-4d9b-850d-6562c10eb1ff_67867590"
}
]
}
}
}
+15407
View File
File diff suppressed because it is too large. Load diff
+113 -8
View File
@@ -17,7 +17,7 @@ import SubSonic
from textual import on, events
from textual.app import App, ComposeResult
from textual.widgets import Footer, Header, OptionList, DataTable, Tabs, Tab, TabbedContent, TabPane
from textual.widgets import Footer, Header, OptionList, DataTable, Tabs, Tab, TabbedContent, TabPane, ProgressBar, Label
from textual.screen import Screen
from textual.widgets.option_list import Option
@@ -28,9 +28,14 @@ conn = SubSonic.SubpyConn(u, p, "https://music.0x01fe.net")
class AlbumSongs(Screen):
BINDINGS = [
('escape', 'die()', "Back")
('escape', 'die()', "Back"),
('p', 'play()', 'Play Song'),
('q' 'queue()', 'Queue Song')
]
selected_song_id: str | None = None
songs = None
def __init__(self, album_id: str):
self.album_id = album_id
super().__init__()
@@ -40,15 +45,31 @@ class AlbumSongs(Screen):
yield Footer()
def on_mount(self) -> None:
songs = conn.getAlbumSongs(self.album_id)
self.songs = conn.getAlbumSongs(self.album_id)
songsTable: DataTable = self.query_one(DataTable)
songsTable.cursor_type = 'row'
songsTable.add_columns("#", "Title", "Artist", "Duration", "Bitrate")
for song in songs:
for song in self.songs:
songsTable.add_row(song.trackNumber, song.title, song.artist, song.duration, song.bitRate, key=song.id)
@on(DataTable.RowHighlighted)
def row_highlighted(self, event: DataTable.RowHighlighted) -> None:
self.selected_song_id = event.row_key.value
def action_play(self) -> None:
app.play_song(self._find_selected_song())
def action_queue(self) -> None:
app.queue_song(self._find_selected_song())
# Find the song that was selected
def _find_selected_song(self) -> SubSonic.Song:
for song in self.songs:
if song.id == self.selected_song_id:
return song
# Pops and uninstalls self
def action_die(self) -> None:
@@ -74,10 +95,10 @@ class ArtistAlbums(Screen):
albumTable.cursor_type = 'row'
albumTable.add_columns("Title", "Songs")
albumTable.add_columns("Title", "Songs", "Plays", "Year", "Time")
for album in albums:
albumTable.add_row(album.title, album.songCount, key=album.id)
albumTable.add_row(album.title, album.songCount, album.playCount, album.year, album.duration, key=album.id)
@on(DataTable.RowSelected)
async def album_selected(self, event: DataTable.RowSelected) -> None:
@@ -120,23 +141,107 @@ class Albums(Screen):
yield Footer()
def on_mount(self) -> None:
albums = conn.getAlbums()
albums = conn.getAllAlbums()
albumTable = self.query_one(DataTable)
albumTable.cursor_type = 'row'
albumTable.add_columns("Title", "Songs", "Plays", "Year", "Time")
for album in albums:
albumTable.add_row(album.title, album.songCount, album.playCount, album.year, album.duration, key=album.id)
@on(DataTable.RowSelected)
def album_selected(self, event: DataTable.RowSelected) -> None:
app.install_screen(AlbumSongs(event.row_key.value), 'albumSongs')
app.push_screen('albumSongs')
class Playlists(Screen):
BINDINGS = [
('escape', 'app.pop_screen', "Back")
]
playlists: list[SubSonic.Playlist] | None = None
def compose(self) -> ComposeResult:
yield Header(icon="")
yield DataTable()
yield Footer()
def on_mount(self) -> None:
app.sub_title = "Playlists"
self.playlists = conn.getPlaylists()
playlistTable = self.query_one(DataTable)
playlistTable.cursor_type = "row"
playlistTable.add_columns("Name", "Songs", "Time", "Owner")
for playlist in self.playlists:
playlistTable.add_row(playlist.name, playlist.songCount, playlist.duration, playlist.owner, key=playlist.id)
class Favourites(Screen):
BINDINGS = [
('escape', 'app.pop_screen', "Back")
]
songs: list[SubSonic.Song] | None = None
def compose(self) -> ComposeResult:
yield Header(icon="")
yield DataTable()
yield Footer()
def on_mount(self) -> None:
app.sub_title = "Favourites"
self.songs = conn.getStarredSongs()
songTable = self.query_one(DataTable)
songTable.cursor_type = "row"
songTable.add_columns("Title", "Album", "Artist", "Plays", "Duration", "Bitrate")
for song in self.songs:
songTable.add_row(song.title, song.album, song.artist, song.playCount, song.duration, song.bitRate, key=song.id)
class TextualSubpyPlayer(App):
BINDINGS = [
("f1", "push_screen('artists')", "Artists"),
("f2", "push_screen('albums')", "Albums")
("f2", "push_screen('albums')", "Albums"),
("f3", "push_screen('favourites')", "Favourites"),
("f4", "push_screen('playlists')", "Playlists")
]
currently_playing: SubSonic.Song | None = None
song_queue: list[SubSonic.Song] = []
def compose(self) -> ComposeResult:
yield Label()
yield ProgressBar()
yield Footer()
def on_mount(self) -> None:
logging.debug("mount called")
self.title = "SubPy"
self.install_screen(Artists(), name="artists")
self.install_screen(Albums(), name="albums")
self.install_screen(Favourites(), name="favourites")
self.install_screen(Playlists(), name="playlists")
def on_key(self, event: events.Key) -> None:
logging.debug(f'Key Pressed {event.name}')
def play_song(self, song: SubSonic.Song) -> None:
self.currently_playing = song
logging.debug(f"Playing song {song.title} by {song.artist}.")
# Set callback loop for progress bar
# self.progress_timer = self.set_interval(1 / 10, self.update_progress, pause=False)
# def update_progress(self) -> None:
# self.query_one(ProgressBar).advance(1)
def queue_song(self, song: SubSonic.Song) -> None:
logging.debug(f'Queue\'d song "{song.title}" by {song.artist}.')
self.song_queue.append(song)
if __name__ == '__main__':
app = TextualSubpyPlayer()
app.run()
+306 -1
View File
@@ -1 +1,306 @@
[2025-01-23 12:06:54,543] DEBUG in selector_events: Using selector: EpollSelector
[2025-01-23 16:30:12,660] DEBUG in proactor_events: Using proactor: IocpProactor
[2025-01-23 16:30:12,688] DEBUG in screens-test: mount called
[2025-01-23 16:30:13,222] DEBUG in screens-test: Key Pressed f3
[2025-01-23 16:30:13,249] DEBUG in connectionpool: Starting new HTTPS connection (1): music.0x01fe.net:443
[2025-01-23 16:30:13,561] DEBUG in connectionpool: https://music.0x01fe.net:443 "GET /rest/getStarred?u=pseudo&t=9b4d304e86861c6941ca94888cc7663f&s=KKZ4XKZK&v=1.16.1&c=testing&f=json HTTP/1.1" 200 None
[2025-01-23 16:30:14,577] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,070] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,100] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,130] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,163] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,193] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,242] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,272] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,308] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,339] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,370] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,400] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,432] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,464] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,499] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,529] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,561] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,592] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,627] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,658] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,703] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,739] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,769] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,800] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,838] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,863] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,894] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,928] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,959] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:15,990] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,024] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,054] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,109] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,118] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,164] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,199] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,231] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,261] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,293] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,330] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,359] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,391] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,424] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,452] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,491] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,518] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,552] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,580] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,630] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,659] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,693] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,721] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,752] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,786] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,817] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,849] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,879] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,911] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,960] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:16,990] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,020] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,052] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,089] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,115] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,149] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,180] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,210] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,249] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,299] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,305] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,358] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,386] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,418] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,459] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,482] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,516] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,544] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,609] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,630] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,640] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,673] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,704] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,736] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,769] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,800] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,859] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,899] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,938] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:17,969] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,000] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,009] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,040] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,070] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,102] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,169] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,170] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,211] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,249] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,279] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,319] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,349] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,385] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,449] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,449] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,489] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,519] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,551] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,589] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,618] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,649] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,720] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,720] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,754] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,783] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,814] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,854] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,880] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,924] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,949] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:18,957] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,019] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,051] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,083] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,119] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,150] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,179] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,210] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,284] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,289] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,289] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,322] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,352] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,389] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,433] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,468] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,499] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,571] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,574] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,600] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,629] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,669] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,700] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,738] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,764] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,799] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,870] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,870] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,899] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,929] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:19,960] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,002] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,033] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,069] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,099] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,173] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,173] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,210] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,249] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,258] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,289] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,323] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,360] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,420] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,420] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,499] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,499] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,549] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,551] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,589] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,636] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,679] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,685] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,730] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,779] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,779] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,872] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,876] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,909] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,909] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,971] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:20,971] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,017] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,057] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,088] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,119] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,189] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,189] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,206] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,240] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,290] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,334] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,336] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:21,799] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,304] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,340] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,371] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,400] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,449] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,481] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,509] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,541] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,574] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,605] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,639] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,670] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,702] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,736] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,765] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,799] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,829] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,860] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,909] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,941] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:22,976] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:23,004] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:23,042] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:23,070] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:23,103] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:23,132] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:23,163] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:23,195] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:23,462] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:23,972] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,004] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,039] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,070] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,100] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,132] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,169] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,199] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,231] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,260] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,295] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,326] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,370] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,402] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,434] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,468] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,500] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,529] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,561] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,592] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,630] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,654] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,701] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,732] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,769] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,799] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,829] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,861] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,893] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,939] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:24,971] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,059] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,060] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,062] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,112] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,173] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,178] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,221] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,226] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,259] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,299] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,337] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,420] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,420] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,420] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,462] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,510] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,571] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,574] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,599] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,640] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,673] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,703] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,788] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,789] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,789] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,828] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,873] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,899] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,941] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:25,941] DEBUG in screens-test: Key Pressed down
[2025-01-23 16:30:26,190] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,699] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,740] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,773] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,801] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,833] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,869] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,899] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,930] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,964] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:26,992] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:27,029] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:27,060] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:27,093] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:27,122] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:27,164] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:27,188] DEBUG in screens-test: Key Pressed up
[2025-01-23 16:30:41,251] DEBUG in screens-test: Key Pressed escape