Use more ScopeGuards.
[dcpomatic.git] / src / tools / dcpomatic_batch.cc
index ef8816708bbdd4017ef267c5c490fe00a889a2eb..64015a0e30179faa7a0dd7b78bf05a2109dc2e21 100644 (file)
 #include "lib/job.h"
 #include "lib/job_manager.h"
 #include "lib/make_dcp.h"
+#include "lib/scope_guard.h"
 #include "lib/transcode_job.h"
 #include "lib/util.h"
 #include "lib/version.h"
+#include <dcp/warnings.h>
+LIBDCP_DISABLE_WARNINGS
 #include <wx/aboutdlg.h>
 #include <wx/cmdline.h>
+#include <wx/dnd.h>
 #include <wx/preferences.h>
 #include <wx/splash.h>
 #include <wx/stdpaths.h>
 #include <wx/wx.h>
+LIBDCP_ENABLE_WARNINGS
 #include <iostream>
 #include <set>
 
@@ -107,6 +112,36 @@ setup_menu (wxMenuBar* m)
 class DOMFrame : public wxFrame
 {
 public:
+       enum class Tool {
+               ADD,
+               PAUSE
+       };
+
+       class DCPDropTarget : public wxFileDropTarget
+       {
+       public:
+               DCPDropTarget(DOMFrame* owner)
+                       : _frame(owner)
+               {}
+
+               bool OnDropFiles(wxCoord, wxCoord, wxArrayString const& filenames) override
+               {
+                       if (filenames.GetCount() == 1) {
+                               /* Try to load a directory */
+                               auto path = boost::filesystem::path(wx_to_std(filenames[0]));
+                               if (boost::filesystem::is_directory(path)) {
+                                       _frame->start_job(wx_to_std(filenames[0]));
+                                       return true;
+                               }
+                       }
+
+                       return false;
+               }
+
+       private:
+               DOMFrame* _frame;
+       };
+
        explicit DOMFrame (wxString const & title)
                : wxFrame (nullptr, -1, title)
                , _sizer (new wxBoxSizer(wxVERTICAL))
@@ -128,46 +163,47 @@ public:
                s->Add (panel, 1, wxEXPAND);
                SetSizer (s);
 
-               auto job_manager_view = new JobManagerView (panel, true);
-               _sizer->Add (job_manager_view, 1, wxALL | wxEXPAND, 6);
+               wxBitmap add(icon_path("add"), wxBITMAP_TYPE_PNG);
+               wxBitmap pause(icon_path("pause"), wxBITMAP_TYPE_PNG);
 
-               auto buttons = new wxBoxSizer (wxHORIZONTAL);
-               auto add = new Button (panel, _("Add Film..."));
-               add->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::add_film, this));
-               buttons->Add (add, 1, wxALL, 6);
-               _pause = new Button (panel, _("Pause"));
-               _pause->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::pause, this));
-               buttons->Add (_pause, 1, wxALL, 6);
-               _resume = new Button (panel, _("Resume"));
-               _resume->Bind (wxEVT_BUTTON, boost::bind(&DOMFrame::resume, this));
-               buttons->Add (_resume, 1, wxALL, 6);
+               auto toolbar = new wxToolBar(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL);
+               toolbar->SetMargins(4, 4);
+               toolbar->SetToolBitmapSize(wxSize(32, 32));
+               toolbar->AddTool(static_cast<int>(Tool::ADD), _("Add film"), add, _("Add film for conversion"));
+               toolbar->AddCheckTool(static_cast<int>(Tool::PAUSE), _("Pause/resume"), pause, wxNullBitmap, _("Pause or resume conversion"));
+               toolbar->Realize();
+               _sizer->Add(toolbar, 0, wxALL, 6);
 
-               setup_sensitivity ();
+               toolbar->Bind(wxEVT_TOOL, bind(&DOMFrame::tool_clicked, this, _1));
 
-               _sizer->Add (buttons, 0, wxALL, 6);
+               auto job_manager_view = new JobManagerView (panel, true);
+               _sizer->Add (job_manager_view, 1, wxALL | wxEXPAND, 6);
 
                panel->SetSizer (_sizer);
 
                Bind (wxEVT_CLOSE_WINDOW, boost::bind(&DOMFrame::close, this, _1));
                Bind (wxEVT_SIZE, boost::bind(&DOMFrame::sized, this, _1));
-       }
-
-       void setup_sensitivity ()
-       {
-               _pause->Enable (!JobManager::instance()->paused());
-               _resume->Enable (JobManager::instance()->paused());
-       }
 
-       void pause ()
-       {
-               JobManager::instance()->pause();
-               setup_sensitivity ();
+               SetDropTarget(new DCPDropTarget(this));
        }
 
-       void resume ()
+       void tool_clicked(wxCommandEvent& ev)
        {
-               JobManager::instance()->resume();
-               setup_sensitivity ();
+               switch (static_cast<Tool>(ev.GetId())) {
+               case Tool::ADD:
+                       add_film();
+                       break;
+               case Tool::PAUSE:
+               {
+                       auto jm = JobManager::instance();
+                       if (jm->paused()) {
+                               jm->resume();
+                       } else {
+                               jm->pause();
+                       }
+                       break;
+               }
+               }
        }
 
        void start_job (boost::filesystem::path path)
@@ -239,10 +275,9 @@ private:
                        _("Unfinished jobs"),
                        wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION
                        );
+               ScopeGuard sg = [d]{ d->Destroy(); };
 
-               bool const r = d->ShowModal() == wxID_YES;
-               d->Destroy ();
-               return r;
+               return d->ShowModal() == wxID_YES;
        }
 
        void close (wxCloseEvent& ev)
@@ -287,21 +322,22 @@ private:
        void help_about ()
        {
                auto d = new AboutDialog (this);
+               ScopeGuard sg = [d]() { d->Destroy(); };
                d->ShowModal ();
-               d->Destroy ();
        }
 
        void add_film ()
        {
-               auto c = new wxDirDialog (this, _("Select film to open"), wxStandardPaths::Get().GetDocumentsDir(), wxDEFAULT_DIALOG_STYLE | wxDD_DIR_MUST_EXIST);
+               auto dialog = new wxDirDialog(this, _("Select film to open"), wxStandardPaths::Get().GetDocumentsDir(), wxDEFAULT_DIALOG_STYLE | wxDD_DIR_MUST_EXIST);
+               ScopeGuard sg = [dialog]() { dialog->Destroy(); };
                if (_last_parent) {
-                       c->SetPath (std_to_wx(_last_parent.get().string()));
+                       dialog->SetPath(std_to_wx(_last_parent.get().string()));
                }
 
                int r;
                while (true) {
-                       r = c->ShowModal ();
-                       if (r == wxID_OK && c->GetPath() == wxStandardPaths::Get().GetDocumentsDir()) {
+                       r = dialog->ShowModal();
+                       if (r == wxID_OK && dialog->GetPath() == wxStandardPaths::Get().GetDocumentsDir()) {
                                error_dialog (this, _("You did not select a folder.  Make sure that you select a folder before clicking Open."));
                        } else {
                                break;
@@ -309,12 +345,10 @@ private:
                }
 
                if (r == wxID_OK) {
-                       start_job (wx_to_std (c->GetPath ()));
+                       start_job(wx_to_std(dialog->GetPath()));
                }
 
-               _last_parent = boost::filesystem::path (wx_to_std (c->GetPath ())).parent_path ();
-
-               c->Destroy ();
+               _last_parent = boost::filesystem::path(wx_to_std(dialog->GetPath())).parent_path();
        }
 
        void config_changed (Config::Property what)
@@ -351,8 +385,6 @@ private:
        wxSizer* _sizer;
        wxPreferencesEditor* _config_dialog = nullptr;
        ServersListDialog* _servers_list_dialog = nullptr;
-       wxButton* _pause;
-       wxButton* _resume;
 };
 
 
@@ -398,7 +430,7 @@ class App : public wxApp
                SetAppName (_("DCP-o-matic Batch Converter"));
                is_batch_converter = true;
 
-               Config::FailedToLoad.connect (boost::bind(&App::config_failed_to_load, this));
+               Config::FailedToLoad.connect(boost::bind(&App::config_failed_to_load, this, _1));
                Config::Warning.connect (boost::bind(&App::config_warning, this, _1));
 
                auto splash = maybe_show_splash ();
@@ -439,8 +471,12 @@ class App : public wxApp
                }
                _frame->Show ();
 
-               auto server = new JobServer (_frame);
-               new thread (boost::bind (&JobServer::run, server));
+               try {
+                       auto server = new JobServer (_frame);
+                       new thread (boost::bind (&JobServer::run, server));
+               } catch (boost::system::system_error& e) {
+                       error_dialog(_frame, _("Could not listen for new batch jobs.  Perhaps another instance of the DCP-o-matic Batch Converter is running."));
+               }
 
                signal_manager = new wxSignalManager (this);
                this->Bind (wxEVT_IDLE, boost::bind (&App::idle, this));
@@ -485,9 +521,9 @@ class App : public wxApp
                return true;
        }
 
-       void config_failed_to_load ()
+       void config_failed_to_load(Config::LoadFailure what)
        {
-               message_dialog (_frame, _("The existing configuration failed to load.  Default values will be used instead.  These may take a short time to create."));
+               report_config_load_failure(_frame, what);
        }
 
        void config_warning (string m)