#!/usr/bin/env python # -*- Mode: Python -*- # vi:si:et:sw=4:sts=4:ts=4 import pygtk pygtk.require('2.0') import sys import gobject gobject.threads_init() import pygst pygst.require('0.10') import gst import gst.interfaces import gtk gtk.gdk.threads_init() class SwitchTest: def __init__(self, videowidget): self.playing = False pipestr = ('videotestsrc pattern=0 ! queue ! s.sink0' ' videotestsrc pattern=1 ! queue ! s.sink1' ' input-selector name=s ! autovideosink') self.pipeline = gst.parse_launch(pipestr) self.videowidget = videowidget bus = self.pipeline.get_bus() bus.enable_sync_message_emission() bus.add_signal_watch() bus.connect('sync-message::element', self.on_sync_message) bus.connect('message', self.on_message) def on_sync_message(self, bus, message): if message.structure is None: return if message.structure.get_name() == 'prepare-xwindow-id': # Sync with the X server before giving the X-id to the sink gtk.gdk.threads_enter() gtk.gdk.display_get_default().sync() self.videowidget.set_sink(message.src) message.src.set_property('force-aspect-ratio', True) gtk.gdk.threads_leave() def on_message(self, bus, message): t = message.type if t == gst.MESSAGE_ERROR: err, debug = message.parse_error() print "Error: %s" % err, debug if self.on_eos: self.on_eos() self.playing = False elif t == gst.MESSAGE_EOS: if self.on_eos: self.on_eos() self.playing = False def play(self): self.playing = True gst.info("playing player") self.pipeline.set_state(gst.STATE_PLAYING) def stop(self): self.pipeline.set_state(gst.STATE_NULL) gst.info("stopped player") self.playing = False def get_state(self, timeout=1): return self.pipeline.get_state(timeout=timeout) def is_playing(self): return self.playing def switch(self, padname): switch = self.pipeline.get_by_name('s') stop_time = switch.emit('block') newpad = switch.get_static_pad(padname) start_time = newpad.get_property('running-time') gst.warning('stop time = %d' % (stop_time,)) gst.warning('stop time = %s' % (gst.TIME_ARGS(stop_time),)) gst.warning('start time = %d' % (start_time,)) gst.warning('start time = %s' % (gst.TIME_ARGS(start_time),)) gst.warning('switching from %r to %r' % (switch.get_property('active-pad'), padname)) switch.emit('switch', newpad, stop_time, start_time) class VideoWidget(gtk.DrawingArea): def __init__(self): gtk.DrawingArea.__init__(self) self.imagesink = None self.unset_flags(gtk.DOUBLE_BUFFERED) def do_expose_event(self, event): if self.imagesink: self.imagesink.expose() return False else: return True def set_sink(self, sink): assert self.window.xid self.imagesink = sink self.imagesink.set_xwindow_id(self.window.xid) class SwitchWindow(gtk.Window): UPDATE_INTERVAL = 500 def __init__(self): gtk.Window.__init__(self) self.set_default_size(410, 325) self.create_ui() self.player = SwitchTest(self.videowidget) self.populate_combobox() self.update_id = -1 self.changed_id = -1 self.seek_timeout_id = -1 self.p_position = gst.CLOCK_TIME_NONE self.p_duration = gst.CLOCK_TIME_NONE def on_delete_event(): self.player.stop() gtk.main_quit() self.connect('delete-event', lambda *x: on_delete_event()) def load_file(self, location): self.player.set_location(location) def play(self): self.player.play() def populate_combobox(self): switch = self.player.pipeline.get_by_name('s') for i, pad in enumerate([p for p in switch.pads() if p.get_direction() == gst.PAD_SINK]): self.combobox.append_text(pad.get_name()) if switch.get_property('active-pad') == pad.get_name(): self.combobox.set_active(i) if self.combobox.get_active() == -1: self.combobox.set_active(0) def combobox_changed(self): model = self.combobox.get_model() row = model[self.combobox.get_active()] padname, = row self.player.switch(padname) def create_ui(self): vbox = gtk.VBox() self.add(vbox) self.videowidget = VideoWidget() vbox.pack_start(self.videowidget) hbox = gtk.HBox() vbox.pack_start(hbox, fill=False, expand=False) self.combobox = combobox = gtk.combo_box_new_text() combobox.show() hbox.pack_start(combobox) self.combobox.connect('changed', lambda *x: self.combobox_changed()) self.videowidget.connect_after('realize', lambda *x: self.play()) def main(args): def usage(): sys.stderr.write("usage: %s\n" % args[0]) return 1 # Need to register our derived widget types for implicit event # handlers to get called. gobject.type_register(SwitchWindow) gobject.type_register(VideoWidget) if len(args) != 1: return usage() w = SwitchWindow() w.show_all() gtk.main() return 0 if __name__ == '__main__': sys.exit(main(sys.argv))