X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Ftools%2Fdcpomatic.cc;h=a2b55691ed6557f9517097a9a7eebf09a9b9a311;hp=80b25ba2e5dee5549601288f96c73420cba0d16b;hb=df17bbd25da69fc38eb2dcd8b4a2531cf0bab0bc;hpb=f042aceec251608860118c97ee30c8ae3c54a70f diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 80b25ba2e..a2b55691e 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2017 Carl Hetherington + Copyright (C) 2012-2018 Carl Hetherington This file is part of DCP-o-matic. @@ -25,10 +25,11 @@ #include "wx/film_viewer.h" #include "wx/film_editor.h" #include "wx/job_manager_view.h" -#include "wx/config_dialog.h" +#include "wx/full_config_dialog.h" #include "wx/wx_util.h" #include "wx/film_name_location_dialog.h" #include "wx/wx_signal_manager.h" +#include "wx/recreate_chain_dialog.h" #include "wx/about_dialog.h" #include "wx/kdm_dialog.h" #include "wx/self_dkdm_dialog.h" @@ -42,6 +43,8 @@ #include "wx/templates_dialog.h" #include "wx/nag_dialog.h" #include "wx/export_dialog.h" +#include "wx/paste_dialog.h" +#include "wx/focus_manager.h" #include "lib/film.h" #include "lib/config.h" #include "lib/util.h" @@ -67,6 +70,8 @@ #include "lib/ffmpeg_encoder.h" #include "lib/transcode_job.h" #include "lib/dkdm_wrapper.h" +#include "lib/audio_content.h" +#include "lib/text_content.h" #include #include #include @@ -105,12 +110,13 @@ using std::exception; using boost::shared_ptr; using boost::dynamic_pointer_cast; using boost::optional; +using boost::function; using dcp::raw_convert; class FilmChangedClosingDialog : public boost::noncopyable { public: - FilmChangedClosingDialog (string name) + explicit FilmChangedClosingDialog (string name) { _dialog = new wxMessageDialog ( 0, @@ -143,7 +149,7 @@ private: class FilmChangedDuplicatingDialog : public boost::noncopyable { public: - FilmChangedDuplicatingDialog (string name) + explicit FilmChangedDuplicatingDialog (string name) { _dialog = new wxMessageDialog ( 0, @@ -173,11 +179,15 @@ private: wxMessageDialog* _dialog; }; -#define ALWAYS 0x0 -#define NEEDS_FILM 0x1 -#define NOT_DURING_DCP_CREATION 0x2 -#define NEEDS_CPL 0x4 -#define NEEDS_SELECTED_VIDEO_CONTENT 0x8 +#define ALWAYS 0x0 +#define NEEDS_FILM 0x1 +#define NOT_DURING_DCP_CREATION 0x2 +#define NEEDS_CPL 0x4 +#define NEEDS_SINGLE_SELECTED_CONTENT 0x8 +#define NEEDS_SELECTED_CONTENT 0x10 +#define NEEDS_SELECTED_VIDEO_CONTENT 0x20 +#define NEEDS_CLIPBOARD 0x40 +#define NEEDS_ENCRYPTION 0x80 map menu_items; @@ -190,7 +200,9 @@ enum { ID_file_duplicate_and_open, ID_file_history, /* Allow spare IDs after _history for the recent files list */ - ID_content_scale_to_fit_width = 100, + ID_edit_copy = 100, + ID_edit_paste, + ID_content_scale_to_fit_width, ID_content_scale_to_fit_height, ID_jobs_make_dcp, ID_jobs_make_dcp_batch, @@ -199,7 +211,9 @@ enum { ID_jobs_export, ID_jobs_send_dcp_to_tms, ID_jobs_show_dcp, - ID_tools_video_waveform, + ID_jobs_open_dcp_in_player, + ID_view_closed_captions, + ID_view_video_waveform, ID_tools_hints, ID_tools_encoding_servers, ID_tools_manage_templates, @@ -208,13 +222,17 @@ enum { ID_help_report_a_problem, /* IDs for shortcuts (with no associated menu item) */ ID_add_file, - ID_remove + ID_remove, + ID_start_stop, + ID_timeline, + ID_back_frame, + ID_forward_frame }; class DOMFrame : public wxFrame { public: - DOMFrame (wxString const & title) + explicit DOMFrame (wxString const & title) : wxFrame (NULL, -1, title) , _video_waveform_dialog (0) , _hints_dialog (0) @@ -267,6 +285,8 @@ public: Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_duplicate_and_open, this), ID_file_duplicate_and_open); Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_history, this, _1), ID_file_history, ID_file_history + HISTORY_SIZE); Bind (wxEVT_MENU, boost::bind (&DOMFrame::file_exit, this), wxID_EXIT); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_copy, this), ID_edit_copy); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_paste, this), ID_edit_paste); Bind (wxEVT_MENU, boost::bind (&DOMFrame::edit_preferences, this), wxID_PREFERENCES); Bind (wxEVT_MENU, boost::bind (&DOMFrame::content_scale_to_fit_width, this), ID_content_scale_to_fit_width); Bind (wxEVT_MENU, boost::bind (&DOMFrame::content_scale_to_fit_height, this), ID_content_scale_to_fit_height); @@ -277,7 +297,9 @@ public: Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_export, this), ID_jobs_export); Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_send_dcp_to_tms, this), ID_jobs_send_dcp_to_tms); Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_show_dcp, this), ID_jobs_show_dcp); - Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_video_waveform, this), ID_tools_video_waveform); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_open_dcp_in_player, this), ID_jobs_open_dcp_in_player); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_closed_captions, this), ID_view_closed_captions); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::view_video_waveform, this), ID_view_video_waveform); Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_hints, this), ID_tools_hints); Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_encoding_servers, this), ID_tools_encoding_servers); Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_manage_templates, this), ID_tools_manage_templates); @@ -308,21 +330,51 @@ public: set_menu_sensitivity (); _film_editor->FileChanged.connect (bind (&DOMFrame::file_changed, this, _1)); + _film_editor->content_panel()->SelectionChanged.connect (boost::bind (&DOMFrame::set_menu_sensitivity, this)); file_changed (""); JobManager::instance()->ActiveJobsChanged.connect (boost::bind (&DOMFrame::set_menu_sensitivity, this)); overall_panel->SetSizer (main_sizer); - wxAcceleratorEntry accel[2]; + UpdateChecker::instance()->StateChanged.connect (boost::bind (&DOMFrame::update_checker_state_changed, this)); + + FocusManager::instance()->SetFocus.connect (boost::bind (&DOMFrame::remove_accelerators, this)); + FocusManager::instance()->KillFocus.connect (boost::bind (&DOMFrame::add_accelerators, this)); + add_accelerators (); + } + + void add_accelerators () + { +#ifdef __WXOSX__ + int accelerators = 7; +#else + int accelerators = 6; +#endif + wxAcceleratorEntry* accel = new wxAcceleratorEntry[accelerators]; accel[0].Set (wxACCEL_CTRL, static_cast('A'), ID_add_file); accel[1].Set (wxACCEL_NORMAL, WXK_DELETE, ID_remove); + accel[2].Set (wxACCEL_NORMAL, WXK_SPACE, ID_start_stop); + accel[3].Set (wxACCEL_CTRL, static_cast('T'), ID_timeline); + accel[4].Set (wxACCEL_NORMAL, WXK_LEFT, ID_back_frame); + accel[5].Set (wxACCEL_NORMAL, WXK_RIGHT, ID_forward_frame); +#ifdef __WXOSX__ + accel[6].Set (wxACCEL_CTRL, static_cast('W'), wxID_EXIT); +#endif Bind (wxEVT_MENU, boost::bind (&ContentPanel::add_file_clicked, _film_editor->content_panel()), ID_add_file); Bind (wxEVT_MENU, boost::bind (&DOMFrame::remove_clicked, this, _1), ID_remove); - wxAcceleratorTable accel_table (2, accel); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::start_stop_pressed, this), ID_start_stop); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::timeline_pressed, this), ID_timeline); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::back_frame, this), ID_back_frame); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::forward_frame, this), ID_forward_frame); + wxAcceleratorTable accel_table (accelerators, accel); SetAcceleratorTable (accel_table); + delete[] accel; + } - UpdateChecker::instance()->StateChanged.connect (boost::bind (&DOMFrame::update_checker_state_changed, this)); + void remove_accelerators () + { + SetAcceleratorTable (wxAcceleratorTable ()); } void remove_clicked (wxCommandEvent& ev) @@ -366,7 +418,7 @@ public: catch (std::exception& e) { wxString p = std_to_wx (file.string ()); wxCharBuffer b = p.ToUTF8 (); - error_dialog (this, wxString::Format (_("Could not open film at %s (%s)"), p.data(), std_to_wx (e.what()).data())); + error_dialog (this, wxString::Format (_("Could not open film at %s"), p.data()), std_to_wx (e.what())); } void set_film (shared_ptr film) @@ -374,12 +426,15 @@ public: _film = film; _film_viewer->set_film (_film); _film_editor->set_film (_film); - delete _video_waveform_dialog; - _video_waveform_dialog = 0; + if (_video_waveform_dialog) { + _video_waveform_dialog->Destroy (); + _video_waveform_dialog = 0; + } set_menu_sensitivity (); if (_film->directory()) { Config::instance()->add_to_history (_film->directory().get()); } + _film->Changed.connect (boost::bind (&DOMFrame::set_menu_sensitivity, this)); } shared_ptr film () const { @@ -404,7 +459,11 @@ private: int const r = d->ShowModal (); if (r == wxID_OK && d->check_path() && maybe_save_then_delete_film()) { - new_film (d->path(), d->template_name()); + try { + new_film (d->path(), d->template_name()); + } catch (boost::filesystem::filesystem_error& e) { + error_dialog (this, _("Could not create folder to store film"), std_to_wx(e.what())); + } } d->Destroy (); @@ -497,10 +556,47 @@ private: Close (false); } + void edit_copy () + { + ContentList const sel = _film_editor->content_panel()->selected(); + DCPOMATIC_ASSERT (sel.size() == 1); + _clipboard = sel.front()->clone(); + } + + void edit_paste () + { + DCPOMATIC_ASSERT (_clipboard); + + PasteDialog* d = new PasteDialog (this, static_cast(_clipboard->video), static_cast(_clipboard->audio), !_clipboard->caption.empty()); + if (d->ShowModal() == wxID_OK) { + BOOST_FOREACH (shared_ptr i, _film_editor->content_panel()->selected()) { + if (d->video() && i->video) { + DCPOMATIC_ASSERT (_clipboard->video); + i->video->take_settings_from (_clipboard->video); + } + if (d->audio() && i->audio) { + DCPOMATIC_ASSERT (_clipboard->audio); + i->audio->take_settings_from (_clipboard->audio); + } + + if (d->caption()) { + list >::iterator j = i->caption.begin (); + list >::const_iterator k = _clipboard->caption.begin (); + while (j != i->caption.end() && k != _clipboard->caption.end()) { + (*j)->take_settings_from (*k); + ++j; + ++k; + } + } + } + } + d->Destroy (); + } + void edit_preferences () { if (!_config_dialog) { - _config_dialog = create_config_dialog (); + _config_dialog = create_full_config_dialog (); } _config_dialog->Show (this); } @@ -576,9 +672,9 @@ private: _film->write_metadata (); _film->make_dcp (); } catch (BadSettingError& e) { - error_dialog (this, wxString::Format (_("Bad setting for %s (%s)"), std_to_wx(e.setting()).data(), std_to_wx(e.what()).data())); + error_dialog (this, wxString::Format (_("Bad setting for %s."), std_to_wx(e.setting()).data()), std_to_wx(e.what())); } catch (std::exception& e) { - error_dialog (this, wxString::Format (_("Could not make DCP: %s."), std_to_wx(e.what()).data())); + error_dialog (this, wxString::Format (_("Could not make DCP.")), std_to_wx(e.what())); } } @@ -597,55 +693,73 @@ private: _kdm_dialog->Show (); } - void jobs_make_dcp_batch () + /** @return false if we succeeded, true if not */ + bool send_to_other_tool (int port, function start, string message) { - if (!_film) { - return; - } - - if (!get_hints(_film).empty() && Config::instance()->show_hints_before_make_dcp()) { - HintsDialog* hints = new HintsDialog (this, _film, false); - int const r = hints->ShowModal(); - hints->Destroy (); - if (r == wxID_CANCEL) { - return; - } - } - - _film->write_metadata (); - /* i = 0; try to connect via socket - i = 1; try again, and then try to start the batch converter + i = 1; try again, and then try to start the tool i = 2 onwards; try again. */ for (int i = 0; i < 8; ++i) { try { boost::asio::io_service io_service; boost::asio::ip::tcp::resolver resolver (io_service); - boost::asio::ip::tcp::resolver::query query ("127.0.0.1", raw_convert (BATCH_JOB_PORT)); + boost::asio::ip::tcp::resolver::query query ("127.0.0.1", raw_convert (port)); boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve (query); Socket socket (5); socket.connect (*endpoint_iterator); DCPOMATIC_ASSERT (_film->directory ()); - string s = _film->directory()->string (); - socket.write (s.length() + 1); - socket.write ((uint8_t *) s.c_str(), s.length() + 1); + socket.write (message.length() + 1); + socket.write ((uint8_t *) message.c_str(), message.length() + 1); /* OK\0 */ uint8_t ok[3]; socket.read (ok, 3); - return; + return false; } catch (exception& e) { } if (i == 1) { - start_batch_converter (wx_to_std (wxStandardPaths::Get().GetExecutablePath())); + start (wx_to_std (wxStandardPaths::Get().GetExecutablePath())); } dcpomatic_sleep (1); } - error_dialog (this, _("Could not find batch converter.")); + return true; + } + + void jobs_make_dcp_batch () + { + if (!_film) { + return; + } + + if (!get_hints(_film).empty() && Config::instance()->show_hints_before_make_dcp()) { + HintsDialog* hints = new HintsDialog (this, _film, false); + int const r = hints->ShowModal(); + hints->Destroy (); + if (r == wxID_CANCEL) { + return; + } + } + + _film->write_metadata (); + + if (send_to_other_tool (BATCH_JOB_PORT, bind (&start_batch_converter, _1), _film->directory()->string())) { + error_dialog (this, _("Could not find batch converter.")); + } + } + + void jobs_open_dcp_in_player () + { + if (!_film) { + return; + } + + if (send_to_other_tool (PLAYER_PLAY_PORT, bind (&start_player, _1), _film->dir(_film->dcp_name(false)).string())) { + error_dialog (this, _("Could not find player.")); + } } void jobs_make_self_dkdm () @@ -667,7 +781,7 @@ private: _("You are making a DKDM which is encrypted by a private key held in" "\n\n%s\n\nIt is VITALLY IMPORTANT " "that you BACK UP THIS FILE since if it is lost " - "your DKDMs (and the DCPs they protect) will become useless."), std_to_wx(Config::config_path().string()).data() + "your DKDMs (and the DCPs they protect) will become useless."), std_to_wx(Config::config_file().string()).data() ) ); @@ -679,7 +793,9 @@ private: d->cpl (), dcp::LocalTime ("2012-01-01T01:00:00+00:00"), dcp::LocalTime ("2112-01-01T01:00:00+00:00"), - dcp::MODIFIED_TRANSITIONAL_1 + dcp::MODIFIED_TRANSITIONAL_1, + true, + 0 ); } catch (dcp::NotEncryptedError& e) { error_dialog (this, _("CPL's content is not encrypted.")); @@ -749,14 +865,14 @@ private: if (WEXITSTATUS (r) == 0) { r = system (String::compose("nautilus \"%1\"", _film->directory()->string()).c_str()); if (WEXITSTATUS (r)) { - error_dialog (this, _("Could not show DCP (could not run nautilus)")); + error_dialog (this, _("Could not show DCP."), _("Could not run nautilus")); } } else { int r = system ("which konqueror"); if (WEXITSTATUS (r) == 0) { r = system (String::compose ("konqueror \"%1\"", _film->directory()->string()).c_str()); if (WEXITSTATUS (r)) { - error_dialog (this, _("Could not show DCP (could not run konqueror)")); + error_dialog (this, _("Could not show DCP"), _("Could not run konqueror")); } } } @@ -770,7 +886,12 @@ private: #endif } - void tools_video_waveform () + void view_closed_captions () + { + _film_viewer->show_closed_captions (); + } + + void view_video_waveform () { if (!_video_waveform_dialog) { _video_waveform_dialog = new VideoWaveformDialog (this, _film, _film_viewer); @@ -892,6 +1013,8 @@ private: } bool const dcp_creation = (i != jobs.end ()) && !(*i)->finished (); bool const have_cpl = _film && !_film->cpls().empty (); + bool const have_single_selected_content = _film_editor->content_panel()->selected().size() == 1; + bool const have_selected_content = !_film_editor->content_panel()->selected().empty(); bool const have_selected_video_content = !_film_editor->content_panel()->selected_video().empty(); for (map::iterator j = menu_items.begin(); j != menu_items.end(); ++j) { @@ -910,10 +1033,26 @@ private: enabled = false; } + if ((j->second & NEEDS_SELECTED_CONTENT) && !have_selected_content) { + enabled = false; + } + + if ((j->second & NEEDS_SINGLE_SELECTED_CONTENT) && !have_single_selected_content) { + enabled = false; + } + if ((j->second & NEEDS_SELECTED_VIDEO_CONTENT) && !have_selected_video_content) { enabled = false; } + if ((j->second & NEEDS_CLIPBOARD) && !_clipboard) { + enabled = false; + } + + if ((j->second & NEEDS_ENCRYPTION) && (!_film || !_film->encrypted())) { + enabled = false; + } + j->first->Enable (enabled); } } @@ -984,10 +1123,13 @@ private: add_item (_file_menu, _("&Quit"), wxID_EXIT, ALWAYS); #endif + wxMenu* edit = new wxMenu; + add_item (edit, _("Copy settings\tCtrl-C"), ID_edit_copy, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_SINGLE_SELECTED_CONTENT); + add_item (edit, _("Paste settings...\tCtrl-V"), ID_edit_paste, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_SELECTED_CONTENT | NEEDS_CLIPBOARD); + #ifdef __WXOSX__ add_item (_file_menu, _("&Preferences...\tCtrl-P"), wxID_PREFERENCES, ALWAYS); #else - wxMenu* edit = new wxMenu; add_item (edit, _("&Preferences...\tCtrl-P"), wxID_PREFERENCES, ALWAYS); #endif @@ -1000,15 +1142,19 @@ private: add_item (jobs_menu, _("Make DCP in &batch converter\tCtrl-B"), ID_jobs_make_dcp_batch, NEEDS_FILM | NOT_DURING_DCP_CREATION); jobs_menu->AppendSeparator (); add_item (jobs_menu, _("Make &KDMs...\tCtrl-K"), ID_jobs_make_kdms, NEEDS_FILM); - add_item (jobs_menu, _("Make DKDM for DCP-o-matic..."), ID_jobs_make_self_dkdm, NEEDS_FILM); + add_item (jobs_menu, _("Make DKDM for DCP-o-matic..."), ID_jobs_make_self_dkdm, NEEDS_FILM | NEEDS_ENCRYPTION); jobs_menu->AppendSeparator (); add_item (jobs_menu, _("Export...\tCtrl-E"), ID_jobs_export, NEEDS_FILM); jobs_menu->AppendSeparator (); 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); + add_item (jobs_menu, _("Open DCP in &player"), ID_jobs_open_dcp_in_player, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL); + + wxMenu* view = new wxMenu; + add_item (view, _("Closed captions..."), ID_view_closed_captions, NEEDS_FILM); + add_item (view, _("Video waveform..."), ID_view_video_waveform, NEEDS_FILM); wxMenu* tools = new wxMenu; - add_item (tools, _("Video waveform..."), ID_tools_video_waveform, NEEDS_FILM); add_item (tools, _("Hints..."), ID_tools_hints, 0); add_item (tools, _("Encoding servers..."), ID_tools_encoding_servers, 0); add_item (tools, _("Manage templates..."), ID_tools_manage_templates, 0); @@ -1025,11 +1171,10 @@ private: add_item (help, _("Report a problem..."), ID_help_report_a_problem, NEEDS_FILM); m->Append (_file_menu, _("&File")); -#ifndef __WXOSX__ m->Append (edit, _("&Edit")); -#endif m->Append (content, _("&Content")); m->Append (jobs_menu, _("&Jobs")); + m->Append (view, _("&View")); m->Append (tools, _("&Tools")); m->Append (help, _("&Help")); } @@ -1122,6 +1267,30 @@ private: _update_news_requested = false; } + void start_stop_pressed () + { + if (_film_viewer->playing()) { + _film_viewer->stop(); + } else { + _film_viewer->start(); + } + } + + void timeline_pressed () + { + _film_editor->content_panel()->timeline_clicked (); + } + + void back_frame () + { + _film_viewer->back_frame (); + } + + void forward_frame () + { + _film_viewer->forward_frame (); + } + FilmEditor* _film_editor; FilmViewer* _film_viewer; VideoWaveformDialog* _video_waveform_dialog; @@ -1137,6 +1306,7 @@ private: wxMenuItem* _history_separator; boost::signals2::scoped_connection _config_changed_connection; bool _update_news_requested; + shared_ptr _clipboard; }; static const wxCmdLineEntryDesc command_line_description[] = { @@ -1166,20 +1336,9 @@ private: wxInitAllImageHandlers (); Config::FailedToLoad.connect (boost::bind (&App::config_failed_to_load, this)); + Config::Warning.connect (boost::bind (&App::config_warning, this, _1)); - wxSplashScreen* splash = 0; - try { - if (!Config::have_existing ("config.xml")) { - wxBitmap bitmap; - boost::filesystem::path p = shared_path () / "splash.png"; - if (bitmap.LoadFile (std_to_wx (p.string ()), wxBITMAP_TYPE_PNG)) { - splash = new wxSplashScreen (bitmap, wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT, 0, 0, -1); - wxYield (); - } - } - } catch (boost::filesystem::filesystem_error& e) { - /* Maybe we couldn't find the splash image; never mind */ - } + wxSplashScreen* splash = maybe_show_splash (); SetAppName (_("DCP-o-matic")); @@ -1217,6 +1376,8 @@ private: */ Config::drop (); + Config::BadSignerChain.connect (boost::bind (&App::config_bad_signer_chain, this)); + _frame = new DOMFrame (_("DCP-o-matic")); SetTopWindow (_frame); _frame->Maximize (); @@ -1229,7 +1390,7 @@ private: try { _frame->load_film (_film_to_load); } catch (exception& e) { - error_dialog (0, std_to_wx (String::compose (wx_to_std (_("Could not load film %1 (%2)")), _film_to_load, e.what()))); + error_dialog (0, std_to_wx (String::compose (wx_to_std (_("Could not load film %1 (%2)")), _film_to_load)), std_to_wx(e.what())); } } @@ -1260,7 +1421,7 @@ private: } catch (exception& e) { - error_dialog (0, wxString::Format ("DCP-o-matic could not start: %s", e.what ())); + error_dialog (0, wxString::Format ("DCP-o-matic could not start."), std_to_wx(e.what())); return true; } @@ -1351,6 +1512,23 @@ private: message_dialog (_frame, _("The existing configuration failed to load. Default values will be used instead. These may take a short time to create.")); } + void config_warning (string m) + { + message_dialog (_frame, std_to_wx (m)); + } + + bool config_bad_signer_chain () + { + if (Config::instance()->nagged(Config::NAG_BAD_SIGNER_CHAIN)) { + return false; + } + + RecreateChainDialog* d = new RecreateChainDialog (_frame); + int const r = d->ShowModal (); + d->Destroy (); + return r == wxID_OK; + } + DOMFrame* _frame; shared_ptr _timer; string _film_to_load;