]> git.plutz.net Git - viper/blob - main.py
implemeted most basic cropping controls
[viper] / main.py
1 #!/usr/bin/python
2 #encoding: utf-8
3
4 # Viper - Video In Python Editing Reptile, a video editor
5 # Copyright 2009 - 2011 Paul Hänsch
6 #
7 # This file is part of Viper.
8 #
9 # Viper is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # Viper is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with Viper.  If not, see <http://www.gnu.org/licenses/>
21
22 from Tkinter import *
23 from timeline import *
24 from videoview import *
25 from filters import *
26 from effects import *
27 from pysqlite2 import dbapi2 as sqlite
28 import tkFileDialog
29 import fileExport
30 import Pmw
31 import os
32
33 class Main(Tk):
34     """
35     Build main window
36     """
37
38     def __init__(self):
39         Tk.__init__(self)
40         self.subgets = {}
41         self.protocol('WM_DELETE_WINDOW', self.quit)
42         self.title('Viper')
43
44         upper = Frame(self, height = 300)
45         upper.pack(side = TOP, expand = True, fill = BOTH)
46
47         self.subgets['menubar'] = Menu(self)
48         self.config(menu = self.subgets['menubar'])
49         self.subgets['timeline'] = Timeline(self)
50         self.subgets['timeline'].pack(fill = X, side = BOTTOM, anchor = S)
51         self.subgets['mainview'] = VideoView(upper)
52         self.subgets['mainview'].place( relx = .55, rely = 0, relwidth = .45, relheight = 1)
53         self.subgets['editbook'] = Pmw.NoteBook(upper)
54         self.subgets['editbook'].place( relx = 0, rely = 0, relwidth = .55, relheight = 1)
55         self.subgets['filtertab'] = self.subgets['editbook'].add('Filters')
56         self.subgets['effecttab'] = self.subgets['editbook'].add('Effects')
57         self.subgets['filterdiag'] = FilterDiag( self.subgets['filtertab'] )
58         self.subgets['filterdiag'].pack( expand = True, fill = BOTH)
59         self.subgets['effectdiag'] = EffectDiag( self.subgets['effecttab'] )
60         self.subgets['effectdiag'].pack( expand = True, fill = BOTH)
61
62         self.subgets['timeline'].set_view(self.subgets['mainview'])
63         self.subgets['timeline'].set_mods([self.subgets['filterdiag'],
64                                            self.subgets['effectdiag']
65                                            ])
66
67         self.build_menu()
68
69     def build_menu(self):
70         """
71         Deploy menu bar
72         """
73
74         file_menu = Menu()
75         file_menu.add_command(label = 'Open Project', command = self.open_project)
76         file_menu.add_command(label = 'Save Project', command = self.save_project)
77         file_menu.add_command(label = 'Save Project As...', command = self.named_save_project)
78         file_menu.add_separator()
79         file_menu.add_command(label = 'Import Video', command = self.open_video)
80         file_menu.add_command(label = 'Export Video', command = self.export_video)
81         file_menu.add_separator()
82         file_menu.add_command(label = 'Quit', command = self.quit)
83
84
85         view_menu = Menu()
86         view_menu.add_checkbutton(label = 'Animate Chunks',
87                                   variable = self.subgets['timeline'].animChunks,
88                                   command = self.subgets['timeline'].switch_animChunks)
89
90         self.subgets['menubar'].add_cascade(label='File', menu = file_menu)
91         self.subgets['menubar'].add_cascade(label='View', menu = view_menu)
92         self.subgets['menubar'].add_command(label='Help')
93
94     def m_animChunks(self):
95         pass
96
97     def save_project(self):
98         """
99         Save a project to project directory
100
101         call named_save_project() if no
102         project directory is set yet
103         """
104         if self.subgets['timeline'].get_basedir() == None:
105             self.named_save_project()
106         else:
107             savedir = self.subgets['timeline'].get_basedir()
108             try: os.unlink(savedir + '/description.sqlite')
109             except: pass
110
111             dbcon = sqlite.connect(savedir + '/description.sqlite')
112             dbcur =  dbcon.cursor()
113             dbcur.execute('CREATE TABLE chunks (iorder INTEGER PRIMARY KEY, filename TEXT, start REAL, frames INTEGER, played INTEGER, marked BOOLEAN);')
114             dbcur.execute('CREATE TABLE filters (iorder INTEGER PRIMARY KEY, chunk INTEGER, FOREIGN KEY (chunk) REFERENCES chunks (iorder));')
115             dbcur.execute('CREATE TABLE filter_lines (iorder INTEGER PRIMARY KEY, line TEXT, filter INTEGER, FOREIGN KEY (filter) REFERENCES filters (iorder));')
116             for chunk in self.subgets['timeline'].chunks:
117                 chunk.store(dbcur)
118     
119             dbcur.close()
120             dbcon.commit()
121             dbcon.close()
122
123     def named_save_project(self):
124         """
125         Ask for directory to save to (and save project)
126         """
127         savedir = tkFileDialog.asksaveasfilename(filetypes = [('Viper Project Directory', '*.vpd')])
128         os.makedirs(savedir)
129         self.subgets['timeline'].set_basedir(savedir)
130         self.save_project()
131
132     def open_project(self):
133         """
134         Load a previously saved project
135         (includes Open-Dialog)
136         """
137
138         opendir = tkFileDialog.askopenfilename(filetypes = [('Project Description', '*/description.sqlite')])
139         self.subgets['timeline'].set_basedir(opendir[0:-19])
140
141         for chunk in self.subgets['timeline'].chunks: chunk.delete()
142
143         dbcon = sqlite.connect(opendir)
144         dbcur = dbcon.cursor()
145
146         dbcur.execute('SELECT iorder, filename, start, frames, played, marked ' +
147                       'FROM chunks ORDER BY iorder;')
148         for vc in dbcur.fetchall():
149             self.subgets['timeline'].add(file = vc[1], start = vc[2], frames = vc[3])
150             if vc[4] == 1: self.subgets['timeline'].chunks[-1].played.set(True)
151             else: self.subgets['timeline'].chunks[-1].played.set(False)
152             if vc[5] == 1: self.subgets['timeline'].chunks[-1].marked.set(True)
153             else: self.subgets['timeline'].chunks[-1].marked.set(False)
154             self.subgets['timeline'].chunks[-1].load_filters(dbcur, vc[0])
155
156     def export_video(self):
157         """
158         Call export dialog
159         """
160         for vc in self.subgets['timeline'].chunks:
161             vc.stop()        
162         fileExport.export(self.subgets['timeline'].chunks)
163
164     def open_video(self):
165         """
166         Import video files
167         """
168
169         filetypes = [('3GP Cell Phone Video', '*.3gp'),
170                      ('Advanced Systems Format', '*.asf'),
171                      ('Advanced Video Codec High Definition', '*.avchd'),
172                      ('Audio Video Interleave', '*.avi'),
173                      ('Digital Video (Tape/Disc)', '*.dv'),
174                      ('DVD Track', '*.vob'),
175                      ('Flash Video', '*.flv *.swf'),
176                      ('Matroska', '*.mkv *.MKV'),
177                      ('Moving Pictures Experts Group (MPEG)', '*.mpe *.mpeg *.mpg'),
178                      ('MPEG 1', '*.m1v *.mp1 *.mpg1'),
179                      ('MPEG 2', '*.m2v *.mp2 *.mpg2'),
180                      ('MPEG 4', '*.m4v *.mp4 *.mpg4'),
181                      ('Ogg Media Stream', '*.ogg *.ogm'),
182                      ('Quake 3', '*.roq'),
183                      ('Quick Time', '*.mov'),
184                      ('Real Media', '*.rm'),
185                      ('Windows Media Video', '*.wmv'),
186                      ('Undefined', '*.flic *.vid *.video'),
187                      ]
188         mimes = ''
189         typelist = []
190         for type in filetypes:
191             typelist.append((type[0], type[1] + ' ' + type[1].upper()))
192             mimes += ' ' + type[1]
193
194         typelist.insert(0, ('All known Video File Types', mimes))
195         typelist.append(('All Types', '*'))
196         files = tkFileDialog.askopenfilenames(parent = self,
197                                               title = 'Import Video',
198                                               filetypes = typelist
199                                               )
200         for file in files: self.subgets['timeline'].add(file)
201
202     def quit(self):
203         """
204         Gracefully terminate the program
205         """
206         self.subgets['mainview'].stop_video()
207         if not self.subgets['mainview'].attached_view:
208             self.subgets['mainview'].attach_view()
209         for chunk in self.subgets['timeline'].chunks:
210             chunk.stop()
211         self.after(50, self.destroy)
212
213 win = Main()
214 #win.wm_geometry("800x600")
215 win.mainloop()