def add_path(self, path, album=False, session=None): self.log.info("add_path: %s, album=%s" % (path, album)) assert session eid = None record = None record_a = None if not isinstance(path, unicode): path_u = to_unicode(path) else: path_u = path if os.path.isdir(path): eid = MediaManager.uuid(path) if album: record = self.Album(path) else: record = self.Artist(path) self.log.info("adding directory: %s, %s " % (eid, path_u)) elif MediaManager.is_allowed_extension(path_u): try: record = self.Media(path) # Create a virtual album using a mock album id # every song with the same virtual album (artist,album) # is tied to it. if record.album != basename(path) and record.artist and record.album: vpath = join("/", record.artist, record.album) record_a = self.Album(vpath) record.albumId = MediaManager.uuid(vpath) eid = record.id self.log.info("adding file: %s, %s " % ( eid, path_u)) except UnsupportedMediaError, e: raise IposonicException(e)
def get_info(self, path_u): return { 'id': MediaManager.uuid(path_u), 'name': basename(path_u), 'path': path_u, 'isDir': 'true' }
def get_info_harn(self, file_name, expected): info = MediaManager.get_info(os.getcwd() + "/" + file_name) print("info: %s" % info) for f in expected.keys(): assert info[f] == expected[ f], "Mismatching field %s. Expected %s get %s" % ( f, expected[f], info[f])
def scrobble_view(): """Add song to last.fm id Yes A string which uniquely identifies the file to scrobble. time No (Since 1.8.0) The time (in milliseconds since 1 Jan 1970) at which the song was listened to. submission No True Whether this is a "submission" or a "now playing" notification. """ from mediamanager.scrobble import q (u, p, v, c, f, callback) = map( request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback']) (eid, ts, submission) = map( request.args.get, ['id', 'time', 'submission']) assert eid, "Missing song id" log.info("Retrieving scrobbling credentials") lastfm_user = app.iposonic.get_users(MediaManager.uuid(u)) log.info("Scobbling credentials: %s" % lastfm_user) # get song info and append timestamp info = app.iposonic.get_entry_by_id(eid) info.update({'timestamp': int(time.time())}) q.put(({ 'username': lastfm_user.get('scrobbleUser'), 'password': lastfm_user.get('scrobblePassword')}, info)) return request.formatter({})
def get_now_playing_view(): """TODO: save timestamp and song duration of every stream.view request xml response: <nowPlaying> <entry username="******" minutesAgo="12" playerId="2" ... # all media properties /> <entry username="******" minutesAgo="1" playerId="4" playerName="Kitchen" ... # all media properties /> </nowPlaying> """ (u, p, v, c, f, callback) = map(request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback']) user = app.iposonic.get_users(eid=MediaManager.uuid(u)) assert user.get('nowPlaying'), "Nothing playing now..." song = app.iposonic.get_songs(eid=user.get('nowPlaying')) song.update({'username': u}) return request.formatter({'nowPlaying': {'entry': song}})
def get_now_playing_view(): """TODO: save timestamp and song duration of every stream.view request xml response: <nowPlaying> <entry username="******" minutesAgo="12" playerId="2" ... # all media properties /> <entry username="******" minutesAgo="1" playerId="4" playerName="Kitchen" ... # all media properties /> </nowPlaying> """ (u, p, v, c, f, callback) = map( request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback']) user = app.iposonic.get_users(eid=MediaManager.uuid(u)) assert user.get('nowPlaying'), "Nothing playing now..." song = app.iposonic.get_songs(eid=user.get('nowPlaying')) song.update({'username': u}) return request.formatter({'nowPlaying': {'entry': song}})
def test_get_info_from_name2(self): for name in [ 'While my guitar gently weeps.mp3', 'The Beatles - While my guitar gently weeps.mp3', 'While my guitar gently weeps (1969).mp3', 'The Beatles - While my guitar gently weeps (1969).mp3', 'Greatest Hits - 01 - While my guitar gently weeps.mp3', 'While my guitar gently weeps (Disk1)', 'While my guitar gently weeps (EP) - 2003' ]: info = MediaManager.get_info_from_filename2(name) print "info: %s" % info assert info.get( 'title') == 'While my guitar gently weeps', "ret: %s" % info
def get_info(self, path): """TODO use path_u directly.""" eid = MediaManager.uuid(path) path_u = stringutils.to_unicode(path) parent = dirname(path) dirname_u = MediaManager.get_album_name(path_u) return { 'id': eid, 'name': dirname_u, 'isDir': 'true', 'path': path_u, 'title': dirname_u, 'parent': MediaManager.uuid(parent), 'album': dirname_u, 'artist': basename(parent), 'coverArt': eid }
def test_normalize(self): info_l = [ {'album': 'pippo', 'artist': u'Fiorella Mannoia'}, {'album': 'pippo', 'artist': u'Fiorella_Mannoia'} ] for info in info_l: ret = MediaManager.normalize_artist(info) assert ret == 'fiorellamannoia'
def test_normalize_stopwords(self): info_l = [ {'album': 'pippo', 'artist': u'The Beatles'}, {'album': 'pippo', 'artist': u'Beatles'} ] for info in info_l: ret = MediaManager.normalize_artist(info, stopwords=True) assert ret == 'beatles'
def walk_music_directory_old(self): """Find all artists (top-level directories) and create indexes. TODO: create a cache for this. """ #raise NotImplementedError("This method should not be used") log.info("walking: ", self.get_music_folders()) # reset database self.reset() # find all artists for music_folder in self.get_music_folders(): artists_local = [ x for x in os.listdir(music_folder) if os.path.isdir(join("/", music_folder, x)) ] #index all artists for a in artists_local: if a: path = join("/", music_folder, a) try: self.add_path(path) self.artists[MediaManager.uuid( path)] = IposonicDB.Artist(path) artist_j = { 'artist': { 'id': MediaManager.uuid(path), 'name': a } } # # indexes = { 'A' : {'artist': {'id': .., 'name': ...}}} # first = a[0:1].upper() self.indexes.setdefault(first, []) self.indexes[first].append(artist_j) log.info("Adding to index converted entry: %s" % artist_j) except IposonicException as e: log.error(e) log.info("artists: %s" % self.artists) return self.get_indexes()
def test_coverart_uuid(self): info_l = [ {'artist': 'Antony & the Johnsons', 'album': 'The crying light'}, {'artist': 'Antony and the Johnsons', 'album': 'The crying light'}, ] for info in info_l: ret = MediaManager.cover_art_uuid(info) print "coverid:", ret
def cover_art_worker(cache_dir, cover_search=cover_search): log.info("starting downloader thread with tmp_dir: %s" % cache_dir) info = True while info: info = q.get() try: cover_art_path = os.path.join("/", cache_dir, MediaManager.cover_art_uuid(info)) log.info("coverart %s: searching album: %s " % (info.get('id'), info.get('album'))) covers = cover_search(info.get('album')) for cover in covers: # TODO consider multiple authors in info # ex. Actually "U2 & Frank Sinatra" != "U2" # leads to a false negative # TODO con print "confronting info: %s with: %s" % (info, cover) normalize_info, normalize_cover = map( MediaManager.normalize_artist, [info, cover]) full_match = len(set([normalize_info, normalize_cover])) == 1 stopwords_match = len( set([ MediaManager.normalize_artist(x, stopwords=True) for x in [info, cover] ])) == 1 partial_match = len([ x for x in normalize_info if x not in normalize_cover ]) == 0 if full_match or stopwords_match or partial_match: log.warn("Saving image %s -> %s" % (cover.get('cover_small'), cover_art_path)) fd = open(cover_art_path, "w") fd.write(urlopen(cover.get('cover_small')).read()) fd.close() else: log.info("Artist mismatch: %s, %s" % tuple([ x.get('artist', x.get('name')) for x in [info, cover] ])) except Exception as e: log.error("Error while downloading albumart.", e) q.task_done() log.warn("finish download thread")
def stream_view(): """@params - id=1409097050 - maxBitRate=0 TODO """ (u, p, v, c, f, callback) = map( request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback']) (eid, maxBitRate) = map(request.args.get, ['id', 'maxBitRate']) print("request.headers: %s" % request.headers) if not eid: raise SubsonicProtocolException( "Missing required parameter: 'id' in stream.view") info = app.iposonic.get_entry_by_id(eid) path = info.get('path', None) assert path, "missing path in song: %s" % info def is_transcode(maxBitRate, info): try: maxBitRate = int(maxBitRate) if maxBitRate: return maxBitRate < info.get('bitRate') except: print("sending unchanged") return False log.info("actual - bitRate: %s" % info.get('bitRate')) assert os.path.isfile(path), "Missing file: %s" % path # update now playing try: log.info("Update nowPlaying: %s for user: %s -> %s" % (eid, u, MediaManager.uuid(u))) user = app.iposonic.update_user( MediaManager.uuid(u), {'nowPlaying': eid}) except: log.exception("Can't update nowPlaying for user: %s" % u) if is_transcode(maxBitRate, info): return Response(_transcode(path, maxBitRate), direct_passthrough=True) log.info("sending static file: %s" % path) return send_file(path)
def cover_art_worker(cache_dir, cover_search=cover_search): log.info("starting downloader thread with tmp_dir: %s" % cache_dir) info = True while info: info = q.get() try: cover_art_path = os.path.join("/", cache_dir, MediaManager.cover_art_uuid(info) ) log.info("coverart %s: searching album: %s " % ( info.get('id'), info.get('album'))) covers = cover_search(info.get('album')) for cover in covers: # TODO consider multiple authors in info # ex. Actually "U2 & Frank Sinatra" != "U2" # leads to a false negative # TODO con print "confronting info: %s with: %s" % (info, cover) normalize_info, normalize_cover = map( MediaManager.normalize_artist, [info, cover]) full_match = len(set([normalize_info, normalize_cover])) == 1 stopwords_match = len(set([MediaManager.normalize_artist( x, stopwords=True) for x in [info, cover]])) == 1 partial_match = len( [x for x in normalize_info if x not in normalize_cover]) == 0 if full_match or stopwords_match or partial_match: log.warn("Saving image %s -> %s" % ( cover.get('cover_small'), cover_art_path) ) fd = open(cover_art_path, "w") fd.write(urlopen(cover.get('cover_small')).read()) fd.close() else: log.info("Artist mismatch: %s, %s" % tuple( [x.get('artist', x.get('name')) for x in [info, cover]]) ) except Exception as e: log.error("Error while downloading albumart.", e) q.task_done() log.warn("finish download thread")
def get_info_test_mp3_3(self): file_name = "./test/data/edith_piaf/letoile_de_la_chanson/16_bal_dans_ma_rue.mp3" parent = dirname(file_name) expected = { 'title': 'bal dans ma rue', 'artist': 'Edith Piaf', 'parent': MediaManager.uuid(join("/", os.getcwd(), parent)) } self.get_info_harn(file_name, expected)
def test_get_album_name2(self): for name in ['20 mock_album - 2004', '20 mock_album (2004)', '20 mock_album (Disk1)']: path_u = join("/", os.getcwd(), "test/data/mock_artist/", name) try: os.mkdir(path_u) except: pass ret = MediaManager.get_info_from_filename2(path_u) assert ret['title'] == '20 mock_album', "ret: %s" % ret os.rmdir(path_u)
def get_info_test_ogg(self): file_name = "./test/data/mock_artist/mock_album/sample.ogg" parent = dirname(file_name) expected = { 'title': 'mock_title', 'artist': 'mock_artist', 'year': 'mock_year', 'parent': MediaManager.uuid(join("/", os.getcwd(), parent)) } self.get_info_harn(file_name, expected)
def get_info_test_mp3_2(self): file_name = "./test/data/Aretha Franklin/20 Greatest hits/Angel.mp3" parent = dirname(file_name) expected = { 'title': 'Angel', 'artist': 'Aretha Franklin', 'bitRate': 128, 'parent': MediaManager.uuid(join("/", os.getcwd(), parent)) } self.get_info_harn(file_name, expected)
def test_normalize(self): info_l = [{ 'album': 'pippo', 'artist': u'Fiorella Mannoia' }, { 'album': 'pippo', 'artist': u'Fiorella_Mannoia' }] for info in info_l: ret = MediaManager.normalize_artist(info) assert ret == 'fiorellamannoia'
def test_normalize_stopwords(self): info_l = [{ 'album': 'pippo', 'artist': u'The Beatles' }, { 'album': 'pippo', 'artist': u'Beatles' }] for info in info_l: ret = MediaManager.normalize_artist(info, stopwords=True) assert ret == 'beatles'
def get_info_test_mp3(self): file_name = "./test/data/lara.mp3" parent = dirname(file_name) expected = { 'title': 'BWV 1041 : I. Allegro (PREVIEW: buy it at www.magnatune.com)', 'artist': 'Lara St John (PREVIEW: buy it at www.magnatune.com)', 'bitRate': 128, 'parent': MediaManager.uuid(join("/", os.getcwd(), parent)) } self.get_info_harn(file_name, expected)
def test_normalize_album(self): info_l = [ {'artist': 'pippo', 'album': u'Evanescence'}, {'artist': 'pippo', 'album': u'evanescence (EP)'}, {'artist': 'pippo', 'album': u'Evanescence [EP]'}, ] expected = 'evanescence' for info in info_l: ret = MediaManager.normalize_album(info) assert ret == expected, "Expecting: [%s], got [%s]" % ( expected, ret)
def get_music_folders_view(): """Return all music folders.""" (u, p, v, c, f, callback) = map(request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback']) return request.formatter({ 'musicFolders': { 'musicFolder': [{ 'id': MediaManager.uuid(d), 'name': d } for d in app.iposonic.get_music_folders() if isdir(d)] } })
def test_get_album_name(self): for name in [ 'mock_album - 2004', 'mock_album (2004)', 'mock_album (Disk1)' ]: path_u = join("/", os.getcwd(), "test/data/mock_artist/", name) try: os.mkdir(path_u) except: pass ret = MediaManager.get_info_from_filename2(path_u) assert ret['title'] == 'mock_album', "ret: %s" % ret os.rmdir(path_u)
def walk_music_directory_old(self): """Find all artists (top-level directories) and create indexes. TODO: create a cache for this. """ #raise NotImplementedError("This method should not be used") log.info("walking: ", self.get_music_folders()) # reset database self.reset() # find all artists for music_folder in self.get_music_folders(): artists_local = [x for x in os.listdir( music_folder) if os.path.isdir(join("/", music_folder, x))] #index all artists for a in artists_local: if a: path = join("/", music_folder, a) try: self.add_path(path) self.artists[MediaManager.uuid( path)] = IposonicDB.Artist(path) artist_j = {'artist': { 'id': MediaManager.uuid(path), 'name': a}} # # indexes = { 'A' : {'artist': {'id': .., 'name': ...}}} # first = a[0:1].upper() self.indexes.setdefault(first, []) self.indexes[first].append(artist_j) log.info( "Adding to index converted entry: %s" % artist_j) except IposonicException as e: log.error(e) log.info("artists: %s" % self.artists) return self.get_indexes()
def test_coverart_uuid(self): info_l = [ { 'artist': 'Antony & the Johnsons', 'album': 'The crying light' }, { 'artist': 'Antony and the Johnsons', 'album': 'The crying light' }, ] for info in info_l: ret = MediaManager.cover_art_uuid(info) print "coverid:", ret
def get_music_folders_view(): """Return all music folders.""" (u, p, v, c, f, callback) = map( request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback']) return request.formatter( {'musicFolders': {'musicFolder': [ { 'id': MediaManager.uuid(d), 'name': d } for d in app.iposonic.get_music_folders() if isdir(d) ] }} )
def test_get_similar_playlist(): info = { 'title': 'buonanotte fiorellino', 'artist': 'francesco de gregori', 'timestamp': int(time.time()) } lastfm_user = {'username': '******', 'password': '******'} from mediamanager.scrobble import get_similar from mediamanager import MediaManager ret_l = get_similar(info, lastfm_user) uid_l = [MediaManager.lyrics_uuid( {'artist': a, 'title': t}) for (a, t) in ret_l] playlist = [] for x in uid_l: assert iposonic.get
def add_path(self, path, album=False): """Create an entry from path and add it to the DB.""" if os.path.isdir(path): self.log.warn( "Adding %s: %s " % ("album" if album else "artist", stringutils.to_unicode(path))) eid = MediaManager.uuid(path) if album: self.albums[eid] = IposonicDB.Album(path) else: self.artists[eid] = IposonicDB.Artist(path) self.log.info(u"adding directory: %s, %s " % (eid, stringutils.to_unicode(path))) return eid elif MediaManager.is_allowed_extension(path): try: info = MediaManager.get_info(path) info.update({'coverArt': MediaManager.cover_art_uuid(info)}) self.songs[info['id']] = info self.log.info("adding file: %s, %s " % (info['id'], path)) return info['id'] except UnsupportedMediaError as e: raise IposonicException(e) raise IposonicException("Path not found or bad extension: %s " % path)
def add_path(self, path, album=False): """Create an entry from path and add it to the DB.""" if os.path.isdir(path): self.log.warn( "Adding %s: %s " % ("album" if album else "artist", stringutils.to_unicode(path))) eid = MediaManager.uuid(path) if album: self.albums[eid] = IposonicDB.Album(path) else: self.artists[eid] = IposonicDB.Artist(path) self.log.info(u"adding directory: %s, %s " % (eid, stringutils.to_unicode(path))) return eid elif MediaManager.is_allowed_extension(path): try: info = MediaManager.get_info(path) info.update({ 'coverArt': MediaManager.cover_art_uuid(info) }) self.songs[info['id']] = info self.log.info("adding file: %s, %s " % (info['id'], path)) return info['id'] except UnsupportedMediaError as e: raise IposonicException(e) raise IposonicException("Path not found or bad extension: %s " % path)
def test_get_similar_playlist(): info = { 'title': 'buonanotte fiorellino', 'artist': 'francesco de gregori', 'timestamp': int(time.time()) } lastfm_user = {'username': '******', 'password': '******'} from mediamanager.scrobble import get_similar from mediamanager import MediaManager ret_l = get_similar(info, lastfm_user) uid_l = [ MediaManager.lyrics_uuid({ 'artist': a, 'title': t }) for (a, t) in ret_l ] playlist = [] for x in uid_l: assert iposonic.get
def create_playlist_view(): """TODO move to app.iposonic request body: name=2012-09-08& songId=-2072958145& songId=-2021195453& songId=-1785884780 """ (u, p, v, c, f, callback) = map( request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback']) (name, playlistId) = map(request.values.get, ['name', 'playlistId']) songId_l = request.values.getlist('songId') print("songId: %s" % songId_l) if not (name or playlistId): print("request: %s" % request.data) raise SubsonicMissingParameterException( 'id or playlistId', 'create_playlist_view') # create a new playlist if not playlistId: eid = MediaManager.uuid(name) try: playlist = app.iposonic.get_playlists(eid=eid) raise IposonicException("Playlist esistente") except: pass # TODO DAO should not be exposed playlist = app.iposonic.db.Playlist(name) playlist.update({'entry': ",".join(songId_l)}) app.iposonic.create_entry(playlist) # update else: playlist = app.iposonic.get_playlists(eid=playlistId) assert playlist songs = playlist.get('entry') songs += ",".join(songId_l) app.iposonic.update_entry(eid=playlistId, new={'entry': songs}) return request.formatter({'status': 'ok'})
def test_normalize_album(self): info_l = [ { 'artist': 'pippo', 'album': u'Evanescence' }, { 'artist': 'pippo', 'album': u'evanescence (EP)' }, { 'artist': 'pippo', 'album': u'Evanescence [EP]' }, ] expected = 'evanescence' for info in info_l: ret = MediaManager.normalize_album(info) assert ret == expected, "Expecting: [%s], got [%s]" % (expected, ret)
def test_get_similar_playlist(): info = { 'title': 'buonanotte fiorellino', 'artist': 'francesco de gregori', 'timestamp': int(time.time()) } lastfm_user = {'username': '******', 'password': '******'} ret_l = get_similar(info, lastfm_user) uid_l = [ MediaManager.lyrics_uuid({ 'artist': a, 'title': t }) for (a, t) in ret_l ] playlist = [] for x in uid_l: try: info = iposonic.db.get_songs(query={'scrobbleId': x}) assert info print "found song: %s" % x except: print "not found: %s" % x
def get_lyrics_view(): """ artist No The artist name. title json_response: {lyrics: { artist: ..., title: ...} } xml_response: <lyrics artist="Muse" title="Hysteria">....""" (u, p, v, c, f, callback) = map( request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback']) (artist, title) = map(request.args.get, ['artist', 'title']) assert artist and title assert 'null' not in [artist, title], "A required field (artist,title) is empty." info = {'artist': artist, 'title': title} lyrics_id = MediaManager.lyrics_uuid(info) lyrics = get_lyrics(lyrics_id, info=info) assert 'lyrics' in lyrics, "Missing lyrics in %s" % lyrics ret = {'lyrics': {'artist': artist, 'title': title, '': [lyrics[ 'lyrics']]}} return request.formatter(ret) raise NotImplementedError("WriteMe")
def __init__(self, username): IposonicDBTables.BaseB.__init__(self) self.update({ 'id': MediaManager.uuid(username), 'username': username} )
def test_utf16_bom(self): f = "./test/data/id3_with_bom_utf16_le.mp3" info = MediaManager.get_info(f) album = info.get('album').strip(u'\x01\xff\xfe') print("info:%s\nalbum:%s" % (info, album))
def get_music_directory_view(): """Return the content of a directory. params: - id=-493506601 - xml response 1: <directory id="1" name="ABBA"> <child id="11" parent="1" title="Arrival" artist="ABBA" isDir="true" coverArt="22"/> <child id="12" parent="1" title="Super Trouper" artist="ABBA" isDir="true" coverArt="23"/> </directory> xml response 2: <directory id="11" parent="1" name="Arrival"> <child id="111" parent="11" title="Dancing Queen" isDir="false" album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="24" size="8421341" contentType="audio/mpeg" suffix="mp3" duration="146" bitRate="128" path="ABBA/Arrival/Dancing Queen.mp3"/> <child id="112" parent="11" ... # se above contentType="audio/flac" suffix="flac" transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="208" bitRate="128" /> </directory> jsonp response """ (u, p, v, c, f, callback, dir_id) = map(request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback', 'id']) if not dir_id: raise SubsonicProtocolException( "Missing required parameter: 'id' in getMusicDirectory.view") (path, dir_path) = app.iposonic.get_directory_path_by_id(dir_id) mf = app.iposonic.db.music_folders[0] dir_path = os.path.join("/", mf, dir_path) log.info("Getting entries in path: %s" % dir_path) children = [] artist = app.iposonic.db.Artist(dir_path) # # if nothing changed before our last visit # or is a virtual path (eg. uniexistent) # don't rescan # try: last_modified = os.stat(dir_path).st_ctime except: last_modified = -1 if last_modified == -1: print("Getting items from valbum.") children = app.iposonic.get_songs(query={'albumId': dir_id}) elif fs_cache.get(dir_id, 0) == last_modified: print("Getting items from cache.") children = app.iposonic.get_songs(query={'parent': dir_id}) children.extend(app.iposonic.get_albums(query={'parent': dir_id})) else: for child in os.listdir(unicode(dir_path)): # TODO find a way to support non-unicode directories and # folders. The easiest way is to simply RENAME THEM! # ................ print("checking string type: ", type(child)) #child = to_unicode(child) if child[0] in ['.', '_']: continue # # To manage non-utf8 filenames # the easiest thing is to rename # paths in utf. # # This may cause issues for collections # stored on windows or vfat filesystem. # # This is the KISS-siest approach # that avoids continuously encode # and decode of the filenames. # if not isinstance(child, unicode): if not app.config.get('rename_non_utf8'): log.warn("skipping non unicode path: %s " % to_unicode(child)) continue child_new = to_unicode(child) os.rename( b'%s/%s' % (dir_path.encode('utf-8'), child), b'%s/%s' % (dir_path.encode('utf-8'), child_new.encode('utf-8'))) child = child_new path = join(dir_path, child) try: child_j = {} is_dir = isdir(path) # This is a Lazy Indexing. It should not be there # unless a cache is set # XXX eid = MediaManager.uuid(path) try: child_j = app.iposonic.get_entry_by_id(eid) except IposonicException: app.iposonic.add_path(path, album=is_dir) child_j = app.iposonic.get_entry_by_id(eid) children.append(child_j) except IposonicException as e: log.info(e) fs_cache.setdefault(dir_id, last_modified) def _track_or_die(x): try: return int(x['track']) except: return 0 # Sort songs by track id, if possible children = sorted(children, key=_track_or_die) return request.formatter({ 'directory': { 'id': dir_id, 'name': artist.get('name'), 'child': children } })
def browse_path_test(self): MediaManager.browse_path("/opt/music")
def get_music_directory_view(): """Return the content of a directory. params: - id=-493506601 - xml response 1: <directory id="1" name="ABBA"> <child id="11" parent="1" title="Arrival" artist="ABBA" isDir="true" coverArt="22"/> <child id="12" parent="1" title="Super Trouper" artist="ABBA" isDir="true" coverArt="23"/> </directory> xml response 2: <directory id="11" parent="1" name="Arrival"> <child id="111" parent="11" title="Dancing Queen" isDir="false" album="Arrival" artist="ABBA" track="7" year="1978" genre="Pop" coverArt="24" size="8421341" contentType="audio/mpeg" suffix="mp3" duration="146" bitRate="128" path="ABBA/Arrival/Dancing Queen.mp3"/> <child id="112" parent="11" ... # se above contentType="audio/flac" suffix="flac" transcodedContentType="audio/mpeg" transcodedSuffix="mp3" duration="208" bitRate="128" /> </directory> jsonp response """ (u, p, v, c, f, callback, dir_id) = map( request.args.get, ['u', 'p', 'v', 'c', 'f', 'callback', 'id']) if not dir_id: raise SubsonicProtocolException( "Missing required parameter: 'id' in getMusicDirectory.view") (path, dir_path) = app.iposonic.get_directory_path_by_id(dir_id) mf = app.iposonic.db.music_folders[0] dir_path = os.path.join("/", mf, dir_path) log.info("Getting entries in path: %s" % dir_path) children = [] artist = app.iposonic.db.Artist(dir_path) # # if nothing changed before our last visit # or is a virtual path (eg. uniexistent) # don't rescan # try: last_modified = os.stat(dir_path).st_ctime except: last_modified = -1 if last_modified == -1: print("Getting items from valbum.") children = app.iposonic.get_songs(query={'albumId': dir_id}) elif fs_cache.get(dir_id, 0) == last_modified: print("Getting items from cache.") children = app.iposonic.get_songs(query={'parent': dir_id}) children.extend(app.iposonic.get_albums(query={'parent': dir_id})) else: for child in os.listdir(unicode(dir_path)): # TODO find a way to support non-unicode directories and # folders. The easiest way is to simply RENAME THEM! # ................ print("checking string type: ", type(child)) #child = to_unicode(child) if child[0] in ['.', '_']: continue # # To manage non-utf8 filenames # the easiest thing is to rename # paths in utf. # # This may cause issues for collections # stored on windows or vfat filesystem. # # This is the KISS-siest approach # that avoids continuously encode # and decode of the filenames. # if not isinstance(child, unicode): if not app.config.get('rename_non_utf8'): log.warn( "skipping non unicode path: %s " % to_unicode(child)) continue child_new = to_unicode(child) os.rename( b'%s/%s' % (dir_path.encode('utf-8'), child), b'%s/%s' % ( dir_path.encode('utf-8'), child_new.encode('utf-8')) ) child = child_new path = join(dir_path, child) try: child_j = {} is_dir = isdir(path) # This is a Lazy Indexing. It should not be there # unless a cache is set # XXX eid = MediaManager.uuid(path) try: child_j = app.iposonic.get_entry_by_id(eid) except IposonicException: app.iposonic.add_path(path, album=is_dir) child_j = app.iposonic.get_entry_by_id(eid) children.append(child_j) except IposonicException as e: log.info(e) fs_cache.setdefault(dir_id, last_modified) def _track_or_die(x): try: return int(x['track']) except: return 0 # Sort songs by track id, if possible children = sorted(children, key=_track_or_die) return request.formatter( {'directory': { 'id': dir_id, 'name': artist.get('name'), 'child': children } })
def test_get_playlist(self): eid = MediaManager.uuid('mock_playlist') ret = self.db.get_playlists(eid=eid) assert ret, "Can't find playlist %s" % eid assert ret.get('name') == 'mock_playlist', "No playlists: %s" % ret
def test_get_user(self): from mediamanager import MediaManager eid = MediaManager.uuid('mock_user') ret = self.db.get_users(eid) assert ret, "Can't find user %s" % eid assert ret.get('username') == 'mock_user', "No user: %s" % ret
def get_folder_by_id(self, folder_id): """It's ok just because self.db.get_music_folders() are few""" for folder in self.db.get_music_folders(): if MediaManager.uuid(folder) == folder_id: return folder raise IposonicException("Missing music folder with id: %s" % folder_id)
def test_get_info_from_name2_full_path(self): for path in ['/opt/music/CSI/CSI - Kodemondo/Celluloide 03.ogg']: info = MediaManager.get_info_from_filename2(path) print "info: %s" % info
def test_utf16_bom(self): f = "./test/data/id3_with_bom_utf16_le.mp3" info = MediaManager.get_info(f) album = info.get('album').strip(u'\x01\xff\xfe') print ("info:%s\nalbum:%s" % (info, album))
def get_info_harn(self, file_name, expected): info = MediaManager.get_info(os.getcwd() + "/" + file_name) print("info: %s" % info) for f in expected.keys(): assert info[f] == expected[f], "Mismatching field %s. Expected %s get %s" % (f, expected[f], info[f])