From: Carl Hetherington Date: Sat, 4 May 2013 14:59:31 +0000 (+0100) Subject: Merge master. X-Git-Tag: v2.0.48~1337^2~408 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=cd4a82d90677cec80e891ac190000cb70767446f Merge master. --- cd4a82d90677cec80e891ac190000cb70767446f diff --cc src/lib/config.cc index 4f90581f6,8c65e371a..b6f464717 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@@ -49,7 -47,8 +51,9 @@@ Config::Config ( , _reference_scaler (Scaler::from_id (N_("bicubic"))) , _tms_path (N_(".")) , _sound_processor (SoundProcessor::from_id (N_("dolby_cp750"))) + , _default_still_length (10) + , _default_format (0) + , _default_dcp_content_type (0) { _allowed_dcp_frame_rates.push_back (24); _allowed_dcp_frame_rates.push_back (25); @@@ -57,52 -56,8 +61,66 @@@ _allowed_dcp_frame_rates.push_back (48); _allowed_dcp_frame_rates.push_back (50); _allowed_dcp_frame_rates.push_back (60); + + if (!boost::filesystem::exists (file (false))) { + read_old_metadata (); + return; + } + + cxml::File f (file (false), "Config"); + optional c; + + _num_local_encoding_threads = f.number_child ("NumLocalEncodingThreads"); + _default_directory = f.string_child ("DefaultDirectory"); + _server_port = f.number_child ("ServerPort"); + c = f.optional_string_child ("ReferenceScaler"); + if (c) { + _reference_scaler = Scaler::from_id (c.get ()); + } + + list > filters = f.node_children ("ReferenceFilter"); + for (list >::iterator i = filters.begin(); i != filters.end(); ++i) { + _reference_filters.push_back (Filter::from_id ((*i)->content ())); + } - ifstream f (file().c_str ()); + list > servers = f.node_children ("Server"); + for (list >::iterator i = servers.begin(); i != servers.end(); ++i) { + _servers.push_back (new ServerDescription (*i)); + } + + _tms_ip = f.string_child ("TMSIP"); + _tms_path = f.string_child ("TMSPath"); + _tms_user = f.string_child ("TMSUser"); + _tms_password = f.string_child ("TMSPassword"); + + c = f.optional_string_child ("SoundProcessor"); + if (c) { + _sound_processor = SoundProcessor::from_id (c.get ()); + } + + _language = f.optional_string_child ("Language"); ++ ++ c = f.optional_string_child ("DefaultFormat"); ++ if (c) { ++ _default_format = Format::from_id (c.get ()); ++ } ++ ++ c = f.optional_string_child ("DefaultDCPContentType"); ++ if (c) { ++ _default_dcp_content_type = DCPContentType::from_dci_name (c.get ()); ++ } ++ ++ _dcp_metadata.issuer = f.optional_string_child ("DCPMetadataIssuer").get_value_or (""); ++ _dcp_metadata.creator = f.optional_string_child ("DCPMetadataCreator").get_value_or (""); ++ + _default_dci_metadata = DCIMetadata (f.node_child ("DCIMetadata")); + _default_still_length = f.optional_number_child("DefaultStillLength").get_value_or (10); +} + +void +Config::read_old_metadata () +{ + ifstream f (file(true).c_str ()); string line; while (getline (f, line)) { if (line.empty ()) { @@@ -145,9 -100,19 +163,19 @@@ _sound_processor = SoundProcessor::from_id (v); } else if (k == "language") { _language = v; + } else if (k == "default_format") { - _default_format = Format::from_metadata (v); ++ _default_format = Format::from_id (v); + } else if (k == "default_dcp_content_type") { + _default_dcp_content_type = DCPContentType::from_dci_name (v); + } else if (k == "dcp_metadata_issuer") { + _dcp_metadata.issuer = v; + } else if (k == "dcp_metadata_creator") { + _dcp_metadata.creator = v; + } else if (k == "dcp_metadata_issue_date") { + _dcp_metadata.issue_date = v; } - _default_dci_metadata.read (k, v); + _default_dci_metadata.read_old_metadata (k, v); } } @@@ -195,25 -155,30 +223,33 @@@ Config::write () cons } for (vector::const_iterator i = _servers.begin(); i != _servers.end(); ++i) { - f << "server " << (*i)->as_metadata () << "\n"; + (*i)->as_xml (root->add_child ("Server")); } - f << "tms_ip " << _tms_ip << "\n"; - f << "tms_path " << _tms_path << "\n"; - f << "tms_user " << _tms_user << "\n"; - f << "tms_password " << _tms_password << "\n"; + root->add_child("TMSIP")->add_child_text (_tms_ip); + root->add_child("TMSPath")->add_child_text (_tms_path); + root->add_child("TMSUser")->add_child_text (_tms_user); + root->add_child("TMSPassword")->add_child_text (_tms_password); if (_sound_processor) { - f << "sound_processor " << _sound_processor->id () << "\n"; + root->add_child("SoundProcessor")->add_child_text (_sound_processor->id ()); } if (_language) { - f << "language " << _language.get() << "\n"; + root->add_child("Language")->add_child_text (_language.get()); } + if (_default_format) { - f << "default_format " << _default_format->as_metadata() << "\n"; ++ root->add_child("DefaultFormat")->add_child_text (_default_format->id ()); + } + if (_default_dcp_content_type) { - f << "default_dcp_content_type " << _default_dcp_content_type->dci_name() << "\n"; ++ root->add_child("DefaultDCPContentType")->add_child_text (_default_dcp_content_type->dci_name ()); + } - f << "dcp_metadata_issuer " << _dcp_metadata.issuer << "\n"; - f << "dcp_metadata_creator " << _dcp_metadata.creator << "\n"; - f << "dcp_metadata_issue_date " << _dcp_metadata.issue_date << "\n"; ++ root->add_child("DCPMetadataIssuer")->add_child_text (_dcp_metadata.issuer); ++ root->add_child("DCPMetadataCreator")->add_child_text (_dcp_metadata.creator); + + _default_dci_metadata.as_xml (root->add_child ("DCIMetadata")); + + root->add_child("DefaultStillLength")->add_child_text (lexical_cast (_default_still_length)); - _default_dci_metadata.write (f); + doc.write_to_file_formatted (file (false)); } string diff --cc src/lib/config.h index 91926750b,a59cdcae0..05005e590 --- a/src/lib/config.h +++ b/src/lib/config.h @@@ -107,10 -110,18 +110,22 @@@ public return _language; } + int default_still_length () const { + return _default_still_length; + } + + Format const * default_format () const { + return _default_format; + } + + DCPContentType const * default_dcp_content_type () const { + return _default_dcp_content_type; + } + + libdcp::XMLMetadata dcp_metadata () const { + return _dcp_metadata; + } + /** @param n New number of local encoding threads */ void set_num_local_encoding_threads (int n) { _num_local_encoding_threads = n; @@@ -174,10 -185,18 +189,22 @@@ _language = boost::none; } + void set_default_still_length (int s) { + _default_still_length = s; + } + + void set_default_format (Format const * f) { + _default_format = f; + } + + void set_default_dcp_content_type (DCPContentType const * t) { + _default_dcp_content_type = t; + } + + void set_dcp_metadata (libdcp::XMLMetadata m) { + _dcp_metadata = m; + } + void write () const; static Config* instance (); @@@ -215,7 -233,9 +242,10 @@@ private /** Default DCI metadata for newly-created Films */ DCIMetadata _default_dci_metadata; boost::optional _language; + int _default_still_length; + Format const * _default_format; + DCPContentType const * _default_dcp_content_type; + libdcp::XMLMetadata _dcp_metadata; /** Singleton instance, or 0 */ static Config* _instance; diff --cc src/lib/film.cc index 5481bd012,0ca374604..8fed87122 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@@ -90,11 -86,10 +90,11 @@@ int const Film::state_version = 4 */ Film::Film (string d, bool must_exist) - : _use_dci_name (true) - , _trust_content_header (true) + : _playlist (new Playlist) + , _use_dci_name (true) + , _trust_content_headers (true) - , _dcp_content_type (0) - , _format (Format::from_id ("185")) + , _dcp_content_type (Config::instance()->default_dcp_content_type ()) + , _format (Config::instance()->default_format ()) , _scaler (Scaler::from_id ("bicubic")) , _trim_start (0) , _trim_end (0) diff --cc src/lib/format.cc index a83d53ebd,8c3d0d8ad..f5026c0da --- a/src/lib/format.cc +++ b/src/lib/format.cc @@@ -60,13 -59,13 +60,6 @@@ FixedFormat::name () cons return s.str (); } --/** @return Identifier for this format as metadata for a Film's metadata file */ --string --Format::as_metadata () const --{ -- return _id; --} -- /** Fill our _formats vector with all available formats */ void Format::setup_formats () @@@ -165,16 -164,16 +158,6 @@@ Format::from_id (string i return *j; } -- --/** @param m Metadata, as returned from as_metadata(). -- * @return Matching Format, or 0. -- */ --Format const * --Format::from_metadata (string m) --{ -- return from_id (m); --} -- /** @return All available formats */ vector Format::all () diff --cc src/lib/format.h index f240c89fc,e95306232..d45a3a10a --- a/src/lib/format.h +++ b/src/lib/format.h @@@ -67,10 -67,10 +67,7 @@@ public return _dci_name; } -- std::string as_metadata () const; -- static Format const * from_nickname (std::string n); -- static Format const * from_metadata (std::string m); static Format const * from_id (std::string i); static std::vector all (); static void setup_formats (); diff --cc src/lib/writer.cc index 8e771a5e2,177e929ae..b545848cb --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@@ -22,16 -22,14 +22,18 @@@ #include #include #include +#include + #include #include "writer.h" #include "compose.hpp" #include "film.h" #include "format.h" #include "log.h" #include "dcp_video_frame.h" +#include "dcp_content_type.h" +#include "player.h" +#include "audio_mapping.h" + #include "config.h" #include "i18n.h" diff --cc src/tools/dcpomatic_cli.cc index 86c3cf4b1,000000000..d4a4210de mode 100644,000000..100644 --- a/src/tools/dcpomatic_cli.cc +++ b/src/tools/dcpomatic_cli.cc @@@ -1,217 -1,0 +1,204 @@@ +/* + Copyright (C) 2012 Carl Hetherington + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include - #include +#include +#include "format.h" +#include "film.h" +#include "filter.h" +#include "transcode_job.h" +#include "job_manager.h" +#include "ab_transcode_job.h" +#include "util.h" +#include "scaler.h" +#include "version.h" +#include "cross.h" +#include "config.h" +#include "log.h" + +using std::string; +using std::cerr; +using std::cout; +using std::vector; +using std::pair; +using std::list; +using boost::shared_ptr; + +static void +help (string n) +{ + cerr << "Syntax: " << n << " [OPTION] \n" + << " -v, --version show DCP-o-matic version\n" + << " -h, --help show this help\n" + << " -d, --deps list DCP-o-matic dependency details and quit\n" - << " -t, --test run in test mode (repeatable UUID generation, timestamps etc.)\n" + << " -n, --no-progress do not print progress to stdout\n" + << " -r, --no-remote do not use any remote servers\n" + << "\n" + << " is the film directory.\n"; +} + +int +main (int argc, char* argv[]) +{ + string film_dir; - bool test_mode = false; + bool progress = true; + bool no_remote = false; + int log_level = 0; + + int option_index = 0; + while (1) { + static struct option long_options[] = { + { "version", no_argument, 0, 'v'}, + { "help", no_argument, 0, 'h'}, + { "deps", no_argument, 0, 'd'}, - { "test", no_argument, 0, 't'}, + { "no-progress", no_argument, 0, 'n'}, + { "no-remote", no_argument, 0, 'r'}, + { "log-level", required_argument, 0, 'l' }, + { 0, 0, 0, 0 } + }; + - int c = getopt_long (argc, argv, "vhdtnrl:", long_options, &option_index); ++ int c = getopt_long (argc, argv, "vhdnrl:", long_options, &option_index); + + if (c == -1) { + break; + } + + switch (c) { + case 'v': + cout << "dcpomatic version " << dcpomatic_version << " " << dcpomatic_git_commit << "\n"; + exit (EXIT_SUCCESS); + case 'h': + help (argv[0]); + exit (EXIT_SUCCESS); + case 'd': + cout << dependency_version_summary () << "\n"; + exit (EXIT_SUCCESS); - case 't': - test_mode = true; - break; + case 'n': + progress = false; + break; + case 'r': + no_remote = true; + break; + case 'l': + log_level = atoi (optarg); + break; + } + } + + if (optind >= argc) { + help (argv[0]); + exit (EXIT_FAILURE); + } + + film_dir = argv[optind]; + + dcpomatic_setup (); + + if (no_remote) { + Config::instance()->set_servers (vector ()); + } + + cout << "DCP-o-matic " << dcpomatic_version << " git " << dcpomatic_git_commit; + char buf[256]; + if (gethostname (buf, 256) == 0) { + cout << " on " << buf; + } + cout << "\n"; + - if (test_mode) { - libdcp::enable_test_mode (); - cout << dependency_version_summary() << "\n"; - } - + shared_ptr film; + try { + film.reset (new Film (film_dir, true)); + } catch (std::exception& e) { + cerr << argv[0] << ": error reading film `" << film_dir << "' (" << e.what() << ")\n"; + exit (EXIT_FAILURE); + } + + film->log()->set_level ((Log::Level) log_level); + + cout << "\nMaking "; + if (film->ab()) { + cout << "A/B "; + } + cout << "DCP for " << film->name() << "\n"; - cout << "Test mode: " << (test_mode ? "yes" : "no") << "\n"; +// cout << "Content: " << film->content() << "\n"; + pair const f = Filter::ffmpeg_strings (film->filters ()); + cout << "Filters: " << f.first << " " << f.second << "\n"; + + film->make_dcp (); + + bool should_stop = false; + bool first = true; + bool error = false; + while (!should_stop) { + + dcpomatic_sleep (5); + + list > jobs = JobManager::instance()->get (); + + if (!first && progress) { + cout << "\033[" << jobs.size() << "A"; + cout.flush (); + } + + first = false; + + int unfinished = 0; + int finished_in_error = 0; + + for (list >::iterator i = jobs.begin(); i != jobs.end(); ++i) { + if (progress) { + cout << (*i)->name() << ": "; + + float const p = (*i)->overall_progress (); + + if (p >= 0) { + cout << (*i)->status() << " \n"; + } else { + cout << ": Running \n"; + } + } + + if (!(*i)->finished ()) { + ++unfinished; + } + + if ((*i)->finished_in_error ()) { + ++finished_in_error; + error = true; + } + + if (!progress && (*i)->finished_in_error ()) { + /* We won't see this error if we haven't been showing progress, + so show it now. + */ + cout << (*i)->status() << "\n"; + } + } + + if (unfinished == 0 || finished_in_error != 0) { + should_stop = true; + } + } + + return error ? EXIT_FAILURE : EXIT_SUCCESS; +} + + diff --cc src/wx/config_dialog.cc index e1fc7a20f,98657b666..50b8990b1 --- a/src/wx/config_dialog.cc +++ b/src/wx/config_dialog.cc @@@ -230,15 -284,15 +266,33 @@@ ConfigDialog::make_ab_panel ( table->Add (s, 1, wxEXPAND); table->AddSpacer (0); } ++} ++ ++void ++ConfigDialog::make_metadata_panel () ++{ ++ _metadata_panel = new wxPanel (_notebook); ++ wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); ++ _metadata_panel->SetSizer (s); ++ ++ wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6); ++ table->AddGrowableCol (1, 1); ++ s->Add (table, 1, wxALL | wxEXPAND, 8); ++ ++ add_label_to_sizer (table, _metadata_panel, _("Issuer")); ++ _issuer = new wxTextCtrl (_metadata_panel, wxID_ANY); ++ table->Add (_issuer, 1, wxEXPAND); ++ ++ add_label_to_sizer (table, _metadata_panel, _("Creator")); ++ _creator = new wxTextCtrl (_metadata_panel, wxID_ANY); ++ table->Add (_creator, 1, wxEXPAND); Config* config = Config::instance (); -- -- _reference_scaler->SetSelection (Scaler::as_index (config->reference_scaler ())); -- _reference_scaler->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (ConfigDialog::reference_scaler_changed), 0, this); -- pair p = Filter::ffmpeg_strings (config->reference_filters ()); -- _reference_filters->SetLabel (std_to_wx (p.first) + N_(" ") + std_to_wx (p.second)); -- _reference_filters_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ConfigDialog::edit_reference_filters_clicked), 0, this); ++ _issuer->SetValue (std_to_wx (config->dcp_metadata().issuer)); ++ _issuer->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::issuer_changed), 0, this); ++ _creator->SetValue (std_to_wx (config->dcp_metadata().creator)); ++ _creator->Connect (wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler (ConfigDialog::creator_changed), 0, this); } void @@@ -472,8 -526,32 +526,38 @@@ ConfigDialog::setup_language_sensitivit _language->Enable (_set_language->GetValue ()); } +void +ConfigDialog::default_still_length_changed (wxCommandEvent &) +{ + Config::instance()->set_default_still_length (_default_still_length->GetValue ()); +} ++ + void + ConfigDialog::default_format_changed (wxCommandEvent &) + { + vector fmt = Format::all (); + Config::instance()->set_default_format (fmt[_default_format->GetSelection()]); + } + + void + ConfigDialog::default_dcp_content_type_changed (wxCommandEvent &) + { + vector ct = DCPContentType::all (); + Config::instance()->set_default_dcp_content_type (ct[_default_dcp_content_type->GetSelection()]); + } + + void + ConfigDialog::issuer_changed (wxCommandEvent &) + { + libdcp::XMLMetadata m = Config::instance()->dcp_metadata (); + m.issuer = wx_to_std (_issuer->GetValue ()); + Config::instance()->set_dcp_metadata (m); + } + + void + ConfigDialog::creator_changed (wxCommandEvent &) + { + libdcp::XMLMetadata m = Config::instance()->dcp_metadata (); + m.creator = wx_to_std (_creator->GetValue ()); + Config::instance()->set_dcp_metadata (m); + }