def test_list_composer_should_not_return_artists_without_names(self): self.backend.library.dummy_find_exact_result = SearchResult( tracks=[Track(composers=[Artist(name='')])]) self.send_request('list "composer"') self.assertNotInResponse('Artist: ') self.assertNotInResponse('Albumartist: ') self.assertNotInResponse('Composer: ') self.assertNotInResponse('Performer: ') self.assertInResponse('OK')
def _convert_album(self, album): """ Transforms a beets album into a mopidy Track """ if not album: return album_kwargs = {} artist_kwargs = {} if 'album' in album: album_kwargs['name'] = album['album'] if 'disctotal' in album: album_kwargs['num_discs'] = album['disctotal'] if 'tracktotal' in album: album_kwargs['num_tracks'] = album['tracktotal'] if 'mb_albumid' in album: album_kwargs['musicbrainz_id'] = album['mb_albumid'] album_kwargs['date'] = None if self.backend.use_original_release_date: if 'original_year' in album: album_kwargs['date'] = self._build_date( album['original_year'], album['original_month'], album['original_day']) else: if 'year' in album: album_kwargs['date'] = self._build_date( album['year'], album['month'], album['day']) # if 'added' in item: # album_kwargs['last_modified'] = album['added'] # if 'artpath' in album: # album_kwargs['images'] = [album['artpath']] if 'albumartist' in album: artist_kwargs['name'] = album['albumartist'] if 'mb_albumartistid' in album: artist_kwargs['musicbrainz_id'] = album['mb_albumartistid'] if artist_kwargs: artist = Artist(**artist_kwargs) album_kwargs['artists'] = [artist] if 'id' in album: album_kwargs['uri'] = uricompose('beetslocal', None, 'album:%s:' % album['id']) album = Album(**album_kwargs) return album
def test_serialize_with_artists(self): artist = Artist(name="foo") self.assertDictEqual( { "__model__": "Track", "uri": "uri", "name": "name", "artists": [artist.serialize()], }, Track(uri="uri", name="name", artists=[artist]).serialize(), )
def test_list_albumartist_should_not_return_artists_without_names(self): self.backend.library.dummy_find_exact_result = SearchResult( tracks=[Track(album=Album(artists=[Artist(name="")]))] ) self.send_request('list "albumartist"') self.assertNotInResponse("Artist: ") self.assertNotInResponse("Albumartist: ") self.assertNotInResponse("Composer: ") self.assertNotInResponse("Performer: ") self.assertInResponse("OK")
def to_mopidy_album(track): if track is None: return artist = track['albumArtist'] if artist.strip() == '': artist = track['artist'] return Album(name=track['album'], artists=[Artist(name=artist)], num_tracks=track.get('totalTracks', 1), num_discs=track.get('totalDiscs', track.get('disc', 1)), date=track.get('year', 1970))
def raw_album_to_album(self, album): if album is None: return None return Album(name=album.get('title') or album.get('name') or UNKNOWN_ALBUM, num_tracks=album.get('songCount'), uri=uri.get_album_uri(album.get('id')), artists=[ Artist(name=album.get('artist'), uri=uri.get_artist_uri(album.get('artistId'))) ])
def test_unicode_cache(self): tracks = parse_mpd_tag_cache( path_to_data_dir('utf8_tag_cache'), path_to_data_dir('')) artists = [Artist(name='æøå')] album = Album(name='æøå', artists=artists) track = Track( uri='local:track:song1.mp3', name='æøå', artists=artists, album=album, length=4000, last_modified=1272319626) self.assertEqual(track, list(tracks)[0])
def test_unicode_cache(self): tracks = parse_mpd_tag_cache( path_to_data_dir('utf8_tag_cache'), path_to_data_dir('')) uri = path_to_uri(path_to_data_dir('song1.mp3')) artists = [Artist(name='æøå')] album = Album(name='æøå', artists=artists) track = Track( uri=uri, name='æøå', artists=artists, album=album, length=4000) self.assertEqual(track, list(tracks)[0])
def uploadArtistToTracks(artist): for track in artist: TRACKS[track["videoId"]] = Track( uri=f"ytm:video?id={track['videoId']}", name=track["title"], artists=[ Artist( uri=f"ytm:artist?id={a['id']}&upload=true", name=a["name"], sortname=a["name"], musicbrainz_id="", ) for a in track["artist"] ], album=Album( uri=f"ytm:album?id={track['album']['id']}&upload=true", name=track["album"]["name"], artists=[ Artist( uri=f"ytm:artist?id={a['id']}&upload=true", name=a["name"], sortname=a["name"], musicbrainz_id="", ) for a in track["artist"] ], num_tracks=None, num_discs=None, date="1999", musicbrainz_id="", ), composers=[], performers=[], genre="", track_no=None, disc_no=None, date="1999", length=None, bitrate=0, comment="", musicbrainz_id="", last_modified=None, )
def test_ne(self): track1 = Track(uri='uri1', name='name1', artists=[Artist(name='name1')], album=Album(name='name1'), track_no=1, date='1977-01-01', length=100, bitrate=100, musicbrainz_id='id1') track2 = Track(uri='uri2', name='name2', artists=[Artist(name='name2')], album=Album(name='name2'), track_no=2, date='1977-01-02', length=200, bitrate=200, musicbrainz_id='id2') self.assertNotEqual(track1, track2) self.assertNotEqual(hash(track1), hash(track2))
def wrap_album(plexalbum, plex_uri_method, resolve_uri_method): '''Wrap a plex search result in mopidy.model.album''' return Album(uri=plex_uri_method(plexalbum.ratingKey, 'plex:album'), name=plexalbum.title, artists=[Artist(uri=plex_uri_method(plexalbum.parentKey, 'plex:artist'), name=plexalbum.parentTitle)], num_tracks=plexalbum.leafCount, num_discs=None, date=str(plexalbum.year), images=[resolve_uri_method(plexalbum.thumb), resolve_uri_method(plexalbum.art)] )
def test_eq(self): date = '1977-01-01' artists = [Artist()] album = Album() track1 = Track( uri='uri', name='name', artists=artists, album=album, track_no=1, date=date, length=100, bitrate=100, musicbrainz_id='id') track2 = Track( uri='uri', name='name', artists=artists, album=album, track_no=1, date=date, length=100, bitrate=100, musicbrainz_id='id') self.assertEqual(track1, track2) self.assertEqual(hash(track1), hash(track2))
def test_ne(self): track1 = Track(uri=u'uri1', name=u'name1', artists=[Artist(name=u'name1')], album=Album(name=u'name1'), track_no=1, date=datetime.date.today(), length=100, bitrate=100, musicbrainz_id='id1') track2 = Track(uri=u'uri2', name=u'name2', artists=[Artist(name=u'name2')], album=Album(name=u'name2'), track_no=2, date=datetime.date.today() - datetime.timedelta(days=1), length=200, bitrate=200, musicbrainz_id='id2') self.assertNotEqual(track1, track2) self.assertNotEqual(hash(track1), hash(track2))
def test_lookup_artist(r_get_mock, emby_client): with open('tests/data/lookup_artist0.json', 'r') as f: r_get_mock.return_value = json.load(f) assert emby_client.lookup_artist(0) == [ Track(album=Album(artists=[Artist(name=u'Jawbreaker')], name=u'24 Hour Revenge Therapy'), artists=[Artist(name=u'Jawbreaker')], length=159840, name=u'The Boat Dreams From The Hill', track_no=1, uri='emby:track:05321ccb30ff9e43bf8070cd5f70c783'), Track(album=Album(artists=[Artist(name=u'Jawbreaker')], name=u'Dear You'), artists=[Artist(name=u'Jawbreaker')], length=131133, name=u'Bad Scene, Everyone\u2019s Fault', track_no=10, uri='emby:track:0a24ce6c243f2f3a81fa0f99625630b4'), Track(album=Album(artists=[Artist(name=u'Jawbreaker')], name=u'Dear You'), artists=[Artist(name=u'Jawbreaker')], length=254107, name=u'Sluttering (May 4th)', track_no=11, uri='emby:track:057801bc10cf08ce96e1e19bf98c407f') ]
def search(self, query=None, uris=None, exact=False): # TODO Support exact search logger.info('youtube LibraryProvider.search "%s"', query) # handle only searching (queries with 'any') not browsing! if not (query and "any" in query): return None search_query = " ".join(query["any"]) logger.info('Searching YouTube for query "%s"', search_query) try: entries = youtube.Entry.search(search_query) except Exception as e: logger.error('search error "%s"', e) return None # load playlist info (to get video_count) of all playlists together playlists = [entry for entry in entries if not entry.is_video] youtube.Playlist.load_info(playlists) tracks = [] for entry in entries: if entry.is_video: uri_base = "youtube:video" album = "YouTube Video" length = int(entry.length.get()) * 1000 else: uri_base = "youtube:playlist" album = "YouTube Playlist (%s videos)" % entry.video_count.get() length = 0 name = entry.title.get() tracks.append( Track( name=name.replace(";", ""), comment=entry.id, length=length, artists=[Artist(name=entry.channel.get())], album=Album(name=album), uri="%s/%s.%s" % (uri_base, safe_url(name), entry.id), ) ) # load video info and playlist videos in the background. they should be # ready by the time the user adds search results to the playing queue for pl in playlists: pl.videos # start loading return SearchResult(uri="youtube:search", tracks=tracks)
def wrap_track(plextrack, plex_uri_method): '''Wrap a plex search result in mopidy.model.track''' return Track(uri=plex_uri_method(plextrack.ratingKey, 'plex:track'), name=plextrack.title, artists=[Artist(uri=plex_uri_method(plextrack.grandparentKey, 'plex:artist'), name=plextrack.grandparentTitle)], album=Album(uri=plex_uri_method(plextrack.parentKey, 'plex:album'), name=plextrack.parentTitle), track_no=None, #plextrack.index, length=plextrack.duration, # TODO: bitrate=plextrack.media.bitrate, comment=plextrack.summary )
def translator(data): albumartist_kwargs = {} album_kwargs = {} artist_kwargs = {} track_kwargs = {} def _retrieve(source_key, target_key, target): if source_key in data: target[target_key] = data[source_key] _retrieve(gst.TAG_ALBUM, 'name', album_kwargs) _retrieve(gst.TAG_TRACK_COUNT, 'num_tracks', album_kwargs) _retrieve(gst.TAG_ARTIST, 'name', artist_kwargs) if gst.TAG_DATE in data and data[gst.TAG_DATE]: date = data[gst.TAG_DATE] date = datetime.date(date.year, date.month, date.day) track_kwargs['date'] = date _retrieve(gst.TAG_TITLE, 'name', track_kwargs) _retrieve(gst.TAG_TRACK_NUMBER, 'track_no', track_kwargs) # Following keys don't seem to have TAG_* constant. _retrieve('album-artist', 'name', albumartist_kwargs) _retrieve('musicbrainz-trackid', 'musicbrainz_id', track_kwargs) _retrieve('musicbrainz-artistid', 'musicbrainz_id', artist_kwargs) _retrieve('musicbrainz-albumid', 'musicbrainz_id', album_kwargs) _retrieve('musicbrainz-albumartistid', 'musicbrainz_id', albumartist_kwargs) if albumartist_kwargs: album_kwargs['artists'] = [Artist(**albumartist_kwargs)] track_kwargs['uri'] = data['uri'] track_kwargs['length'] = data[gst.TAG_DURATION] track_kwargs['album'] = Album(**album_kwargs) track_kwargs['artists'] = [Artist(**artist_kwargs)] return Track(**track_kwargs)
def test_albumartist_tag_cache(self): tracks = parse_mpd_tag_cache(path_to_data_dir('albumartist_tag_cache'), path_to_data_dir('')) uri = path_to_uri(path_to_data_dir('song1.mp3')) artist = Artist(name='albumartistname') album = expected_albums[0].copy(artists=[artist]) track = Track(name='trackname', artists=expected_artists, track_no=1, album=album, length=4000, uri=uri) self.assertEqual(track, list(tracks)[0])
def setUp(self): # noqa: N802 self.tags = { 'album': ['album'], 'track-number': [1], 'artist': ['artist'], 'composer': ['composer'], 'performer': ['performer'], 'album-artist': ['albumartist'], 'title': ['track'], 'track-count': [2], 'album-disc-number': [2], 'album-disc-count': [3], 'date': [datetime.date(2006, 1, 1,)], 'container-format': ['ID3 tag'], 'genre': ['genre'], 'comment': ['comment'], 'musicbrainz-trackid': ['trackid'], 'musicbrainz-albumid': ['albumid'], 'musicbrainz-artistid': ['artistid'], 'musicbrainz-sortname': ['sortname'], 'musicbrainz-albumartistid': ['albumartistid'], 'bitrate': [1000], } artist = Artist(name='artist', musicbrainz_id='artistid', sortname='sortname') composer = Artist(name='composer') performer = Artist(name='performer') albumartist = Artist(name='albumartist', musicbrainz_id='albumartistid') album = Album(name='album', num_tracks=2, num_discs=3, musicbrainz_id='albumid', artists=[albumartist]) self.track = Track(name='track', date='2006-01-01', genre='genre', track_no=1, disc_no=2, comment='comment', musicbrainz_id='trackid', album=album, bitrate=1000, artists=[artist], composers=[composer], performers=[performer])
def get_items(self, uri): id_, upload = parse_uri(uri) logger.info("YTMusic getting playlist items for \"%s\"", id_) try: pls = API.get_playlist(id_, limit=100) except Exception: logger.exception("YTMusic failed getting playlist items") pls = None if pls: refs = [] if "tracks" in pls: for track in pls["tracks"]: refs.append(Ref.track(uri=f"ytm:video?id={track['videoId']}", name=track["title"])) duration = track["duration"].split(":") artists = [Artist( uri=f"ytm:artist?id={a['id']}&upload=false", name=a["name"], sortname=a["name"], musicbrainz_id="", ) for a in track["artists"]] if track["album"]: album = Album( uri=f"ytm:album?id={track['album']['id']}&upload=false", name=track["album"]["name"], artists=artists, num_tracks=None, num_discs=None, date="1999", musicbrainz_id="", ) else: album = None TRACKS[track["videoId"]] = Track( uri=f"ytm:video?id={track['videoId']}", name=track["title"], artists=artists, album=album, composers=[], performers=[], genre="", track_no=None, disc_no=None, date="1999", length=(int(duration[0]) * 60 * 1000) + (int(duration[1]) * 1000), bitrate=0, comment="", musicbrainz_id="", last_modified=None, ) return refs return None
def _to_mopidy_artist(self, song): name = song.get('artist', '') uri = 'gmusic:artist:' + self._create_id(name) # First try to process the artist as an aa artist # (Difference being that non aa artists don't have artistId) try: artist = self._aa_to_mopidy_artist(song) self.artists[uri] = artist return artist except KeyError: artist = Artist(uri=uri, name=name) self.artists[uri] = artist return artist
def _create_track(self, row): art_id = row[b'ArtworkID'] images = [os.path.join(self.art_dir, art_id + '.jpg')] if art_id else [] artist = Artist(name=row[b'ArtistName'], ) album = Album(name=row[b'AlbumName'], artists=[artist], images=images) track = Track(name=row[b'TrackName'], track_no=row[b'TrackNumber'], artists=[artist], album=album, uri=row[b'Uri'], date=unicode(row[b'Year']), length=row[b'Duration']) return track
def test_albumartist_tag_cache(self): tracks = parse_mpd_tag_cache(path_to_data_dir('albumartist_tag_cache'), path_to_data_dir('')) artist = Artist(name='albumartistname') album = expected_albums[0].copy(artists=[artist]) track = Track(uri='local:track:song1.mp3', name='trackname', artists=expected_artists, track_no=1, album=album, date='2006', length=4000, last_modified=1272319626) self.assertEqual(track, list(tracks)[0])
def test_eq(self): artists = [Artist()] album1 = Album(name='name', uri='uri', artists=artists, num_tracks=2, musicbrainz_id='id') album2 = Album(name='name', uri='uri', artists=artists, num_tracks=2, musicbrainz_id='id') self.assertEqual(album1, album2) self.assertEqual(hash(album1), hash(album2))
def raw_album_to_album(self, album): if album is None: return None return Album( name=album.get("title") or album.get("name") or UNKNOWN_ALBUM, num_tracks=album.get("songCount"), uri=uri.get_album_uri(album.get("id")), artists=[ Artist( name=album.get("artist"), uri=uri.get_artist_uri(album.get("artistId")), ) ], )
def parse_track(self, data, remote_url=False): if not data: return None if not data.get("streamable"): logger.info( f"{data.get('title')!r} can't be streamed from SoundCloud") return None if not data.get("kind") == "track": logger.debug(f"{data.get('title')} is not a track") return None track_kwargs = {} artist_kwargs = {} album_kwargs = {} if "title" in data: label_name = data.get("label_name") if not label_name: label_name = data.get("user", {}).get("username", "Unknown label") track_kwargs["name"] = data["title"] artist_kwargs["name"] = label_name album_kwargs["name"] = "SoundCloud" if "date" in data: track_kwargs["date"] = data["date"] if remote_url: args = (data["sharing"], data["permalink_url"], data["stream_url"]) track_kwargs["uri"] = self.get_streamable_url(*args) if track_kwargs["uri"] is None: logger.info( f"{data.get('title')} can't be streamed from SoundCloud") return None else: track_kwargs[ "uri"] = f"soundcloud:song/{readable_url(data.get('title'))}.{data.get('id')}" track_kwargs["length"] = int(data.get("duration", 0)) track_kwargs["comment"] = data.get("permalink_url", "") if artist_kwargs: track_kwargs["artists"] = [Artist(**artist_kwargs)] if album_kwargs: track_kwargs["album"] = Album(**album_kwargs) return Track(**track_kwargs)
def _find_artists(self, query): statement = ('select Distinct albumartist, mb_albumartistid' ' from albums where 1=1 ') statement += self._build_statement(query, 'genre', 'genre') statement += self._build_statement(query, 'artist', 'albumartist') statement += self._build_statement(query, 'date', 'year') statement += self._build_statement(query, 'mb_albumartistid', 'mb_albumartistid') artists = [] result = self._query_beets_db(statement) for row in result: artists.append( Artist(name=row[0], musicbrainz_id=row[1], uri="beetslocal:artist:%s:" % row[1])) return artists
def test_search(self): self.backend.library.dummy_search_result = SearchResult( albums=[Album(uri='dummy:album:a', name='A')], artists=[Artist(uri='dummy:artist:b', name='B')], tracks=[Track(uri='dummy:track:c', name='C')]) self.send_request('search "any" "foo"') self.assertInResponse('file: dummy:album:a') self.assertInResponse('Title: Album: A') self.assertInResponse('file: dummy:artist:b') self.assertInResponse('Title: Artist: B') self.assertInResponse('file: dummy:track:c') self.assertInResponse('Title: C') self.assertInResponse('OK')
def parse_track(self, data, remote_url=False): if not data: return None # NOTE kwargs dict keys must be bytestrings to work on Python < 2.6.5 # See https://github.com/mopidy/mopidy/issues/302 for details. track_kwargs = {} artist_kwargs = {} album_kwargs = {} if STR_NAME in data: name = data[STR_NAME] label_name = data.get(STR_NAME) if bool(label_name): track_kwargs[b'name'] = name artist_kwargs[b'name'] = label_name else: track_kwargs[b'name'] = name artist_kwargs[b'name'] = data[STR_USER]['name'] album_kwargs[b'name'] = 'Mixcloud' if STR_DATE in data: track_kwargs[b'date'] = data[STR_DATE] track_kwargs[b'uri'] = 'mixcloud:' + data.get('key') track_kwargs[b'length'] = int(data.get('duration', 0)) track_kwargs[b'comment'] = data.get('permalink_url', '') if artist_kwargs: artist = Artist(**artist_kwargs) track_kwargs[b'artists'] = [artist] """if album_kwargs: if 'artwork_url' in data and data['artwork_url']: album_kwargs[b'images'] = [data['artwork_url']] else: image = data.get('user').get('avatar_url') album_kwargs[b'images'] = [image] album = Album(**album_kwargs) track_kwargs[b'album'] = album """ track = Track(**track_kwargs) return track
def albumToTracks(self, album, bId): ret = [] date = f"{album['releaseDate']['year']}" artists = [] for artist in album['artist']: if artist['id'] not in self.ARTISTS: self.ARTISTS[artist['id']] = Artist( uri=f"youtubemusic:artist:{artist['id']}", name=artist["name"], sortname=artist["name"], musicbrainz_id="", ) artists.append(self.ARTISTS[artist['id']]) if bId not in self.ALBUMS: self.ALBUMS[bId] = Album( uri=f"youtubemusic:album:{bId}", name=album["title"], artists=artists, num_tracks=int(album["trackCount"]) if str(album["trackCount"]).isnumeric() else None, num_discs=None, date=date, musicbrainz_id="", ) for song in album["tracks"]: if song['videoId'] not in self.TRACKS: self.TRACKS[song["videoId"]] = Track( uri=f"youtubemusic:track:{song['videoId']}", name=song["title"], artists=artists, album=self.ALBUMS[bId], composers=[], performers=[], genre="", track_no=int(song["index"]) if str(song["index"]).isnumeric() else None, disc_no=None, date=date, length=int(song["lengthMs"]) if str(song["lengthMs"]).isnumeric() else None, bitrate=0, comment="", musicbrainz_id="", last_modified=None, ) ret.append(self.TRACKS[song['videoId']]) return (ret)