bulk commit
[talkcutter.git] / src / mediaplayer.py
1 import os
2 import gst, gtk, gobject
3 import sys
4 import pygtk
5 import gtk
6 import gtk.glade
7 import time
8
9 class mediaplayer(object):
10     PLAY_IMAGE = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON)
11     PAUSE_IMAGE = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_BUTTON)
12
13     def __init__( self ):
14         self.playbin = gst.element_factory_make('playbin2')
15
16         self.bus = self.playbin.get_bus()
17         self.bus.add_signal_watch()
18         self.bus.connect("message::eos", self.on_finish)
19
20         self.spinner.set_range(0, 100)
21         self.spinner.set_increments(1, 10)
22         self.spinner.connect('value-changed', self.on_spinner_change)
23         self.spinner.connect('output', self.on_spinner_output)
24
25         self.seeker.set_range(0, 100)
26         self.seeker.set_increments(1, 10)
27         self.seeker.connect('change-value', self.on_seeker_change)
28         self.seeker.connect('button-press-event', self.on_button_press)
29         self.seeker.connect('button-release-event', self.on_button_release)
30
31         label = gtk.Label()
32         label.set_text('Begin:')
33         self.markers.pack_start(label, True)
34
35         self.begin = gtk.SpinButton()
36         self.begin.connect('output', self.on_spinner_output)
37         self.markers.pack_start(self.begin, True)
38
39         label = gtk.Label()
40         label.set_text('End:')
41         self.markers.pack_start(label, True)
42
43         self.end = gtk.SpinButton()
44         self.end.connect('output', self.on_spinner_output)
45         self.markers.pack_start(self.end, True)
46
47         label = gtk.Label()
48         label.set_text('Length:')
49         self.markers.pack_start(label, True)
50
51         self.length = gtk.SpinButton()
52         self.length.connect('output', self.on_spinner_output)
53         self.markers.pack_start(self.length, True)
54
55         self.markers.show_all()
56
57         self.play_button = gtk.Button()
58         self.image_play = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_BUTTON)
59         self.image_pause = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_BUTTON)
60         self.play_button.set_image(self.PLAY_IMAGE)
61         self.play_button.connect('clicked', self.on_play_clicked)
62         self.bbox.pack_start(self.play_button, False)
63
64         self.begin_button = gtk.Button()
65         self.begin_button.set_image(gtk.image_new_from_stock(gtk.STOCK_GOTO_FIRST, gtk.ICON_SIZE_BUTTON))
66         self.begin_button.connect('clicked', self.on_begin_clicked)
67         self.bbox.pack_start(self.begin_button, False)
68
69         self.end_button = gtk.Button()
70         self.end_button.set_image(gtk.image_new_from_stock(gtk.STOCK_GOTO_LAST, gtk.ICON_SIZE_BUTTON))
71         self.end_button.connect('clicked', self.on_end_clicked)
72         self.bbox.pack_start(self.end_button, False)
73
74         self.bbox.show_all()
75
76         self.is_loaded = False
77         self.is_playing = False
78         self.known_range = False
79         self.lock_slider = 0
80
81     def play(self, uri):
82         self.playbin.set_property('uri', uri)
83         self.playbin.set_state(gst.STATE_PLAYING)
84         self.label.label = 'f';
85         gobject.timeout_add(50, self.update_slider)
86         self.is_playing = True
87         self.is_loaded = True
88         self.known_range = False
89         self.label.set_text(uri)
90
91     def on_finish(self, bus, message):
92         self.playbin.set_state(gst.STATE_PAUSED);
93         self.spinner.set_value(0);
94         self.seeker.set_value(0);
95
96     def on_video_realized(self, sender):
97         self.sink.set_xwindow_id(self.drawingarea.window.xid)
98
99     def get_pos(self):
100         nanosecs, format = self.playbin.query_position(gst.FORMAT_TIME)
101         return float(nanosecs) / gst.SECOND;
102
103     def update_slider(self):
104         if not self.is_playing:
105             return True
106         if self.lock_slider > time.time():
107             return True
108
109         try:
110             if not self.known_range:
111                 duration_nanosecs, format = self.playbin.query_duration(gst.FORMAT_TIME)
112                 if duration_nanosecs > 0:
113                   duration_secs = float(duration_nanosecs) / gst.SECOND
114                   print duration_secs
115                   self.seeker.set_range(0, duration_secs)
116                   self.spinner.set_range(0, duration_secs)
117                   self.begin.set_range(0, duration_secs)
118                   self.end.set_range(0, duration_secs)
119                   self.length.set_range(0, duration_secs)
120                   self.known_range = True
121                   print "Duration: %f" % (duration_secs) 
122
123             value = self.get_pos()
124             self.set_value(value)
125
126         except gst.QueryError:
127             # pipeline must not be ready and does not know position
128             pass
129
130         return True # continue calling every 30 milliseconds
131
132     def set_value(self, value):
133         # block seek handler so we don't seek when we set_value()
134         self.seeker.handler_block_by_func(self.on_seeker_change)
135         self.spinner.handler_block_by_func(self.on_spinner_change)
136
137         #print "Trigger: %f" % (value) 
138
139         self.seeker.set_value(value)
140         self.spinner.set_value(value)
141
142         self.seeker.handler_unblock_by_func(self.on_seeker_change)
143         self.spinner.handler_unblock_by_func(self.on_spinner_change)
144
145     def formatSecondsToMencoder(self, s):
146         ds = s % 1
147         ws = s - ds
148         ds *= 1000
149         s = ws % 60
150         ws -= s
151         m = ws % 3600 / 60
152         ws -= ws % 3600
153         h = ws / 3600
154         return "%02d:%02d:%02d.%03d" % (h, m, s, ds)
155
156     def on_spinner_change(self, element):
157         seek_time_secs = element.get_value()
158         self.mseek(seek_time_secs)
159
160     def on_seeker_change(self, element, a, b):
161         seek_time_secs = element.get_value()
162         self.mseek(seek_time_secs)
163
164     def on_spinner_output(self, element):
165         element.set_text(self.formatSecondsToMencoder(element.get_value()))
166         return True
167
168     def mplay(self):
169         self.playbin.set_state(gst.STATE_PLAYING)
170         self.mseek(self.get_pos())
171
172     def mpause(self):
173         self.playbin.set_state(gst.STATE_PAUSED)
174
175     def mseek(self, seek_time_secs):
176         #print 'seek: %f' % (seek_time_secs)
177         self.set_value(seek_time_secs)
178         self.lock_slider = time.time() + 0.1;
179         self.playbin.seek_simple(gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_KEY_UNIT, seek_time_secs * gst.SECOND)
180
181     def on_button_press(self, element, a):
182         if self.is_playing:
183           self.mpause()
184
185     def on_button_release(self, element, a):
186         if self.is_playing:
187           self.mplay()
188
189     def on_play_clicked(self, element):
190         if self.is_playing:
191           self.mpause()
192           self.play_button.set_image(self.PLAY_IMAGE)
193           self.is_playing = False;
194         else:
195           self.mplay()
196           self.play_button.set_image(self.PAUSE_IMAGE)
197           self.is_playing = True;
198           
199     def on_begin_clicked(self, element):
200         pos = self.get_pos()
201         print 'Begin clicked: %f' % (pos)
202         self.begin.set_value(pos)
203         self.update_length()
204         
205     def on_end_clicked(self, element):
206         pos = self.get_pos()
207         print 'End clicked: %f' % (pos)
208         self.end.set_value(pos)
209         self.update_length()
210     
211     def update_length(self):
212         self.length.set_value(self.end.get_value() - self.begin.get_value())
213