2 Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
21 #include "lib/audio_content.h"
22 #include "lib/config.h"
23 #include "lib/content_factory.h"
24 #include "lib/create_cli.h"
25 #include "lib/cross.h"
26 #include "lib/dcp_content.h"
27 #include "lib/dcp_content_type.h"
29 #include "lib/image_content.h"
31 #include "lib/job_manager.h"
32 #include "lib/ratio.h"
33 #include "lib/signal_manager.h"
35 #include "lib/version.h"
36 #include "lib/version.h"
37 #include "lib/video_content.h"
38 #include <dcp/exceptions.h>
39 #include <dcp/filesystem.h>
40 #include <libxml++/libxml++.h>
41 #include <boost/filesystem.hpp>
51 using std::dynamic_pointer_cast;
54 using std::make_shared;
55 using std::shared_ptr;
58 using boost::optional;
61 class SimpleSignalManager : public SignalManager
64 /* Do nothing in this method so that UI events happen in our thread
65 when we call SignalManager::ui_idle().
67 void wake_ui () override {}
71 main (int argc, char* argv[])
73 dcpomatic_setup_path_encoding ();
76 CreateCLI cc (argc, argv);
78 cerr << *cc.error << "\n";
83 cout << "dcpomatic version " << dcpomatic_version << " " << dcpomatic_git_commit << "\n";
88 State::override_path = *cc.config_dir;
91 signal_manager = new SimpleSignalManager ();
92 auto jm = JobManager::instance ();
95 auto film = cc.make_film();
97 for (auto cli_content: cc.content) {
98 auto const can = dcp::filesystem::canonical(cli_content.path);
99 vector<shared_ptr<Content>> film_content_list;
101 if (dcp::filesystem::exists(can / "ASSETMAP") || (dcp::filesystem::exists(can / "ASSETMAP.xml"))) {
102 auto dcp = make_shared<DCPContent>(can);
103 film_content_list.push_back (dcp);
104 if (cli_content.kdm) {
105 dcp->add_kdm (dcp::EncryptedKDM(dcp::file_to_string(*cli_content.kdm)));
107 if (cli_content.cpl) {
108 dcp->set_cpl(*cli_content.cpl);
111 /* I guess it's not a DCP */
112 film_content_list = content_factory (can);
115 for (auto film_content: film_content_list) {
116 film->examine_and_add_content (film_content);
119 while (jm->work_to_do ()) {
120 dcpomatic_sleep_seconds (1);
123 while (signal_manager->ui_idle() > 0) {}
125 for (auto film_content: film_content_list) {
126 if (film_content->video) {
127 film_content->video->set_frame_type (cli_content.frame_type);
129 if (film_content->audio && cli_content.channel) {
130 for (auto stream: film_content->audio->streams()) {
131 AudioMapping mapping(stream->channels(), film->audio_channels());
132 for (int channel = 0; channel < stream->channels(); ++channel) {
133 mapping.set(channel, *cli_content.channel, 1.0f);
135 stream->set_mapping (mapping);
138 if (film_content->audio && cli_content.gain) {
139 film_content->audio->set_gain (*cli_content.gain);
144 if (cc.dcp_frame_rate) {
145 film->set_video_frame_rate (*cc.dcp_frame_rate);
148 for (auto i: film->content()) {
149 auto ic = dynamic_pointer_cast<ImageContent> (i);
150 if (ic && ic->still()) {
151 ic->video->set_length(cc.still_length.get_value_or(10) * 24);
156 for (auto i: jm->get()) {
157 if (i->finished_in_error()) {
158 cerr << i->error_summary() << "\n";
159 if (!i->error_details().empty()) {
160 cout << i->error_details() << "\n";
168 film->write_metadata ();
170 film->metadata()->write_to_stream_formatted(cout, "UTF-8");
172 } catch (exception& e) {
173 cerr << argv[0] << ": " << e.what() << "\n";