implement album listings
This commit is contained in:
parent
33e501928e
commit
ac9b3620e9
104
pysonic/api.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!
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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…
Reference in New Issue