#! /usr/bin/env python """ This is a gstreamer source element which draws its data from an internal python dictionary variable. Copyright (C) 2006 Scott Shawcroft This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ import pygtk pygtk.require('2.0') import gtk import pango from time_converter import * import clip import cliplist class ScriptView(gtk.TextView): """This class handles both a gtk.textBuffer and a gtk.textView. It wraps all data storage and display functions of clip information.""" def __init__(self,instructions): """ This constructor returns the textview to be packed into the window.""" self.__text = gtk.TextBuffer() self.__text.props.text = instructions gtk.TextView.__init__(self) self.__tag_clip = self.__text.create_tag("clip", underline=pango.UNDERLINE_SINGLE) self.__tag_speaker = self.__text.create_tag("speaker",invisible=True) self.__tag_current = self.__text.create_tag("current",foreground="red") self.set_editable(True) self.set_wrap_mode(gtk.WRAP_WORD) self.props.can_focus = True self.set_buffer(self.__text) self.__tracks = {} self.__last_track = "subtitle-en_US" self.__last_speaker = None self.__current_track = None self.__visible_marks = False self.__ended_previous = True def append(self, clip): """This adds text at the end of the buffer.""" if clip.get_track() == None: clip.set_track(self.__last_track) if not clip.get_speaker(): clip.set_speaker(self.__last_speaker) if not self.__tracks.has_key(clip.get_track()): self.__tracks[clip.get_track()] = cliplist.cliplist() # Make sure current track is valid. if not self.__tracks.has_key(self.__current_track): self.__current_track = clip.get_track() # Add track type specific decorations. if clip.get_track().startswith('subtitle') and not clip.get_speaker()==self.__last_speaker: if self.__tracks[clip.get_track()].length()!=0 or len(self.__tracks.keys())>1: self.__text.insert(self.__text.get_end_iter(),"\n\n") self.__text.insert(self.__text.get_end_iter(),clip.get_speaker()+":\n") elif clip.get_track().startswith('subtitle'): #Handles spaces between clips. self.__text.insert(self.__text.get_end_iter()," ") else: if self.__tracks[clip.get_track()].length()!=0: self.__text.insert(self.__text.get_end_iter(),"\n\n") self.__text.insert(self.__text.get_end_iter(),"Chapter " + str(self.__tracks[clip.get_track()].length()+1) + ": ") speaker = None self.__last_speaker = clip.get_speaker() self.__last_track = clip.get_track() #Avoid duplicate mark if same mark time ended last clip. if self.__tracks[clip.get_track()].length()!=0: last_clip = self.__tracks[clip.get_track()].get_last_clip() if last_clip.get_end()==None: last_clip.set_end(clip.get_start()) if self.__tracks[clip.get_track()].length()==0 or last_clip.get_end() != clip.get_start(): mark = self.__text.create_mark(clip.get_track() + '-' + str(clip.get_start()),self.__text.get_end_iter(),True) mark.set_visible(self.__visible_marks) #Insert and tag speaker string. (will be invisible) if clip.get_speaker(): self.__text.insert_with_tags(self.__text.get_end_iter(),clip.get_speaker(),self.__tag_speaker) #Insert text. self.__text.insert_with_tags(self.__text.get_end_iter(),clip.get_text(),self.__tag_clip) if clip.get_end() != None: mark = self.__text.create_mark(clip.get_track() + '-' + str(clip.get_end()),self.__text.get_end_iter(),True) mark.set_visible(self.__visible_marks) self.__tracks[clip.get_track()].append(clip) def current_clip(self,time): """This function returns the index of the clip in the track. Parameters: time: The time in a clip.""" last_clip = None for current_clip in self.__tracks[self.__current_track]: if time>=current_clip.get_start(): last_clip = current_clip else: break if last_clip != None and time>last_clip.get_end(): return None if last_clip != None: return last_clip if self.__tracks[self.__current_track].get_last_clip()!=last_clip and time<=current_clip.get_end(): return current_clip #Upon error. return -2 def next(self,time): """This returns the beginning timestamp of the next clip after the current time. If the current clip is the end then return None.""" current = self.current_clip(time) if self.__tracks[self.__current_track].next(current): return self.__tracks[self.__current_track].next(current) else: return None def previous(self,time): """This returns the beginning timestamp of the previous clip relative to the given time. If the current clip is the first then return None.""" current = self.current_clip(time) if current!=None and self.__tracks[self.__current_track].previous(current): return self.__tracks[self.__current_track].previous(current) elif current==None: return self.__tracks[self.__current_track].get_last_clip() return clip.clip(0,10,None) def highlight(self,clip): """This highlights the text for the clip with the given start time. Also note that it will remove any other highlights.""" self.__text.remove_tag(self.__tag_current, self.__text.get_start_iter(),self.__text.get_end_iter()) if clip.get_text()!=None and clip.get_text()!="": mark = self.__text.get_mark(clip.get_track() + "-" + str(clip.get_start())) start_iter = self.__text.get_iter_at_mark(mark) if not start_iter.begins_tag(self.__tag_clip): start_iter.forward_to_tag_toggle(self.__tag_clip) end_iter = start_iter.copy() end_iter.forward_to_tag_toggle(self.__tag_clip) self.__text.apply_tag(self.__tag_current, start_iter, end_iter) self.scroll_to_mark(mark,0.1) def export_buffer(self, end="01:30:00.000"): # Returns cliplist. This function now just updates the clip's text for clips in the cliplists. """for track in self.__tracks.keys(): for clip in self.__tracks[track]: iter = self.__text.get_iter_at_mark(self.__text.get_mark(clip.get_track() + "-" + str(clip.get_start()))) #Checks that the next mark is not at the same location. try: count = iter.get_marks().count(self.__text.get_mark(clip.get_track() + "-" + str(clip.get_end()))) except: count = 0 #Checks for content/text between this iter and the next. if clip.get_end(): tmp_iter = iter.copy() tmp_iter.forward_to_tag_toggle(self.__tag_clip) tmp_mark = self.__text.get_mark(clip.get_track() + "-" + str(clip.get_end())) con = self.__text.get_iter_at_mark(tmp_mark).compare(tmp_iter) if con>0 or (con==0 and tmp_iter.ends_tag(self.__tag_clip)): content = True else: content = False else: tmp_iter = iter.copy() tmp_iter.forward_to_tag_toggle(self.__tag_clip) con = self.__text.get_end_iter().compare(tmp_iter) if con>0 or (con==0 and tmp_iter.ends_tag(self.__tag_clip)): content = True else: content = False #If the conditions check out, pull the content. if count<1 and not iter.is_end() and content: if track.startswith("subtitle"): if not iter.begins_tag(self.__tag_speaker): iter.forward_to_tag_toggle(self.__tag_speaker) middle_iter = iter.copy() middle_iter.forward_to_tag_toggle(None) last_iter = middle_iter.copy() speaker = self.__text.get_text(iter,middle_iter) iter = middle_iter else: last_iter = iter.copy() last_iter.forward_to_tag_toggle(None) desc = self.__text.get_text(iter,last_iter) if desc != "/placeholder/": desc = desc.strip("/") clip.set_text(desc)""" return self.__tracks def clear(self): """Clears the data from the scriptview.""" self.__text.delete(self.__text.get_start_iter(),self.__text.get_end_iter()) self.__tracks = {} def scroll_to_bottom(self): self.scroll_to_iter(self.__text.get_end_iter(),0.1) def next_track(self): keys = self.__tracks.keys() new_track = keys.index(self.__current_track)+1 print "Switched to " + keys[new_track%len(keys)] + "." self.__current_track = keys[new_track%len(keys)] return self.__current_track def get_clip_text(self,time,track): """Legacy FIXME""" mark = self.__text.get_mark(track + "-" + str(time)) start_iter = self.__text.get_iter_at_mark(mark) if not start_iter.begins_tag(self.__tag_clip): start_iter.forward_to_tag_toggle(self.__tag_clip) end_iter = start_iter.copy() end_iter.forward_to_tag_toggle(self.__tag_clip) return self.__text.get_text(start_iter, end_iter) def get_all_text(self): """Returns all displayed text from the buffer.""" return self.__text.get_text(self.__text.get_start_iter(),self.__text.get_end_iter(),False)