diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-10-14 23:34:36 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2026-02-16 01:20:17 +0100 |
| commit | 144590d21b70f0239612b82f7c1d422533c64fbb (patch) | |
| tree | ca7d399ae53929ed469f8dfba430b51e6cdf6733 /src/lib | |
| parent | 1deb9a98a0a6204720c2e701b39c9e3f43a21873 (diff) | |
Move content store handling into ContentStore rather than it being done in the GUI.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/content_store.cc | 163 | ||||
| -rw-r--r-- | src/lib/content_store.h | 25 | ||||
| -rw-r--r-- | src/lib/wscript | 1 |
3 files changed, 186 insertions, 3 deletions
diff --git a/src/lib/content_store.cc b/src/lib/content_store.cc new file mode 100644 index 000000000..35fde3c8e --- /dev/null +++ b/src/lib/content_store.cc @@ -0,0 +1,163 @@ +/* + 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 "config.h" +#include "content_factory.h" +#include "content_store.h" +#include "cross.h" +#include "dcp_content.h" +#include "examine_content_job.h" +#include "job_manager.h" +#include "util.h" +#include <dcp/cpl.h> +#include <dcp/exceptions.h> +#include <dcp/filesystem.h> +#include <dcp/search.h> + + +using std::dynamic_pointer_cast; +using std::make_shared; +using std::pair; +using std::shared_ptr; +using std::string; +using std::vector; + + +ContentStore* ContentStore::_instance = nullptr; + + +vector<pair<string, string>> +ContentStore::update(std::function<bool()> pulse) +{ + _content.clear(); + auto dir = Config::instance()->player_content_directory(); + if (!dir || !dcp::filesystem::is_directory(*dir)) { + return {}; + } + + auto jm = JobManager::instance(); + + vector<shared_ptr<ExamineContentJob>> jobs; + + auto examine = [&](shared_ptr<Content> content) { + auto job = make_shared<ExamineContentJob>(vector<shared_ptr<Content>>{content}, true); + jm->add(job); + jobs.push_back(job); + }; + + for (auto i: boost::filesystem::directory_iterator(*dir)) { + try { + pulse(); + + if (is_directory(i) && contains_assetmap(i)) { + auto dcp = make_shared<DCPContent>(i); + /* 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)) { + auto copy = dynamic_pointer_cast<DCPContent>(dcp->clone()); + copy->set_cpl(cpl->id()); + examine(copy); + } + } else if (i.path().extension() == ".mp4") { + auto all_content = content_factory(i); + if (!all_content.empty()) { + examine(all_content[0]); + } + } + } catch (boost::filesystem::filesystem_error& e) { + /* Never mind */ + } catch (dcp::ReadError& e) { + /* Never mind */ + } + } + + while (jm->work_to_do()) { + if (!pulse()) { + /* user pressed cancel */ + for (auto i: jm->get()) { + i->cancel(); + } + return {}; + } + dcpomatic_sleep_seconds(1); + } + + /* Add content from successful jobs and report errors */ + vector<pair<string, string>> errors; + for (auto i: jobs) { + if (i->finished_in_error()) { + errors.push_back({fmt::format("{}.\n", i->error_summary()), i->error_details()}); + } else { + _content.push_back(i->content().front()); + } + } + + return errors; +} + + +shared_ptr<Content> +ContentStore::get_by_digest(string digest) const +{ + auto iter = std::find_if(_content.begin(), _content.end(), [digest](shared_ptr<const Content> content) { + return content->digest() == digest; + }); + + if (iter == _content.end()) { + return {}; + } + + return *iter; +} + + +shared_ptr<Content> +ContentStore::get_by_cpl_id(string id) const +{ + auto iter = std::find_if(_content.begin(), _content.end(), [id](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() == id) { + return true; + } + } + } + return false; + }); + + if (iter == _content.end()) { + return {}; + } + + return *iter; +} + + +ContentStore* +ContentStore::instance() +{ + if (!_instance) { + _instance = new ContentStore(); + } + + return _instance; +} diff --git a/src/lib/content_store.h b/src/lib/content_store.h index c615a856e..1b3afc85d 100644 --- a/src/lib/content_store.h +++ b/src/lib/content_store.h @@ -19,18 +19,37 @@ */ +#include <functional> #include <memory> +#include <vector> class Content; /** @class ContentStore - * @brief Parent for classes which store content and can return content with a given digest or CPL ID. + * @brief Class to maintain details of what content we have available to play */ class ContentStore { public: - virtual std::shared_ptr<Content> get_by_digest(std::string digest) const = 0; - virtual std::shared_ptr<Content> get_by_cpl_id(std::string id) const = 0; + std::shared_ptr<Content> get_by_digest(std::string digest) const; + std::shared_ptr<Content> get_by_cpl_id(std::string id) const; + + /** Examine content in the configured directory and update our list. + * @param pulse Called every so often to indicate progress. Return false to cancel the scan. + * @return Errors (first of the pair is the summary, second is the detail). + */ + std::vector<std::pair<std::string, std::string>> update(std::function<bool()> pulse); + + static ContentStore* instance(); + + std::vector<std::shared_ptr<Content>> const& all() const { + return _content; + } + +private: + std::vector<std::shared_ptr<Content>> _content; + + static ContentStore* _instance; }; diff --git a/src/lib/wscript b/src/lib/wscript index 8e4b4d783..a6130e41c 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -57,6 +57,7 @@ sources = """ config.cc content.cc content_factory.cc + content_store.cc combine_dcp_job.cc copy_dcp_details_to_film.cc cover_sheet.cc |
