mirror of
https://github.com/beetbox/beets.git
synced 2026-01-05 23:43:31 +01:00
bpd: support decoders command
This uses GStreamer APIs to extract a list of audio decoders and the relevant MIME types and file extensions. Some clients like ncmpcpp use this command to fetch a list of supported file extensions.
This commit is contained in:
parent
7b910c3fde
commit
3da23167ca
3 changed files with 75 additions and 4 deletions
|
|
@ -1321,6 +1321,16 @@ class Server(BaseServer):
|
|||
u'db_update: ' + six.text_type(int(self.updated_time)),
|
||||
)
|
||||
|
||||
def cmd_decoders(self, conn):
|
||||
"""Send list of supported decoders and formats."""
|
||||
decoders = self.player.get_decoders()
|
||||
for name, (mimes, exts) in decoders.items():
|
||||
yield u'plugin: {}'.format(name)
|
||||
for ext in exts:
|
||||
yield u'suffix: {}'.format(ext)
|
||||
for mime in mimes:
|
||||
yield u'mime_type: {}'.format(mime)
|
||||
|
||||
# Searching.
|
||||
|
||||
tagtype_map = {
|
||||
|
|
|
|||
|
|
@ -215,6 +215,59 @@ class GstPlayer(object):
|
|||
while self.playing:
|
||||
time.sleep(1)
|
||||
|
||||
def get_decoders(self):
|
||||
return get_decoders()
|
||||
|
||||
|
||||
def get_decoders():
|
||||
"""Get supported audio decoders from GStreamer.
|
||||
Returns a dict mapping decoder element names to the associated media types
|
||||
and file extensions.
|
||||
"""
|
||||
# We only care about audio decoder elements.
|
||||
filt = (Gst.ELEMENT_FACTORY_TYPE_DEPAYLOADER |
|
||||
Gst.ELEMENT_FACTORY_TYPE_DEMUXER |
|
||||
Gst.ELEMENT_FACTORY_TYPE_PARSER |
|
||||
Gst.ELEMENT_FACTORY_TYPE_DECODER |
|
||||
Gst.ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)
|
||||
|
||||
decoders = {}
|
||||
mime_types = set()
|
||||
for f in Gst.ElementFactory.list_get_elements(filt, Gst.Rank.NONE):
|
||||
for pad in f.get_static_pad_templates():
|
||||
if pad.direction == Gst.PadDirection.SINK:
|
||||
caps = pad.static_caps.get()
|
||||
mimes = set()
|
||||
for i in range(caps.get_size()):
|
||||
struct = caps.get_structure(i)
|
||||
mime = struct.get_name()
|
||||
if mime == 'unknown/unknown':
|
||||
continue
|
||||
mimes.add(mime)
|
||||
mime_types.add(mime)
|
||||
if mimes:
|
||||
decoders[f.get_name()] = (mimes, set())
|
||||
|
||||
# Check all the TypeFindFactory plugin features form the registry. If they
|
||||
# are associated with an audio media type that we found above, get the list
|
||||
# of corresponding file extensions.
|
||||
mime_extensions = {mime: set() for mime in mime_types}
|
||||
for feat in Gst.Registry.get().get_feature_list(Gst.TypeFindFactory):
|
||||
caps = feat.get_caps()
|
||||
if caps:
|
||||
for i in range(caps.get_size()):
|
||||
struct = caps.get_structure(i)
|
||||
mime = struct.get_name()
|
||||
if mime in mime_types:
|
||||
mime_extensions[mime].update(feat.get_extensions())
|
||||
|
||||
# Fill in the slot we left for file extensions.
|
||||
for name, (mimes, exts) in decoders.items():
|
||||
for mime in mimes:
|
||||
exts.update(mime_extensions[mime])
|
||||
|
||||
return decoders
|
||||
|
||||
|
||||
def play_simple(paths):
|
||||
"""Play the files in paths in a straightforward way, without
|
||||
|
|
|
|||
|
|
@ -44,13 +44,14 @@ def _gstplayer_play(*_): # noqa: 42
|
|||
gstplayer._GstPlayer = mock.MagicMock(
|
||||
spec_set=[
|
||||
"time", "volume", "playing", "run", "play_file", "pause", "stop",
|
||||
"seek", "play"
|
||||
"seek", "play", "get_decoders",
|
||||
], **{
|
||||
'playing': False,
|
||||
'volume': 0,
|
||||
'time.return_value': (0, 0),
|
||||
'play_file.side_effect': _gstplayer_play,
|
||||
'play.side_effect': _gstplayer_play,
|
||||
'get_decoders.return_value': {'default': ({'audio/mpeg'}, {'mp3'})},
|
||||
})
|
||||
gstplayer.GstPlayer = lambda _: gstplayer._GstPlayer
|
||||
sys.modules["beetsplug.bpd.gstplayer"] = gstplayer
|
||||
|
|
@ -879,9 +880,16 @@ class BPDDeviceTest(BPDTestHelper):
|
|||
|
||||
class BPDReflectionTest(BPDTestHelper):
|
||||
test_implements_reflection = implements({
|
||||
'config', 'commands', 'notcommands', 'urlhandlers',
|
||||
'decoders',
|
||||
}, expectedFailure=True)
|
||||
'config', 'commands', 'notcommands', 'urlhandlers',
|
||||
}, expectedFailure=True)
|
||||
|
||||
def test_cmd_decoders(self):
|
||||
with self.run_bpd() as client:
|
||||
response = client.send_command('decoders')
|
||||
self._assert_ok(response)
|
||||
self.assertEqual('default', response.data['plugin'])
|
||||
self.assertEqual('mp3', response.data['suffix'])
|
||||
self.assertEqual('audio/mpeg', response.data['mime_type'])
|
||||
|
||||
|
||||
class BPDPeersTest(BPDTestHelper):
|
||||
|
|
|
|||
Loading…
Reference in a new issue