Add Version File dialog.
authorCarl Hetherington <cth@carlh.net>
Sun, 14 May 2023 21:42:27 +0000 (23:42 +0200)
committerCarl Hetherington <cth@carlh.net>
Sat, 16 Dec 2023 01:07:38 +0000 (02:07 +0100)
src/tools/dcpomatic.cc
src/wx/dcp_referencing_dialog.cc [new file with mode: 0644]
src/wx/dcp_referencing_dialog.h [new file with mode: 0644]
src/wx/wscript

index 956735198e4e6edfa7b492570603c0dafcdbc449..3464a73d5ab10d74d793c3a82cd8c10e92911fcc 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "wx/about_dialog.h"
 #include "wx/content_panel.h"
+#include "wx/dcp_referencing_dialog.h"
 #include "wx/dkdm_dialog.h"
 #include "wx/export_subtitles_dialog.h"
 #include "wx/export_video_file_dialog.h"
@@ -209,6 +210,7 @@ private:
 #define NEEDS_SELECTED_VIDEO_CONTENT  0x20
 #define NEEDS_CLIPBOARD               0x40
 #define NEEDS_ENCRYPTION              0x80
+#define NEEDS_DCP_CONTENT             0x100
 
 
 map<wxMenuItem*, int> menu_items;
@@ -238,6 +240,7 @@ enum {
        ID_jobs_open_dcp_in_player,
        ID_view_closed_captions,
        ID_view_video_waveform,
+       ID_tools_version_file,
        ID_tools_hints,
        ID_tools_encoding_servers,
        ID_tools_manage_templates,
@@ -349,6 +352,7 @@ public:
                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_version_file, this),      ID_tools_version_file);
                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);
@@ -1065,6 +1069,17 @@ private:
                _system_information_dialog->Show ();
        }
 
+       void tools_version_file()
+       {
+               if (_dcp_referencing_dialog) {
+                       _dcp_referencing_dialog->Destroy();
+                       _dcp_referencing_dialog = nullptr;
+               }
+
+               _dcp_referencing_dialog = new DCPReferencingDialog(this, _film);
+               _dcp_referencing_dialog->Show();
+       }
+
        void tools_hints ()
        {
                if (!_hints_dialog) {
@@ -1217,6 +1232,13 @@ private:
                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();
+               vector<shared_ptr<Content>> content;
+               if (_film) {
+                       content = _film->content();
+               }
+               bool const have_dcp_content = std::find_if(content.begin(), content.end(), [](shared_ptr<const Content> content) {
+                       return static_cast<bool>(dynamic_pointer_cast<const DCPContent>(content));
+               }) != content.end();
 
                for (auto j: menu_items) {
 
@@ -1254,6 +1276,10 @@ private:
                                enabled = false;
                        }
 
+                       if ((j.second & NEEDS_DCP_CONTENT) && !have_dcp_content) {
+                               enabled = false;
+                       }
+
                        j.first->Enable (enabled);
                }
        }
@@ -1387,6 +1413,7 @@ private:
                add_item (view, _("Video waveform..."), ID_view_video_waveform, NEEDS_FILM);
 
                auto tools = new wxMenu;
+               add_item (tools, _("Version File (VF)..."), ID_tools_version_file, NEEDS_FILM | NEEDS_DCP_CONTENT);
                add_item (tools, _("Hints..."), ID_tools_hints, NEEDS_FILM);
                add_item (tools, _("Encoding servers..."), ID_tools_encoding_servers, 0);
                add_item (tools, _("Manage templates..."), ID_tools_manage_templates, 0);
@@ -1557,6 +1584,7 @@ private:
        StandardControls* _controls;
        wx_ptr<VideoWaveformDialog> _video_waveform_dialog;
        SystemInformationDialog* _system_information_dialog = nullptr;
+       DCPReferencingDialog* _dcp_referencing_dialog = nullptr;
        HintsDialog* _hints_dialog = nullptr;
        ServersListDialog* _servers_list_dialog = nullptr;
        wxPreferencesEditor* _config_dialog = nullptr;
diff --git a/src/wx/dcp_referencing_dialog.cc b/src/wx/dcp_referencing_dialog.cc
new file mode 100644 (file)
index 0000000..853391b
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+    Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "check_box.h"
+#include "dcp_referencing_dialog.h"
+#include "static_text.h"
+#include "wx_util.h"
+#include "lib/dcp_content.h"
+#include "lib/film.h"
+#include "lib/types.h"
+#include <wx/gbsizer.h>
+#include <wx/wx.h>
+
+
+using std::dynamic_pointer_cast;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+using std::weak_ptr;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
+
+
+DCPReferencingDialog::DCPReferencingDialog(wxWindow* parent, shared_ptr<const Film> film)
+       : wxDialog(parent, wxID_ANY, _("Version file (VF) setup"))
+       , _film(film)
+       , _dcp_grid(new wxGridBagSizer(DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP))
+       , _overall_sizer(new wxBoxSizer(wxVERTICAL))
+{
+       _film_connection = film->Change.connect(boost::bind(&DCPReferencingDialog::film_changed, this, _1, _2));
+       _film_content_connection = film->ContentChange.connect(boost::bind(&DCPReferencingDialog::film_content_changed, this, _1, _3));
+
+       _overall_sizer->Add(_dcp_grid, 1, wxALL, DCPOMATIC_DIALOG_BORDER);
+       SetSizer(_overall_sizer);
+
+       auto buttons = CreateSeparatedButtonSizer(wxOK);
+       if (buttons) {
+               _overall_sizer->Add(buttons, wxSizerFlags().Expand().DoubleBorder());
+       }
+
+       setup();
+}
+
+
+void
+DCPReferencingDialog::film_changed(ChangeType type, FilmProperty property)
+{
+       if (type != ChangeType::DONE) {
+               return;
+       }
+
+       if (
+               property == FilmProperty::INTEROP ||
+               property == FilmProperty::RESOLUTION ||
+               property == FilmProperty::CONTAINER ||
+               property == FilmProperty::REEL_TYPE ||
+               property == FilmProperty::VIDEO_FRAME_RATE ||
+               property == FilmProperty::CONTENT) {
+               setup();
+       }
+}
+
+
+void
+DCPReferencingDialog::film_content_changed(ChangeType type, int property)
+{
+       if (type != ChangeType::DONE) {
+               return;
+       }
+
+       if (
+               property != DCPContentProperty::REFERENCE_VIDEO &&
+               property != DCPContentProperty::REFERENCE_AUDIO &&
+               property != DCPContentProperty::REFERENCE_TEXT) {
+               setup();
+       }
+}
+
+
+void
+DCPReferencingDialog::setup()
+{
+       _dcps.clear();
+       _dcp_grid->Clear(true);
+
+       int column = 0;
+       for (auto const& heading: { _("DCP"), _("Picture"), _("Sound"), _("Subtitles"), _("Closed captions") }) {
+               auto text = new StaticText(this, heading);
+               wxFont font(*wxNORMAL_FONT);
+               font.SetWeight(wxFONTWEIGHT_BOLD);
+               text->SetFont(font);
+               _dcp_grid->Add(text, wxGBPosition(0, column), wxDefaultSpan, wxALL, DCPOMATIC_SIZER_GAP);
+               ++column;
+       };
+
+       auto const all_parts = { Part::VIDEO, Part::AUDIO, Part::SUBTITLES, Part::CLOSED_CAPTIONS };
+
+       int row = 1;
+       for (auto& content: _film->content()) {
+               auto dcp_content = dynamic_pointer_cast<DCPContent>(content);
+               if (!dcp_content) {
+                       continue;
+               }
+
+               DCP record;
+               record.content = dcp_content;
+               _dcp_grid->Add(new StaticText(this, std_to_wx(dcp_content->name())), wxGBPosition(row, 0));
+               column = 1;
+               for (auto const& part: all_parts) {
+                       record.check_box[part] = new CheckBox(this, wxT(""));
+                       switch (part) {
+                       case Part::VIDEO:
+                               record.check_box[part]->set(dcp_content->reference_video());
+                               break;
+                       case Part::AUDIO:
+                               record.check_box[part]->set(dcp_content->reference_audio());
+                               break;
+                       case Part::SUBTITLES:
+                               record.check_box[part]->set(dcp_content->reference_text(TextType::OPEN_SUBTITLE));
+                               break;
+                       case Part::CLOSED_CAPTIONS:
+                               record.check_box[part]->set(dcp_content->reference_text(TextType::CLOSED_CAPTION));
+                               break;
+                       default:
+                               DCPOMATIC_ASSERT(false);
+                       }
+                       record.check_box[part]->bind(&DCPReferencingDialog::checkbox_changed, this, weak_ptr<DCPContent>(dcp_content), record.check_box[part], part);
+                       _dcp_grid->Add(record.check_box[part], wxGBPosition(row, column++), wxDefaultSpan, wxALIGN_CENTER);
+               }
+               ++row;
+
+               auto add_problem = [this, &row](wxString const& cannot, string why_not) {
+                       auto reason = new StaticText(this, cannot + wxT(": ") + std_to_wx(why_not));
+                       wxFont font(*wxNORMAL_FONT);
+                       font.SetStyle(wxFONTSTYLE_ITALIC);
+                       reason->SetFont(font);
+                       _dcp_grid->Add(reason, wxGBPosition(row, 0), wxGBSpan(1, 5), wxLEFT, DCPOMATIC_SIZER_X_GAP * 4);
+                       ++row;
+               };
+
+               string why_not;
+
+               if (!dcp_content->can_reference_anything(_film, why_not)) {
+                       for (auto const& part: all_parts) {
+                               record.check_box[part]->Enable(false);
+                       }
+                       add_problem(_("Cannot reference this DCP"), why_not);
+               } else {
+                       if (!dcp_content->can_reference_video(_film, why_not)) {
+                               record.check_box[Part::VIDEO]->Enable(false);
+                               if (dcp_content->video) {
+                                       add_problem(_("Cannot reference this DCP's video"), why_not);
+                               }
+                       }
+
+                       if (!dcp_content->can_reference_audio(_film, why_not)) {
+                               record.check_box[Part::AUDIO]->Enable(false);
+                               if (dcp_content->audio) {
+                                       add_problem(_("Cannot reference this DCP's audio"), why_not);
+                               }
+                       }
+
+                       if (!dcp_content->can_reference_text(_film, TextType::OPEN_SUBTITLE, why_not)) {
+                               record.check_box[Part::SUBTITLES]->Enable(false);
+                               if (dcp_content->text_of_original_type(TextType::OPEN_SUBTITLE)) {
+                                       add_problem(_("Cannot reference this DCP's subtitles"), why_not);
+                               }
+                       }
+
+                       if (!dcp_content->can_reference_text(_film, TextType::CLOSED_CAPTION, why_not)) {
+                               record.check_box[Part::CLOSED_CAPTIONS]->Enable(false);
+                               if (dcp_content->text_of_original_type(TextType::CLOSED_CAPTION)) {
+                                       add_problem(_("Cannot reference this DCP's closed captions"), why_not);
+                               }
+                       }
+               }
+
+               _dcps.push_back(record);
+       }
+
+       _dcp_grid->Layout();
+       _overall_sizer->Layout();
+       _overall_sizer->SetSizeHints(this);
+}
+
+
+void
+DCPReferencingDialog::checkbox_changed(weak_ptr<DCPContent> weak_content, CheckBox* check_box, Part part)
+{
+       auto content = weak_content.lock();
+       if (!content) {
+               return;
+       }
+
+       switch (part) {
+       case Part::VIDEO:
+               content->set_reference_video(check_box->get());
+               break;
+       case Part::AUDIO:
+               content->set_reference_audio(check_box->get());
+               break;
+       case Part::SUBTITLES:
+               content->set_reference_text(TextType::OPEN_SUBTITLE, check_box->get());
+               break;
+       case Part::CLOSED_CAPTIONS:
+               content->set_reference_text(TextType::CLOSED_CAPTION, check_box->get());
+               break;
+       default:
+               DCPOMATIC_ASSERT(false);
+       }
+}
+
diff --git a/src/wx/dcp_referencing_dialog.h b/src/wx/dcp_referencing_dialog.h
new file mode 100644 (file)
index 0000000..e49292c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+    Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "lib/enum_indexed_vector.h"
+#include "lib/film.h"
+#include <wx/wx.h>
+#include <memory>
+#include <vector>
+
+
+class CheckBox;
+class DCPContent;
+class Film;
+class wxBoxSizer;
+class wxGridBagSizer;
+
+
+class DCPReferencingDialog : public wxDialog
+{
+public:
+       DCPReferencingDialog(wxWindow* parent, std::shared_ptr<const Film> film);
+
+private:
+       enum class Part {
+               VIDEO,
+               AUDIO,
+               SUBTITLES,
+               CLOSED_CAPTIONS,
+               COUNT
+       };
+
+       void setup();
+       void checkbox_changed(std::weak_ptr<DCPContent> content, CheckBox* check_box, Part part);
+       void film_changed(ChangeType type, FilmProperty property);
+       void film_content_changed(ChangeType type, int property);
+
+       std::shared_ptr<const Film> _film;
+
+       wxGridBagSizer* _dcp_grid;
+       wxBoxSizer* _overall_sizer;
+
+       struct DCP {
+               std::shared_ptr<DCPContent> content;
+               EnumIndexedVector<CheckBox*, Part> check_box;
+       };
+
+       std::vector<DCP> _dcps;
+
+       boost::signals2::scoped_connection _film_connection;
+       boost::signals2::scoped_connection _film_content_connection;
+};
+
index 9c6ea6b8435c0ab71f00b1f08d402c04cccfd143..7dbd214c6ebc305833137fa91deed7f727717eff 100644 (file)
@@ -53,6 +53,7 @@ sources = """
           controls.cc
           credentials_download_certificate_panel.cc
           custom_scale_dialog.cc
+          dcp_referencing_dialog.cc
           dcp_panel.cc
           dcp_text_track_dialog.cc
           dcpomatic_button.cc