mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
examples/remuxer.py: Updates! Nothing gstreamery, it's all ui, so I won't bother you with the details.
Original commit message from CVS: 2006-05-05 Andy Wingo <wingo@pobox.com> * examples/remuxer.py: Updates! Nothing gstreamery, it's all ui, so I won't bother you with the details.
This commit is contained in:
parent
4ec7c5c5d8
commit
bf5fe2593e
2 changed files with 115 additions and 51 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2006-05-05 Andy Wingo <wingo@pobox.com>
|
||||||
|
|
||||||
|
* examples/remuxer.py: Updates! Nothing gstreamery, it's all ui,
|
||||||
|
so I won't bother you with the details.
|
||||||
|
|
||||||
2006-04-29 Edward Hervey <edward@fluendo.com>
|
2006-04-29 Edward Hervey <edward@fluendo.com>
|
||||||
|
|
||||||
* examples/gstfile.py:
|
* examples/gstfile.py:
|
||||||
|
|
|
@ -21,7 +21,6 @@ class GstPlayer:
|
||||||
self.playing = False
|
self.playing = False
|
||||||
self.player = gst.element_factory_make("playbin", "player")
|
self.player = gst.element_factory_make("playbin", "player")
|
||||||
self.videowidget = videowidget
|
self.videowidget = videowidget
|
||||||
self.on_eos = False
|
|
||||||
|
|
||||||
bus = self.player.get_bus()
|
bus = self.player.get_bus()
|
||||||
bus.enable_sync_message_emission()
|
bus.enable_sync_message_emission()
|
||||||
|
@ -50,6 +49,7 @@ class GstPlayer:
|
||||||
self.playing = False
|
self.playing = False
|
||||||
|
|
||||||
def set_location(self, location):
|
def set_location(self, location):
|
||||||
|
self.player.set_state(gst.STATE_NULL)
|
||||||
self.player.set_property('uri', location)
|
self.player.set_property('uri', location)
|
||||||
|
|
||||||
def get_location(self):
|
def get_location(self):
|
||||||
|
@ -187,6 +187,9 @@ class TimeControl(gtk.HBox):
|
||||||
self.pack_start(goto, False, False, 0)
|
self.pack_start(goto, False, False, 0)
|
||||||
set.connect('clicked', lambda *x: self.set_now())
|
set.connect('clicked', lambda *x: self.set_now())
|
||||||
goto.connect('clicked', lambda *x: self.activated())
|
goto.connect('clicked', lambda *x: self.activated())
|
||||||
|
pad = gtk.Label("")
|
||||||
|
pad.show()
|
||||||
|
self.pack_start(pad, True, False, 0)
|
||||||
|
|
||||||
def get_time(self):
|
def get_time(self):
|
||||||
time = 0
|
time = 0
|
||||||
|
@ -198,7 +201,7 @@ class TimeControl(gtk.HBox):
|
||||||
val = int(text)
|
val = int(text)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
val = 0
|
val = 0
|
||||||
w.set_text(val and str(val) or '')
|
w.set_text(val and str(val) or '0')
|
||||||
time += val * multiplier
|
time += val * multiplier
|
||||||
return time
|
return time
|
||||||
|
|
||||||
|
@ -248,6 +251,8 @@ class ProgressDialog(gtk.Dialog):
|
||||||
vbox.pack_start(label, False)
|
vbox.pack_start(label, False)
|
||||||
|
|
||||||
label = gtk.Label(description)
|
label = gtk.Label(description)
|
||||||
|
label.set_use_markup(True)
|
||||||
|
label.set_alignment(0.0, 0.0)
|
||||||
label.set_line_wrap(True)
|
label.set_line_wrap(True)
|
||||||
label.set_padding(0, 12)
|
label.set_padding(0, 12)
|
||||||
label.show()
|
label.show()
|
||||||
|
@ -260,6 +265,7 @@ class ProgressDialog(gtk.Dialog):
|
||||||
self.progresstext = label = gtk.Label('')
|
self.progresstext = label = gtk.Label('')
|
||||||
label.set_use_markup(True)
|
label.set_use_markup(True)
|
||||||
label.set_alignment(0.0, 0.0)
|
label.set_alignment(0.0, 0.0)
|
||||||
|
label.set_selectable(True)
|
||||||
label.show()
|
label.show()
|
||||||
vbox.pack_start(label)
|
vbox.pack_start(label)
|
||||||
self.set_task(task)
|
self.set_task(task)
|
||||||
|
@ -273,12 +279,12 @@ FAILURE = 2
|
||||||
CANCELLED = 3
|
CANCELLED = 3
|
||||||
|
|
||||||
class RemuxProgressDialog(ProgressDialog):
|
class RemuxProgressDialog(ProgressDialog):
|
||||||
def __init__(self, parent, start, stop):
|
def __init__(self, parent, start, stop, fromname, toname):
|
||||||
ProgressDialog.__init__(self,
|
ProgressDialog.__init__(self,
|
||||||
"Writing to disk",
|
"Writing to disk",
|
||||||
('Writing the selected segment of your '
|
('Writing the selected segment of <b>%s</b> '
|
||||||
'media file to disk. This may take some '
|
'to <b>%s</b>. This may take some time.'
|
||||||
'time depending on the file size.'),
|
% (fromname, toname)),
|
||||||
'Starting media pipeline',
|
'Starting media pipeline',
|
||||||
parent,
|
parent,
|
||||||
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||||
|
@ -290,7 +296,6 @@ class RemuxProgressDialog(ProgressDialog):
|
||||||
self.set_completed(False)
|
self.set_completed(False)
|
||||||
|
|
||||||
def update_position(self, pos):
|
def update_position(self, pos):
|
||||||
print pos
|
|
||||||
pos = min(max(pos, self.start), self.stop)
|
pos = min(max(pos, self.start), self.stop)
|
||||||
remaining = self.stop - pos
|
remaining = self.stop - pos
|
||||||
minutes = remaining // (gst.SECOND * 60)
|
minutes = remaining // (gst.SECOND * 60)
|
||||||
|
@ -344,6 +349,9 @@ class Remuxer(gst.Pipeline):
|
||||||
assert start >= 0
|
assert start >= 0
|
||||||
assert stop > start
|
assert stop > start
|
||||||
|
|
||||||
|
self.fromuri = fromuri
|
||||||
|
self.touri = touri
|
||||||
|
|
||||||
self.src = gst.element_make_from_uri(gst.URI_SRC, fromuri)
|
self.src = gst.element_make_from_uri(gst.URI_SRC, fromuri)
|
||||||
self.remuxbin = RemuxBin(start, stop)
|
self.remuxbin = RemuxBin(start, stop)
|
||||||
self.sink = gst.element_make_from_uri(gst.URI_SINK, touri)
|
self.sink = gst.element_make_from_uri(gst.URI_SINK, touri)
|
||||||
|
@ -401,8 +409,8 @@ class Remuxer(gst.Pipeline):
|
||||||
pos, duration = pad.query_position(gst.FORMAT_TIME)
|
pos, duration = pad.query_position(gst.FORMAT_TIME)
|
||||||
if pos != gst.CLOCK_TIME_NONE:
|
if pos != gst.CLOCK_TIME_NONE:
|
||||||
self.pdialog.update_position(pos)
|
self.pdialog.update_position(pos)
|
||||||
except gst.QueryError:
|
except:
|
||||||
print 'query failed'
|
# print 'query failed'
|
||||||
pass
|
pass
|
||||||
return True
|
return True
|
||||||
if self._query_id == -1:
|
if self._query_id == -1:
|
||||||
|
@ -433,14 +441,16 @@ class Remuxer(gst.Pipeline):
|
||||||
elif message.type == gst.MESSAGE_WARNING:
|
elif message.type == gst.MESSAGE_WARNING:
|
||||||
print 'warning', message
|
print 'warning', message
|
||||||
elif message.type == gst.MESSAGE_SEGMENT_DONE:
|
elif message.type == gst.MESSAGE_SEGMENT_DONE:
|
||||||
print 'eos, woot', message.src
|
# print 'eos, woot', message.src
|
||||||
self.pdialog.set_task('Finished')
|
name = self.touri
|
||||||
|
if name.startswith('file://'):
|
||||||
|
name = name[7:]
|
||||||
|
self.pdialog.set_task('Finished writing %s' % name)
|
||||||
self.pdialog.update_position(self.stop_time)
|
self.pdialog.update_position(self.stop_time)
|
||||||
self._stop_queries()
|
self._stop_queries()
|
||||||
self.pdialog.set_completed(True)
|
self.pdialog.set_completed(True)
|
||||||
elif message.type == gst.MESSAGE_STATE_CHANGED:
|
elif message.type == gst.MESSAGE_STATE_CHANGED:
|
||||||
if message.src == self:
|
if message.src == self:
|
||||||
print message
|
|
||||||
old, new, pending = message.parse_state_changed()
|
old, new, pending = message.parse_state_changed()
|
||||||
if ((old, new, pending) ==
|
if ((old, new, pending) ==
|
||||||
(gst.STATE_READY, gst.STATE_PAUSED,
|
(gst.STATE_READY, gst.STATE_PAUSED,
|
||||||
|
@ -467,8 +477,10 @@ class Remuxer(gst.Pipeline):
|
||||||
if self.window:
|
if self.window:
|
||||||
# can be None if we are debugging...
|
# can be None if we are debugging...
|
||||||
self.window.set_sensitive(False)
|
self.window.set_sensitive(False)
|
||||||
|
fromname = self.fromuri.split('/')[-1]
|
||||||
|
toname = self.touri.split('/')[-1]
|
||||||
self.pdialog = RemuxProgressDialog(main_window, self.start_time,
|
self.pdialog = RemuxProgressDialog(main_window, self.start_time,
|
||||||
self.stop_time)
|
self.stop_time, fromname, toname)
|
||||||
self.pdialog.show()
|
self.pdialog.show()
|
||||||
self.pdialog.connect('response', lambda w, r: self.response(r))
|
self.pdialog.connect('response', lambda w, r: self.response(r))
|
||||||
|
|
||||||
|
@ -573,7 +585,14 @@ class PlayerWindow(gtk.Window):
|
||||||
self.connect('delete-event', lambda *x: on_delete_event())
|
self.connect('delete-event', lambda *x: on_delete_event())
|
||||||
|
|
||||||
def load_file(self, location):
|
def load_file(self, location):
|
||||||
|
filename = location.split('/')[-1]
|
||||||
|
self.set_title('Cutting %s with blunt instruments' % filename)
|
||||||
self.player.set_location(location)
|
self.player.set_location(location)
|
||||||
|
if self.videowidget.flags() & gtk.REALIZED:
|
||||||
|
self.play_toggled()
|
||||||
|
else:
|
||||||
|
self.videowidget.connect_after('realize',
|
||||||
|
lambda *x: self.play_toggled())
|
||||||
|
|
||||||
def create_ui(self):
|
def create_ui(self):
|
||||||
vbox = gtk.VBox()
|
vbox = gtk.VBox()
|
||||||
|
@ -599,32 +618,33 @@ class PlayerWindow(gtk.Window):
|
||||||
hscale.show()
|
hscale.show()
|
||||||
self.hscale = hscale
|
self.hscale = hscale
|
||||||
|
|
||||||
self.videowidget.connect_after('realize',
|
|
||||||
lambda *x: self.play_toggled())
|
|
||||||
|
|
||||||
table = gtk.Table(2,3)
|
table = gtk.Table(2,3)
|
||||||
table.show()
|
table.show()
|
||||||
vbox.pack_start(table, fill=False, expand=False, padding=6)
|
vbox.pack_start(table, fill=False, expand=False, padding=6)
|
||||||
|
|
||||||
self.pause_image = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PAUSE,
|
self.button = button = gtk.Button(stock=gtk.STOCK_MEDIA_PLAY)
|
||||||
gtk.ICON_SIZE_LARGE_TOOLBAR)
|
|
||||||
self.pause_image.show()
|
|
||||||
self.play_image = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PLAY,
|
|
||||||
gtk.ICON_SIZE_LARGE_TOOLBAR)
|
|
||||||
self.play_image.show()
|
|
||||||
self.button = button = gtk.Button()
|
|
||||||
button.add(self.play_image)
|
|
||||||
button.set_property('can-default', True)
|
button.set_property('can-default', True)
|
||||||
button.set_focus_on_click(False)
|
button.set_focus_on_click(False)
|
||||||
button.show()
|
button.show()
|
||||||
aspect = gtk.AspectFrame(obey_child=False, xalign=0.0)
|
|
||||||
aspect.set_property('shadow_type', gtk.SHADOW_NONE)
|
# problem: play and paused are of different widths and cause the
|
||||||
aspect.show()
|
# window to re-layout
|
||||||
aspect.add(button)
|
# "solution": add more buttons to a vbox so that the horizontal
|
||||||
table.attach(aspect, 0, 1, 0, 2, gtk.EXPAND|gtk.FILL, gtk.EXPAND|gtk.FILL)
|
# width is enough
|
||||||
|
bvbox = gtk.VBox()
|
||||||
|
bvbox.add(button)
|
||||||
|
bvbox.add(gtk.Button(stock=gtk.STOCK_MEDIA_PLAY))
|
||||||
|
bvbox.add(gtk.Button(stock=gtk.STOCK_MEDIA_PAUSE))
|
||||||
|
sizegroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
|
||||||
|
for kid in bvbox.get_children():
|
||||||
|
sizegroup.add_widget(kid)
|
||||||
|
bvbox.show()
|
||||||
|
table.attach(bvbox, 0, 1, 0, 2, gtk.FILL, gtk.FILL)
|
||||||
|
|
||||||
|
# can't set this property before the button has a window
|
||||||
button.set_property('has-default', True)
|
button.set_property('has-default', True)
|
||||||
button.connect('clicked', lambda *args: self.play_toggled())
|
button.connect('clicked', lambda *args: self.play_toggled())
|
||||||
|
|
||||||
self.cutin = cut = TimeControl(self, "Cut in time")
|
self.cutin = cut = TimeControl(self, "Cut in time")
|
||||||
cut.show()
|
cut.show()
|
||||||
table.attach(cut, 1, 2, 0, 1, gtk.EXPAND, 0, 12)
|
table.attach(cut, 1, 2, 0, 1, gtk.EXPAND, 0, 12)
|
||||||
|
@ -633,21 +653,21 @@ class PlayerWindow(gtk.Window):
|
||||||
cut.show()
|
cut.show()
|
||||||
table.attach(cut, 1, 2, 1, 2, gtk.EXPAND, 0, 12)
|
table.attach(cut, 1, 2, 1, 2, gtk.EXPAND, 0, 12)
|
||||||
|
|
||||||
buttonbox = gtk.HButtonBox()
|
button = gtk.Button("_Open other movie...")
|
||||||
buttonbox.set_layout(gtk.BUTTONBOX_END)
|
button.show()
|
||||||
buttonbox.show()
|
button.connect('clicked', lambda *x: self.do_choose_file())
|
||||||
table.attach(buttonbox, 2, 3, 1, 2, 0, 0)
|
table.attach(button, 2, 3, 0, 1, gtk.FILL, gtk.FILL)
|
||||||
|
|
||||||
button = gtk.Button("_Write to disk")
|
button = gtk.Button("_Write to disk")
|
||||||
button.set_property('image',
|
button.set_property('image',
|
||||||
gtk.image_new_from_stock(gtk.STOCK_SAVE_AS,
|
gtk.image_new_from_stock(gtk.STOCK_SAVE_AS,
|
||||||
gtk.ICON_SIZE_BUTTON))
|
gtk.ICON_SIZE_BUTTON))
|
||||||
|
button.connect('clicked', lambda *x: self.do_remux())
|
||||||
button.show()
|
button.show()
|
||||||
buttonbox.pack_start(button, False)
|
table.attach(button, 2, 3, 1, 2, gtk.FILL, gtk.FILL)
|
||||||
|
|
||||||
self.cutin.connect('notify::time', lambda *x: self.check_cutout())
|
self.cutin.connect('notify::time', lambda *x: self.check_cutout())
|
||||||
self.cutout.connect('notify::time', lambda *x: self.check_cutin())
|
self.cutout.connect('notify::time', lambda *x: self.check_cutin())
|
||||||
button.connect('clicked', lambda *x: self.do_remux())
|
|
||||||
|
|
||||||
def do_remux(self):
|
def do_remux(self):
|
||||||
if self.player.is_playing():
|
if self.player.is_playing():
|
||||||
|
@ -658,6 +678,42 @@ class PlayerWindow(gtk.Window):
|
||||||
self.cutin.get_time(), self.cutout.get_time())
|
self.cutin.get_time(), self.cutout.get_time())
|
||||||
r.run(self)
|
r.run(self)
|
||||||
|
|
||||||
|
def do_choose_file(self):
|
||||||
|
if self.player.is_playing():
|
||||||
|
self.play_toggled()
|
||||||
|
chooser = gtk.FileChooserDialog('Choose a movie to cut cut cut',
|
||||||
|
self,
|
||||||
|
buttons=(gtk.STOCK_CANCEL,
|
||||||
|
CANCELLED,
|
||||||
|
gtk.STOCK_OPEN,
|
||||||
|
SUCCESS))
|
||||||
|
chooser.set_local_only(False)
|
||||||
|
chooser.set_select_multiple(False)
|
||||||
|
f = gtk.FileFilter()
|
||||||
|
f.set_name("All files")
|
||||||
|
f.add_pattern("*")
|
||||||
|
chooser.add_filter(f)
|
||||||
|
f = gtk.FileFilter()
|
||||||
|
f.set_name("Ogg files")
|
||||||
|
f.add_pattern("*.ogg") # as long as this is the only thing we
|
||||||
|
# support...
|
||||||
|
chooser.add_filter(f)
|
||||||
|
chooser.set_filter(f)
|
||||||
|
|
||||||
|
prev = self.player.get_location()
|
||||||
|
if prev:
|
||||||
|
chooser.set_uri(prev)
|
||||||
|
|
||||||
|
resp = chooser.run()
|
||||||
|
uri = chooser.get_uri()
|
||||||
|
chooser.destroy()
|
||||||
|
|
||||||
|
if resp == SUCCESS:
|
||||||
|
self.load_file(uri)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def check_cutout(self):
|
def check_cutout(self):
|
||||||
if self.cutout.get_time() <= self.cutin.get_time():
|
if self.cutout.get_time() <= self.cutin.get_time():
|
||||||
pos, dur = self.player.query_position()
|
pos, dur = self.player.query_position()
|
||||||
|
@ -668,16 +724,15 @@ class PlayerWindow(gtk.Window):
|
||||||
self.cutin.set_time(0)
|
self.cutin.set_time(0)
|
||||||
|
|
||||||
def play_toggled(self):
|
def play_toggled(self):
|
||||||
self.button.remove(self.button.child)
|
|
||||||
if self.player.is_playing():
|
if self.player.is_playing():
|
||||||
self.player.pause()
|
self.player.pause()
|
||||||
self.button.add(self.play_image)
|
self.button.set_label(gtk.STOCK_MEDIA_PLAY)
|
||||||
else:
|
else:
|
||||||
self.player.play()
|
self.player.play()
|
||||||
if self.update_id == -1:
|
if self.update_id == -1:
|
||||||
self.update_id = gobject.timeout_add(self.UPDATE_INTERVAL,
|
self.update_id = gobject.timeout_add(self.UPDATE_INTERVAL,
|
||||||
self.update_scale_cb)
|
self.update_scale_cb)
|
||||||
self.button.add(self.pause_image)
|
self.button.set_label(gtk.STOCK_MEDIA_PAUSE)
|
||||||
|
|
||||||
def scale_format_value_cb(self, scale, value):
|
def scale_format_value_cb(self, scale, value):
|
||||||
if self.p_duration == -1:
|
if self.p_duration == -1:
|
||||||
|
@ -737,30 +792,34 @@ class PlayerWindow(gtk.Window):
|
||||||
self.update_scale_cb)
|
self.update_scale_cb)
|
||||||
|
|
||||||
def update_scale_cb(self):
|
def update_scale_cb(self):
|
||||||
|
had_duration = self.p_duration != gst.CLOCK_TIME_NONE
|
||||||
self.p_position, self.p_duration = self.player.query_position()
|
self.p_position, self.p_duration = self.player.query_position()
|
||||||
if self.p_position != gst.CLOCK_TIME_NONE:
|
if self.p_position != gst.CLOCK_TIME_NONE:
|
||||||
value = self.p_position * 100.0 / self.p_duration
|
value = self.p_position * 100.0 / self.p_duration
|
||||||
self.adjustment.set_value(value)
|
self.adjustment.set_value(value)
|
||||||
|
if not had_duration:
|
||||||
|
self.cutin.set_time(0)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def main(args):
|
def main(args):
|
||||||
def usage():
|
def usage():
|
||||||
sys.stderr.write("usage: %s URI-OF-MEDIA-FILE\n" % args[0])
|
sys.stderr.write("usage: %s [URI-OF-MEDIA-FILE]\n" % args[0])
|
||||||
sys.exit(1)
|
return 1
|
||||||
|
|
||||||
w = PlayerWindow()
|
w = PlayerWindow()
|
||||||
|
|
||||||
if len(args) != 2:
|
|
||||||
usage()
|
|
||||||
|
|
||||||
if not gst.uri_is_valid(args[1]):
|
|
||||||
sys.stderr.write("Error: Invalid URI: %s\n" % args[1])
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
w.load_file(args[1])
|
|
||||||
w.show()
|
w.show()
|
||||||
|
|
||||||
|
if len(args) == 1:
|
||||||
|
if not w.do_choose_file():
|
||||||
|
return 1
|
||||||
|
elif len(args) == 2:
|
||||||
|
if not gst.uri_is_valid(args[1]):
|
||||||
|
sys.stderr.write("Error: Invalid URI: %s\n" % args[1])
|
||||||
|
return 1
|
||||||
|
w.load_file(args[1])
|
||||||
|
else:
|
||||||
|
return usage()
|
||||||
|
|
||||||
gtk.main()
|
gtk.main()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Reference in a new issue