Browse Source

implement album listings

v2
dave 4 years ago
parent
commit
ac9b3620e9
  1. 104
      pysonic/api.py
  2. 38
      pysonic/database.py
  3. 4
      pysonic/scanner.py

104
pysonic/api.py

@ -202,41 +202,39 @@ class PysonicApi(object):
response.add_child("artist", _real_parent=index, id=artist["dir"], name=artist["name"])
return response
@cherrypy.expose
def savePlayQueue_view(self, id, current, position, **kwargs):
print("TODO save playlist with items {} current {} position {}".format(id, current, position))
@cherrypy.expose
@formatresponse
def getAlbumList_view(self, type, size=50, offset=0, **kwargs):
albums = self.library.get_albums()
qargs = {}
if type == "random":
shuffle(albums)
qargs.update(sortby="random")
elif type == "alphabeticalByName":
albums.sort(key=lambda item: item.get("id3_album", item["album"] if item["album"] else "zzzzzUnsortable"))
qargs.update(sortby="name", order="asc")
elif type == "newest":
qargs.update(sortby="added", order="desc")
else:
raise NotImplemented()
albumset = albums[0 + int(offset):int(size) + int(offset)]
qargs.update(limit=(offset, size))
albums = self.library.get_albums(**qargs)
response = ApiResponse()
response.add_child("albumList")
for album in albumset:
album_meta = album['metadata']
album_kw = dict(id=album["id"],
parent=album["parent"],
isDir="true" if album['isdir'] else "false",
title=album_meta.get("id3_title", album["name"]), #TODO these cant be blank or dsub gets mad
album=album_meta.get("id3_album", album["album"]),
artist=album_meta.get("id3_artist", album["artist"]),
for album in albums:
album_kw = dict(id=album["dir"],
parent=album["artistdir"],
isDir="true",
title=album["name"],
album=album["name"],
artist=album["artistname"],
coverArt=album["coverid"]
#year=TODO
# playCount="0"
# created="2016-05-08T05:31:31.000Z"/>)
)
if 'cover' in album_meta:
album_kw["coverArt"] = album_meta["cover"]
if 'id3_year' in album_meta:
album_kw["year"] = album_meta['id3_year']
response.add_child("album", _parent="albumList", **album_kw)
return response
@ -247,18 +245,10 @@ class PysonicApi(object):
List an artist dir
"""
dir_id = int(id)
cherrypy.response.headers['Content-Type'] = 'text/xml; charset=utf-8'
dirtype, dirinfo, entity = self.library.db.get_musicdir(dirid=dir_id)
response = ApiResponse()
response.add_child("directory")
dirtype, dirinfo, entity = self.library.db.get_musicdir(dirid=dir_id)
from pprint import pprint
pprint(dirinfo)
pprint(entity)
response.set_attrs(_path="directory", name=entity['name'], id=entity['id'],
parent=dirinfo['parent'], playCount=420)
@ -297,53 +287,9 @@ class PysonicApi(object):
type="music",
**moreargs)
cherrypy.response.headers['Content-Type'] = 'text/xml; charset=utf-8'
return response
def render_node(self, item, item_meta, directory, dir_meta):
"""
Given a node and it's parent directory, and meta, return a dict with the keys formatted how the subsonic clients
expect them to be
:param item:
:param item_meta:
:param directory:
:param dir_meta:
"""
raise Exception("stop using this")
child = dict(id=item["id"],
parent=item["id"],
isDir="true" if "file" not in item else "false",
title=item_meta.get("id3_title", item["name"]),
album=item_meta.get("id3_album", item["album"]),
artist=item_meta.get("id3_artist", item["artist"]),
# playCount="5",
# created="2016-04-25T07:31:33.000Z"
# genre="Other",
# path="Cosmic Gate/Sign Of The Times/03 Flatline (featuring Kyler England).mp3"
type="music")
if 'kbitrate' in item_meta:
child["bitrate"] = item_meta["kbitrate"]
if item["size"] != -1:
child["size"] = item["size"]
if "media_length" in item_meta:
child["duration"] = item_meta["media_length"]
if "albumId" in directory:
child["albumId"] = directory["id"]
if "artistId" in directory:
child["artistId"] = directory["parent"]
if "." in item["name"]:
child["suffix"] = item["name"].split(".")[-1]
if item["type"]:
child["contentType"] = item["type"]
if 'cover' in item_meta:
child["coverArt"] = item_meta["cover"]
elif 'cover' in dir_meta:
child["coverArt"] = dir_meta["cover"]
if 'track' in item_meta:
child["track"] = item_meta['track']
if 'id3_year' in item_meta:
child["year"] = item_meta['id3_year']
return child
@cherrypy.expose
def stream_view(self, id, maxBitRate="256", **kwargs):
maxBitRate = int(maxBitRate)
@ -372,7 +318,6 @@ class PysonicApi(object):
# transcode_meta = "transcoded_{}_size".format(to_bitrate)
# if transcode_meta in meta:
# cherrypy.response.headers['Content-Length'] = str(int(meta[transcode_meta]))
print(fpath)
transcode_args = ["ffmpeg", "-i", fpath, "-map", "0:0", "-b:a",
"{}k".format(to_bitrate),
"-v", "0", "-f", "mp3", "-"]
@ -437,7 +382,6 @@ class PysonicApi(object):
yield data
logging.info("\nSent {} bytes for {}".format(total, fpath))
return content()
getCoverArt_view._cp_config = {'response.stream': True}
@cherrypy.expose
@ -558,7 +502,7 @@ class PysonicApi(object):
:param submission: True if end of song reached. False on start of track.
"""
submission = True if submission == "true" else False
# TODO save played track stats
# TODO save played track stats and/or do last.fm bullshit
return ApiResponse()
@cherrypy.expose
@ -606,3 +550,9 @@ class PysonicApi(object):
def setRating_view(self, id, rating):
# rating is 1-5
pass
@cherrypy.expose
def savePlayQueue_view(self, id, current, position, **kwargs):
print("TODO save playlist with items {} current {} position {}".format(id, current, position))
# TODO save playlist with items ['378', '386', '384', '380', '383'] current 383 position 4471
# id entries are strings!

38
pysonic/database.py

@ -73,6 +73,7 @@ class PysonicDatabase(object):
'coverid' INTEGER,
'dir' INTEGER,
'name' TEXT,
'added' INTEGER NOT NULL DEFAULT -1,
UNIQUE (artistid, dir));""",
"""CREATE TABLE 'songs' (
'id' INTEGER PRIMARY KEY AUTOINCREMENT,
@ -181,11 +182,31 @@ class PysonicDatabase(object):
return artists
@readcursor
def get_albums(self, cursor, id=None, artist=None, sortby=None, order=None):
assert order in ["asc", "desc", None]
def get_albums(self, cursor, id=None, artist=None, sortby=None, order=None, limit=None):
"""
:param limit: int or tuple of int, int. translates directly to sql logic.
"""
if order:
order = {"asc": "ASC", "desc": "DESC"}[order]
if sortby and sortby == "random":
sortby = "RANDOM()"
albums = []
q = "SELECT * FROM albums"
q = """
SELECT
alb.*,
art.name as artistname,
dirs.parent as artistdir
FROM albums as alb
INNER JOIN artists as art
on alb.artistid = art.id
INNER JOIN dirs
on dirs.id = alb.dir
"""
#q = "SELECT * FROM albums"
params = []
conditions = []
@ -199,7 +220,14 @@ class PysonicDatabase(object):
q += " WHERE " + " AND ".join(conditions)
if sortby:
q += " ORDER BY {} {}".format(sortby, order.upper() if order else "ASC")
q += " ORDER BY {}".format(sortby)
if order:
q += " {}".format(order)
if limit:
q += " LIMIT {}".format(limit) if isinstance(limit, int) \
else " LIMIT {}, {}".format(*limit)
cursor.execute(q, params)
for row in cursor:
albums.append(row)
@ -253,8 +281,6 @@ class PysonicDatabase(object):
if limit:
q += " LIMIT {}".format(limit) # TODO support limit pagination
print(q)
cursor.execute(q, params)
for row in cursor:
songs.append(row)

4
pysonic/scanner.py

@ -191,8 +191,8 @@ class PysonicFilesystemScanner(object):
if row:
album_id = row['id']
else:
cursor.execute("INSERT INTO albums (artistid, dir, name) VALUES (?, ?, ?)",
(artist_id, album_dirid, dirnames[-1]))
cursor.execute("INSERT INTO albums (artistid, dir, name, added) VALUES (?, ?, ?, ?)",
(artist_id, album_dirid, dirnames[-1], int(time())))
album_id = cursor.lastrowid
return album_id, album_dirid

Loading…
Cancel
Save