From ff6a484add5b42b3f819a7a8f8a886c9089c5d10 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 3 Nov 2010 23:00:34 +0100 Subject: [PATCH 1/7] docs: Add dummy output --- docs/api/outputs.rst | 1 + docs/modules/outputs/dummy.rst | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 docs/modules/outputs/dummy.rst diff --git a/docs/api/outputs.rst b/docs/api/outputs.rst index 5ef1606d..0650563e 100644 --- a/docs/api/outputs.rst +++ b/docs/api/outputs.rst @@ -17,4 +17,5 @@ Outputs are responsible for playing audio. Output implementations ====================== +* :mod:`mopidy.outputs.dummy` * :mod:`mopidy.outputs.gstreamer` diff --git a/docs/modules/outputs/dummy.rst b/docs/modules/outputs/dummy.rst new file mode 100644 index 00000000..56436c94 --- /dev/null +++ b/docs/modules/outputs/dummy.rst @@ -0,0 +1,10 @@ +******************************************************* +:mod:`mopidy.outputs.dummy` -- Dummy output for testing +******************************************************* + +.. inheritance-diagram:: mopidy.outputs.dummy + +.. automodule:: mopidy.outputs.dummy + :synopsis: Dummy output for testing + :members: + :undoc-members: From 7accf783ca5725d8e6bf2326cd863db6af56f311 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 3 Nov 2010 23:23:30 +0100 Subject: [PATCH 2/7] Remove call to stop() on LocalPlaybackController init --- mopidy/backends/local/__init__.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index 532c3976..6a1d3c51 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -50,12 +50,6 @@ class LocalBackend(Backend): class LocalPlaybackController(PlaybackController): - def __init__(self, *args, **kwargs): - super(LocalPlaybackController, self).__init__(*args, **kwargs) - - # XXX Why do we call stop()? Is it to set GStreamer state to 'READY'? - self.stop() - @property def time_position(self): return self.backend.output.get_position() From be225c23f1a794b10124fb21c4ef61b1ee1f7eb0 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 3 Nov 2010 23:31:11 +0100 Subject: [PATCH 3/7] Simplify DummyBackend instantiation --- mopidy/backends/dummy/__init__.py | 7 +++++-- tests/frontends/mpd/audio_output_test.py | 3 +-- tests/frontends/mpd/command_list_test.py | 3 +-- tests/frontends/mpd/connection_test.py | 3 +-- tests/frontends/mpd/current_playlist_test.py | 3 +-- tests/frontends/mpd/dispatcher_test.py | 3 +-- tests/frontends/mpd/music_db_test.py | 9 ++++----- tests/frontends/mpd/playback_test.py | 5 ++--- tests/frontends/mpd/reflection_test.py | 3 +-- tests/frontends/mpd/regression_test.py | 7 +++---- tests/frontends/mpd/status_test.py | 3 +-- tests/frontends/mpd/stickers_test.py | 3 +-- tests/frontends/mpd/stored_playlists_test.py | 3 +-- 13 files changed, 23 insertions(+), 32 deletions(-) diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 9c6885bc..2d72ec8a 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -2,7 +2,9 @@ from mopidy.backends.base import (Backend, CurrentPlaylistController, PlaybackController, BasePlaybackProvider, LibraryController, BaseLibraryProvider, StoredPlaylistsController, BaseStoredPlaylistsProvider) +from mopidy.mixers.dummy import DummyMixer from mopidy.models import Playlist +from mopidy.outputs.dummy import DummyOutput class DummyQueue(object): @@ -22,10 +24,11 @@ class DummyBackend(Backend): """ def __init__(self, *args, **kwargs): + kwargs['core_queue'] = DummyQueue() + kwargs['output'] = DummyOutput(core_queue=DummyQueue()) + kwargs['mixer_class'] = DummyMixer super(DummyBackend, self).__init__(*args, **kwargs) - self.core_queue = DummyQueue() - self.current_playlist = CurrentPlaylistController(backend=self) library_provider = DummyLibraryProvider(backend=self) diff --git a/tests/frontends/mpd/audio_output_test.py b/tests/frontends/mpd/audio_output_test.py index b81e727e..77ed05c4 100644 --- a/tests/frontends/mpd/audio_output_test.py +++ b/tests/frontends/mpd/audio_output_test.py @@ -2,11 +2,10 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer class AudioOutputHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_enableoutput(self): diff --git a/tests/frontends/mpd/command_list_test.py b/tests/frontends/mpd/command_list_test.py index 6c801c3f..effc9862 100644 --- a/tests/frontends/mpd/command_list_test.py +++ b/tests/frontends/mpd/command_list_test.py @@ -2,11 +2,10 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer class CommandListsTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_command_list_begin(self): diff --git a/tests/frontends/mpd/connection_test.py b/tests/frontends/mpd/connection_test.py index 21753054..a4abbd27 100644 --- a/tests/frontends/mpd/connection_test.py +++ b/tests/frontends/mpd/connection_test.py @@ -2,11 +2,10 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer class ConnectionHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_close(self): diff --git a/tests/frontends/mpd/current_playlist_test.py b/tests/frontends/mpd/current_playlist_test.py index a4179637..06ff30ac 100644 --- a/tests/frontends/mpd/current_playlist_test.py +++ b/tests/frontends/mpd/current_playlist_test.py @@ -2,12 +2,11 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer from mopidy.models import Track class CurrentPlaylistHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_add(self): diff --git a/tests/frontends/mpd/dispatcher_test.py b/tests/frontends/mpd/dispatcher_test.py index 2a2ee4db..183f01d8 100644 --- a/tests/frontends/mpd/dispatcher_test.py +++ b/tests/frontends/mpd/dispatcher_test.py @@ -4,11 +4,10 @@ from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher from mopidy.frontends.mpd.exceptions import MpdAckError from mopidy.frontends.mpd.protocol import request_handlers, handle_pattern -from mopidy.mixers.dummy import DummyMixer class MpdDispatcherTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_register_same_pattern_twice_fails(self): diff --git a/tests/frontends/mpd/music_db_test.py b/tests/frontends/mpd/music_db_test.py index 05b8ebd0..36d92adf 100644 --- a/tests/frontends/mpd/music_db_test.py +++ b/tests/frontends/mpd/music_db_test.py @@ -2,11 +2,10 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer class MusicDatabaseHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_count(self): @@ -65,7 +64,7 @@ class MusicDatabaseHandlerTest(unittest.TestCase): class MusicDatabaseFindTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_find_album(self): @@ -104,7 +103,7 @@ class MusicDatabaseFindTest(unittest.TestCase): class MusicDatabaseListTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_list_foo_returns_ack(self): @@ -295,7 +294,7 @@ class MusicDatabaseListTest(unittest.TestCase): class MusicDatabaseSearchTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_search_album(self): diff --git a/tests/frontends/mpd/playback_test.py b/tests/frontends/mpd/playback_test.py index 4e60546d..45aaaf83 100644 --- a/tests/frontends/mpd/playback_test.py +++ b/tests/frontends/mpd/playback_test.py @@ -2,12 +2,11 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer from mopidy.models import Track class PlaybackOptionsHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_consume_off(self): @@ -166,7 +165,7 @@ class PlaybackOptionsHandlerTest(unittest.TestCase): class PlaybackControlHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_next(self): diff --git a/tests/frontends/mpd/reflection_test.py b/tests/frontends/mpd/reflection_test.py index a4491d75..0f096930 100644 --- a/tests/frontends/mpd/reflection_test.py +++ b/tests/frontends/mpd/reflection_test.py @@ -2,11 +2,10 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer class ReflectionHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_commands_returns_list_of_all_commands(self): diff --git a/tests/frontends/mpd/regression_test.py b/tests/frontends/mpd/regression_test.py index 3cfdb855..63dc5ae4 100644 --- a/tests/frontends/mpd/regression_test.py +++ b/tests/frontends/mpd/regression_test.py @@ -3,7 +3,6 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer from mopidy.models import Track class IssueGH17RegressionTest(unittest.TestCase): @@ -18,7 +17,7 @@ class IssueGH17RegressionTest(unittest.TestCase): """ def setUp(self): - self.backend = DummyBackend(mixer_class=DummyMixer) + self.backend = DummyBackend() self.backend.current_playlist.append([ Track(uri='a'), Track(uri='b'), None, Track(uri='d'), Track(uri='e'), Track(uri='f')]) @@ -52,7 +51,7 @@ class IssueGH18RegressionTest(unittest.TestCase): """ def setUp(self): - self.backend = DummyBackend(mixer_class=DummyMixer) + self.backend = DummyBackend() self.backend.current_playlist.append([ Track(uri='a'), Track(uri='b'), Track(uri='c'), Track(uri='d'), Track(uri='e'), Track(uri='f')]) @@ -91,7 +90,7 @@ class IssueGH22RegressionTest(unittest.TestCase): """ def setUp(self): - self.backend = DummyBackend(mixer_class=DummyMixer) + self.backend = DummyBackend() self.backend.current_playlist.append([ Track(uri='a'), Track(uri='b'), Track(uri='c'), Track(uri='d'), Track(uri='e'), Track(uri='f')]) diff --git a/tests/frontends/mpd/status_test.py b/tests/frontends/mpd/status_test.py index 1afe6ccd..14fef262 100644 --- a/tests/frontends/mpd/status_test.py +++ b/tests/frontends/mpd/status_test.py @@ -2,12 +2,11 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer from mopidy.models import Track class StatusHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_clearerror(self): diff --git a/tests/frontends/mpd/stickers_test.py b/tests/frontends/mpd/stickers_test.py index 5b66d723..e5aed398 100644 --- a/tests/frontends/mpd/stickers_test.py +++ b/tests/frontends/mpd/stickers_test.py @@ -2,11 +2,10 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer class StickersHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_sticker_get(self): diff --git a/tests/frontends/mpd/stored_playlists_test.py b/tests/frontends/mpd/stored_playlists_test.py index a24cbb88..f0b37b1a 100644 --- a/tests/frontends/mpd/stored_playlists_test.py +++ b/tests/frontends/mpd/stored_playlists_test.py @@ -3,12 +3,11 @@ import unittest from mopidy.backends.dummy import DummyBackend from mopidy.frontends.mpd import dispatcher -from mopidy.mixers.dummy import DummyMixer from mopidy.models import Track, Playlist class StoredPlaylistsHandlerTest(unittest.TestCase): def setUp(self): - self.b = DummyBackend(mixer_class=DummyMixer) + self.b = DummyBackend() self.h = dispatcher.MpdDispatcher(backend=self.b) def test_listplaylist(self): From 52cdaa9d4f5fed89d75294a9ce9a669b2a0fe452 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 3 Nov 2010 23:33:10 +0100 Subject: [PATCH 4/7] Output.get_position() should return None if position is unknown --- mopidy/outputs/base.py | 2 +- mopidy/outputs/dummy.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mopidy/outputs/base.py b/mopidy/outputs/base.py index 372d7d70..ae1af8cf 100644 --- a/mopidy/outputs/base.py +++ b/mopidy/outputs/base.py @@ -67,7 +67,7 @@ class BaseOutput(object): *MUST be implemented by subclass.* - :rtype: int + :rtype: int or :class:`None` if unknown """ raise NotImplementedError diff --git a/mopidy/outputs/dummy.py b/mopidy/outputs/dummy.py index 060ee02f..e78d269c 100644 --- a/mopidy/outputs/dummy.py +++ b/mopidy/outputs/dummy.py @@ -32,7 +32,7 @@ class DummyOutput(BaseOutput): end_of_data_stream_called = False #: For testing. Contains the current position. - position = 0 + position = None #: For testing. Contains the current state. state = 'NULL' From 4515f0764e9082632893df9c042d95f54bd11223 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 3 Nov 2010 23:33:53 +0100 Subject: [PATCH 5/7] Use time position from output if provided, else internally calculated position --- mopidy/backends/base/playback.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mopidy/backends/base/playback.py b/mopidy/backends/base/playback.py index 8a3eeee5..8ab60470 100644 --- a/mopidy/backends/base/playback.py +++ b/mopidy/backends/base/playback.py @@ -282,6 +282,9 @@ class PlaybackController(object): @property def time_position(self): """Time position in milliseconds.""" + output_position = self.backend.output.get_position() + if output_position is not None: + return output_position if self.state == self.PLAYING: time_since_started = (self._current_wall_time - self._play_time_started) From 4b13dd9046b46d9fd04bfdc072c68dcf463d81c5 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 3 Nov 2010 23:34:08 +0100 Subject: [PATCH 6/7] Remove LocalPlaybackController which is now redundant --- mopidy/backends/local/__init__.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index 6a1d3c51..578e0b5e 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -39,7 +39,7 @@ class LocalBackend(Backend): provider=library_provider) playback_provider = LocalPlaybackProvider(backend=self) - self.playback = LocalPlaybackController(backend=self, + self.playback = PlaybackController(backend=self, provider=playback_provider) stored_playlists_provider = LocalStoredPlaylistsProvider(backend=self) @@ -49,12 +49,6 @@ class LocalBackend(Backend): self.uri_handlers = [u'file://'] -class LocalPlaybackController(PlaybackController): - @property - def time_position(self): - return self.backend.output.get_position() - - class LocalPlaybackProvider(BasePlaybackProvider): def pause(self): return self.backend.output.set_state('PAUSED') From 1f9414d2a77c98a2f23d18d60b87f3ca14892958 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 3 Nov 2010 23:38:27 +0100 Subject: [PATCH 7/7] Return None from GStreamerOutput.get_position() upon failure --- mopidy/outputs/gstreamer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mopidy/outputs/gstreamer.py b/mopidy/outputs/gstreamer.py index 3b037f62..3c2f5ea7 100644 --- a/mopidy/outputs/gstreamer.py +++ b/mopidy/outputs/gstreamer.py @@ -265,5 +265,5 @@ class GStreamerPlayerThread(BaseThread): position = self.gst_pipeline.query_position(gst.FORMAT_TIME)[0] return position // gst.MSECOND except gst.QueryError, e: - logger.error('time_position failed: %s', e) - return 0 + logger.debug(u'GStreamer time position: %s', e) + return None