#include trimming.
[dcpomatic.git] / src / tools / dcpomatic.cc
index 8bb9b230a2a3d9540fa2620be50db554770358f1..e67703b22fe34a69b544a34b660c74f693e39ca8 100644 (file)
@@ -30,6 +30,7 @@
 #include <wx/stdpaths.h>
 #include <wx/cmdline.h>
 #include <wx/preferences.h>
+#include <dcp/exceptions.h>
 #include "wx/film_viewer.h"
 #include "wx/film_editor.h"
 #include "wx/job_manager_view.h"
@@ -44,6 +45,7 @@
 #include "wx/servers_list_dialog.h"
 #include "wx/hints_dialog.h"
 #include "wx/update_dialog.h"
+#include "wx/content_panel.h"
 #include "lib/film.h"
 #include "lib/config.h"
 #include "lib/util.h"
@@ -71,17 +73,12 @@ using std::exception;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 
-static FilmEditor* film_editor = 0;
-static FilmViewer* film_viewer = 0;
 static shared_ptr<Film> film;
-static std::string log_level;
 static std::string film_to_load;
 static std::string film_to_create;
 static std::string content_to_add;
 static wxMenu* jobs_menu = 0;
 
-static void set_menu_sensitivity ();
-
 // #define DCPOMATIC_WINDOWS_CONSOLE 1
 
 class FilmChangedDialog
@@ -157,13 +154,13 @@ load_film (boost::filesystem::path file)
        for (list<string>::const_iterator i = notes.begin(); i != notes.end(); ++i) {
                error_dialog (0, std_to_wx (*i));
        }
-       film->log()->set_level (log_level);
 }
 
-#define ALWAYS                  0x0
-#define NEEDS_FILM              0x1
-#define NOT_DURING_DCP_CREATION 0x2
-#define NEEDS_DCP               0x4
+#define ALWAYS                       0x0
+#define NEEDS_FILM                   0x1
+#define NOT_DURING_DCP_CREATION      0x2
+#define NEEDS_CPL                    0x4
+#define NEEDS_SELECTED_VIDEO_CONTENT 0x8
 
 map<wxMenuItem*, int> menu_items;
        
@@ -174,42 +171,13 @@ add_item (wxMenu* menu, wxString text, int id, int sens)
        menu_items.insert (make_pair (item, sens));
 }
 
-static void
-set_menu_sensitivity ()
-{
-       list<shared_ptr<Job> > jobs = JobManager::instance()->get ();
-       list<shared_ptr<Job> >::iterator i = jobs.begin();
-       while (i != jobs.end() && dynamic_pointer_cast<TranscodeJob> (*i) == 0) {
-               ++i;
-       }
-       bool const dcp_creation = (i != jobs.end ()) && !(*i)->finished ();
-       bool const have_dcp = film && !film->dcps().empty ();
-
-       for (map<wxMenuItem*, int>::iterator j = menu_items.begin(); j != menu_items.end(); ++j) {
-
-               bool enabled = true;
-
-               if ((j->second & NEEDS_FILM) && film == 0) {
-                       enabled = false;
-               }
-
-               if ((j->second & NOT_DURING_DCP_CREATION) && dcp_creation) {
-                       enabled = false;
-               }
-
-               if ((j->second & NEEDS_DCP) && !have_dcp) {
-                       enabled = false;
-               }
-               
-               j->first->Enable (enabled);
-       }
-}
-
 enum {
        ID_file_new = 1,
        ID_file_open,
        ID_file_save,
        ID_file_properties,
+       ID_content_scale_to_fit_width,
+       ID_content_scale_to_fit_height,
        ID_jobs_make_dcp,
        ID_jobs_make_kdms,
        ID_jobs_send_dcp_to_tms,
@@ -245,13 +213,17 @@ setup_menu (wxMenuBar* m)
 #else
        wxMenu* edit = new wxMenu;
        add_item (edit, _("&Preferences..."), wxID_PREFERENCES, ALWAYS);
-#endif 
+#endif
+
+       wxMenu* content = new wxMenu;
+       add_item (content, _("Scale to fit &width"), ID_content_scale_to_fit_width, NEEDS_FILM | NEEDS_SELECTED_VIDEO_CONTENT);
+       add_item (content, _("Scale to fit &height"), ID_content_scale_to_fit_height, NEEDS_FILM | NEEDS_SELECTED_VIDEO_CONTENT);
 
        jobs_menu = new wxMenu;
        add_item (jobs_menu, _("&Make DCP"), ID_jobs_make_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION);
-       add_item (jobs_menu, _("Make &KDMs..."), ID_jobs_make_kdms, NEEDS_FILM | NEEDS_DCP);
-       add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_DCP);
-       add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_DCP);
+       add_item (jobs_menu, _("Make &KDMs..."), ID_jobs_make_kdms, NEEDS_FILM);
+       add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
+       add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL);
 
        wxMenu* tools = new wxMenu;
        add_item (tools, _("Hints..."), ID_tools_hints, 0);
@@ -268,7 +240,8 @@ setup_menu (wxMenuBar* m)
        m->Append (file, _("&File"));
 #ifndef __WXOSX__      
        m->Append (edit, _("&Edit"));
-#endif 
+#endif
+       m->Append (content, _("&Content"));
        m->Append (jobs_menu, _("&Jobs"));
        m->Append (tools, _("&Tools"));
        m->Append (help, _("&Help"));
@@ -309,6 +282,8 @@ public:
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::file_properties, this),         ID_file_properties);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::file_exit, this),               wxID_EXIT);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::edit_preferences, this),        wxID_PREFERENCES);
+               Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::content_scale_to_fit_width, this), ID_content_scale_to_fit_width);
+               Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::content_scale_to_fit_height, this), ID_content_scale_to_fit_height);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::jobs_make_dcp, this),           ID_jobs_make_dcp);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::jobs_make_kdms, this),          ID_jobs_make_kdms);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::jobs_send_dcp_to_tms, this),    ID_jobs_send_dcp_to_tms);
@@ -325,28 +300,28 @@ public:
                */
                wxPanel* overall_panel = new wxPanel (this, wxID_ANY);
 
-               film_editor = new FilmEditor (film, overall_panel);
-               film_viewer = new FilmViewer (film, overall_panel);
+               _film_editor = new FilmEditor (film, overall_panel);
+               _film_viewer = new FilmViewer (film, overall_panel);
                JobManagerView* job_manager_view = new JobManagerView (overall_panel, static_cast<JobManagerView::Buttons> (0));
 
                wxBoxSizer* right_sizer = new wxBoxSizer (wxVERTICAL);
-               right_sizer->Add (film_viewer, 2, wxEXPAND | wxALL, 6);
+               right_sizer->Add (_film_viewer, 2, wxEXPAND | wxALL, 6);
                right_sizer->Add (job_manager_view, 1, wxEXPAND | wxALL, 6);
 
                wxBoxSizer* main_sizer = new wxBoxSizer (wxHORIZONTAL);
-               main_sizer->Add (film_editor, 1, wxEXPAND | wxALL, 6);
+               main_sizer->Add (_film_editor, 1, wxEXPAND | wxALL, 6);
                main_sizer->Add (right_sizer, 2, wxEXPAND | wxALL, 6);
 
                set_menu_sensitivity ();
 
-               film_editor->FileChanged.connect (bind (&Frame::file_changed, this, _1));
+               _film_editor->FileChanged.connect (bind (&Frame::file_changed, this, _1));
                if (film) {
                        file_changed (film->directory ());
                } else {
                        file_changed ("");
                }
 
-               JobManager::instance()->ActiveJobsChanged.connect (boost::bind (set_menu_sensitivity));
+               JobManager::instance()->ActiveJobsChanged.connect (boost::bind (&Frame::set_menu_sensitivity, this));
 
                set_film ();
                overall_panel->SetSizer (main_sizer);
@@ -356,8 +331,8 @@ private:
 
        void set_film ()
        {
-               film_viewer->set_film (film);
-               film_editor->set_film (film);
+               _film_viewer->set_film (film);
+               _film_editor->set_film (film);
                set_menu_sensitivity ();
        }
 
@@ -401,7 +376,6 @@ private:
                        maybe_save_then_delete_film ();
                        film.reset (new Film (d->get_path ()));
                        film->write_metadata ();
-                       film->log()->set_level (log_level);
                        film->set_name (boost::filesystem::path (d->get_path()).filename().generic_string());
                        set_film ();
                }
@@ -419,7 +393,7 @@ private:
                        );
                
                int r;
-               while (1) {
+               while (true) {
                        r = c->ShowModal ();
                        if (r == wxID_OK && c->GetPath() == wxStandardPaths::Get().GetDocumentsDir()) {
                                error_dialog (this, _("You did not select a folder.  Make sure that you select a folder before clicking Open."));
@@ -457,7 +431,8 @@ private:
        
        void file_exit ()
        {
-               Close (true);
+               /* false here allows the close handler to veto the close request */
+               Close (false);
        }
 
        void edit_preferences ()
@@ -496,12 +471,14 @@ private:
 
                try {
                        if (d->write_to ()) {
-                               write_kdm_files (film, d->screens (), d->dcp (), d->from (), d->until (), d->directory ());
+                               write_kdm_files (film, d->screens (), d->cpl (), d->from (), d->until (), d->formulation (), d->directory ());
                        } else {
                                JobManager::instance()->add (
-                                       shared_ptr<Job> (new SendKDMEmailJob (film, d->screens (), d->dcp (), d->from (), d->until ()))
+                                       shared_ptr<Job> (new SendKDMEmailJob (film, d->screens (), d->cpl (), d->from (), d->until (), d->formulation ()))
                                        );
                        }
+               } catch (dcp::NotEncryptedError& e) {
+                       error_dialog (this, _("CPL's content is not encrypted."));
                } catch (exception& e) {
                        error_dialog (this, e.what ());
                } catch (...) {
@@ -510,6 +487,22 @@ private:
        
                d->Destroy ();
        }
+
+       void content_scale_to_fit_width ()
+       {
+               VideoContentList vc = _film_editor->content_panel()->selected_video ();
+               for (VideoContentList::iterator i = vc.begin(); i != vc.end(); ++i) {
+                       (*i)->scale_and_crop_to_fit_width ();
+               }
+       }
+
+       void content_scale_to_fit_height ()
+       {
+               VideoContentList vc = _film_editor->content_panel()->selected_video ();
+               for (VideoContentList::iterator i = vc.begin(); i != vc.end(); ++i) {
+                       (*i)->scale_and_crop_to_fit_height ();
+               }
+       }
        
        void jobs_send_dcp_to_tms ()
        {
@@ -602,13 +595,49 @@ private:
                ev.Skip ();
        }
 
+       void set_menu_sensitivity ()
+       {
+               list<shared_ptr<Job> > jobs = JobManager::instance()->get ();
+               list<shared_ptr<Job> >::iterator i = jobs.begin();
+               while (i != jobs.end() && dynamic_pointer_cast<TranscodeJob> (*i) == 0) {
+                       ++i;
+               }
+               bool const dcp_creation = (i != jobs.end ()) && !(*i)->finished ();
+               bool const have_cpl = film && !film->cpls().empty ();
+               bool const have_selected_video_content = !_film_editor->content_panel()->selected_video().empty();
+               
+               for (map<wxMenuItem*, int>::iterator j = menu_items.begin(); j != menu_items.end(); ++j) {
+                       
+                       bool enabled = true;
+                       
+                       if ((j->second & NEEDS_FILM) && film == 0) {
+                               enabled = false;
+                       }
+                       
+                       if ((j->second & NOT_DURING_DCP_CREATION) && dcp_creation) {
+                               enabled = false;
+                       }
+                       
+                       if ((j->second & NEEDS_CPL) && !have_cpl) {
+                               enabled = false;
+                       }
+                       
+                       if ((j->second & NEEDS_SELECTED_VIDEO_CONTENT) && !have_selected_video_content) {
+                               enabled = false;
+                       }
+                       
+                       j->first->Enable (enabled);
+               }
+       }
+       
+       FilmEditor* _film_editor;
+       FilmViewer* _film_viewer;
        HintsDialog* _hints_dialog;
        ServersListDialog* _servers_list_dialog;
        wxPreferencesEditor* _config_dialog;
 };
 
 static const wxCmdLineEntryDesc command_line_description[] = {
-       { wxCMD_LINE_OPTION, "l", "log", "set log level (silent, verbose or timing)", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
        { wxCMD_LINE_SWITCH, "n", "new", "create new film", wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL },
        { wxCMD_LINE_OPTION, "c", "content", "add content file", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
        { wxCMD_LINE_PARAM, 0, 0, "film to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
@@ -670,7 +699,6 @@ class App : public wxApp
                if (!film_to_create.empty ()) {
                        film.reset (new Film (film_to_create));
                        film->write_metadata ();
-                       film->log()->set_level (log_level);
                        film->set_name (boost::filesystem::path (film_to_create).filename().generic_string ());
                }
 
@@ -728,11 +756,6 @@ class App : public wxApp
                        content_to_add = wx_to_std (content);
                }
 
-               wxString log;
-               if (parser.Found (wxT ("log"), &log)) {
-                       log_level = wx_to_std (log);
-               }
-
                return true;
        }