#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"
#define NEEDS_SELECTED_VIDEO_CONTENT 0x20
#define NEEDS_CLIPBOARD 0x40
#define NEEDS_ENCRYPTION 0x80
+#define NEEDS_DCP_CONTENT 0x100
map<wxMenuItem*, int> menu_items;
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,
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);
_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) {
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) {
enabled = false;
}
+ if ((j.second & NEEDS_DCP_CONTENT) && !have_dcp_content) {
+ enabled = false;
+ }
+
j.first->Enable (enabled);
}
}
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);
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;
--- /dev/null
+/*
+ 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);
+ }
+}
+
--- /dev/null
+/*
+ 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;
+};
+