Merge remote-tracking branch 'adamcik/feature/visualization' into develop
Conflicts: docs/changelog.rst
This commit is contained in:
commit
f0b69c3394
@ -22,6 +22,11 @@ v0.15.0 (UNRELEASED)
|
|||||||
- :option:`mopidy --show-config` will now take into consideration any
|
- :option:`mopidy --show-config` will now take into consideration any
|
||||||
:option:`mopidy --option` arguments appearing later on the command line.
|
:option:`mopidy --option` arguments appearing later on the command line.
|
||||||
|
|
||||||
|
**Audio**
|
||||||
|
|
||||||
|
- Added support for viusalization. :confval:`audio/visualizer` can now be set
|
||||||
|
to GStreamer visualizers.
|
||||||
|
|
||||||
**Local backend**
|
**Local backend**
|
||||||
|
|
||||||
- An album's number of discs and a track's disc number are now extracted when
|
- An album's number of discs and a track's disc number are now extracted when
|
||||||
|
|||||||
@ -90,6 +90,16 @@ Core configuration values
|
|||||||
``gst-inspect-0.10`` to see what output properties can be set on the sink.
|
``gst-inspect-0.10`` to see what output properties can be set on the sink.
|
||||||
For example: ``gst-inspect-0.10 shout2send``
|
For example: ``gst-inspect-0.10 shout2send``
|
||||||
|
|
||||||
|
.. confval:: audio/visualizer
|
||||||
|
|
||||||
|
Visualizer to use.
|
||||||
|
|
||||||
|
Can be left blank if no visualizer is desired. Otherwise this expects a
|
||||||
|
GStreamer visualizer. Typical values are ``monoscope``, ``goom``,
|
||||||
|
``goom2k1`` or one of the `libvisual`_ visualizers.
|
||||||
|
|
||||||
|
.. _libvisual: http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-plugins/html/gst-plugins-base-plugins-plugin-libvisual.html
|
||||||
|
|
||||||
.. confval:: logging/console_format
|
.. confval:: logging/console_format
|
||||||
|
|
||||||
The log format used for informational logging.
|
The log format used for informational logging.
|
||||||
|
|||||||
@ -22,6 +22,22 @@ mixers.register_mixers()
|
|||||||
|
|
||||||
MB = 1 << 20
|
MB = 1 << 20
|
||||||
|
|
||||||
|
# GST_PLAY_FLAG_VIDEO (1<<0)
|
||||||
|
# GST_PLAY_FLAG_AUDIO (1<<1)
|
||||||
|
# GST_PLAY_FLAG_TEXT (1<<2)
|
||||||
|
# GST_PLAY_FLAG_VIS (1<<3)
|
||||||
|
# GST_PLAY_FLAG_SOFT_VOLUME (1<<4)
|
||||||
|
# GST_PLAY_FLAG_NATIVE_AUDIO (1<<5)
|
||||||
|
# GST_PLAY_FLAG_NATIVE_VIDEO (1<<6)
|
||||||
|
# GST_PLAY_FLAG_DOWNLOAD (1<<7)
|
||||||
|
# GST_PLAY_FLAG_BUFFERING (1<<8)
|
||||||
|
# GST_PLAY_FLAG_DEINTERLACE (1<<9)
|
||||||
|
# GST_PLAY_FLAG_SOFT_COLORBALANCE (1<<10)
|
||||||
|
|
||||||
|
# Default flags to use for playbin: AUDIO, SOFT_VOLUME, DOWNLOAD
|
||||||
|
PLAYBIN_FLAGS = (1<<1) | (1<<4) | (1<<7)
|
||||||
|
PLAYBIN_VIS_FLAGS = PLAYBIN_FLAGS | (1<<3)
|
||||||
|
|
||||||
|
|
||||||
class Audio(pykka.ThreadingActor):
|
class Audio(pykka.ThreadingActor):
|
||||||
"""
|
"""
|
||||||
@ -55,6 +71,7 @@ class Audio(pykka.ThreadingActor):
|
|||||||
try:
|
try:
|
||||||
self._setup_playbin()
|
self._setup_playbin()
|
||||||
self._setup_output()
|
self._setup_output()
|
||||||
|
self._setup_visualizer()
|
||||||
self._setup_mixer()
|
self._setup_mixer()
|
||||||
self._setup_message_processor()
|
self._setup_message_processor()
|
||||||
except gobject.GError as ex:
|
except gobject.GError as ex:
|
||||||
@ -78,9 +95,7 @@ class Audio(pykka.ThreadingActor):
|
|||||||
|
|
||||||
def _setup_playbin(self):
|
def _setup_playbin(self):
|
||||||
playbin = gst.element_factory_make('playbin2')
|
playbin = gst.element_factory_make('playbin2')
|
||||||
|
playbin.set_property('flags', PLAYBIN_FLAGS)
|
||||||
fakesink = gst.element_factory_make('fakesink')
|
|
||||||
playbin.set_property('video-sink', fakesink)
|
|
||||||
|
|
||||||
self._connect(playbin, 'about-to-finish', self._on_about_to_finish)
|
self._connect(playbin, 'about-to-finish', self._on_about_to_finish)
|
||||||
self._connect(playbin, 'notify::source', self._on_new_source)
|
self._connect(playbin, 'notify::source', self._on_new_source)
|
||||||
@ -149,6 +164,19 @@ class Audio(pykka.ThreadingActor):
|
|||||||
'Failed to create audio output "%s": %s', output_desc, ex)
|
'Failed to create audio output "%s": %s', output_desc, ex)
|
||||||
process.exit_process()
|
process.exit_process()
|
||||||
|
|
||||||
|
def _setup_visualizer(self):
|
||||||
|
visualizer_element = self._config['audio']['visualizer']
|
||||||
|
if not visualizer_element:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
visualizer = gst.element_factory_make(visualizer_element)
|
||||||
|
self._playbin.set_property('vis-plugin', visualizer)
|
||||||
|
self._playbin.set_property('flags', PLAYBIN_VIS_FLAGS)
|
||||||
|
logger.info('Audio visualizer set to "%s"', visualizer_element)
|
||||||
|
except gobject.GError as ex:
|
||||||
|
logger.error(
|
||||||
|
'Failed to create audio visualizer "%s": %s', visualizer_element, ex)
|
||||||
|
|
||||||
def _setup_mixer(self):
|
def _setup_mixer(self):
|
||||||
mixer_desc = self._config['audio']['mixer']
|
mixer_desc = self._config['audio']['mixer']
|
||||||
track_desc = self._config['audio']['mixer_track']
|
track_desc = self._config['audio']['mixer_track']
|
||||||
|
|||||||
@ -24,6 +24,7 @@ _audio_schema = ConfigSchema('audio')
|
|||||||
_audio_schema['mixer'] = String()
|
_audio_schema['mixer'] = String()
|
||||||
_audio_schema['mixer_track'] = String(optional=True)
|
_audio_schema['mixer_track'] = String(optional=True)
|
||||||
_audio_schema['output'] = String()
|
_audio_schema['output'] = String()
|
||||||
|
_audio_schema['visualizer'] = String(optional=True)
|
||||||
|
|
||||||
_proxy_schema = ConfigSchema('proxy')
|
_proxy_schema = ConfigSchema('proxy')
|
||||||
_proxy_schema['scheme'] = String(optional=True,
|
_proxy_schema['scheme'] = String(optional=True,
|
||||||
|
|||||||
@ -11,6 +11,7 @@ pykka = info
|
|||||||
mixer = autoaudiomixer
|
mixer = autoaudiomixer
|
||||||
mixer_track =
|
mixer_track =
|
||||||
output = autoaudiosink
|
output = autoaudiosink
|
||||||
|
visualizer =
|
||||||
|
|
||||||
[proxy]
|
[proxy]
|
||||||
scheme =
|
scheme =
|
||||||
|
|||||||
@ -21,6 +21,7 @@ class AudioTest(unittest.TestCase):
|
|||||||
'mixer': 'fakemixer track_max_volume=65536',
|
'mixer': 'fakemixer track_max_volume=65536',
|
||||||
'mixer_track': None,
|
'mixer_track': None,
|
||||||
'output': 'fakesink',
|
'output': 'fakesink',
|
||||||
|
'visualizer': None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.song_uri = path_to_uri(path_to_data_dir('song1.wav'))
|
self.song_uri = path_to_uri(path_to_data_dir('song1.wav'))
|
||||||
@ -70,6 +71,7 @@ class AudioTest(unittest.TestCase):
|
|||||||
'mixer': 'fakemixer track_max_volume=40',
|
'mixer': 'fakemixer track_max_volume=40',
|
||||||
'mixer_track': None,
|
'mixer_track': None,
|
||||||
'output': 'fakesink',
|
'output': 'fakesink',
|
||||||
|
'visualizer': None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.audio = audio.Audio.start(config=config).proxy()
|
self.audio = audio.Audio.start(config=config).proxy()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user