summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-10-20 21:22:17 +0200
committerCarl Hetherington <cth@carlh.net>2026-02-16 01:20:38 +0100
commit0cb5e386c282ae34dd065e7e294030969645913e (patch)
treebac83ad896e18c4f576e60971089fb3288cc8073
parent4cb6ab669032ef0584fde63e62addfe8a71a484c (diff)
Replace find_and_resolve_cpls() with storing all CPL IDs in DCPContent (sometimes).
In some places we need other details than the ID, but in lots of places this saves some disk searching.
-rw-r--r--src/lib/dcp_content.cc21
-rw-r--r--src/lib/dcp_content.h6
-rw-r--r--src/lib/dcp_decoder.cc4
-rw-r--r--src/lib/dcp_examiner.cc5
-rw-r--r--src/lib/dcp_examiner.h5
-rw-r--r--src/lib/show_playlist_content_store.cc9
-rw-r--r--src/tools/dcpomatic_player.cc7
-rw-r--r--src/wx/content_menu.cc8
8 files changed, 48 insertions, 17 deletions
diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc
index 6e071e5c0..98c49fae4 100644
--- a/src/lib/dcp_content.cc
+++ b/src/lib/dcp_content.cc
@@ -145,7 +145,17 @@ DCPContent::DCPContent(cxml::ConstNodePtr node, boost::optional<boost::filesyste
if (ck) {
_content_kind = dcp::ContentKind::from_name(*ck);
}
- _cpl = node->optional_string_child("CPL");
+ for (auto cpl: node->node_children("CPL")) {
+ _cpls.push_back(cpl->content());
+ if (auto selected = cpl->optional_bool_attribute("selected")) {
+ if (selected) {
+ _cpl = cpl->content();
+ }
+ }
+ }
+ if (!_cpl && !_cpls.empty()) {
+ _cpl = _cpls.front();
+ }
for (auto i: node->node_children("ReelLength")) {
_reel_lengths.push_back(raw_convert<int64_t>(i->content()));
}
@@ -340,6 +350,7 @@ DCPContent::examine(shared_ptr<Job> job, bool tolerant)
_video_encoding = examiner->video_encoding();
_three_d = examiner->three_d();
_content_kind = examiner->content_kind();
+ _cpls = examiner->cpls();
_cpl = examiner->cpl();
_reel_lengths = examiner->reel_lengths();
_markers = examiner->markers();
@@ -466,8 +477,12 @@ DCPContent::as_xml(xmlpp::Element* element, bool with_paths, PathBehaviour path_
if (_content_kind) {
cxml::add_text_child(element, "ContentKind", _content_kind->name());
}
- if (_cpl) {
- cxml::add_text_child(element, "CPL", _cpl.get());
+ for (auto cpl: _cpls) {
+ auto e = cxml::add_child(element, "CPL");
+ e->add_child_text(cpl);
+ if (cpl == _cpl) {
+ e->set_attribute("selected", "1");
+ }
}
for (auto i: _reel_lengths) {
cxml::add_text_child(element, "ReelLength", fmt::to_string(i));
diff --git a/src/lib/dcp_content.h b/src/lib/dcp_content.h
index 8a34c4bbe..a76028a67 100644
--- a/src/lib/dcp_content.h
+++ b/src/lib/dcp_content.h
@@ -166,6 +166,11 @@ public:
void set_cpl(std::string id);
+ std::vector<std::string> cpls() const {
+ boost::mutex::scoped_lock lm(_mutex);
+ return _cpls;
+ }
+
boost::optional<std::string> cpl() const {
boost::mutex::scoped_lock lm(_mutex);
return _cpl;
@@ -278,6 +283,7 @@ private:
boost::optional<VideoEncoding> _video_encoding;
boost::optional<dcp::ContentKind> _content_kind;
bool _three_d;
+ std::vector<std::string> _cpls;
/** ID of the CPL to use; older metadata might not specify this: in that case
* just use the only CPL.
*/
diff --git a/src/lib/dcp_decoder.cc b/src/lib/dcp_decoder.cc
index 42119a041..4809d772a 100644
--- a/src/lib/dcp_decoder.cc
+++ b/src/lib/dcp_decoder.cc
@@ -101,6 +101,10 @@ DCPDecoder::DCPDecoder(shared_ptr<const Film> film, shared_ptr<const DCPContent>
We do this by storing a digest of the important bits of the DCPContent and then checking that's
the same before we re-use _reels.
+
+ XXX: this seems a bit dubious - why is a complete re-examine not necessary in this case?
+ Or why is this done for DCPs only, and not other files that might change?
+ (see blame for the comment above for some reasons)
*/
_lazy_digest = calculate_lazy_digest(content);
diff --git a/src/lib/dcp_examiner.cc b/src/lib/dcp_examiner.cc
index b749c9686..e5e42a923 100644
--- a/src/lib/dcp_examiner.cc
+++ b/src/lib/dcp_examiner.cc
@@ -119,6 +119,9 @@ DCPExaminer::DCPExaminer(shared_ptr<const DCPContent> content, bool tolerant)
selected_cpl->add(decrypt_kdm_with_helpful_error(content->kdm().get()));
}
+ for (auto cpl: cpls) {
+ _cpls.push_back(cpl->id());
+ }
_cpl = selected_cpl->id();
_name = selected_cpl->content_title_text();
_content_kind = selected_cpl->content_kind();
@@ -364,8 +367,6 @@ DCPExaminer::DCPExaminer(shared_ptr<const DCPContent> content, bool tolerant)
for (auto version: selected_cpl->content_versions()) {
_content_versions.push_back(version.label_text);
}
-
- _cpl = selected_cpl->id();
}
diff --git a/src/lib/dcp_examiner.h b/src/lib/dcp_examiner.h
index 7e73a8b09..12cd32500 100644
--- a/src/lib/dcp_examiner.h
+++ b/src/lib/dcp_examiner.h
@@ -163,6 +163,10 @@ public:
return *_content_kind;
}
+ std::vector<std::string> cpls() const {
+ return _cpls;
+ }
+
std::string cpl() const {
return _cpl;
}
@@ -249,6 +253,7 @@ private:
boost::optional<VideoEncoding> _video_encoding;
bool _three_d = false;
boost::optional<dcp::ContentKind> _content_kind;
+ std::vector<std::string> _cpls;
std::string _cpl;
std::list<int64_t> _reel_lengths;
std::map<dcp::Marker, dcpomatic::ContentTime> _markers;
diff --git a/src/lib/show_playlist_content_store.cc b/src/lib/show_playlist_content_store.cc
index 1a9f533af..6e1100c70 100644
--- a/src/lib/show_playlist_content_store.cc
+++ b/src/lib/show_playlist_content_store.cc
@@ -70,12 +70,13 @@ ShowPlaylistContentStore::update(std::function<bool()> pulse)
if (is_directory(i) && contains_assetmap(i)) {
auto dcp = make_shared<DCPContent>(i);
+ examine(dcp);
/* Add a Content for each CPL in this DCP, so we can choose CPLs to play
* rather than DCPs.
*/
- for (auto cpl: dcp::find_and_resolve_cpls(dcp->directories(), true)) {
+ for (auto cpl: dcp->cpls()) {
auto copy = dynamic_pointer_cast<DCPContent>(dcp->clone());
- copy->set_cpl(cpl->id());
+ copy->set_cpl(cpl);
examine(copy);
}
} else if (i.path().extension() == ".mp4") {
@@ -121,8 +122,8 @@ ShowPlaylistContentStore::get(string const& uuid) const
{
auto iter = std::find_if(_content.begin(), _content.end(), [uuid](shared_ptr<const Content> content) {
if (auto dcp = dynamic_pointer_cast<const DCPContent>(content)) {
- for (auto cpl: dcp::find_and_resolve_cpls(dcp->directories(), true)) {
- if (cpl->id() == uuid) {
+ for (auto cpl: dcp->cpls()) {
+ if (cpl == uuid) {
return true;
}
}
diff --git a/src/tools/dcpomatic_player.cc b/src/tools/dcpomatic_player.cc
index 30a8d1071..b4425fe25 100644
--- a/src/tools/dcpomatic_player.cc
+++ b/src/tools/dcpomatic_player.cc
@@ -549,8 +549,7 @@ public:
if (_film->content().size() == 1) {
/* Offer a CPL menu */
- auto first = dynamic_pointer_cast<DCPContent>(_film->content().front());
- if (first) {
+ if (auto first = dynamic_pointer_cast<DCPContent>(_film->content().front())) {
int id = ID_view_cpl;
for (auto i: dcp::find_and_resolve_cpls(first->directories(), true)) {
auto j = _cpl_menu->AppendRadioItem(
@@ -916,7 +915,7 @@ private:
{
auto dcp = std::dynamic_pointer_cast<DCPContent>(_film->content().front());
DCPOMATIC_ASSERT(dcp);
- auto cpls = dcp::find_and_resolve_cpls(dcp->directories(), true);
+ auto cpls = dcp->cpls();
int id = ev.GetId() - ID_view_cpl;
DCPOMATIC_ASSERT(id >= 0);
DCPOMATIC_ASSERT(id < int(cpls.size()));
@@ -927,7 +926,7 @@ private:
}
_viewer.set_coalesce_player_changes(true);
- dcp->set_cpl((*i)->id());
+ dcp->set_cpl(*i);
examine_content();
_viewer.set_coalesce_player_changes(false);
diff --git a/src/wx/content_menu.cc b/src/wx/content_menu.cc
index b75c29660..527e28624 100644
--- a/src/wx/content_menu.cc
+++ b/src/wx/content_menu.cc
@@ -454,8 +454,8 @@ ContentMenu::kdm()
return;
}
- auto cpls = dcp::find_and_resolve_cpls(dcp->directories(), true);
- bool const kdm_matches_any_cpl = std::any_of(cpls.begin(), cpls.end(), [kdm](shared_ptr<const dcp::CPL> cpl) { return cpl->id() == kdm->cpl_id(); });
+ auto cpls = dcp->cpls();
+ bool const kdm_matches_any_cpl = std::any_of(cpls.begin(), cpls.end(), [kdm](std::string const& cpl) { return cpl == kdm->cpl_id(); });
bool const kdm_matches_selected_cpl = dcp->cpl() || kdm->cpl_id() == dcp->cpl().get();
if (!kdm_matches_any_cpl) {
@@ -549,11 +549,11 @@ ContentMenu::cpl_selected(wxCommandEvent& ev)
auto dcp = dynamic_pointer_cast<DCPContent>(_content.front());
DCPOMATIC_ASSERT(dcp);
- auto cpls = dcp::find_and_resolve_cpls(dcp->directories(), true);
+ auto cpls = dcp->cpls();
DCPOMATIC_ASSERT(ev.GetId() >= DCPOMATIC_CPL_MENU);
DCPOMATIC_ASSERT(ev.GetId() < int(DCPOMATIC_CPL_MENU + cpls.size()));
- dcp->set_cpl(cpls[ev.GetId() - DCPOMATIC_CPL_MENU]->id());
+ dcp->set_cpl(cpls[ev.GetId() - DCPOMATIC_CPL_MENU]);
auto film = _film.lock();
DCPOMATIC_ASSERT(film);