From 9db2168dcc14a803dcd9da047ddd70e2142d82e2 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 21 Jun 2025 11:57:24 +0200 Subject: Allow specification of player crop in playlist. --- src/lib/spl.cc | 4 +-- src/lib/spl_entry.cc | 12 ++++++- src/lib/spl_entry.h | 4 ++- src/tools/dcpomatic_playlist.cc | 24 +++++++++++++ src/wx/spl_entry_dialog.cc | 76 +++++++++++++++++++++++++++++++++++++++++ src/wx/spl_entry_dialog.h | 42 +++++++++++++++++++++++ src/wx/wscript | 1 + 7 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 src/wx/spl_entry_dialog.cc create mode 100644 src/wx/spl_entry_dialog.h diff --git a/src/lib/spl.cc b/src/lib/spl.cc index ff37e5cbf..652efe5b8 100644 --- a/src/lib/spl.cc +++ b/src/lib/spl.cc @@ -47,13 +47,13 @@ SPL::read (boost::filesystem::path path, ContentStore* store) for (auto i: doc.node_children("Entry")) { if (auto cpl = i->optional_string_child("CPL")) { if (auto c = store->get_by_cpl_id(*cpl)) { - add(SPLEntry(c)); + add(SPLEntry(c, i)); } else { _missing = true; } } else { if (auto c = store->get_by_digest(i->string_child("Digest"))) { - add(SPLEntry(c)); + add(SPLEntry(c, i)); } else { _missing = true; } diff --git a/src/lib/spl_entry.cc b/src/lib/spl_entry.cc index 03df91729..2fc179841 100644 --- a/src/lib/spl_entry.cc +++ b/src/lib/spl_entry.cc @@ -23,6 +23,7 @@ #include "dcpomatic_assert.h" #include "spl_entry.h" #include +#include LIBDCP_DISABLE_WARNINGS #include LIBDCP_ENABLE_WARNINGS @@ -32,7 +33,7 @@ using std::dynamic_pointer_cast; using std::shared_ptr; -SPLEntry::SPLEntry(shared_ptr c) +SPLEntry::SPLEntry(shared_ptr c, cxml::ConstNodePtr node) : content(c) , digest(content->digest()) { @@ -46,6 +47,12 @@ SPLEntry::SPLEntry(shared_ptr c) name = content->path(0).filename().string(); kind = dcp::ContentKind::FEATURE; } + + if (node) { + if (auto crop = node->optional_number_child("CropToRatio")) { + crop_to_ratio = *crop; + } + } } @@ -57,4 +64,7 @@ SPLEntry::as_xml(xmlpp::Element* e) } else { cxml::add_text_child(e, "Digest", digest); } + if (crop_to_ratio) { + cxml::add_text_child(e, "CropToRatio", fmt::to_string(*crop_to_ratio)); + } } diff --git a/src/lib/spl_entry.h b/src/lib/spl_entry.h index 02f1c03c9..dd304b374 100644 --- a/src/lib/spl_entry.h +++ b/src/lib/spl_entry.h @@ -25,6 +25,7 @@ #include #include +#include namespace xmlpp { @@ -37,7 +38,7 @@ class Content; class SPLEntry { public: - SPLEntry(std::shared_ptr c); + SPLEntry(std::shared_ptr c, cxml::ConstNodePtr node = {}); void as_xml(xmlpp::Element* e); @@ -49,6 +50,7 @@ public: boost::optional id; boost::optional kind; bool encrypted; + boost::optional crop_to_ratio; private: void construct(std::shared_ptr content); diff --git a/src/tools/dcpomatic_playlist.cc b/src/tools/dcpomatic_playlist.cc index f3b55b72b..f90af4a29 100644 --- a/src/tools/dcpomatic_playlist.cc +++ b/src/tools/dcpomatic_playlist.cc @@ -24,6 +24,7 @@ #include "wx/dcpomatic_button.h" #include "wx/i18n_setup.h" #include "wx/playlist_editor_config_dialog.h" +#include "wx/spl_entry_dialog.h" #include "wx/wx_signal_manager.h" #include "wx/wx_util.h" #include "wx/wx_variant.h" @@ -315,6 +316,7 @@ class PlaylistContent public: PlaylistContent(wxPanel* parent, ContentDialog* content_dialog) : _content_dialog(content_dialog) + , _parent(parent) , _sizer(new wxBoxSizer(wxVERTICAL)) { auto title = new wxBoxSizer(wxHORIZONTAL); @@ -337,6 +339,7 @@ public: _list->AppendColumn(_("CPL"), wxLIST_FORMAT_LEFT, 350); _list->AppendColumn(_("Type"), wxLIST_FORMAT_LEFT, 100); _list->AppendColumn(_("Encrypted"), wxLIST_FORMAT_CENTRE, 90); + _list->AppendColumn(_("Crop"), wxLIST_FORMAT_LEFT, 120); list->Add(_list, 1, wxEXPAND | wxALL, DCPOMATIC_SIZER_GAP); @@ -345,10 +348,12 @@ public: _down = new Button(parent, _("Down")); _add = new Button(parent, _("Add")); _remove = new Button(parent, _("Remove")); + _edit = new Button(parent, _("Edit...")); button_sizer->Add(_up, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); button_sizer->Add(_down, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); button_sizer->Add(_add, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); button_sizer->Add(_remove, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + button_sizer->Add(_edit, 0, wxEXPAND | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); list->Add(button_sizer, 0, wxALL, DCPOMATIC_SIZER_GAP); @@ -362,6 +367,7 @@ public: _down->Bind(wxEVT_BUTTON, bind(&PlaylistContent::down_clicked, this)); _add->Bind(wxEVT_BUTTON, bind(&PlaylistContent::add_clicked, this)); _remove->Bind(wxEVT_BUTTON, bind(&PlaylistContent::remove_clicked, this)); + _edit->Bind(wxEVT_BUTTON, bind(&PlaylistContent::edit_clicked, this)); setup_sensitivity(); } @@ -421,6 +427,7 @@ private: _list->SetItem(N, 1, std_to_wx(e.id.get_value_or(""))); _list->SetItem(N, 2, std_to_wx(e.kind->name())); _list->SetItem(N, 3, e.encrypted ? S_("Question|Y") : S_("Question|N")); + _list->SetItem(N, 4, e.crop_to_ratio ? wxString::Format(char_to_wx("%.2f"), *e.crop_to_ratio) : char_to_wx("")); } void setup_sensitivity() @@ -435,6 +442,7 @@ private: _down->Enable(have_list && selected != -1 && selected <(_list->GetItemCount() - 1)); _add->Enable(have_list); _remove->Enable(have_list && num_selected > 0); + _edit->Enable(have_list && num_selected > 0); } void add_clicked() @@ -493,7 +501,22 @@ private: _list->DeleteItem(s); } + void edit_clicked() + { + long int s = _list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (s == -1) { + return; + } + + SPLEntryDialog dialog(_parent, _playlist->get(s)); + if (dialog.ShowModal() == wxID_OK) { + _playlist->set(s, dialog.get()); + set_item(s, _playlist->get(s)); + } + } + ContentDialog* _content_dialog; + wxWindow* _parent; wxBoxSizer* _sizer; wxTextCtrl* _name; Button* _save_name; @@ -502,6 +525,7 @@ private: wxButton* _down; wxButton* _add; wxButton* _remove; + wxButton* _edit; shared_ptr _playlist; }; diff --git a/src/wx/spl_entry_dialog.cc b/src/wx/spl_entry_dialog.cc new file mode 100644 index 000000000..332b7840c --- /dev/null +++ b/src/wx/spl_entry_dialog.cc @@ -0,0 +1,76 @@ +/* + Copyright (C) 2025 Carl Hetherington + + 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 . + +*/ + + +#include "check_box.h" +#include "ratio_picker.h" +#include "spl_entry_dialog.h" +#include "wx_util.h" +#include "lib/spl.h" +#include + + +using boost::optional; +#if BOOST_VERSION >= 106100 +using namespace boost::placeholders; +#endif + + + +SPLEntryDialog::SPLEntryDialog(wxWindow* parent, SPLEntry entry) + : TableDialog(parent, _("Playlist item"), 2, 1, true) + , _entry(entry) +{ + add(_("Name"), true); + auto name = _entry.name; +#ifdef DCPOMATIC_LINUX + boost::replace_all(name, "_", "__"); +#endif + add(std_to_wx(name), false); + add(_("CPL"), true); + add(std_to_wx(_entry.id.get_value_or("")), false); + add(_("Type"), true); + add(std_to_wx(_entry.kind->name()), false); + add(_("Encrypted"), true); + add(_entry.encrypted ? _("Yes") : _("No"), false); + + _crop = new RatioPicker(this, entry.crop_to_ratio); + add(_crop->enable_checkbox(), false); + add(_crop, false); + + layout(); + + _crop->Changed.connect(boost::bind(&SPLEntryDialog::crop_changed, this, _1)); +} + + +SPLEntry +SPLEntryDialog::get() const +{ + return _entry; +} + + +void +SPLEntryDialog::crop_changed(optional ratio) +{ + _entry.crop_to_ratio = ratio; +} + diff --git a/src/wx/spl_entry_dialog.h b/src/wx/spl_entry_dialog.h new file mode 100644 index 000000000..63e4ba56f --- /dev/null +++ b/src/wx/spl_entry_dialog.h @@ -0,0 +1,42 @@ +/* + Copyright (C) 2025 Carl Hetherington + + 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 . + +*/ + + +#include "table_dialog.h" +#include "lib/spl.h" + + +class RatioPicker; + + +class SPLEntryDialog : public TableDialog +{ +public: + SPLEntryDialog(wxWindow* parent, SPLEntry entry); + + SPLEntry get() const; + +private: + void crop_changed(boost::optional ratio); + + SPLEntry _entry; + + RatioPicker* _crop; +}; diff --git a/src/wx/wscript b/src/wx/wscript index 3049d842d..06e24936c 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -164,6 +164,7 @@ sources = """ simple_video_view.cc smpte_metadata_dialog.cc sound_preferences_page.cc + spl_entry_dialog.cc standard_controls.cc static_text.cc subtag_list_ctrl.cc -- cgit v1.2.3