]> git.plutz.net Git - viper/blob - timeline.py
started basic frameset support
[viper] / timeline.py
1 #encoding: utf-8
2 #Copyright 2009 - 2011 Paul Hänsch
3
4 #This file is part of Viper.
5
6 #Viper is free software: you can redistribute it and/or modify
7 #it under the terms of the GNU General Public License as published by
8 #the Free Software Foundation, either version 3 of the License, or
9 #(at your option) any later version.
10
11 #Viper is distributed in the hope that it will be useful,
12 #but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #GNU General Public License for more details.
15
16 #You should have received a copy of the GNU General Public License
17 #along with Viper.  If not, see <http://www.gnu.org/licenses/>
18
19 from Tkinter import *
20 from vchunk import *
21 from vframeset import *
22 import Pmw
23
24 class Timeline(Frame):
25     """
26     This widget represents a sequence of video chunks.
27
28     It holds a list of chunks and provides an interface to manipulate the order
29     of these chunks. The main control widgets are placed on the VChunk ojects.
30     Properties:
31     subgets       - a dictionary of subordinated widgets 
32     chunks (list) - list of VChunk objects, do not edit this list manually
33                     use add() to add a >chunk< object, the vchunk will be
34                     built and displayed automatically
35     timer (Tk)    - internal timer for regular execution of tasks scheduled by
36                     vchunks
37     """
38
39     def __init__(self, master):
40         """
41         Constructor
42         """
43         Frame.__init__(self, master = master)
44         self.subgets = {}
45         self.chunks = []
46         self.mods = []    # list of chunk modifying objects (filter and effect dialogs)
47         self.view = None  # viewer widget
48         self.basedir = None  #path of project directory, required for framesets
49         self.animChunks = BooleanVar(value = True)
50         tooltips = Pmw.Balloon(self)
51
52         self.subgets['chunklist'] = Pmw.ScrolledFrame(self, usehullsize = 1, 
53                                                       hull_height = 142, hull_width = 800)
54         self.subgets['chunklist'].pack(side=TOP, fill=X)
55         self.subgets['b_PlayAll'] = Button(self, text='Play All', command=self.playall)
56         self.subgets['b_PlayAll'].pack(side=LEFT)
57         self.subgets['b_InvPlay'] = Button(self, text='Invert Play', command=self.invplay)
58         self.subgets['b_InvPlay'].pack(side=LEFT)
59         tooltips.bind(self.subgets['b_PlayAll'],
60                            'Mark all video snippets for playback.')
61         self.subgets['b_MarkAll'] = Button(self, text='Mark All', command=self.markall)
62         self.subgets['b_MarkAll'].pack(side=LEFT)
63         self.subgets['b_InvMark'] = Button(self, text='Invert Mark', command=self.invmark)
64         self.subgets['b_InvMark'].pack(side=LEFT)
65         tooltips.bind(self.subgets['b_MarkAll'],
66                            'Mark all video snippets for filter and effect application.')
67
68         self.subgets['b_info'] = Button(self, text='Video Info', command=self.info)
69         self.subgets['b_info'].pack(side=RIGHT)
70         tooltips.bind(self.subgets['b_info'],
71                            'Show detailed information about the marked video chunks.')
72
73         self.subgets['b_frameset'] = Button(self, text='Make Frameset', command=self.convert,
74                                             state = 'disabled')
75         self.subgets['b_frameset'].pack(side=RIGHT)
76         tooltips.bind(self.subgets['b_frameset'],
77                            'Convert marked video chunks into framesets.\n' +
78                            'This enables you to perform advanced video operations.')
79
80         self.process_schedule()
81
82     def switch_animChunks(self):
83         for chunk in self.chunks:
84             chunk.animate = self.animChunks.get()
85             chunk.chprops()
86
87     def info(self):
88         """
89         Displays a window with information about loaded video files.
90         """
91         win = Tk()
92         frm = LabelFrame(win, text = 'Info')
93         frm.pack(side = TOP, expand = True, fill = BOTH)
94         text = Text(frm, width = 40, height = 10)
95         text.pack(side = LEFT, fill = BOTH, expand = True)
96         scroll = Scrollbar(frm, orient = VERTICAL, command = text.yview)
97         scroll.pack(side = RIGHT, fill = Y, anchor = W)
98         text.config(yscrollcommand = scroll.set)
99         Button(win, command = win.destroy, text = 'OK').pack(side = RIGHT, anchor = N)
100
101         for vc in self.chunks:
102             if vc.marked.get():
103                 text.insert(END, '###=- ' + vc.cget('text') + ':\n####\n')
104                 pkeys = vc.videoprops.keys()
105                 pkeys.sort()
106                 for pkey in pkeys:
107                     text.insert(END, pkey + ':\t')
108                     text.insert(END, vc.videoprops[pkey] + '\n')
109                 text.insert(END, '\n')
110         text.config(state = 'disabled')
111
112     def convert(self):
113         """
114         Converts marked chunks to framesets
115         """
116         for vc in self.chunks:
117             if vc.marked.get():
118                 index = self.chunks.index(vc)
119                 new = VFrameset(self.subgets['chunklist'].interior(),
120                                 vurl = vc.videofile,
121                                )
122                 new.played.set(value = vc.played.get())
123                 new.marked.set(value = vc.marked.get())
124                 new.play()
125                 new.pack(before = vc, side=LEFT)
126                 self.chunks.insert(index, new)
127                 self.chunks.remove(vc)
128                 vc.stop()
129                 vc.destroy()
130
131     def playall(self):
132         """
133         Internal button press execution code
134         """
135         for vc in self.chunks:
136             vc.subgets['c_play'].select()
137
138     def invplay(self):
139         """
140         Internal button press execution code
141         """
142         for vc in self.chunks:
143             vc.subgets['c_play'].toggle()
144
145     def markall(self):
146         """
147         Internal button press execution code
148         """
149         for vc in self.chunks:
150             vc.subgets['c_mark'].select()
151
152     def invmark(self):
153         """
154         Internal button press execution code
155         """
156         for vc in self.chunks:
157             vc.subgets['c_mark'].toggle()
158
159     def process_schedule(self):
160         """
161         Process scheduled events on video chunks.
162
163         This function is internal. Its used to execute actions like 
164         moving and copying of chunks
165         """
166         params = []
167         marked = []
168
169         for vc in self.chunks:
170             if vc.played.get():
171                 params.extend(vc.slave_subcommand())
172             if vc.marked.get():
173                 marked.append(vc)
174
175             if vc.schedule == '':
176                 pass
177             elif vc.schedule == 'delete':
178                 self.chunks.remove(vc)
179                 vc.stop()
180                 vc.destroy()
181             elif vc.schedule == 'copy':
182                 index = self.chunks.index(vc)
183                 new = VChunk(self.subgets['chunklist'].interior(),
184                              file = vc.videofile,
185                              start = vc.start,
186                              frames = vc.frames
187                              )
188                 new.filters = list(vc.filters)
189                 new.played.set(value = vc.played.get())
190                 new.marked.set(value = vc.marked.get())
191                 new.play()
192                 new.pack(before = vc, side=LEFT)
193                 self.chunks.insert(index, new)
194                 vc.schedule = ''
195             elif vc.schedule == 'mv left':
196                 index = self.chunks.index(vc)
197                 if vc != self.chunks[0]:
198                     vc.pack_forget()
199                     self.chunks.remove(vc)
200                     self.chunks.insert(index - 1, vc)
201                     vc.pack(before = self.chunks[index], side = LEFT)
202                 vc.schedule = ''
203             elif vc.schedule == 'mv right':
204                 index = self.chunks.index(vc)
205                 if vc != self.chunks[-1]:
206                     vc.pack_forget()
207                     self.chunks.remove(vc)
208                     self.chunks.insert(index + 1, vc)
209                     vc.pack(after = self.chunks[index], side = LEFT)
210                 vc.schedule = ''
211
212         if self.view != None:
213             self.view.set_playback_params(params)
214         for mod in self.mods:
215             mod.set_chunks(marked)
216
217         self.after(20, self.process_schedule)
218
219     def add(self, file, start = None, frames = None):
220         """
221         Append video chunk to the list
222         """
223         vc = VChunk(self.subgets['chunklist'].interior(),
224                     file = file,
225                     start = start,
226                     frames = frames,
227                     play = self.animChunks.get()
228                     )
229         vc.pack(side = LEFT)
230         self.chunks.append(vc)
231
232     def set_view(self, view):
233         self.view = view
234
235     def set_mods(self, mods):
236         self.mods = mods
237
238     def set_basedir(self, basedir):
239         self.basedir = basedir
240         self.subgets['b_frameset'].config(state = 'normal')
241
242     def get_basedir(self):
243         return self.basedir