audio: Add position_changed event to know when seeks happen
This commit is contained in:
parent
6490d5bd2d
commit
99d581f7fc
@ -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):
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user