summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-06-21 11:57:24 +0200
committerCarl Hetherington <cth@carlh.net>2025-07-10 23:13:14 +0200
commit9db2168dcc14a803dcd9da047ddd70e2142d82e2 (patch)
tree452103b2ed3a65cbaf9f3b4bb731c2afdbd809f7
parentd1c151cfdedbf1946d30e9072dc4a5b2ea5f2f80 (diff)
Allow specification of player crop in playlist.
-rw-r--r--src/lib/spl.cc4
-rw-r--r--src/lib/spl_entry.cc12
-rw-r--r--src/lib/spl_entry.h4
-rw-r--r--src/tools/dcpomatic_playlist.cc24
-rw-r--r--src/wx/spl_entry_dialog.cc76
-rw-r--r--src/wx/spl_entry_dialog.h42
-rw-r--r--src/wx/wscript1
7 files changed, 159 insertions, 4 deletions
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 <dcp/warnings.h>
+#include <fmt/format.h>
LIBDCP_DISABLE_WARNINGS
#include <libxml++/libxml++.h>
LIBDCP_ENABLE_WARNINGS
@@ -32,7 +33,7 @@ using std::dynamic_pointer_cast;
using std::shared_ptr;
-SPLEntry::SPLEntry(shared_ptr<Content> c)
+SPLEntry::SPLEntry(shared_ptr<Content> c, cxml::ConstNodePtr node)
: content(c)
, digest(content->digest())
{
@@ -46,6 +47,12 @@ SPLEntry::SPLEntry(shared_ptr<Content> c)
name = content->path(0).filename().string();
kind = dcp::ContentKind::FEATURE;
}
+
+ if (node) {
+ if (auto crop = node->optional_number_child<float>("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 <libcxml/cxml.h>
#include <dcp/content_kind.h>
+#include <libcxml/cxml.h>
namespace xmlpp {
@@ -37,7 +38,7 @@ class Content;
class SPLEntry
{
public:
- SPLEntry(std::shared_ptr<Content> c);
+ SPLEntry(std::shared_ptr<Content> c, cxml::ConstNodePtr node = {});
void as_xml(xmlpp::Element* e);
@@ -49,6 +50,7 @@ public:
boost::optional<std::string> id;
boost::optional<dcp::ContentKind> kind;
bool encrypted;
+ boost::optional<float> crop_to_ratio;
private:
void construct(std::shared_ptr<Content> 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<SignalSPL> _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 <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 "ratio_picker.h"
+#include "spl_entry_dialog.h"
+#include "wx_util.h"
+#include "lib/spl.h"
+#include <wx/wx.h>
+
+
+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<float> 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 <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 "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<float> 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