Development Team/Almanac/GStreamer: Difference between revisions
No edit summary |
|||
| Line 143: | Line 143: | ||
self.gplayWin.resize( 300, 400 ) | self.gplayWin.resize( 300, 400 ) | ||
self.gplayWin.show_all( ) | self.gplayWin.show_all( ) | ||
</pre> | |||
=== How can I add play/pause buttons and a scrubber to my audio or video? === | |||
<pre> | |||
import gtk | |||
import pygtk | |||
pygtk.require('2.0') | |||
import pygst | |||
pygst.require('0.10') | |||
import gst | |||
import gst.interfaces | |||
import gobject | |||
import sugar.graphics.style | |||
class GScrub(gtk.Window): | |||
def __init__(self, gplay, playImg, pauseImg): | |||
gtk.Window.__init__(self) | |||
self._gplay = gplay | |||
self._playImg = playImg | |||
self._pauseImg = pauseImg | |||
self.UPDATE_INTERVAL = 500 | |||
self.UPDATE_SCALE_ID = 0 | |||
self.CHANGED_ID = 0 | |||
self.was_playing = False | |||
self.p_position = gst.CLOCK_TIME_NONE | |||
self.p_duration = gst.CLOCK_TIME_NONE | |||
self.hbox = gtk.HBox() | |||
self.hbox.modify_bg( gtk.STATE_NORMAL, sugar.graphics.style.COLOR_BLACK.get_gdk_color() ) | |||
self.hbox.modify_bg( gtk.STATE_INSENSITIVE, sugar.graphics.style.COLOR_BLACK.get_gdk_color() ) | |||
self.add( self.hbox ) | |||
self.button = gtk.Button() | |||
buttBox = gtk.EventBox() | |||
buttBox.add(self.button) | |||
buttBox.modify_bg( gtk.STATE_NORMAL, sugar.graphics.style.COLOR_BLACK.get_gdk_color() ) | |||
self.button.set_image( self._playImg ) | |||
self.button.set_property('can-default', True) | |||
self.button.set_relief(gtk.RELIEF_NONE) | |||
self.button.set_size_request( 55, 55 ) | |||
buttBox.set_size_request( 55, 55 ) | |||
self.button.show() | |||
buttBox.modify_bg( gtk.STATE_NORMAL, sugar.graphics.style.COLOR_BLACK.get_gdk_color() ) | |||
self.button.modify_bg( gtk.STATE_ACTIVE, sugar.graphics.style.COLOR_BLACK.get_gdk_color() ) | |||
self.button.connect('clicked', self._buttonClickedCb) | |||
self.hbox.pack_start(buttBox, expand=False) | |||
self.adjustment = gtk.Adjustment(0.0, 0.00, 100.0, 0.1, 1.0, 1.0) | |||
self.hscale = gtk.HScale(self.adjustment) | |||
self.hscale.set_draw_value(False) | |||
self.hscale.set_update_policy(gtk.UPDATE_CONTINUOUS) | |||
hscaleBox = gtk.EventBox() | |||
hscaleBox.modify_bg( gtk.STATE_NORMAL, sugar.graphics.style.COLOR_BLACK.get_gdk_color() ) | |||
hscaleBox.add( self.hscale ) | |||
self.hscale.connect('button-press-event', self._scaleButtonPressCb) | |||
self.hscale.connect('button-release-event', self._scaleButtonReleaseCb) | |||
self.hbox.pack_start(hscaleBox, expand=True) | |||
def removeCallbacks( self ): | |||
if (self.UPDATE_SCALE_ID != 0): | |||
gobject.source_remove(self.UPDATE_SCALE_ID) | |||
self.UPDATE_SCALE_ID = 0 | |||
if (self.CHANGED_ID != 0): | |||
gobject.source_remove(self.CHANGED_ID) | |||
self.CHANGED_ID = 0 | |||
def reset(self): | |||
self.adjustment.set_value(0) | |||
def _buttonClickedCb(self, widget): | |||
self.play_toggled() | |||
def set_button_play(self): | |||
self.button.set_image(self._playImg) | |||
def set_button_pause(self): | |||
self.button.set_image(self._pauseImg) | |||
def play_toggled(self): | |||
self.p_position, self.p_duration = self._gplay.queryPosition() | |||
if (self.p_position == self.p_duration): | |||
self._gplay.seek(0) | |||
self._gplay.pause() | |||
if self._gplay.is_playing(): | |||
self._gplay.pause() | |||
self.set_button_play() | |||
else: | |||
#if self._gplay.error: | |||
# #todo: check if we have "error", and also to disable everything | |||
# self.button.set_disabled() | |||
#else: | |||
self.doPlay() | |||
def doPlay(self): | |||
self._gplay.play() | |||
if self.UPDATE_SCALE_ID == 0: | |||
self.UPDATE_SCALE_ID = gobject.timeout_add(self.UPDATE_INTERVAL, self._updateScaleCb) | |||
self.set_button_pause() | |||
def _scaleButtonPressCb(self, widget, event): | |||
#self.button.set_sensitive(False) | |||
self.was_playing = self._gplay.is_playing() | |||
if self.was_playing: | |||
self._gplay.pause() | |||
# don't timeout-update position during seek | |||
if self.UPDATE_SCALE_ID != 0: | |||
gobject.source_remove(self.UPDATE_SCALE_ID) | |||
self.UPDATE_SCALE_ID = 0 | |||
# make sure we get changed notifies | |||
if self.CHANGED_ID == 0: | |||
self.CHANGED_ID = self.hscale.connect('value-changed', self._scaleValueChangedCb) | |||
def _scaleButtonReleaseCb(self, widget, event): | |||
# see seek.cstop_seek | |||
widget.disconnect(self.CHANGED_ID) | |||
self.CHANGED_ID = 0 | |||
#self.button.set_sensitive(True) | |||
if self.was_playing: | |||
self._gplay.play() | |||
if self.UPDATE_SCALE_ID != 0: | |||
pass | |||
#print('Had a previous update timeout id') | |||
else: | |||
self.UPDATE_SCALE_ID = gobject.timeout_add(self.UPDATE_INTERVAL, self._updateScaleCb) | |||
def _scaleValueChangedCb(self, scale): | |||
real = long(scale.get_value() * self.p_duration / 100) # in ns | |||
self._gplay.seek(real) | |||
# allow for a preroll | |||
self._gplay.get_state(timeout=50*gst.MSECOND) # 50 ms | |||
def _updateScaleCb(self): | |||
self.p_position, self.p_duration = self._gplay.queryPosition() | |||
if self.p_position != gst.CLOCK_TIME_NONE: | |||
value = self.p_position * 100.0 / self.p_duration | |||
if (value > 99): | |||
value = 99 | |||
elif (value < 0): | |||
value = 0 | |||
self.adjustment.set_value(value) | |||
if self._gplay.is_playing() and (self.p_position == self.p_duration): | |||
self._gplay.pause() | |||
self.set_button_play() | |||
return True | |||
</pre> | </pre> | ||