MMX optimizations by Nils Pipenbrinck.
[xiph/unicode.git] / souffleur / Souffleur.py
blob97adb401e0a5a0747e6d524997b4e404c699067b
1 #!/usr/bin/env python
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 #import oggStreams
19 #from gstfile import GstFile
20 from GPlayer import VideoWidget
21 from GPlayer import GstPlayer
22 from Subtitles import Subtitles
23 #from datetime import time
24 import sys
26 from streams import Media
27 from streams import Stream
28 from MediaInfo import MediaInfo
29 from SouffleurXML import ProjectXML
31 try:
32 import pygtk
33 #tell pyGTK, if possible, that we want GTKv2
34 pygtk.require("2.0")
35 except:
36 #Some distributions come with GTK2, but not pyGTK
37 pass
38 try:
39 import gtk
40 import gobject
41 import gtk.glade
42 except:
43 print "You need to install pyGTK or GTKv2 ",
44 print "or set your PYTHONPATH correctly."
45 print "try: export PYTHONPATH=",
46 print "/usr/local/lib/python2.2/site-packages/"
47 sys.exit(1)
48 #now we have both gtk and gtk.glade imported
49 #Also, we know we are running GTK v2
50 import gst
52 class Souffleur:
53 # gladefile=""
54 def __init__(self):
55 """
56 In this init we are going to display the main
57 Souffleur window
58 """
59 gladefile="souffleur.glade"
60 windowname="MAIN_WINDOW"
62 self.update_id = -1
63 self.p_position = gst.CLOCK_TIME_NONE
64 self.p_duration = gst.CLOCK_TIME_NONE
65 self.UPDATE_INTERVAL=100
67 self.Subtitle = None
68 self.Subtitles = []
69 self.curSub = -1
70 self.scroll = 0
71 self.videoWidgetGst = None
72 self.player = None
73 self.t_duration = 0
75 self.media = []
76 self.lastID=0
77 #self.videoWidget=VideoWidget();
78 #gtk.glade.set_custom_handler(self.videoWidget, VideoWidget())
80 #gtk.glade.set_custom_handler(self.custom_handler)
81 self.wTree=gtk.glade.XML (gladefile,windowname)
82 self.gladefile = gladefile
83 # we only have two callbacks to register, but
84 # you could register any number, or use a
85 # special class that automatically
86 # registers all callbacks. If you wanted to pass
87 # an argument, you would use a tuple like this:
88 # dic = { "on button1_clicked" : (self.button1_clicked, arg1,arg2) , ...
89 #dic = { "on_button1_clicked" : self.button1_clicked, \
90 # "gtk_main_quit" : (gtk.mainquit) }
91 dic = { "gtk_main_quit" : (gtk.main_quit),\
92 "on_main_file_quit_activate": (gtk.main_quit), \
93 "on_main_file_open_activate": self.mainFileOpen, \
94 "on_TOOL_PLAY_clicked": self.playerPlay,\
95 "on_TOOL_STOP_clicked": self.playerStop,\
96 "on_MEDIA_ADJUSTMENT_button_press_event": self.buttonPressAdjustment,\
97 "on_MEDIA_ADJUSTMENT_button_release_event": self.buttonReleaseAdjustment,\
98 "on_MEDIA_ADJUSTMENT_change_value": self.changeValueAdjustment,\
99 "on_VIDEO_OUT_PUT_expose_event": self.exposeEventVideoOut,\
100 "on_TOOL_START_clicked": self.cb_setSubStartTime,\
101 "on_TOOL_END_clicked": self.cb_setSubEndTime,\
102 "on_TOOL_SAVE_clicked": self.cb_subChangeSave,\
103 "on_TOOL_DELETE_clicked": self.cb_subDel,\
104 "on_main_file_save_activate": self.cb_onSaveMenu,\
105 "on_main_file_save_as_activate": self.cb_onSaveAsMenu,\
106 "on_main_file_new_activate": self.cb_onNewMenu,\
107 "on_TOOL_FIRST_clicked": self.cb_onToolFirst,\
108 "on_TOOL_LAST_clicked": self.cb_onToolLast,\
109 "on_MAIN_VIEW_STREAMS_activate": self.cb_onStreamsWindow,\
110 "on_MAIN_VIEW_SUBTITLES_activate": self.cb_onSubtitleWindow,\
111 "on_LIST_SUBS_cursor_changed": self.cb_onSubsListSelect}
112 self.wTree.signal_autoconnect (dic)
114 self.windowProjectOpen=None
115 self.windowProjectSO=None
116 self.PFileName=None
117 self.windowMediaOpen=None
118 self.windowStreams=gtk.glade.XML (self.gladefile,"STREAM_WINDOW")
119 dic = {"on_TOOL_DEL_STREAM_clicked": self.cb_delStream,\
120 "on_TOOL_MOD_STREAM_clicked": self.cb_modStream,\
121 "on_TOOL_SAVE_STREAM_clicked": self.cb_saveStream,\
122 "on_TOOL_ADD_STREAM_clicked": self.cb_addNewStream,\
123 "on_STREAM_WINDOW_delete_event": self.cb_StreamWindowDelete}
124 self.windowStreams.signal_autoconnect (dic)
125 ### Setup LIST_STREAMS
126 LIST = self.windowStreams.get_widget("LIST_STREAMS")
127 if LIST:
128 self.streamsTreeStore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_UINT)
129 LIST.set_model(self.streamsTreeStore)
130 cell = gtk.CellRendererText()
131 tvcolumn = gtk.TreeViewColumn('Streams', cell, text = 0)
132 LIST.append_column(tvcolumn)
134 self.windowSubsList=gtk.glade.XML (self.gladefile,"SUBS_LIST")
135 dic = {"on_LIST_SUBS_cursor_changed": self.cb_onSubsListSelect,\
136 "on_SUBS_LIST_delete_event": self.cb_onSubsWindowDelete}
137 self.windowSubsList.signal_autoconnect (dic)
138 SUBLIST = self.windowSubsList.get_widget("LIST_SUBS")
139 if SUBLIST:
140 self.subsListStore = gtk.ListStore(gobject.TYPE_UINT,
141 gobject.TYPE_UINT,
142 gobject.TYPE_STRING)
143 SUBLIST.set_model(self.subsListStore)
144 cell = gtk.CellRendererText()
145 tvcolumn = gtk.TreeViewColumn('Start', cell, text = 0)
146 SUBLIST.append_column(tvcolumn)
147 cell = gtk.CellRendererText()
148 tvcolumn = gtk.TreeViewColumn('End', cell, text = 1)
149 SUBLIST.append_column(tvcolumn)
150 cell = gtk.CellRendererText()
151 tvcolumn = gtk.TreeViewColumn('Text', cell, text = 2)
152 SUBLIST.append_column(tvcolumn)
153 WND=self.windowStreams.get_widget("STREAM_WINDOW")
154 WND.hide()
155 WND=self.windowSubsList.get_widget("SUBS_LIST")
156 WND.hide()
157 ### Main window setup
158 self.videoWidget = self.wTree.get_widget("VIDEO_OUT_PUT")
159 self.adjustment = self.wTree.get_widget("MEDIA_ADJUSTMENT")
160 self.SubEdit = self.wTree.get_widget("VIEW_SUB")
161 self.labelHour = self.wTree.get_widget("LABEL_HOUR")
162 self.labelMin = self.wTree.get_widget("LABEL_MIN")
163 self.labelSec = self.wTree.get_widget("LABEL_SEC")
164 self.labelMSec = self.wTree.get_widget("LABEL_MSEC")
165 self.subStartTime = self.wTree.get_widget("SUB_START_TIME")
166 self.subEndTime = self.wTree.get_widget("SUB_END_TIME")
167 self.playButton = self.wTree.get_widget("TOOL_PLAY")
168 return
169 #==============================================================================
170 def cb_onSubsWindowDelete(self, widget, event):
171 widget.hide()
172 return True
173 #==============================================================================
174 def cb_StreamWindowDelete(self, widget, event):
175 widget.hide()
176 return True
177 #==============================================================================
178 def cb_onSubtitleWindow(self, menu):
179 if self.windowSubsList:
180 WND=self.windowSubsList.get_widget("SUBS_LIST")
181 WND.show()
182 #==============================================================================
183 def cb_onStreamsWindow(self, menu):
184 if self.windowStreams:
185 WND=self.windowStreams.get_widget("STREAM_WINDOW")
186 WND.show()
187 #==============================================================================
188 def cb_onToolLast(self, widget):
189 if self.Subtitle:
190 time = self.Subtitle.subKeys[-1]
191 self.setEditSubtitle(self.Subtitle.getSub(time))
192 self.player.seek(time*1000000)
193 #==============================================================================
194 def cb_onToolFirst(self, widget):
195 if self.Subtitle:
196 time = self.Subtitle.subKeys[0]
197 self.setEditSubtitle(self.Subtitle.getSub(time))
198 self.player.seek(time*1000000)
199 #==============================================================================
200 def getSubtitle(self, source):
201 for i in self.Subtitles:
202 if i.subSource==source:
203 return i
204 return None
205 #==============================================================================
206 def cb_saveStream(self, widget):
207 if not self.windowStreams:
208 return
209 if not self.streamsTreeStore:
210 return
211 TView = self.windowStreams.get_widget("LIST_STREAMS")
212 TSelec = TView.get_selection()
213 TModel, TIter = TSelec.get_selected()
214 if not TIter:
215 return
216 N=TModel.get_value(TIter, 1)
217 mInfo = self.media[N]
218 if "subtitle" in mInfo.MIME:
219 tSubtitle = self.getSubtitle(mInfo.Streams[0].ID)
220 tSubtitle.subSave(mInfo.source, 1)
221 #==============================================================================
222 def cb_modStream(self, widget):
223 if not self.windowStreams:
224 return
225 if not self.streamsTreeStore:
226 return
227 TView = self.windowStreams.get_widget("LIST_STREAMS")
228 TSelec = TView.get_selection()
229 TModel, TIter = TSelec.get_selected()
230 if not TIter:
231 return
232 N=TModel.get_value(TIter, 1)
233 mInfo = self.media[N]
234 if "subtitle" in mInfo.MIME:
235 self.setSubtitle(mInfo.Streams[0].ID)
236 #==============================================================================
237 def setSubtitle(self, source):
238 for i in self.Subtitles:
239 if i.subSource==source:
240 self.Subtitle=i
241 break
242 if self.Subtitle:
243 if (self.windowStreams):
244 WND=self.windowSubsList.get_widget("SUBS_LIST")
245 WND.show()
246 self.subsWindowUpdate()
247 #==============================================================================
248 def updateStreamWindow(self):
249 if not self.streamsTreeStore:
250 return
251 self.streamsTreeStore.clear()
252 for mInfo in self.media:
253 iter = self.streamsTreeStore.append(None)
254 self.streamsTreeStore.set(iter, 0, mInfo.MIME + " ("+mInfo.source+")", 1, self.media.index(mInfo))
255 for i in mInfo.Streams:
256 child = self.streamsTreeStore.append(iter)
257 self.streamsTreeStore.set(child, 0, i.MIME + " ("+i.Name+")", 1, self.media.index(mInfo))
258 #==============================================================================
259 def cb_delStream(self, widget):
260 if not self.windowStreams:
261 return
262 if not self.streamsTreeStore:
263 return
264 TView = self.windowStreams.get_widget("LIST_STREAMS")
265 TSelec = TView.get_selection()
266 TModel, TIter = TSelec.get_selected()
267 if not TIter:
268 return
269 N=TModel.get_value(TIter, 1)
270 del self.media[N]
271 self.updateStreamWindow()
272 #==============================================================================
273 def cb_openMediaCancel(self, widget):
274 if self.windowMediaOpen:
275 WND=self.windowMediaOpen.get_widget("OPEN_MEDIA")
276 WND.hide()
277 #==============================================================================
278 def cb_openMediaOpen(self, widget):
279 WND=self.windowMediaOpen.get_widget("OPEN_MEDIA")
280 FN=WND.get_filename()
281 URI=WND.get_uri()
282 WND.hide()
283 MI = MediaInfo(URI, FN, self.lastID)
284 MI.run()
285 tMedia = MI.getMedia()
286 MI=None
287 self.addMedia(tMedia)
288 #==============================================================================
289 def cb_addNewStream(self, widget):
290 if(self.windowMediaOpen==None):
291 self.windowMediaOpen=gtk.glade.XML (self.gladefile,"OPEN_MEDIA")
292 dic={"on_OPEN_BUTTON_CANCEL_clicked": self.cb_openMediaCancel,\
293 "on_OPEN_BUTTON_OPEN_clicked": self.cb_openMediaOpen }
294 self.windowMediaOpen.signal_autoconnect(dic)
295 else:
296 WND=self.windowMediaOpen.get_widget("OPEN_MEDIA")
297 if not WND:
298 self.windowMediaOpen=None
299 else:
300 WND.show()
301 return
302 #==============================================================================
303 def cb_onNewMenu(self, menu):
304 if self.windowStreams:
305 WND=self.windowStreams.get_widget("STREAM_WINDOW")
306 WND.show()
307 #==============================================================================
308 def setEditSubtitle(self, Sub):
309 if not self.Subtitle:
310 return
311 if Sub == None:
312 if (self.curSub!=-1):
313 BUF=gtk.TextBuffer()
314 BUF.set_text("")
315 self.SubEdit.set_buffer(BUF)
316 self.curSub=-1
317 self.setSubStartTime(0)
318 self.setSubEndTime(0)
319 else:
320 if (Sub.start_time!=self.curSub):
321 BUF=gtk.TextBuffer()
322 BUF.set_text(Sub.text)
323 self.SubEdit.set_buffer(BUF)
324 self.curSub=int(Sub.start_time)
325 self.setSubStartTime(Sub.start_time)
326 self.setSubEndTime(Sub.end_time)
327 #==============================================================================
328 def cb_onSubsListSelect(self, widget):
329 Row=None
330 Selection = widget.get_selection()
331 if Selection==None:
332 return
333 Model, Rows = Selection.get_selected_rows()
334 if Rows != None:
335 Row = Model[Rows[0][0]]
336 if self.Subtitle:
337 Sub = self.Subtitle.subs[Row[0]]
338 self.setEditSubtitle(Sub)
339 if self.player:
340 B=0;
341 if self.player.is_playing():
343 self.play_toggled()
344 real = long(Row[0]) # in ns
345 self.player.seek(real*1000000)
346 # allow for a preroll
347 self.player.get_state(timeout=50*gst.MSECOND) # 50 ms
348 if B==1:
349 self.play_toggled()
350 #==============================================================================
351 def subsWindowUpdate(self):
352 if not self.Subtitle:
353 return
354 if self.windowSubsList:
355 self.subsListStore.clear()
356 for i in self.Subtitle.subKeys:
357 S=self.Subtitle.subs[i]
358 iter = self.subsListStore.append(None)
359 self.subsListStore.set(iter, 0, int(S.start_time),
360 1, int(S.end_time),
361 2, str(S.text))
362 #==============================================================================
363 def saveProject(self):
364 if not self.PFileName:
365 return
366 if self.PFileName[-4:]!=".spf":
367 self.PFileName=self.PFileName+".spf"
368 PXML=ProjectXML()
369 PXML.addHeadInfo("title", "Soufleur development version")
370 PXML.addHeadInfo("desc", "This is version current at development stage.")
371 PXML.addHeadInfo("author", "DarakuTenshi")
372 PXML.addHeadInfo("email", "otaky@ukr.net")
373 PXML.addHeadInfo("info", "Sample of save function")
374 for i in self.media:
375 PXML.addMedia(i)
376 for i in self.Subtitles:
377 PXML.addSubtitle(i)
378 PXML.write(self.PFileName)
379 #==============================================================================
380 def cb_projectSaveOpen(self, widget):
381 WND=self.windowProjectSO.get_widget("SAVE_OPEN_PFILE")
382 self.PFileName=WND.get_filename()
383 self.saveProject()
384 WND.hide()
385 #==============================================================================
386 def cb_projectSaveCancel(self, widget):
387 if(self.windowProjectSO==None): return
388 WND=self.windowProjectSO.get_widget("SAVE_OPEN_PFILE")
389 WND.hide()
390 #==============================================================================
391 def cb_onSaveAsMenu(self, widget):
392 self.PFileName=None
393 self.cb_onSaveMenu(widget)
394 #==============================================================================
395 def cb_onSaveMenu(self, widget):
396 if self.PFileName:
397 self.saveProject()
398 return
399 if(self.windowProjectSO==None):
400 self.windowProjectSO=gtk.glade.XML (self.gladefile,"SAVE_OPEN_PFILE")
401 dic={"on_PROJECT_BUTTON_CANCEL_clicked": self.cb_projectSaveCancel,\
402 "on_PROJECT_BUTTON_OK_clicked": self.cb_projectSaveOpen }
403 self.windowProjectSO.signal_autoconnect(dic)
404 WND=self.windowProjectSO.get_widget("SAVE_OPEN_PFILE")
405 WND.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
406 OKB = self.windowProjectSO.get_widget("PROJECT_BUTTON_OK")
407 OKB.set_label("gtk-save")
408 OKB.set_use_stock(True)
409 Filter=gtk.FileFilter()
410 Filter.set_name("Souffleur project file")
411 Filter.add_pattern("*.spf")
412 WND.add_filter(Filter)
413 else:
414 WND=self.windowProjectSO.get_widget("SAVE_OPEN_PFILE")
415 if(WND==None):
416 self.windowProjectSO=None
417 self.cb_onSaveMenu(widget)
418 else:
419 WND.show()
420 #==============================================================================
421 def cb_subDel(self, widget):
422 if (self.Subtitle != None) and (self.curSub != -1):
423 self.Subtitle.subDel(self.curSub)
424 #==============================================================================
425 def cb_subChangeSave(self, widget):
426 if (self.Subtitle != None):
427 if (self.curSub != -1):
428 BUF = self.SubEdit.get_buffer()
429 TEXT = BUF.get_text(BUF.get_start_iter(), BUF.get_end_iter())
430 self.Subtitle.subs[int(self.curSub)].text = str(TEXT)
431 self.Subtitle.subs[int(self.curSub)].end_time=self.subEndTime.get_value_as_int()
432 if self.Subtitle.subs[int(self.curSub)].start_time!=self.subStartTime.get_value_as_int():
433 newTime=self.subStartTime.get_value_as_int()
434 self.Subtitle.subs[int(self.curSub)].start_time=newTime
435 self.Subtitle.subUpdate(int(self.curSub))
436 self.curSub = newTime
437 #for i in self.Subtitles:
438 # if i.subSource == self.Subtitle.subSource:
439 # self.Subtitles[self.Subtitles.index(i)]=self.Subtitle
440 self.subsWindowUpdate()
441 else:
442 self.subAdd()
443 #==============================================================================
444 def subAdd(self):
445 ST = self.subStartTime.get_value()
446 ET = self.subEndTime.get_value()
447 BUF = self.SubEdit.get_buffer()
448 Text = BUF.get_text(BUF.get_start_iter(), BUF.get_end_iter())
449 if (( ST > 0 ) and ( ET > ST ) and ( Text != "" )):
450 self.Subtitle.subAdd(ST, ET, Text, None, 1)
451 self.curSub = ST
452 #==============================================================================
453 def cb_setSubStartTime(self, widget):
454 self.subStartTime.set_value(self.p_position/1000000)
455 #==============================================================================
456 def cb_setSubEndTime(self, widget):
457 self.subEndTime.set_value(self.p_position/1000000)
458 #==============================================================================
459 def setSubStartTime(self, time):
460 self.subStartTime.set_value(time)
461 #==============================================================================
462 def setSubEndTime(self, time):
463 self.subEndTime.set_value(time)
464 #==============================================================================
465 def exposeEventVideoOut(self, widget, event):
466 if self.videoWidgetGst:
467 self.videoWidgetGst.do_expose_event(event)
468 #==============================================================================
469 def changeValueAdjustment(self, widget, t1, t2):
470 #if (not self.scroll):
471 real = long(self.adjustment.get_value()) # in ns
472 self.player.seek(real)
473 # allow for a preroll
474 self.player.get_state(timeout=50*gst.MSECOND) # 50 ms
476 #==============================================================================
477 def buttonReleaseAdjustment(self, widget, event):
478 self.scroll=0
479 #==============================================================================
480 def buttonPressAdjustment(self, widget, event):
481 self.scroll=1
482 #==============================================================================
483 def playerStop(self, widget):
484 if self.player:
485 if self.player.is_playing():
486 self.play_toggled()
487 self.player.stop()
488 #==============================================================================
489 def playerPlay(self, widget):
490 if self.player:
491 self.play_toggled()
492 #==============================================================================
493 def mainFileOpen(self, widget):
494 if(self.windowProjectOpen==None):
495 self.windowProjectOpen=gtk.glade.XML (self.gladefile,"SAVE_OPEN_PFILE")
496 dic={"on_PROJECT_BUTTON_CANCEL_clicked": self.openFileCancel,\
497 "on_PROJECT_BUTTON_OK_clicked": self.openFileOpen }
498 self.windowProjectOpen.signal_autoconnect(dic)
499 WND=self.windowProjectOpen.get_widget("SAVE_OPEN_PFILE")
500 WND.set_action(gtk.FILE_CHOOSER_ACTION_OPEN)
501 OKB = self.windowProjectOpen.get_widget("PROJECT_BUTTON_OK")
502 OKB.set_label("gtk-open")
503 OKB.set_use_stock(True)
504 Filter=gtk.FileFilter()
505 Filter.set_name("Souffleur project file")
506 Filter.add_pattern("*.spf")
507 WND.add_filter(Filter)
508 else:
509 WND=self.windowProjectOpen.get_widget("SAVE_OPEN_PFILE")
510 if(WND==None):
511 self.windowProjectOpen=None
512 self.mainFileOpen(widget)
513 else:
514 WND.show()
515 return
516 #==============================================================================
517 def openFileCancel(self, widget):
518 if(self.windowProjectOpen==None): return
519 WND=self.windowProjectOpen.get_widget("SAVE_OPEN_PFILE")
520 WND.hide()
521 return
522 #==============================================================================
523 def openFileOpen(self, widget):
524 WND=self.windowProjectOpen.get_widget("SAVE_OPEN_PFILE")
525 self.PFileName=WND.get_filename()
526 WND.hide()
527 PXML=ProjectXML()
528 PXML.load(self.PFileName)
529 for i in PXML.getMedia():
530 self.addMedia(i)
531 self.Subtitles=[]
532 for i in PXML.getSubtitle():
533 self.Subtitles.append(i)
534 if len(self.media)>0:
535 WND=self.windowStreams.get_widget("STREAM_WINDOW")
536 WND.show()
537 return
538 #==============================================================================
539 def addMedia(self, mInfo):
540 if not mInfo:
541 return
542 N=len(self.media)
543 self.media.append(mInfo)
544 self.lastID = mInfo.lastID
545 self.updateStreamWindow()
546 if "subtitle" in mInfo.MIME:
547 tSubtitle = Subtitles()
548 tSubtitle.subLoad(mInfo.source, mInfo.Streams[0].ID)
549 self.Subtitles.append(tSubtitle)
550 else:
551 self.videoWidgetGst=VideoWidget(self.videoWidget)
552 self.player=GstPlayer(self.videoWidgetGst)
553 self.player.set_location("file://"+mInfo.source)
554 if self.videoWidget.flags() & gtk.REALIZED:
555 self.play_toggled()
556 else:
557 self.videoWidget.connect_after('realize',
558 lambda *x: self.play_toggled())
559 return
560 #==============================================================================
561 def play_toggled(self):
562 if self.player.is_playing():
563 self.player.pause()
564 self.playButton.set_stock_id(gtk.STOCK_MEDIA_PLAY)
565 #self.playButton.set_icon_name(gtk.STOCK_MEDIA_PLAY)
566 else:
567 self.player.play()
568 if self.update_id == -1:
569 self.update_id = gobject.timeout_add(self.UPDATE_INTERVAL,
570 self.update_scale_cb)
571 self.playButton.set_stock_id(gtk.STOCK_MEDIA_PAUSE)
572 #==============================================================================
573 def update_scale_cb(self):
574 had_duration = self.p_duration != gst.CLOCK_TIME_NONE
575 self.p_position, self.p_duration = self.player.query_position()
576 if self.p_duration != self.t_duration:
577 self.t_duration = self.p_duration
578 self.adjustment.set_range(0, self.t_duration)
579 tmSec= self.p_position/1000000
580 MSec = tmSec
581 tmSec = tmSec/1000
582 Sec = tmSec%60
583 tmSec = tmSec/60
584 Min = tmSec%60
585 Hour = tmSec/60
586 if self.Subtitle:
587 TText = self.Subtitle.getSub(MSec)
588 if self.player.is_playing():
589 if TText:
590 self.setEditSubtitle(TText)
591 else:
592 self.setEditSubtitle(None)
593 if (self.p_position != gst.CLOCK_TIME_NONE):# and (not self.scroll):
594 value = self.p_position
595 self.adjustment.set_value(value)
596 self.labelHour.set_text("%02d"%Hour)
597 self.labelMin.set_text("%02d"%Min)
598 self.labelSec.set_text("%02d"%Sec)
599 self.labelMSec.set_text("%09d"%MSec)
600 return True
601 #==============================================================================
602 # MAIN:
603 #==============================================================================
604 souffleur=Souffleur()
605 gtk.main()