X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Ftools%2Fdcpomatic.cc;h=b221201435deac4504cf1090b2602e2edac9457a;hb=c6871fe8617b3de03662b7630355059393bf8043;hp=4b79d67ed028e37d2c69888bb72d97c1475eec14;hpb=9bf9d637a6fd105418c0af84727ba68823142943;p=dcpomatic.git diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 4b79d67ed..b22120143 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,7 +25,7 @@ #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" @@ -42,6 +42,7 @@ #include "wx/templates_dialog.h" #include "wx/nag_dialog.h" #include "wx/export_dialog.h" +#include "wx/paste_dialog.h" #include "lib/film.h" #include "lib/config.h" #include "lib/util.h" @@ -67,6 +68,8 @@ #include "lib/ffmpeg_encoder.h" #include "lib/transcode_job.h" #include "lib/dkdm_wrapper.h" +#include "lib/audio_content.h" +#include "lib/subtitle_content.h" #include #include #include @@ -110,7 +113,7 @@ using dcp::raw_convert; class FilmChangedClosingDialog : public boost::noncopyable { public: - FilmChangedClosingDialog (string name) + explicit FilmChangedClosingDialog (string name) { _dialog = new wxMessageDialog ( 0, @@ -143,7 +146,7 @@ private: class FilmChangedDuplicatingDialog : public boost::noncopyable { public: - FilmChangedDuplicatingDialog (string name) + explicit FilmChangedDuplicatingDialog (string name) { _dialog = new wxMessageDialog ( 0, @@ -173,11 +176,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 +197,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, @@ -214,7 +223,7 @@ enum { 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 +276,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); @@ -308,19 +319,29 @@ 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]; +#ifdef __WXOSX__ + int accelerators = 3; +#else + int accelerators = 2; +#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); +#ifdef __WXOSX__ + accel[2].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); + wxAcceleratorTable accel_table (accelerators, accel); SetAcceleratorTable (accel_table); + delete[] accel; UpdateChecker::instance()->StateChanged.connect (boost::bind (&DOMFrame::update_checker_state_changed, this)); } @@ -366,7 +387,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) @@ -380,6 +401,7 @@ public: 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 { @@ -497,10 +519,41 @@ 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), static_cast(_clipboard->subtitle)); + 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->subtitle() && i->subtitle) { + DCPOMATIC_ASSERT (_clipboard->subtitle); + i->subtitle->take_settings_from (_clipboard->subtitle); + } + } + } + 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 +629,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())); } } @@ -679,7 +732,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 +804,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")); } } } @@ -892,6 +947,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 +967,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 +1057,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,7 +1076,7 @@ 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 (); @@ -1025,9 +1101,7 @@ 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 (tools, _("&Tools")); @@ -1137,6 +1211,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 +1241,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")); @@ -1229,7 +1293,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 +1324,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 +1415,11 @@ 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)); + } + DOMFrame* _frame; shared_ptr _timer; string _film_to_load;