From 5e0e541cf9e240b45d54479f162805424f01d691 Mon Sep 17 00:00:00 2001 From: dave Date: Tue, 6 Oct 2020 16:59:23 -0700 Subject: [PATCH] fix suffix field --- pysonic/api.py | 38 +++++++++++++++++++++++++++----------- pysonic/scanner.py | 15 +++++++++++---- pysonic/types.py | 19 +++++++++++++++++++ 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/pysonic/api.py b/pysonic/api.py index 2d56944..442de79 100644 --- a/pysonic/api.py +++ b/pysonic/api.py @@ -4,13 +4,19 @@ import subprocess from time import time from threading import Thread from pysonic.database import LETTER_GROUPS -from pysonic.types import MUSIC_TYPES +from pysonic.types import MUSIC_TYPES, TYPE_TO_EXTENSION from pysonic.apilib import formatresponse, ApiResponse import cherrypy logging = logging.getLogger("api") +def extension(mime): + r = TYPE_TO_EXTENSION.get(mime) + print(f"getting extension for {mime}: {r}") + return r + + class PysonicSubsonicApi(object): def __init__(self, db, options): self.db = db @@ -127,7 +133,7 @@ class PysonicSubsonicApi(object): response.set_attrs(_path="directory", parent=dirinfo["parent"], playCount=entity["plays"]) - #TODO Meeeeee + #TODO refactor meeeeee for childtype, child in entity["children"]: # omit not dirs and media in browser # if not item["isdir"] and item["type"] not in MUSIC_TYPES: @@ -146,7 +152,10 @@ class PysonicSubsonicApi(object): # artist=artist["name"], # coverArt=item["coverid"], elif childtype == "song": - moreargs.update(name=child["title"], + moreargs.update(title=child["title"], + albumId=entity["dir"], + album=entity["name"], + artistId=child["_artist"]["dir"], artist=child["_artist"]["name"], contentType=child["format"], id=child["id"], @@ -154,11 +163,20 @@ class PysonicSubsonicApi(object): isDir="false", parent=entity["dir"], track=child["track"], - # title=xxx + playCount=child["plays"], + #TODO suffix can be null/omitted, which causes the client to cache files wrong, while + # this isn't ideal, fixing it properly would require significant changes to the scanner. + suffix=extension(child["format"]), + path=child["file"], + # bitRate + # discNumber + # created= + # year=1999 + # genre="Alternative & Punk" ) if entity["coverid"]: moreargs.update(coverArt=entity["coverid"]) - # duration="230" size="8409237" suffix="mp3" track="2" year="2005"/> + response.add_child("child", _parent="directory", size="4096", type="music", @@ -368,8 +386,6 @@ class PysonicSubsonicApi(object): if song["year"]: moreargs.update(year=song["year"]) - file_extension = song["file"].split(".")[-1] - response.add_child("song", _parent="randomSongs", title=song["title"], @@ -379,7 +395,7 @@ class PysonicSubsonicApi(object): isDir="false", parent=song["albumid"], size=song["size"], - suffix=file_extension, + suffix=extension(song["format"]), type="music", **moreargs) return response @@ -463,8 +479,8 @@ class PysonicSubsonicApi(object): path=song["file"], playCount=song["plays"], albumId=song["albumid"], - type="music" - # suffix="mp3" + type="music", + suffix=extension(song["format"]), # created="2012-09-17T22:35:19.000Z" ) @@ -555,7 +571,7 @@ class PysonicSubsonicApi(object): coverArt=song["albumcoverid"], size=song["size"], contentType=song["format"], - # suffix="mp3" + suffix=extension(song["format"]), duration=song["length"], bitRate=song["bitrate"] / 1024 if song["bitrate"] else None, #TODO macro for this sort of logic path=song["file"], diff --git a/pysonic/scanner.py b/pysonic/scanner.py index de43b20..0b2bfa4 100644 --- a/pysonic/scanner.py +++ b/pysonic/scanner.py @@ -5,7 +5,8 @@ from contextlib import closing import mimetypes from time import time from threading import Thread -from pysonic.types import KNOWN_MIMES, MUSIC_TYPES, MPX_TYPES, FLAC_TYPES, WAV_TYPES, MUSIC_EXTENSIONS, IMAGE_EXTENSIONS, IMAGE_TYPES +from pysonic.types import MUSIC_TYPES, MPX_TYPES, FLAC_TYPES, MUSIC_EXTENSIONS, IMAGE_EXTENSIONS, \ + TYPE_TO_EXTENSION, UNKNOWN_MIME from mutagen.id3 import ID3 from mutagen import MutagenError from mutagen.id3._util import ID3NoHeaderError @@ -17,6 +18,11 @@ logging = logging.getLogger("scanner") RE_NUMBERS = re.compile(r'^([0-9]+)') +def guess_format(fname): + ext = fname.split(".")[-1].lower() + return TYPE_TO_EXTENSION.get(ext, UNKNOWN_MIME) + + class PysonicFilesystemScanner(object): def __init__(self, db): self.db = db @@ -147,13 +153,14 @@ class PysonicFilesystemScanner(object): if not cursor.fetchall(): # We leave most fields blank now and return later # TODO probably not here but track file sizes and mark them for rescan on change - cursor.execute("INSERT INTO songs (library, albumid, file, size, title) " - "VALUES (?, ?, ?, ?, ?)", + cursor.execute("INSERT INTO songs (library, albumid, file, size, title, format) " + "VALUES (?, ?, ?, ?, ?, ?)", (pid, album_id, fpath, os.stat(os.path.join(root_dir, fpath)).st_size, - fname, )) + fname, + guess_format(fpath))) return True return False diff --git a/pysonic/types.py b/pysonic/types.py index e6a11a9..bf7d196 100644 --- a/pysonic/types.py +++ b/pysonic/types.py @@ -14,3 +14,22 @@ IMAGE_TYPES = ["image/jpeg", "image/png", "image/gif"] IMAGE_EXTENSIONS = ["jpg", "jpeg", "png", "gif"] MUSIC_EXTENSIONS = ["mp3", "flac", "wav"] + +TYPE_TO_EXTENSION = { + "audio/mpeg": "mp3", + "audio/flac": "flac", + "audio/x-wav": "wav", + "image/jpeg": "jpg", + "image/png": "png", +} + +EXTENSION_TO_TYPE = { + "mp3": "audio/mpeg", + "flac": "audio/flac", + "wav": "audio/x-wav", + "jpg": "image/jpeg", + "png": "image/png", +} + + +UNKNOWN_MIME = None