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 <simonvermeersch@gmail.com>] # [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()