gstreamer/examples/switch.py
Jan Schmidt 839bc5b0d4 examples/: Sync with the X server before giving an XID to our sink with a different display connection. This avoids s...
Original commit message from CVS:
* examples/play.py:
* examples/remuxer.py:
* examples/switch.py:
* examples/synchronizer.py:
Sync with the X server before giving an XID to our sink with a different
display connection. This avoids spurious X servers where the sink's
display connection doesn't know the XID that the GDK thread's does.
2008-04-24 11:35:38 +00:00

189 lines
5.6 KiB
Python
Executable file

#!/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
class SwitchTest:
def __init__(self, videowidget):
self.playing = False
pipestr = ('videotestsrc pattern=0 ! queue ! s.sink0'
' videotestsrc pattern=1 ! queue ! s.sink1'
' switch 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.display_get_default().sync()
self.videowidget.set_sink(message.src)
message.src.set_property('force-aspect-ratio', True)
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', padname, 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))