Merge branch 'feature/multi-backend' into develop

This commit is contained in:
Stein Magnus Jodal 2011-04-25 15:07:41 +02:00
commit c8639f48da
8 changed files with 40 additions and 17 deletions

View File

@ -17,4 +17,5 @@ Outputs are responsible for playing audio.
Output implementations
======================
* :mod:`mopidy.outputs.dummy`
* :mod:`mopidy.outputs.gstreamer`

View File

@ -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:

View File

@ -5,6 +5,7 @@ import time
from pykka.registry import ActorRegistry
from mopidy.frontends.base import BaseFrontend
from mopidy.outputs.base import BaseOutput
logger = logging.getLogger('mopidy.backends.base')
@ -288,6 +289,9 @@ class PlaybackController(object):
@property
def time_position(self):
"""Time position in milliseconds."""
output_position = self._time_position_from_output()
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)
@ -297,6 +301,13 @@ class PlaybackController(object):
elif self.state == self.STOPPED:
return 0
def _time_position_from_output(self):
output_refs = ActorRegistry.get_by_class(BaseOutput)
if not output_refs:
return None
output = output_refs[0].proxy()
return output.get_position()
def _play_time_start(self):
self.play_time_accumulated = 0
self.play_time_started = self._current_wall_time

View File

@ -41,7 +41,7 @@ class LocalBackend(ThreadingActor, 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)
@ -58,18 +58,6 @@ class LocalBackend(ThreadingActor, Backend):
self.output = output_refs[0].proxy()
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().get()
class LocalPlaybackProvider(BasePlaybackProvider):
def pause(self):
return self.backend.output.set_state('PAUSED').get()

View File

@ -40,7 +40,7 @@ class BaseOutput(object):
*MUST be implemented by subclass.*
:rtype: int
:rtype: int or :class:`None` if unknown
"""
raise NotImplementedError

View File

@ -25,7 +25,7 @@ class DummyOutput(ThreadingActor, 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'

View File

@ -165,3 +165,18 @@ class GStreamerOutput(ThreadingActor, BaseOutput):
gst_volume = self.gst_pipeline.get_by_name('volume')
gst_volume.set_property('volume', volume / 100.0)
return True
def set_position(self, position):
self.gst_pipeline.get_state() # block until state changes are done
handeled = self.gst_pipeline.seek_simple(gst.Format(gst.FORMAT_TIME),
gst.SEEK_FLAG_FLUSH, position * gst.MSECOND)
self.gst_pipeline.get_state() # block until seek is done
return handeled
def get_position(self):
try:
position = self.gst_pipeline.query_position(gst.FORMAT_TIME)[0]
return position // gst.MSECOND
except gst.QueryError, e:
logger.debug(u'GStreamer time position: %s', e)
return None

View File

@ -386,5 +386,3 @@ class MusicDatabaseSearchTest(unittest.TestCase):
def test_search_else_should_fail(self):
result = self.h.handle_request(u'search "sometype" "something"')
self.assertEqual(result[0], u'ACK [2@0] {search} incorrect arguments')