1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 | 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.video_area = gtk.DrawingArea()
self.play_button = gtk.Button()
self.info_label = gtk.Label("Not playing")
self.slider = gtk.HScale()
self.button_box = gtk.HBox()
self.button_box.pack_start(self.play_button, False)
self.button_box.pack_start(self.info_label, True, True)
self.main_vbox = gtk.VBox(spacing=6)
self.main_vbox.pack_start(self.video_area, True, True)
self.main_vbox.pack_start(self.slider, False)
self.main_vbox.pack_start(self.button_box, False)
self.main_window.add(self.main_vbox)
self.main_window.connect('destroy', self.on_destroy)
self.video_area.connect('realize', self.on_video_area_realized)
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, 400)
self.playbin = gst.element_factory_make('playbin2')
current_dir = os.path.abspath('.')
self.playbin.set_property('uri', 'file://' + os.path.join(current_dir, 'Hurricane_Connie_1955.ogg'))
self.sink = gst.element_factory_make('xvimagesink')
self.sink.set_property('force-aspect-ratio', True)
self.playbin.set_property('video-sink', self.sink)
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.info_label.set_label("Not playing")
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.info_label.set_label("Playing")
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.info_label.set_label("Paused")
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 on_video_area_realized(self, video_area):
self.sink.set_xwindow_id(self.video_area.window.xid)
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()
|