audio: Add position_changed event to know when seeks happen

This commit is contained in:
Thomas Adamcik 2014-01-27 23:04:15 +01:00
parent 6490d5bd2d
commit 99d581f7fc
4 changed files with 78 additions and 0 deletions

View File

@ -180,6 +180,8 @@ class Audio(pykka.ThreadingActor):
queue.set_property('max-size-time', 5 * gst.SECOND)
queue.set_property('min-threshold-time', 3 * gst.SECOND)
queue.get_pad('src').add_event_probe(self._on_pad_event)
output.add(user_output)
output.add(queue)
@ -294,6 +296,13 @@ class Audio(pykka.ThreadingActor):
self._disconnect(bus, 'message')
bus.remove_signal_watch()
def _on_pad_event(self, pad, event):
if event.type == gst.EVENT_NEWSEGMENT:
# update, rate, format, start, stop, position
position = event.parse_new_segment()[5] // gst.MSECOND
AudioListener.send('position_changed', position=position)
return True
def _on_message(self, bus, message):
if (message.type == gst.MESSAGE_STATE_CHANGED
and message.src == self._playbin):

View File

@ -37,6 +37,16 @@ class AudioListener(listener.Listener):
"""
pass
def position_changed(self, position_changed):
"""
Called whenever the position of the stream changes.
*MAY* be implemented by actor.
:param int position: Position in milliseconds.
"""
pass
def state_changed(self, old_state, new_state):
"""
Called after the playback state have changed.

View File

@ -231,6 +231,62 @@ class AudioEventTest(unittest.TestCase):
call = mock.call('stream_changed', uri=None)
self.assertIn(call, send_mock.call_args_list)
def test_position_changed_on_pause(self, send_mock):
self.audio.prepare_change()
self.audio.set_uri(self.song_uri)
self.audio.pause_playback()
self.audio.wait_for_state_change()
self.audio.wait_for_state_change().get()
call = mock.call('position_changed', position=0)
self.assertIn(call, send_mock.call_args_list)
def test_position_changed_on_play(self, send_mock):
self.audio.prepare_change()
self.audio.set_uri(self.song_uri)
self.audio.start_playback()
self.audio.wait_for_state_change()
self.audio.wait_for_state_change().get()
call = mock.call('position_changed', position=0)
self.assertIn(call, send_mock.call_args_list)
def test_position_changed_on_seek(self, send_mock):
self.audio.prepare_change()
self.audio.set_uri(self.song_uri)
self.audio.set_position(2000)
self.audio.wait_for_state_change().get()
call = mock.call('position_changed', position=0)
self.assertNotIn(call, send_mock.call_args_list)
def test_position_changed_on_seek_after_play(self, send_mock):
self.audio.prepare_change()
self.audio.set_uri(self.song_uri)
self.audio.start_playback()
self.audio.wait_for_state_change()
self.audio.set_position(2000)
self.audio.wait_for_state_change().get()
call = mock.call('position_changed', position=2000)
self.assertIn(call, send_mock.call_args_list)
def test_position_changed_on_seek_after_pause(self, send_mock):
self.audio.prepare_change()
self.audio.set_uri(self.song_uri)
self.audio.pause_playback()
self.audio.wait_for_state_change()
self.audio.set_position(2000)
self.audio.wait_for_state_change().get()
call = mock.call('position_changed', position=2000)
self.assertIn(call, send_mock.call_args_list)
# Unlike the other events, having the state changed done is not
# enough to ensure our event is called. So we setup a threading
# event that we can wait for with a timeout while the track playback

View File

@ -27,3 +27,6 @@ class AudioListenerTest(unittest.TestCase):
def test_listener_has_default_impl_for_stream_changed(self):
self.listener.stream_changed(None)
def test_listener_has_default_impl_for_position_changed(self):
self.listener.position_changed(None)