Seeking with gstreamer
# [SNIPPET_NAME: Seeking with gstreamer]
# [SNIPPET_CATEGORIES: GStreamer, PyGTK]
# [SNIPPET_DESCRIPTION: Shows a slider that you can use to seek into the current song ]
# [SNIPPET_AUTHOR: Simon Vermeersch <[email protected]>]
# [SNIPPET_LICENSE: GPL]
#
# Adapted from Laszlo Pandy's code
#
import os
import gst, gtk, gobject
class PlaybackInterface:
PLAY_IMAGE = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON)
PAUSE_IMAGE = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_BUTTON)
def __init__(self):
self.main_window = gtk.Window()
self.play_button = gtk.Button()
self.slider = gtk.HScale()
self.hbox = gtk.HBox()
self.hbox.pack_start(self.play_button, False)
self.hbox.pack_start(self.slider, True, True)
self.main_window.add(self.hbox)
self.main_window.connect('destroy', self.on_destroy)
self.play_button.set_image(self.PLAY_IMAGE)
self.play_button.connect('clicked', self.on_play)
self.slider.set_range(0, 100)
self.slider.set_increments(1, 10)
self.slider.connect('value-changed', self.on_slider_change)
self.main_window.set_border_width(6)
self.main_window.set_size_request(600, 50)
self.playbin = gst.element_factory_make('playbin2')
self.playbin.set_property('uri', 'file:///usr/share/example-content/Ubuntu_Free_Culture_Showcase/InTheCircle.oga')
self.bus = self.playbin.get_bus()
self.bus.add_signal_watch()
self.bus.connect("message::eos", self.on_finish)
self.is_playing = False
self.main_window.show_all()
def on_finish(self, bus, message):
self.playbin.set_state(gst.STATE_PAUSED)
self.play_button.set_image(self.PLAY_IMAGE)
self.is_playing = False
self.playbin.seek_simple(gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH, 0)
self.slider.set_value(0)
def on_destroy(self, window):
# NULL state allows the pipeline to release resources
self.playbin.set_state(gst.STATE_NULL)
self.is_playing = False
gtk.main_quit()
def on_play(self, button):
if not self.is_playing:
self.play_button.set_image(self.PAUSE_IMAGE)
self.is_playing = True
self.playbin.set_state(gst.STATE_PLAYING)
gobject.timeout_add(100, self.update_slider)
else:
self.play_button.set_image(self.PLAY_IMAGE)
self.is_playing = False
self.playbin.set_state(gst.STATE_PAUSED)
def on_slider_change(self, slider):
seek_time_secs = slider.get_value()
self.playbin.seek_simple(gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_KEY_UNIT, seek_time_secs * gst.SECOND)
def update_slider(self):
if not self.is_playing:
return False # cancel timeout
try:
nanosecs, format = self.playbin.query_position(gst.FORMAT_TIME)
duration_nanosecs, format = self.playbin.query_duration(gst.FORMAT_TIME)
# block seek handler so we don't seek when we set_value()
self.slider.handler_block_by_func(self.on_slider_change)
self.slider.set_range(0, float(duration_nanosecs) / gst.SECOND)
self.slider.set_value(float(nanosecs) / gst.SECOND)
self.slider.handler_unblock_by_func(self.on_slider_change)
except gst.QueryError:
# pipeline must not be ready and does not know position
pass
return True # continue calling every 30 milliseconds
if __name__ == "__main__":
PlaybackInterface()
gtk.main()