X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Ftools%2Fdcpomatic.cc;h=459ce341c3d026254522d36afa3b47437dd36b17;hb=3ffd0163026be24e5373e0674c3301ed37546e44;hp=d40976094a0b95125c533ee6789a588a92fbda61;hpb=79f957a6f37276f71cf98d4fa1ae5e0ab3beb76d;p=dcpomatic.git diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index d40976094..459ce341c 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -36,7 +36,9 @@ #include "wx/full_config_dialog.h" #include "wx/hints_dialog.h" #include "wx/html_dialog.h" +#include "wx/file_dialog.h" #include "wx/i18n_hook.h" +#include "wx/id.h" #include "wx/job_manager_view.h" #include "wx/kdm_dialog.h" #include "wx/nag_dialog.h" @@ -74,6 +76,7 @@ #include "lib/exceptions.h" #include "lib/ffmpeg_encoder.h" #include "lib/film.h" +#include "lib/font_config.h" #include "lib/hints.h" #include "lib/job_manager.h" #include "lib/kdm_with_metadata.h" @@ -90,6 +93,7 @@ #include "lib/version.h" #include "lib/video_content.h" #include +#include #include #include LIBDCP_DISABLE_WARNINGS @@ -209,7 +213,7 @@ private: map menu_items; enum { - ID_file_new = 1, + ID_file_new = DCPOMATIC_MAIN_MENU, ID_file_open, ID_file_save, ID_file_save_as_template, @@ -217,7 +221,7 @@ enum { ID_file_duplicate_and_open, ID_file_history, /* Allow spare IDs after _history for the recent files list */ - ID_file_close = 100, + ID_file_close = DCPOMATIC_MAIN_MENU + 100, ID_edit_copy, ID_edit_paste, ID_edit_select_all, @@ -241,6 +245,7 @@ enum { ID_tools_system_information, ID_tools_restore_default_preferences, ID_tools_export_preferences, + ID_tools_import_preferences, ID_help_report_a_problem, /* IDs for shortcuts (with no associated menu item) */ ID_add_file, @@ -305,25 +310,6 @@ public: , _right_panel(new wxPanel(_splitter, wxID_ANY)) , _film_viewer(_right_panel) { -#if defined(DCPOMATIC_WINDOWS) - if (Config::instance()->win32_console()) { - AllocConsole(); - - HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); - int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT); - FILE* hf_out = _fdopen(hCrt, "w"); - setvbuf(hf_out, NULL, _IONBF, 1); - *stdout = *hf_out; - - HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); - hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT); - FILE* hf_in = _fdopen(hCrt, "r"); - setvbuf(hf_in, NULL, _IONBF, 128); - *stdin = *hf_in; - - cout << "DCP-o-matic is starting." << "\n"; - } -#endif auto bar = new wxMenuBar; setup_menu (bar); @@ -371,6 +357,7 @@ public: Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_system_information, this),ID_tools_system_information); Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_restore_default_preferences, this), ID_tools_restore_default_preferences); Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_export_preferences, this), ID_tools_export_preferences); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_import_preferences, this), ID_tools_import_preferences); Bind (wxEVT_MENU, boost::bind (&DOMFrame::help_about, this), wxID_ABOUT); Bind (wxEVT_MENU, boost::bind (&DOMFrame::help_report_a_problem, this), ID_help_report_a_problem); @@ -387,6 +374,7 @@ public: left_panel->SetSizerAndFit(left_sizer); _controls = new StandardControls(_right_panel, _film_viewer, true); + _controls->set_film(_film_viewer.film()); auto job_manager_view = new JobManagerView(_right_panel, false); auto right_sizer = new wxBoxSizer (wxVERTICAL); @@ -492,7 +480,7 @@ public: } catch (FileNotFoundError& e) { auto const dir = e.file().parent_path(); - if (boost::filesystem::exists(dir / "ASSETMAP") || boost::filesystem::exists(dir / "ASSETMAP.xml")) { + if (dcp::filesystem::exists(dir / "ASSETMAP") || dcp::filesystem::exists(dir / "ASSETMAP.xml")) { error_dialog ( this, _("Could not open this folder as a DCP-o-matic project."), _("It looks like you are trying to open a DCP. File -> Open is for loading DCP-o-matic projects, not DCPs. To import a DCP, create a new project with File -> New and then click the \"Add DCP...\" button.") @@ -705,13 +693,16 @@ private: void edit_copy () { auto const sel = _film_editor->content_panel()->selected(); - DCPOMATIC_ASSERT (sel.size() == 1); - _clipboard = sel.front()->clone(); + if (sel.size() == 1) { + _clipboard = sel.front()->clone(); + } } void edit_paste () { - DCPOMATIC_ASSERT (_clipboard); + if (!_clipboard) { + return; + } PasteDialog dialog(this, static_cast(_clipboard->video), static_cast(_clipboard->audio), !_clipboard->text.empty()); if (dialog.ShowModal() != wxID_OK) { @@ -769,13 +760,31 @@ private: void tools_export_preferences () { - wxFileDialog dialog( - this, _("Specify ZIP file"), wxEmptyString, wxT("dcpomatic_config.zip"), wxT("ZIP files (*.zip)|*.zip"), - wxFD_SAVE | wxFD_OVERWRITE_PROMPT + FileDialog dialog( + this, _("Specify ZIP file"), wxT("ZIP files (*.zip)|*.zip"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT, "Preferences", string("dcpomatic_config.zip") ); if (dialog.ShowModal() == wxID_OK) { - save_all_config_as_zip(wx_to_std(dialog.GetPath())); + auto const path = boost::filesystem::path(wx_to_std(dialog.GetPath())); + if (boost::filesystem::exists(path)) { + boost::system::error_code ec; + boost::filesystem::remove(path, ec); + if (ec) { + error_dialog(nullptr, _("Could not remove existing preferences file"), std_to_wx(path.string())); + return; + } + } + + save_all_config_as_zip(path); + } + } + + void tools_import_preferences() + { + FileDialog dialog(this, _("Specify ZIP file"), wxT("ZIP files (*.zip)|*.zip"), wxFD_OPEN, "Preferences"); + + if (dialog.show()) { + Config::instance()->load_from_zip(dialog.path()); } } @@ -817,11 +826,11 @@ private: /* Remove any existing DCP if the user agrees */ auto const dcp_dir = _film->dir (_film->dcp_name(), false); - if (boost::filesystem::exists(dcp_dir)) { + if (dcp::filesystem::exists(dcp_dir)) { if (!confirm_dialog (this, wxString::Format (_("Do you want to overwrite the existing DCP %s?"), std_to_wx(dcp_dir.string()).data()))) { return; } - boost::filesystem::remove_all (dcp_dir); + dcp::filesystem::remove_all(dcp_dir); } try { @@ -995,7 +1004,7 @@ private: return; } - if (boost::filesystem::exists(dialog.path())) { + if (dcp::filesystem::exists(dialog.path())) { bool ok = confirm_dialog( this, wxString::Format(_("File %s already exists. Do you want to overwrite it?"), std_to_wx(dialog.path().string()).data()) @@ -1114,12 +1123,11 @@ private: for (auto i: translations) { body += i.first + "\n" + i.second + "\n\n"; } - list to = { "carl@dcpomatic.com" }; if (dialog.email().find("@") == string::npos) { error_dialog (this, _("You must enter a valid email address when sending translations, " "otherwise the DCP-o-matic maintainers cannot credit you or contact you with questions.")); } else { - Emailer emailer(dialog.email(), to, "DCP-o-matic translations", body); + Emailer emailer(dialog.email(), { "carl@dcpomatic.com" }, "DCP-o-matic translations", body); try { emailer.send ("main.carlh.net", 2525, EmailProtocol::STARTTLS); } catch (NetworkError& e) { @@ -1191,6 +1199,8 @@ private: /* Also stop hearing about analytics-related stuff */ _analytics_message_connection.disconnect (); + FontConfig::drop(); + ev.Skip (); } @@ -1266,14 +1276,20 @@ private: return true; } - if (_film->dirty ()) { - T d (_film->name ()); - switch (d.run ()) { + while (_film->dirty()) { + T dialog(_film->name()); + switch (dialog.run()) { case wxID_NO: return true; case wxID_YES: - _film->write_metadata (); - return true; + try { + _film->write_metadata(); + return true; + } catch (exception& e) { + error_dialog(this, _("Could not save project."), std_to_wx(e.what())); + /* Go round again for another try */ + } + break; case wxID_CANCEL: return false; } @@ -1339,7 +1355,7 @@ private: add_item (edit, _("Select all\tShift-Ctrl-A"), ID_edit_select_all, NEEDS_FILM); #ifdef __WXOSX__ - add_item (_file_menu, _("&Preferences...\tCtrl-P"), wxID_PREFERENCES, ALWAYS); + add_item(_file_menu, _("&Preferences...\tCtrl-,"), wxID_PREFERENCES, ALWAYS); #else edit->AppendSeparator (); /* [Shortcut] Ctrl+P:Open preferences window */ @@ -1389,6 +1405,7 @@ private: add_item (tools, _("Restore default preferences"), ID_tools_restore_default_preferences, ALWAYS); tools->AppendSeparator (); add_item (tools, _("Export preferences..."), ID_tools_export_preferences, ALWAYS); + add_item (tools, _("Import preferences..."), ID_tools_import_preferences, ALWAYS); wxMenu* help = new wxMenu; #ifdef __WXOSX__ @@ -1409,7 +1426,8 @@ private: void config_changed (Config::Property what) { /* Instantly save any config changes when using the DCP-o-matic GUI */ - if (what == Config::CINEMAS) { + switch (what) { + case Config::CINEMAS: try { Config::instance()->write_cinemas(); } catch (exception& e) { @@ -1421,7 +1439,21 @@ private: ) ); } - } else { + break; + case Config::DKDM_RECIPIENTS: + try { + Config::instance()->write_dkdm_recipients(); + } catch (exception& e) { + error_dialog ( + this, + wxString::Format ( + _("Could not write to DKDM recipients file at %s. Your changes have not been saved."), + std_to_wx(Config::instance()->dkdm_recipients_file().string()).data() + ) + ); + } + break; + default: try { Config::instance()->write_config(); } catch (exception& e) { @@ -1588,6 +1620,7 @@ public: App () : wxApp () { + dcpomatic_setup_path_encoding (); #ifdef DCPOMATIC_LINUX XInitThreads (); #endif @@ -1598,6 +1631,26 @@ private: bool OnInit () override { try { + +#if defined(DCPOMATIC_WINDOWS) + if (Config::instance()->win32_console()) { + AllocConsole(); + + HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE); + int hCrt = _open_osfhandle((intptr_t) handle_out, _O_TEXT); + FILE* hf_out = _fdopen(hCrt, "w"); + setvbuf(hf_out, NULL, _IONBF, 1); + *stdout = *hf_out; + + HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE); + hCrt = _open_osfhandle((intptr_t) handle_in, _O_TEXT); + FILE* hf_in = _fdopen(hCrt, "r"); + setvbuf(hf_in, NULL, _IONBF, 128); + *stdin = *hf_in; + + cout << "DCP-o-matic is starting." << "\n"; + } +#endif wxInitAllImageHandlers (); Config::FailedToLoad.connect(boost::bind(&App::config_failed_to_load, this, _1)); @@ -1620,8 +1673,6 @@ private: make_foreground_application (); #endif - dcpomatic_setup_path_encoding (); - /* Enable i18n; this will create a Config object to look for a force-configured language. This Config object will be wrong, however, because dcpomatic_setup @@ -1663,7 +1714,7 @@ private: signal_manager = new wxSignalManager (this); Bind (wxEVT_IDLE, boost::bind (&App::idle, this, _1)); - if (!_film_to_load.empty() && boost::filesystem::is_directory(_film_to_load)) { + if (!_film_to_load.empty() && dcp::filesystem::is_directory(_film_to_load)) { try { _frame->load_film (_film_to_load); } catch (exception& e) { @@ -1700,7 +1751,7 @@ private: } catch (exception& e) { - _splash.reset(); + close_splash(); error_dialog (nullptr, wxString::Format ("DCP-o-matic could not start."), std_to_wx(e.what())); } @@ -1812,7 +1863,10 @@ private: void close_splash () { - _splash.reset(); + if (_splash) { + _splash->Destroy(); + _splash = nullptr; + } } void config_failed_to_load (Config::LoadFailure what) @@ -1830,7 +1884,7 @@ private: /* Destroy the splash screen here, as otherwise bad things seem to happen (for reasons unknown) when we open our recreate dialog, close it, *then* try to Destroy the splash (the Destroy fails). */ - _splash.reset(); + close_splash(); auto config = Config::instance(); switch (reason) { @@ -1893,13 +1947,26 @@ private: } return true; } + case Config::BAD_SIGNER_DN_QUALIFIER: + { + RecreateChainDialog dialog( + _frame, _("Recreate signing certificates"), + _("The certificate chain that DCP-o-matic uses for signing DCPs and KDMs contains a small error\n" + "which will prevent DCPs from being validated correctly on some systems. This error was caused\n" + "by a bug in DCP-o-matic which has now been fixed. Do you want to re-create the certificate chain\n" + "for signing DCPs and KDMs?"), + _("Do nothing"), + Config::NAG_BAD_SIGNER_DN_QUALIFIER + ); + return dialog.ShowModal() == wxID_OK; + } default: DCPOMATIC_ASSERT (false); } } DOMFrame* _frame = nullptr; - wx_ptr _splash; + wxSplashScreen* _splash = nullptr; shared_ptr _timer; string _film_to_load; string _film_to_create;