Some vague sort of progress.
[dcpomatic.git] / src / tools / dvdomatic.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <iostream>
21 #include <boost/filesystem.hpp>
22 #include "wx/film_viewer.h"
23 #include "wx/film_editor.h"
24 #ifndef DVDOMATIC_DISABLE_PLAYER
25 #include "wx/film_player.h"
26 #endif
27 //#include "gtk/job_manager_view.h"
28 //#include "gtk/config_dialog.h"
29 //#include "gtk/gpl.h"
30 //#include "gtk/job_wrapper.h"
31 //#include "gtk/dvd_title_dialog.h"
32 //#include "gtk/gtk_util.h"
33 #include "lib/film.h"
34 #include "lib/format.h"
35 #include "lib/config.h"
36 #include "lib/filter.h"
37 #include "lib/util.h"
38 #include "lib/scaler.h"
39 #include "lib/exceptions.h"
40
41 using namespace std;
42 using namespace boost;
43
44 static FilmEditor* film_editor = 0;
45 static FilmViewer* film_viewer = 0;
46
47 #if 0
48
49 static Gtk::Window* window = 0;
50 #ifndef DVDOMATIC_DISABLE_PLAYER
51 static FilmPlayer* film_player = 0;
52 #endif
53 static Film* film = 0;
54
55 static void set_menu_sensitivity ();
56
57 class FilmChangedDialog : public Gtk::MessageDialog
58 {
59 public:
60         FilmChangedDialog ()
61                 : Gtk::MessageDialog ("", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE)
62         {
63                 stringstream s;
64                 s << "Save changes to film \"" << film->name() << "\" before closing?";
65                 set_message (s.str ());
66                 add_button ("Close _without saving", Gtk::RESPONSE_NO);
67                 add_button ("_Cancel", Gtk::RESPONSE_CANCEL);
68                 add_button ("_Save", Gtk::RESPONSE_YES);
69         }
70 };
71
72 bool
73 maybe_save_then_delete_film ()
74 {
75         if (!film) {
76                 return false;
77         }
78                         
79         if (film->dirty ()) {
80                 FilmChangedDialog d;
81                 switch (d.run ()) {
82                 case Gtk::RESPONSE_CANCEL:
83                         return true;
84                 case Gtk::RESPONSE_YES:
85                         film->write_metadata ();
86                         break;
87                 case Gtk::RESPONSE_NO:
88                         return false;
89                 }
90         }
91         
92         delete film;
93         film = 0;
94         return false;
95 }
96
97 void
98 file_new ()
99 {
100         Gtk::FileChooserDialog c (*window, "New Film", Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER);
101 #ifdef DVDOMATIC_WINDOWS        
102         c.set_current_folder (g_get_user_data_dir ());
103 #endif  
104         c.add_button ("_Cancel", Gtk::RESPONSE_CANCEL);
105         c.add_button ("C_reate", Gtk::RESPONSE_ACCEPT);
106
107         int const r = c.run ();
108         if (r == Gtk::RESPONSE_ACCEPT) {
109                 if (maybe_save_then_delete_film ()) {
110                         return;
111                 }
112                 film = new Film (c.get_filename ());
113 #if BOOST_FILESYSTEM_VERSION == 3               
114                 film->set_name (filesystem::path (c.get_filename().c_str()).filename().generic_string());
115 #else           
116                 film->set_name (filesystem::path (c.get_filename().c_str()).filename());
117 #endif          
118                 film_viewer->set_film (film);
119                 film_editor->set_film (film);
120                 set_menu_sensitivity ();
121         }
122 }
123
124 void
125 file_open ()
126 {
127         Gtk::FileChooserDialog c (*window, "Open Film", Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
128 #ifdef DVDOMATIC_WINDOWS        
129         c.set_current_folder (g_get_user_data_dir ());
130 #endif  
131         c.add_button ("_Cancel", Gtk::RESPONSE_CANCEL);
132         c.add_button ("_Open", Gtk::RESPONSE_ACCEPT);
133
134         int const r = c.run ();
135         if (r == Gtk::RESPONSE_ACCEPT) {
136                 if (maybe_save_then_delete_film ()) {
137                         return;
138                 }
139                 film = new Film (c.get_filename ());
140                 film_viewer->set_film (film);
141                 film_editor->set_film (film);
142                 set_menu_sensitivity ();
143         }
144 }
145
146 void
147 file_save ()
148 {
149         film->write_metadata ();
150 }
151
152 void
153 file_quit ()
154 {
155         if (maybe_save_then_delete_film ()) {
156                 return;
157         }
158         
159         Gtk::Main::quit ();
160 }
161
162 void
163 edit_preferences ()
164 {
165         ConfigDialog d;
166         d.run ();
167         Config::instance()->write ();
168 }
169
170 void
171 jobs_make_dcp ()
172 {
173         JobWrapper::make_dcp (film, true);
174 }
175
176 void
177 jobs_make_dcp_from_existing_transcode ()
178 {
179         JobWrapper::make_dcp (film, false);
180 }
181
182 void
183 jobs_copy_from_dvd ()
184 {
185         try {
186                 DVDTitleDialog d;
187                 if (d.run () != Gtk::RESPONSE_OK) {
188                         return;
189                 }
190                 film->copy_from_dvd ();
191         } catch (DVDError& e) {
192                 error_dialog (e.what ());
193         }
194 }
195
196 void
197 jobs_send_dcp_to_tms ()
198 {
199         film->send_dcp_to_tms ();
200 }
201
202 void
203 jobs_examine_content ()
204 {
205         film->examine_content ();
206 }
207
208 void
209 help_about ()
210 {
211         Gtk::AboutDialog d;
212         d.set_name ("DVD-o-matic");
213         d.set_version (DVDOMATIC_VERSION);
214
215         stringstream s;
216         s << "DCP generation from arbitrary formats\n\n"
217           << "Using " << dependency_version_summary() << "\n";
218         d.set_comments (s.str ());
219
220         vector<string> authors;
221         authors.push_back ("Carl Hetherington");
222         authors.push_back ("Terrence Meiczinger");
223         authors.push_back ("Paul Davis");
224         d.set_authors (authors);
225
226         d.set_website ("http://carlh.net/software/dvdomatic");
227         d.set_license (gpl);
228         
229         d.run ();
230 }
231
232 enum Sensitivity {
233         ALWAYS,
234         NEEDS_FILM
235 };
236
237 map<Gtk::MenuItem *, Sensitivity> menu_items;
238         
239 void
240 add_item (Gtk::Menu_Helpers::MenuList& items, string text, sigc::slot0<void> handler, Sensitivity sens)
241 {
242         items.push_back (Gtk::Menu_Helpers::MenuElem (text, handler));
243         menu_items.insert (make_pair (&items.back(), sens));
244 }
245
246 void
247 set_menu_sensitivity ()
248 {
249         for (map<Gtk::MenuItem *, Sensitivity>::iterator i = menu_items.begin(); i != menu_items.end(); ++i) {
250                 if (i->second == NEEDS_FILM) {
251                         i->first->set_sensitive (film != 0);
252                 } else {
253                         i->first->set_sensitive (true);
254                 }
255         }
256 }
257
258 void
259 setup_menu (Gtk::MenuBar& m)
260 {
261         using namespace Gtk::Menu_Helpers;
262
263         Gtk::Menu* file = manage (new Gtk::Menu);
264         MenuList& file_items (file->items ());
265         add_item (file_items, "New...", sigc::ptr_fun (file_new), ALWAYS);
266         add_item (file_items, "_Open...", sigc::ptr_fun (file_open), ALWAYS);
267         file_items.push_back (SeparatorElem ());
268         add_item (file_items, "_Save", sigc::ptr_fun (file_save), NEEDS_FILM);
269         file_items.push_back (SeparatorElem ());
270         add_item (file_items, "_Quit", sigc::ptr_fun (file_quit), ALWAYS);
271
272         Gtk::Menu* edit = manage (new Gtk::Menu);
273         MenuList& edit_items (edit->items ());
274         add_item (edit_items, "_Preferences...", sigc::ptr_fun (edit_preferences), ALWAYS);
275
276         Gtk::Menu* jobs = manage (new Gtk::Menu);
277         MenuList& jobs_items (jobs->items ());
278         add_item (jobs_items, "_Make DCP", sigc::ptr_fun (jobs_make_dcp), NEEDS_FILM);
279         add_item (jobs_items, "_Send DCP to TMS", sigc::ptr_fun (jobs_send_dcp_to_tms), NEEDS_FILM);
280         add_item (jobs_items, "Copy from _DVD...", sigc::ptr_fun (jobs_copy_from_dvd), NEEDS_FILM);
281         jobs_items.push_back (SeparatorElem ());
282         add_item (jobs_items, "_Examine content", sigc::ptr_fun (jobs_examine_content), NEEDS_FILM);
283         add_item (jobs_items, "Make DCP from _existing transcode", sigc::ptr_fun (jobs_make_dcp_from_existing_transcode), NEEDS_FILM);
284
285         Gtk::Menu* help = manage (new Gtk::Menu);
286         MenuList& help_items (help->items ());
287         add_item (help_items, "About", sigc::ptr_fun (help_about), ALWAYS);
288         
289         MenuList& items (m.items ());
290         items.push_back (MenuElem ("_File", *file));
291         items.push_back (MenuElem ("_Edit", *edit));
292         items.push_back (MenuElem ("_Jobs", *jobs));
293         items.push_back (MenuElem ("_Help", *help));
294 }
295
296 bool
297 window_closed (GdkEventAny *)
298 {
299         if (maybe_save_then_delete_film ()) {
300                 return true;
301         }
302
303         return false;
304 }
305
306 void
307 file_changed (string f)
308 {
309         stringstream s;
310         s << "DVD-o-matic";
311         if (!f.empty ()) {
312                 s << " — " << f;
313         }
314         
315         window->set_title (s.str ());
316 }
317
318 #endif
319
320
321 enum {
322         ID_Quit = 1,
323 };
324
325 class Frame : public wxFrame
326 {
327 public:
328         Frame (wxString const & title)
329                 : wxFrame (NULL, -1, title)
330         {
331                 wxMenuBar* bar = new wxMenuBar;
332                 bar->Show (true);
333                 
334                 wxMenu *menu_file = new wxMenu;
335                 menu_file->Append (ID_Quit, _("&Quit"));
336
337                 bar->Append (menu_file, _("&File"));
338
339                 SetMenuBar (bar);
340
341                 CreateStatusBar ();
342                 SetStatusText (_("Welcome to DVD-o-matic!"));
343         }
344         
345         void quit (wxCommandEvent& event)
346         {
347                 Close (true);
348         }
349 };
350
351 class App : public wxApp
352 {
353         bool OnInit ()
354         {
355                 if (!wxApp::OnInit ()) {
356                         return false;
357                 }
358
359                 wxInitAllImageHandlers ();
360                 
361                 dvdomatic_setup ();
362
363 //              if (argc == 2 && boost::filesystem::is_directory (argv[1])) {
364 //                      film = new Film (argv[1]);
365 //              }
366                 
367                 Film* film = new Film ("/home/carl/DCP/BitHarvest");
368                 
369                 Frame* frame = new Frame (_("DVD-o-matic"));
370                 frame->Show (true);
371                 
372                 frame->Connect (
373                         ID_Quit, wxEVT_COMMAND_MENU_SELECTED,
374                         (wxObjectEventFunction) &Frame::quit
375                         );
376
377                 film_editor = new FilmEditor (film, frame);
378                 film_editor->Show (true);
379                 film_viewer = new FilmViewer (film, frame);
380                 film_viewer->Show (true);
381 #ifndef DVDOMATIC_DISABLE_PLAYER
382                 film_player = new FilmPlayer (film, frame);
383 #endif          
384
385                 wxBoxSizer* main_sizer = new wxBoxSizer (wxHORIZONTAL);
386                 main_sizer->Add (film_editor, 0);
387                 main_sizer->Add (film_viewer, 1, wxEXPAND);
388                 frame->SetSizer (main_sizer);
389
390                 SetTopWindow (frame);
391                 frame->Maximize ();
392
393 #if 0
394                 /* XXX: calling these here is a bit of a hack */
395                 film_editor->setup_visibility ();
396 #ifndef DVDOMATIC_DISABLE_PLAYER        
397                 film_player->setup_visibility ();
398 #endif  
399                 film_viewer->setup_visibility ();
400                 
401                 film_editor->FileChanged.connect (ptr_fun (file_changed));
402                 if (film) {
403                         file_changed (film->directory ());
404                 } else {
405                         file_changed ("");
406                 }
407 #endif          
408                 
409                 /* XXX this should be in JobManagerView, shouldn't it? */
410 //XXX           Glib::signal_timeout().connect (sigc::bind_return (sigc::mem_fun (jobs_view, &JobManagerView::update), true), 1000);
411                 
412                 return true;
413         }
414 };
415
416 IMPLEMENT_APP (App)