2017-08-13 18:56:13 -07:00
|
|
|
import os
|
|
|
|
import json
|
2017-08-13 21:13:46 -07:00
|
|
|
import logging
|
2017-08-13 18:56:13 -07:00
|
|
|
from pysonic.scanner import PysonicFilesystemScanner
|
|
|
|
|
|
|
|
|
|
|
|
LETTER_GROUPS = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
|
2017-08-13 21:13:46 -07:00
|
|
|
"u", "v", "w", "xyz", "0123456789"]
|
|
|
|
|
|
|
|
|
|
|
|
logging = logging.getLogger("library")
|
2017-08-13 18:56:13 -07:00
|
|
|
|
|
|
|
|
|
|
|
def memoize(function):
|
|
|
|
memo = {}
|
|
|
|
|
|
|
|
def wrapper(*args):
|
|
|
|
if args in memo:
|
|
|
|
return memo[args]
|
|
|
|
else:
|
|
|
|
rv = function(*args)
|
|
|
|
memo[args] = rv
|
|
|
|
return rv
|
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
|
|
|
class NoDataException(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2017-08-13 21:13:46 -07:00
|
|
|
class DuplicateRootException(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2017-08-13 18:56:13 -07:00
|
|
|
class PysonicLibrary(object):
|
|
|
|
def __init__(self, database):
|
|
|
|
self.db = database
|
|
|
|
self.scanner = PysonicFilesystemScanner(self)
|
2017-08-13 21:13:46 -07:00
|
|
|
logging.info("library ready")
|
2017-08-13 18:56:13 -07:00
|
|
|
|
|
|
|
def update(self):
|
|
|
|
self.scanner.init_scan()
|
|
|
|
|
2017-08-13 21:13:46 -07:00
|
|
|
def add_dir(self, dir_path):
|
|
|
|
dir_path = os.path.abspath(os.path.normpath(dir_path))
|
|
|
|
libraries = [self.db.decode_metadata(i['metadata'])['fspath'] for i in self.db.getnodes(-1)]
|
|
|
|
if dir_path in libraries:
|
|
|
|
raise DuplicateRootException("Dir already in library")
|
|
|
|
else:
|
|
|
|
new_root = self.db._addnode(-1, 'New Library', is_dir=True)
|
|
|
|
self.db.update_metadata(new_root['id'], fspath=dir_path)
|
|
|
|
|
2017-08-13 18:56:13 -07:00
|
|
|
@memoize
|
|
|
|
def get_libraries(self):
|
|
|
|
"""
|
|
|
|
Libraries are top-level nodes
|
|
|
|
"""
|
|
|
|
return self.db.getnodes(-1)
|
|
|
|
|
|
|
|
@memoize
|
|
|
|
def get_artists(self):
|
|
|
|
# Assume artists are second level dirs
|
|
|
|
return self.db.getnodes(*[item["id"] for item in self.get_libraries()])
|
|
|
|
|
|
|
|
def get_dir(self, dirid):
|
|
|
|
return self.db.getnode(dirid)
|
|
|
|
|
|
|
|
def get_dir_children(self, dirid):
|
|
|
|
return self.db.getnodes(dirid)
|
|
|
|
|
2017-08-13 23:54:37 -07:00
|
|
|
@memoize
|
|
|
|
def get_albums(self):
|
|
|
|
return self.db.getnodes(*[item["id"] for item in self.get_artists()])
|
|
|
|
|
2017-08-13 18:56:13 -07:00
|
|
|
@memoize
|
2017-08-13 22:08:40 -07:00
|
|
|
def get_filepath(self, nodeid):
|
|
|
|
parents = [self.db.getnode(nodeid)]
|
2017-08-13 18:56:13 -07:00
|
|
|
while parents[-1]['parent'] != -1:
|
|
|
|
parents.append(self.db.getnode(parents[-1]['parent']))
|
|
|
|
root = parents.pop()
|
|
|
|
parents.reverse()
|
|
|
|
return os.path.join(json.loads(root['metadata'])['fspath'], *[i['name'] for i in parents])
|
|
|
|
|
2017-08-13 22:08:40 -07:00
|
|
|
def get_file_metadata(self, nodeid):
|
|
|
|
return self.db.get_metadata(nodeid)
|
|
|
|
|
2017-08-13 18:56:13 -07:00
|
|
|
def get_artist_info(self, item_id):
|
|
|
|
# artist = self.db.getnode(item_id)
|
|
|
|
return {"biography": "placeholder biography",
|
|
|
|
"musicBrainzId": "playerholder",
|
|
|
|
"lastFmUrl": "https://www.last.fm/music/Placeholder",
|
|
|
|
"smallImageUrl": "",
|
|
|
|
"mediumImageUrl": "",
|
|
|
|
"largeImageUrl": "",
|
|
|
|
"similarArtists": []}
|