lots of progress
This commit is contained in:
1 parent
1d56b5efea
commit
f8815964b5
8 files changed
+16549
-16
No files matched your search
+111
-6
@@ -1,3 +1,4 @@
|
|||||||
|
import time
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
import hashlib
|
import hashlib
|
||||||
@@ -12,6 +13,21 @@ import requests
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
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:
|
class Album:
|
||||||
id: str
|
id: str
|
||||||
@@ -22,6 +38,9 @@ class Album:
|
|||||||
duration: int
|
duration: int
|
||||||
artistId: str
|
artistId: str
|
||||||
songCount: int
|
songCount: int
|
||||||
|
playCount: int
|
||||||
|
year: int | None
|
||||||
|
duration: str
|
||||||
|
|
||||||
def __init__(self, album_info: dict):
|
def __init__(self, album_info: dict):
|
||||||
self.id = album_info['id']
|
self.id = album_info['id']
|
||||||
@@ -32,6 +51,12 @@ class Album:
|
|||||||
self.duration = int(album_info['duration'])
|
self.duration = int(album_info['duration'])
|
||||||
self.artistId = album_info['artistId']
|
self.artistId = album_info['artistId']
|
||||||
self.songCount = int(album_info['songCount'])
|
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:
|
class Song:
|
||||||
id: str
|
id: str
|
||||||
@@ -50,13 +75,14 @@ class Song:
|
|||||||
comment: str
|
comment: str
|
||||||
channelCount: int
|
channelCount: int
|
||||||
samplingRate: int
|
samplingRate: int
|
||||||
|
playCount: int | None
|
||||||
|
|
||||||
def __init__(self, song_info: dict):
|
def __init__(self, song_info: dict):
|
||||||
self.id = song_info['id']
|
self.id = song_info['id']
|
||||||
self.title = song_info['title']
|
self.title = song_info['title']
|
||||||
self.album = song_info['album']
|
self.album = song_info['album']
|
||||||
self.artist = song_info['artist']
|
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.contentType = song_info['contentType']
|
||||||
self.suffix = song_info['suffix']
|
self.suffix = song_info['suffix']
|
||||||
self.duration = int(song_info['duration'])
|
self.duration = int(song_info['duration'])
|
||||||
@@ -64,10 +90,11 @@ class Song:
|
|||||||
self.path = song_info['path']
|
self.path = song_info['path']
|
||||||
self.discNumber = int(song_info['discNumber']) if 'discNumber' in song_info else None
|
self.discNumber = int(song_info['discNumber']) if 'discNumber' in song_info else None
|
||||||
self.albumId = song_info['albumId']
|
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.comment = song_info['comment']
|
||||||
self.channelCount = int(song_info['channelCount'])
|
self.channelCount = int(song_info['channelCount'])
|
||||||
self.samplingRate = int(song_info['samplingRate'])
|
self.samplingRate = int(song_info['samplingRate'])
|
||||||
|
self.playCount = int(song_info['playCount']) if 'playCount' in song_info else None
|
||||||
|
|
||||||
class Artist:
|
class Artist:
|
||||||
id: str
|
id: str
|
||||||
@@ -230,17 +257,95 @@ class SubpyConn:
|
|||||||
|
|
||||||
return artists
|
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?'
|
url = self.base_url + '/rest/getAlbumList?'
|
||||||
|
|
||||||
payload = self._getBasePayload()
|
payload = self._getBasePayload()
|
||||||
payload['type'] = 'alphabeticalByName'
|
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))
|
r = requests.get(url + self._encodePayload(payload))
|
||||||
|
|
||||||
with open("albumList.xml" , 'wb') as file:
|
json_r = r.json()
|
||||||
file.write(r.content)
|
|
||||||
|
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
|
# Returns a requests Response object, the data stream can be found in Response.content
|
||||||
def stream(self, song_id: str) -> requests.Response:
|
def stream(self, song_id: str) -> requests.Response:
|
||||||
|
|||||||
@@ -91,7 +91,14 @@ class SubPyPlayer:
|
|||||||
|
|
||||||
# player = SubPyPlayer(conn)
|
# 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)
|
# player.play_song(echidna_id)
|
||||||
|
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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
File diff suppressed because it is too large.
Load diff
+113
-8
@@ -17,7 +17,7 @@ import SubSonic
|
|||||||
|
|
||||||
from textual import on, events
|
from textual import on, events
|
||||||
from textual.app import App, ComposeResult
|
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.screen import Screen
|
||||||
from textual.widgets.option_list import Option
|
from textual.widgets.option_list import Option
|
||||||
|
|
||||||
@@ -28,9 +28,14 @@ conn = SubSonic.SubpyConn(u, p, "https://music.0x01fe.net")
|
|||||||
|
|
||||||
class AlbumSongs(Screen):
|
class AlbumSongs(Screen):
|
||||||
BINDINGS = [
|
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):
|
def __init__(self, album_id: str):
|
||||||
self.album_id = album_id
|
self.album_id = album_id
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@@ -40,15 +45,31 @@ class AlbumSongs(Screen):
|
|||||||
yield Footer()
|
yield Footer()
|
||||||
|
|
||||||
def on_mount(self) -> None:
|
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: DataTable = self.query_one(DataTable)
|
||||||
|
|
||||||
songsTable.cursor_type = 'row'
|
songsTable.cursor_type = 'row'
|
||||||
songsTable.add_columns("#", "Title", "Artist", "Duration", "Bitrate")
|
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)
|
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
|
# Pops and uninstalls self
|
||||||
def action_die(self) -> None:
|
def action_die(self) -> None:
|
||||||
@@ -74,10 +95,10 @@ class ArtistAlbums(Screen):
|
|||||||
|
|
||||||
albumTable.cursor_type = 'row'
|
albumTable.cursor_type = 'row'
|
||||||
|
|
||||||
albumTable.add_columns("Title", "Songs")
|
albumTable.add_columns("Title", "Songs", "Plays", "Year", "Time")
|
||||||
|
|
||||||
for album in albums:
|
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)
|
@on(DataTable.RowSelected)
|
||||||
async def album_selected(self, event: DataTable.RowSelected) -> None:
|
async def album_selected(self, event: DataTable.RowSelected) -> None:
|
||||||
@@ -120,23 +141,107 @@ class Albums(Screen):
|
|||||||
yield Footer()
|
yield Footer()
|
||||||
|
|
||||||
def on_mount(self) -> None:
|
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):
|
class TextualSubpyPlayer(App):
|
||||||
BINDINGS = [
|
BINDINGS = [
|
||||||
("f1", "push_screen('artists')", "Artists"),
|
("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:
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Label()
|
||||||
|
yield ProgressBar()
|
||||||
yield Footer()
|
yield Footer()
|
||||||
|
|
||||||
def on_mount(self) -> None:
|
def on_mount(self) -> None:
|
||||||
|
logging.debug("mount called")
|
||||||
|
self.title = "SubPy"
|
||||||
self.install_screen(Artists(), name="artists")
|
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:
|
def on_key(self, event: events.Key) -> None:
|
||||||
logging.debug(f'Key Pressed {event.name}')
|
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__':
|
if __name__ == '__main__':
|
||||||
app = TextualSubpyPlayer()
|
app = TextualSubpyPlayer()
|
||||||
app.run()
|
app.run()
|
||||||
+306
-1
@@ -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
|
||||||
Reference in new issue
Block a user