Skip to content

Commit

Permalink
Merge deb442c into 51d1e22
Browse files Browse the repository at this point in the history
  • Loading branch information
ZenithDK committed Nov 9, 2013
2 parents 51d1e22 + deb442c commit b5067cc
Show file tree
Hide file tree
Showing 17 changed files with 679 additions and 42 deletions.
5 changes: 5 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ v0.17.0 (UNRELEASED)
(Fixes: :issue:`565`)
- Fix scanner so that mtime is respected when deciding which files can be skipped.

**MPD frontend**

- Add support for ``composer``, ``comment``, ``genre``, and ``performer``.
These tags can be used with ``list ...``, ``search ...``, and
``find ...`` and their variants, and are supported in the ``any`` tag also

v0.16.1 (2013-11-02)
====================
Expand Down
1 change: 0 additions & 1 deletion docs/ext/mpd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ Items on this list will probably not be supported in the near future.
- Crossfade is not supported
- Replay gain is not supported
- ``stats`` does not provide any statistics
- ``list`` does not support listing tracks by genre
- ``decoders`` does not provide information about available decoders

The following items are currently not supported, but should be added in the
Expand Down
44 changes: 33 additions & 11 deletions mopidy/audio/scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ def audio_data_to_track(data):
albumartist_kwargs = {}
album_kwargs = {}
artist_kwargs = {}
composer_kwargs = {}
performer_kwargs = {}
track_kwargs = {}

def _retrieve(source_key, target_key, target):
Expand All @@ -115,28 +117,32 @@ def _retrieve(source_key, target_key, target):
_retrieve(gst.TAG_TRACK_COUNT, 'num_tracks', album_kwargs)
_retrieve(gst.TAG_ALBUM_VOLUME_COUNT, 'num_discs', 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]
try:
date = datetime.date(date.year, date.month, date.day)
except ValueError:
pass # Ignore invalid dates
else:
track_kwargs['date'] = date.isoformat()

_retrieve(gst.TAG_COMPOSER, 'name', composer_kwargs)
_retrieve(gst.TAG_PERFORMER, 'name', performer_kwargs)
_retrieve(gst.TAG_ALBUM_ARTIST, 'name', albumartist_kwargs)
_retrieve(gst.TAG_TITLE, 'name', track_kwargs)
_retrieve(gst.TAG_TRACK_NUMBER, 'track_no', track_kwargs)
_retrieve(gst.TAG_ALBUM_VOLUME_NUMBER, 'disc_no', track_kwargs)
_retrieve(gst.TAG_GENRE, 'genre', track_kwargs)
_retrieve(gst.TAG_BITRATE, 'bitrate', track_kwargs)

# Following keys don't seem to have TAG_* constant.
_retrieve('album-artist', 'name', albumartist_kwargs)
_retrieve('comment', 'comment', track_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 gst.TAG_DATE in data and data[gst.TAG_DATE]:
date = data[gst.TAG_DATE]
try:
date = datetime.date(date.year, date.month, date.day)
except ValueError:
pass # Ignore invalid dates
else:
track_kwargs['date'] = date.isoformat()

if albumartist_kwargs:
album_kwargs['artists'] = [Artist(**albumartist_kwargs)]

Expand All @@ -146,4 +152,20 @@ def _retrieve(source_key, target_key, target):
track_kwargs['album'] = Album(**album_kwargs)
track_kwargs['artists'] = [Artist(**artist_kwargs)]

if ('name' in composer_kwargs
and not isinstance(composer_kwargs['name'], basestring)):
track_kwargs['composers'] = [Artist(name=artist)
for artist in composer_kwargs['name']]
else:
track_kwargs['composers'] = \
[Artist(**composer_kwargs)] if composer_kwargs else ''

if ('name' in performer_kwargs
and not isinstance(performer_kwargs['name'], basestring)):
track_kwargs['performers'] = [Artist(name=artist)
for artist in performer_kwargs['name']]
else:
track_kwargs['performers'] = \
[Artist(**performer_kwargs)] if performer_kwargs else ''

return Track(**track_kwargs)
46 changes: 44 additions & 2 deletions mopidy/backends/local/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,28 @@ def find_exact(self, query=None, uris=None):
albumartist_filter = lambda t: any([
q == a.name
for a in getattr(t.album, 'artists', [])])
composer_filter = lambda t: any([
q == a.name
for a in getattr(t, 'composers', [])])
performer_filter = lambda t: any([
q == a.name
for a in getattr(t, 'performers', [])])
track_no_filter = lambda t: q == t.track_no
genre_filter = lambda t: t.genre and q == t.genre
date_filter = lambda t: q == t.date
comment_filter = lambda t: q == t.comment
any_filter = lambda t: (
uri_filter(t) or
track_name_filter(t) or
album_filter(t) or
artist_filter(t) or
albumartist_filter(t) or
date_filter(t))
composer_filter(t) or
performer_filter(t) or
track_no_filter(t) or
genre_filter(t) or
date_filter(t) or
comment_filter(t))

if field == 'uri':
result_tracks = filter(uri_filter, result_tracks)
Expand All @@ -99,10 +112,18 @@ def find_exact(self, query=None, uris=None):
result_tracks = filter(artist_filter, result_tracks)
elif field == 'albumartist':
result_tracks = filter(albumartist_filter, result_tracks)
elif field == 'composer':
result_tracks = filter(composer_filter, result_tracks)
elif field == 'performer':
result_tracks = filter(performer_filter, result_tracks)
elif field == 'track_no':
result_tracks = filter(track_no_filter, result_tracks)
elif field == 'genre':
result_tracks = filter(genre_filter, result_tracks)
elif field == 'date':
result_tracks = filter(date_filter, result_tracks)
elif field == 'comment':
result_tracks = filter(comment_filter, result_tracks)
elif field == 'any':
result_tracks = filter(any_filter, result_tracks)
else:
Expand Down Expand Up @@ -137,15 +158,28 @@ def search(self, query=None, uris=None):
albumartist_filter = lambda t: any([
q in a.name.lower()
for a in getattr(t.album, 'artists', [])])
composer_filter = lambda t: any([
q in a.name.lower()
for a in getattr(t, 'composers', [])])
performer_filter = lambda t: any([
q in a.name.lower()
for a in getattr(t, 'performers', [])])
track_no_filter = lambda t: q == t.track_no
genre_filter = lambda t: t.genre and q in t.genre.lower()
date_filter = lambda t: t.date and t.date.startswith(q)
comment_filter = lambda t: t.comment and q in t.comment.lower()
any_filter = lambda t: (
uri_filter(t) or
track_name_filter(t) or
album_filter(t) or
artist_filter(t) or
albumartist_filter(t) or
date_filter(t))
composer_filter(t) or
performer_filter(t) or
track_no_filter(t) or
genre_filter(t) or
date_filter(t) or
comment_filter(t))

if field == 'uri':
result_tracks = filter(uri_filter, result_tracks)
Expand All @@ -157,10 +191,18 @@ def search(self, query=None, uris=None):
result_tracks = filter(artist_filter, result_tracks)
elif field == 'albumartist':
result_tracks = filter(albumartist_filter, result_tracks)
elif field == 'composer':
result_tracks = filter(composer_filter, result_tracks)
elif field == 'performer':
result_tracks = filter(performer_filter, result_tracks)
elif field == 'track_no':
result_tracks = filter(track_no_filter, result_tracks)
elif field == 'genre':
result_tracks = filter(genre_filter, result_tracks)
elif field == 'date':
result_tracks = filter(date_filter, result_tracks)
elif field == 'comment':
result_tracks = filter(comment_filter, result_tracks)
elif field == 'any':
result_tracks = filter(any_filter, result_tracks)
else:
Expand Down
12 changes: 12 additions & 0 deletions mopidy/backends/local/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,27 @@ def _convert_mpd_data(data, tracks):
if 'albumartist' in data:
albumartist_kwargs['name'] = data['albumartist']

if 'composer' in data:
track_kwargs['composers'] = [Artist(name=data['composer'])]

if 'performer' in data:
track_kwargs['performers'] = [Artist(name=data['performer'])]

if 'album' in data:
album_kwargs['name'] = data['album']

if 'title' in data:
track_kwargs['name'] = data['title']

if 'genre' in data:
track_kwargs['genre'] = data['genre']

if 'date' in data:
track_kwargs['date'] = data['date']

if 'comment' in data:
track_kwargs['comment'] = data['comment']

if 'musicbrainz_trackid' in data:
track_kwargs['musicbrainz_id'] = data['musicbrainz_trackid']

Expand Down
52 changes: 45 additions & 7 deletions mopidy/frontends/mpd/protocol/music_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@


QUERY_RE = (
r'(?P<mpd_query>("?([Aa]lbum|[Aa]rtist|[Aa]lbumartist|[Dd]ate|[Ff]ile|'
r'[Ff]ilename|[Tt]itle|[Tt]rack|[Aa]ny)"? "[^"]*"\s?)+)$')
r'(?P<mpd_query>("?([Aa]lbum|[Aa]rtist|[Aa]lbumartist|[Cc]omment|'
r'[Cc]omposer|[Dd]ate|[Ff]ile|[Ff]ilename|[Gg]enre|[Pp]erformer|'
r'[Tt]itle|[Tt]rack|[Aa]ny)"? "[^"]*"\s?)+)$')


def _get_field(field, search_results):
Expand Down Expand Up @@ -100,9 +101,12 @@ def find(context, mpd_query):
return
results = context.core.library.find_exact(**query).get()
result_tracks = []
if 'artist' not in query and 'albumartist' not in query:
if ('artist' not in query and
'albumartist' not in query and
'composer' not in query and
'performer' not in query):
result_tracks += [_artist_as_track(a) for a in _get_artists(results)]
if 'album' not in query:
if 'album' not in query and 'genre' not in query:
result_tracks += [_album_as_track(a) for a in _get_albums(results)]
result_tracks += _get_tracks(results)
return translator.tracks_to_mpd_format(result_tracks)
Expand All @@ -127,8 +131,9 @@ def findadd(context, mpd_query):


@handle_request(
r'^list "?(?P<field>([Aa]rtist|[Aa]lbumartist|[Aa]lbum|[Dd]ate|'
r'[Gg]enre))"?( (?P<mpd_query>.*))?$')
r'^list "?(?P<field>([Aa]rtist|[Aa]lbumartist|[Aa]lbum|[Cc]omposer|'
r'[Dd]ate|[Gg]enre|[Pp]erformer))"?'
r'( (?P<mpd_query>.*))?$')
def list_(context, field, mpd_query=None):
"""
*musicpd.org, music database section:*
Expand Down Expand Up @@ -222,10 +227,14 @@ def list_(context, field, mpd_query=None):
return _list_albumartist(context, query)
elif field == 'album':
return _list_album(context, query)
elif field == 'composer':
return _list_composer(context, query)
elif field == 'performer':
return _list_performer(context, query)
elif field == 'date':
return _list_date(context, query)
elif field == 'genre':
pass # TODO We don't have genre in our internal data structures yet
return _list_genre(context, query)


def _list_artist(context, query):
Expand Down Expand Up @@ -258,6 +267,26 @@ def _list_album(context, query):
return albums


def _list_composer(context, query):
composers = set()
results = context.core.library.find_exact(**query).get()
for track in _get_tracks(results):
for composer in track.composers:
if composer.name:
composers.add(('Composer', composer.name))
return composers


def _list_performer(context, query):
performers = set()
results = context.core.library.find_exact(**query).get()
for track in _get_tracks(results):
for performer in track.performers:
if performer.name:
performers.add(('Performer', performer.name))
return performers


def _list_date(context, query):
dates = set()
results = context.core.library.find_exact(**query).get()
Expand All @@ -267,6 +296,15 @@ def _list_date(context, query):
return dates


def _list_genre(context, query):
genres = set()
results = context.core.library.find_exact(**query).get()
for track in _get_tracks(results):
if track.genre:
genres.add(('Genre', track.genre))
return genres


@handle_request(r'^listall$')
@handle_request(r'^listall "(?P<uri>[^"]+)"$')
def listall(context, uri=None):
Expand Down
Loading

0 comments on commit b5067cc

Please sign in to comment.