bpd: support more tagtypes

This commit is contained in:
Carl Suster 2019-04-25 13:08:26 +10:00
parent cc2c35221d
commit fdd809fd36
3 changed files with 72 additions and 30 deletions

View file

@ -1117,19 +1117,10 @@ class Server(BaseServer):
info_lines = [
u'file: ' + item.destination(fragment=True),
u'Time: ' + six.text_type(int(item.length)),
u'Title: ' + item.title,
u'Artist: ' + item.artist,
u'Album: ' + item.album,
u'Genre: ' + item.genre,
u'duration: ' + u'{:.3f}'.format(item.length),
u'Id: ' + six.text_type(item.id),
]
track = six.text_type(item.track)
if item.tracktotal:
track += u'/' + six.text_type(item.tracktotal)
info_lines.append(u'Track: ' + track)
info_lines.append(u'Date: ' + six.text_type(item.year))
try:
pos = self._id_to_index(item.id)
info_lines.append(u'Pos: ' + six.text_type(pos))
@ -1137,7 +1128,9 @@ class Server(BaseServer):
# Don't include position if not in playlist.
pass
info_lines.append(u'Id: ' + six.text_type(item.id))
for tagtype, field in self.tagtype_map.items():
info_lines.append(u'{}: {}'.format(
tagtype, six.text_type(getattr(item, field))))
return info_lines
@ -1341,18 +1334,24 @@ class Server(BaseServer):
tagtype_map = {
u'Artist': u'artist',
u'ArtistSort': u'artist_sort',
u'Album': u'album',
u'Title': u'title',
u'Track': u'track',
u'AlbumArtist': u'albumartist',
u'AlbumArtistSort': u'albumartist_sort',
# Name?
u'Label': u'label',
u'Genre': u'genre',
u'Date': u'year',
u'OriginalDate': u'original_year',
u'Composer': u'composer',
# Performer?
u'Disc': u'disc',
u'filename': u'path', # Suspect.
u'Comment': u'comments',
u'MUSICBRAINZ_TRACKID': u'mb_trackid',
u'MUSICBRAINZ_ALBUMID': u'mb_albumid',
u'MUSICBRAINZ_ARTISTID': u'mb_artistid',
u'MUSICBRAINZ_ALBUMARTISTID': u'mb_albumartistid',
u'MUSICBRAINZ_RELEASETRACKID': u'mb_releasetrackid',
}
def cmd_tagtypes(self, conn):

View file

@ -125,8 +125,7 @@ These are some of the known differences between BPD and MPD:
* Advanced playback features like cross-fade, ReplayGain and MixRamp are not
supported due to BPD's simple audio player backend.
* Advanced query syntax is not currently supported.
* Not all tags (fields) are currently exposed to BPD. Clients also can't use
the ``tagtypes`` mask to hide fields.
* Clients can't use the ``tagtypes`` mask to hide fields.
* BPD's ``random`` mode is not deterministic and doesn't support priorities.
* Mounts and streams are not supported. BPD can only play files from disk.
* Stickers are not supported (although this is basically a flexattr in beets

View file

@ -392,8 +392,31 @@ class BPDTest(BPDTestHelper):
class BPDQueryTest(BPDTestHelper):
test_implements_query = implements({
'clearerror', 'currentsong',
})
'clearerror',
})
def test_cmd_currentsong(self):
with self.run_bpd() as client:
self._bpd_add(client, self.item1)
responses = client.send_commands(
('play',),
('currentsong',),
('stop',),
('currentsong',))
self._assert_ok(*responses)
self.assertEqual('1', responses[1].data['Id'])
self.assertNotIn('Id', responses[3].data)
def test_cmd_currentsong_tagtypes(self):
with self.run_bpd() as client:
self._bpd_add(client, self.item1)
responses = client.send_commands(
('play',),
('currentsong',))
self._assert_ok(*responses)
self.assertEqual(
BPDConnectionTest.TAGTYPES.union(BPDQueueTest.METADATA),
set(responses[1].data.keys()))
def test_cmd_status(self):
with self.run_bpd() as client:
@ -749,6 +772,8 @@ class BPDQueueTest(BPDTestHelper):
'swap', 'swapid', 'addtagid', 'cleartagid',
}, expectedFailure=True)
METADATA = {'Pos', 'Time', 'Id', 'file', 'duration'}
def test_cmd_add(self):
with self.run_bpd() as client:
self._bpd_add(client, self.item1)
@ -762,6 +787,15 @@ class BPDQueueTest(BPDTestHelper):
('playlistinfo', '200'))
self._assert_failed(responses, bpd.ERROR_ARG, pos=2)
def test_cmd_playlistinfo_tagtypes(self):
with self.run_bpd() as client:
self._bpd_add(client, self.item1)
response = client.send_command('playlistinfo', '0')
self._assert_ok(response)
self.assertEqual(
BPDConnectionTest.TAGTYPES.union(BPDQueueTest.METADATA),
set(response.data.keys()))
def test_cmd_playlistid(self):
with self.run_bpd() as client:
self._bpd_add(client, self.item1, self.item2)
@ -900,8 +934,24 @@ class BPDStickerTest(BPDTestHelper):
class BPDConnectionTest(BPDTestHelper):
test_implements_connection = implements({
'close', 'kill', 'tagtypes',
})
'close', 'kill',
})
ALL_MPD_TAGTYPES = {
'Artist', 'ArtistSort', 'Album', 'AlbumSort', 'AlbumArtist',
'AlbumArtistSort', 'Title', 'Track', 'Name', 'Genre', 'Date',
'Composer', 'Performer', 'Comment', 'Disc', 'Label',
'OriginalDate', 'MUSICBRAINZ_ARTISTID', 'MUSICBRAINZ_ALBUMID',
'MUSICBRAINZ_ALBUMARTISTID', 'MUSICBRAINZ_TRACKID',
'MUSICBRAINZ_RELEASETRACKID', 'MUSICBRAINZ_WORKID',
}
UNSUPPORTED_TAGTYPES = {
'MUSICBRAINZ_WORKID', # not tracked by beets
'Performer', # not tracked by beets
'AlbumSort', # not tracked by beets
'Name', # junk field for internet radio
}
TAGTYPES = ALL_MPD_TAGTYPES.difference(UNSUPPORTED_TAGTYPES)
def test_cmd_password(self):
with self.run_bpd(password='abc123') as client:
@ -921,19 +971,13 @@ class BPDConnectionTest(BPDTestHelper):
response = client.send_command('ping')
self._assert_ok(response)
@unittest.skip
def test_cmd_tagtypes(self):
with self.run_bpd() as client:
response = client.send_command('tagtypes')
self._assert_ok(response)
self.assertEqual({
'Artist', 'ArtistSort', 'Album', 'AlbumSort', 'AlbumArtist',
'AlbumArtistSort', 'Title', 'Track', 'Name', 'Genre', 'Date',
'Composer', 'Performer', 'Comment', 'Disc', 'Label',
'OriginalDate', 'MUSICBRAINZ_ARTISTID', 'MUSICBRAINZ_ALBUMID',
'MUSICBRAINZ_ALBUMARTISTID', 'MUSICBRAINZ_TRACKID',
'MUSICBRAINZ_RELEASETRACKID', 'MUSICBRAINZ_WORKID',
}, set(response.data['tag']))
self.assertEqual(
self.TAGTYPES,
set(response.data['tagtype']))
@unittest.skip
def test_tagtypes_mask(self):