diff --git a/docs/changelog.rst b/docs/changelog.rst index c2c121d5..c3a80955 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -22,6 +22,11 @@ v0.15.0 (UNRELEASED) - :option:`mopidy --show-config` will now take into consideration any :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** - An album's number of discs and a track's disc number are now extracted when diff --git a/docs/config.rst b/docs/config.rst index 9f997b23..6fd7579d 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -90,6 +90,16 @@ Core configuration values ``gst-inspect-0.10`` to see what output properties can be set on the sink. 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 The log format used for informational logging. diff --git a/mopidy/audio/actor.py b/mopidy/audio/actor.py index af0a0c68..d78df9b7 100644 --- a/mopidy/audio/actor.py +++ b/mopidy/audio/actor.py @@ -22,6 +22,22 @@ mixers.register_mixers() 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): """ @@ -55,6 +71,7 @@ class Audio(pykka.ThreadingActor): try: self._setup_playbin() self._setup_output() + self._setup_visualizer() self._setup_mixer() self._setup_message_processor() except gobject.GError as ex: @@ -78,9 +95,7 @@ class Audio(pykka.ThreadingActor): def _setup_playbin(self): playbin = gst.element_factory_make('playbin2') - - fakesink = gst.element_factory_make('fakesink') - playbin.set_property('video-sink', fakesink) + playbin.set_property('flags', PLAYBIN_FLAGS) self._connect(playbin, 'about-to-finish', self._on_about_to_finish) 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) 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): mixer_desc = self._config['audio']['mixer'] track_desc = self._config['audio']['mixer_track'] diff --git a/mopidy/config/__init__.py b/mopidy/config/__init__.py index dfdae6a7..0767b50c 100644 --- a/mopidy/config/__init__.py +++ b/mopidy/config/__init__.py @@ -24,6 +24,7 @@ _audio_schema = ConfigSchema('audio') _audio_schema['mixer'] = String() _audio_schema['mixer_track'] = String(optional=True) _audio_schema['output'] = String() +_audio_schema['visualizer'] = String(optional=True) _proxy_schema = ConfigSchema('proxy') _proxy_schema['scheme'] = String(optional=True, diff --git a/mopidy/config/default.conf b/mopidy/config/default.conf index 3899c2c5..06749ee1 100644 --- a/mopidy/config/default.conf +++ b/mopidy/config/default.conf @@ -11,6 +11,7 @@ pykka = info mixer = autoaudiomixer mixer_track = output = autoaudiosink +visualizer = [proxy] scheme = diff --git a/tests/audio/actor_test.py b/tests/audio/actor_test.py index c311bdc3..617131cc 100644 --- a/tests/audio/actor_test.py +++ b/tests/audio/actor_test.py @@ -21,6 +21,7 @@ class AudioTest(unittest.TestCase): 'mixer': 'fakemixer track_max_volume=65536', 'mixer_track': None, 'output': 'fakesink', + 'visualizer': None, } } 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_track': None, 'output': 'fakesink', + 'visualizer': None, } } self.audio = audio.Audio.start(config=config).proxy()