2 #Copyright 2009 Paul Hänsch
4 #This file is part of Viper.
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.
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.
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/>
26 class ExportDialog(Tk):
28 Dialog Window for exporting a video.
30 This dialog provides handles for the whole video export engine,
31 including plugin support for codec configuration plugins.
32 The actual video encoder will be executed by this dialog.
35 def __init__(self, commands = []):
39 "Commands" is a list of mplayer subcommand lists for playing the video chunks.
40 The very same subcommands are given to the video encoder.
44 self.title('Viper Export')
48 self.commands = commands
55 self.subgets['f_filename'] = LabelFrame(self, text = 'Filename:')
56 self.subgets['f_filename'].pack( side = TOP, expand = True, fill = X)
57 self.subgets['b_filename'] = Button(self.subgets['f_filename'],
58 text = 'Select', command = self.select_file)
59 self.subgets['b_filename'].pack( side = LEFT )
60 self.subgets['e_filename'] = Entry(self.subgets['f_filename'], width = 64)
61 self.subgets['e_filename'].pack( side = LEFT, expand = True, fill = X)
63 self.subgets['f_actions'] = Frame(self)
64 self.subgets['f_actions'].pack( side = BOTTOM, expand = True, fill = X)
65 self.subgets['b_encode'] = Button(self.subgets['f_actions'], text = 'Encode!',
66 command = self.encode)
67 self.subgets['b_encode'].pack( side = RIGHT)
68 self.subgets['b_store'] = Button(self.subgets['f_actions'], text = 'Store Defaults',
69 command = self.store, state = 'disabled')
70 self.subgets['b_store'].pack( side = RIGHT)
72 self.subgets['f_vcodec'] = LabelFrame(self, text = 'Video Codec')
73 self.subgets['f_vcodec'].pack( side = BOTTOM, expand = True, fill = X)
74 self.subgets['lb_vcodec'] = Listbox(self.subgets['f_vcodec'], height = 5, width = 10)
75 self.subgets['lb_vcodec'].pack(side = LEFT)
76 self.subgets['sb_vcodec'] = Scrollbar(self.subgets['f_vcodec'], orient = VERTICAL,
77 command = self.subgets['lb_vcodec'].yview)
78 self.subgets['lb_vcodec'].config(yscrollcommand = self.subgets['sb_vcodec'].set)
79 self.subgets['sb_vcodec'].pack( side = LEFT, fill = Y)
80 self.subgets['cfg_vcodec'] = None
82 self.subgets['f_acodec'] = LabelFrame(self, text = 'Audio Codec')
83 self.subgets['f_acodec'].pack( side = BOTTOM, expand = True, fill = X)
84 self.subgets['lb_acodec'] = Listbox(self.subgets['f_acodec'], height = 5, width = 10)
85 self.subgets['lb_acodec'].pack(side = LEFT)
86 self.subgets['sb_acodec'] = Scrollbar(self.subgets['f_acodec'], orient = VERTICAL,
87 command = self.subgets['lb_acodec'].yview)
88 self.subgets['lb_acodec'].config(yscrollcommand = self.subgets['sb_acodec'].set)
89 self.subgets['sb_acodec'].pack( side = LEFT, fill = Y)
90 self.subgets['cfg_acodec'] = None
92 self.subgets['f_container'] = LabelFrame(self, text = 'Container Format')
93 self.subgets['f_container'].pack( side = BOTTOM, expand = True, fill = X)
94 self.subgets['lb_container'] = Listbox(self.subgets['f_container'], height = 5, width = 10)
95 self.subgets['lb_container'].pack(side = LEFT)
96 self.subgets['sb_container'] = Scrollbar(self.subgets['f_container'], orient = VERTICAL,
97 command = self.subgets['lb_container'].yview)
98 self.subgets['lb_container'].config(yscrollcommand = self.subgets['sb_container'].set)
99 self.subgets['sb_container'].pack( side = LEFT, fill = Y)
100 self.subgets['cfg_container'] = None
107 The method executed when the 'Encode' button is pressed.
109 This will initialize the video encoder and build the status window.
111 command = ['mencoder']
114 for cmd in self.commands:
117 if self.subgets['e_filename'].get() != '':
118 command.extend(['-o', self.subgets['e_filename'].get()])
120 command.extend(['-o', tkFileDialog.asksaveasfilename()])
121 if self.subgets['cfg_container'] != None:
122 command.extend(self.subgets['cfg_container'].subcommand())
124 command.extend(['-of','avi'])
125 if self.subgets['cfg_vcodec'] != None:
126 command.extend(self.subgets['cfg_vcodec'].subcommand())
128 command.extend(['-ovc','copy'])
129 if self.subgets['cfg_acodec'] != None:
130 command.extend(self.subgets['cfg_acodec'].subcommand())
132 command.extend(['-oac','copy'])
134 self.encoder = os.popen2(command)
136 self.subgets['enc_win'] = Tk()
137 self.subgets['enc_win'].title('Encoding ' + self.subgets['e_filename'].get())
138 self.enclabel = Label(self.subgets['enc_win'], width = 64, height = 3)
139 self.enclabel.pack( side = TOP, expand = True, fill = X)
140 self.subgets['enc_b_exit'] = Button(self.subgets['enc_win'],
142 command = self.subgets['enc_win'].destroy)
143 self.subgets['enc_b_exit'].pack( side = BOTTOM, anchor = E )
146 threading.Thread( target = self.encstat ).start()
147 self.subgets['enc_win'].mainloop()
151 Internal methos for providing the status display.
153 This methos is executed in its own thread to read the mencoder
154 status line and display it in the encoding window.
155 It is possible to rewrite it to display a status bar instead.
162 while char != '' and line[-1] != '\r' and line[-1] != '\n':
163 char = self.encoder[1].read(1)
165 self.enclabel.config( text = line.strip() )
166 self.enclabel.config( text = 'Ready' )
168 print 'Reading from pipe impossible'
169 self.enclabel.config( text = 'Ready' )
170 self.subgets['enc_b_exit'].configure(text = 'Close Window')
175 This method is executed when the "Store" butten is pressed.
177 It will store the codec configuration. It is not yet implemented.
181 def select_plugin(self):
185 This method is regularly called to display the configuration dialog of a
186 selected codec plugin.
188 if self.subgets['lb_container'].curselection() != ():
189 c_plugin = int(self.subgets['lb_container'].curselection()[0])
190 if self.subgets['cfg_container'] != self.container[c_plugin]:
191 if self.subgets['cfg_container'] != None:
192 self.subgets['cfg_container'].pack_forget()
193 self.subgets['cfg_container'] = self.container[c_plugin]
194 self.subgets['cfg_container'].pack(side = LEFT, expand = True, fill = BOTH)
196 if self.subgets['lb_vcodec'].curselection() != ():
197 v_plugin = int(self.subgets['lb_vcodec'].curselection()[0])
198 if self.subgets['cfg_vcodec'] != self.vcodec[v_plugin]:
199 if self.subgets['cfg_vcodec'] != None:
200 self.subgets['cfg_vcodec'].pack_forget()
201 self.subgets['cfg_vcodec'] = self.vcodec[v_plugin]
202 self.subgets['cfg_vcodec'].pack(side = LEFT, expand = True, fill = BOTH)
204 if self.subgets['lb_acodec'].curselection() != ():
205 a_plugin = int(self.subgets['lb_acodec'].curselection()[0])
206 if self.subgets['cfg_acodec'] != self.acodec[a_plugin]:
207 if self.subgets['cfg_acodec'] != None:
208 self.subgets['cfg_acodec'].pack_forget()
209 self.subgets['cfg_acodec'] = self.acodec[a_plugin]
210 self.subgets['cfg_acodec'].pack(side = LEFT, expand = True, fill = BOTH)
212 self.after(50, self.select_plugin)
214 def select_file(self):
216 Bring up the file selection dialog.
218 self.subgets['e_filename'].insert(0, tkFileDialog.asksaveasfilename())
220 def load_plugins(self):
222 Load all codec plugins from plugin directory.
224 sys.path.insert(0, 'plugins/')
225 for plugin in os.listdir(sys.path[0]):
226 if plugin[-3:] == '.py':
227 __import__(plugin[:-3], None, None, ['*'])
229 for c_class in C_Plugin.__subclasses__():
230 self.container.append(c_class(self.subgets['f_container']))
231 for c_class in self.container:
232 if c_class.is_available():
233 self.subgets['lb_container'].insert(END, c_class.name())
235 for a_class in A_Plugin.__subclasses__():
236 self.acodec.append(a_class(self.subgets['f_acodec']))
237 for a_class in self.acodec:
238 if a_class.is_available():
239 self.subgets['lb_acodec'].insert(END, a_class.name())
241 for v_class in V_Plugin.__subclasses__():
242 self.vcodec.append(v_class(self.subgets['f_vcodec']))
243 for v_class in self.vcodec:
244 if v_class.is_available():
245 self.subgets['lb_vcodec'].insert(END, v_class.name())
247 def export(chunklist):
249 Easy to call export function.
251 Calling this will build and handle the whole dialog.
257 enclist.append(vc.slave_subcommand())
259 diag = ExportDialog(commands = enclist)