*/
+#include "lib/ansi.h"
#include "lib/audio_content.h"
#include "lib/config.h"
#include "lib/cross.h"
#include "lib/ffmpeg_encoder.h"
#include "lib/film.h"
#include "lib/filter.h"
+#include "lib/hints.h"
#include "lib/job_manager.h"
#include "lib/json_server.h"
#include "lib/log.h"
+#include "lib/make_dcp.h"
#include "lib/ratio.h"
#include "lib/signal_manager.h"
#include "lib/transcode_job.h"
<< " --no-check don't check project's content files for changes before making the DCP\n"
<< " --export-format <format> export project to a file, rather than making a DCP: specify mov or mp4\n"
<< " --export-filename <filename> filename to export to with --export-format\n"
+ << " --hints analyze film for hints before encoding and abort if any are found\n"
<< "\n"
<< "<FILM> is the film directory.\n";
}
}
+bool
+show_jobs_on_console (bool progress)
+{
+ bool first = true;
+ bool error = false;
+ while (true) {
+
+ dcpomatic_sleep_seconds (5);
+
+ auto jobs = JobManager::instance()->get();
+
+ if (!first && progress) {
+ for (size_t i = 0; i < jobs.size(); ++i) {
+ cout << UP_ONE_LINE_AND_ERASE;
+ }
+ cout.flush ();
+ }
+
+ first = false;
+
+ for (auto i: jobs) {
+ if (progress) {
+ cout << i->name();
+ if (!i->sub_name().empty()) {
+ cout << "; " << i->sub_name();
+ }
+ cout << ": ";
+
+ if (i->progress ()) {
+ cout << i->status() << " \n";
+ } else {
+ cout << ": Running \n";
+ }
+ }
+
+ 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 (i->finished_in_error()) {
+ error = true;
+ }
+ }
+
+ if (!JobManager::instance()->work_to_do()) {
+ break;
+ }
+ }
+
+ return error;
+}
+
+
int
main (int argc, char* argv[])
{
bool check = true;
optional<string> export_format;
optional<boost::filesystem::path> export_filename;
+ bool hints = false;
int option_index = 0;
while (true) {
{ "no-check", no_argument, 0, 'B' },
{ "export-format", required_argument, 0, 'C' },
{ "export-filename", required_argument, 0, 'D' },
+ { "hints", no_argument, 0, 'E' },
{ 0, 0, 0, 0 }
};
- int c = getopt_long (argc, argv, "vhfnrt:j:kAs:ldc:BC:D:", long_options, &option_index);
+ int c = getopt_long (argc, argv, "vhfnrt:j:kAs:ldc:BC:D:E", long_options, &option_index);
if (c == -1) {
break;
case 'D':
export_filename = optarg;
break;
+ case 'E':
+ hints = true;
+ break;
}
}
}
if (servers) {
- auto f = fopen_boost (*servers, "r");
+ dcp::File f(*servers, "r");
if (!f) {
cerr << "Could not open servers list file " << *servers << "\n";
exit (EXIT_FAILURE);
}
vector<string> servers;
- while (!feof (f)) {
+ while (!f.eof()) {
char buffer[128];
- if (fscanf (f, "%s.127", buffer) == 1) {
+ if (fscanf(f.get(), "%s.127", buffer) == 1) {
servers.push_back (buffer);
}
}
- fclose (f);
Config::instance()->set_servers (servers);
}
}
}
+ if (!export_format && hints) {
+ string const prefix = "Checking project for hints";
+ bool pulse_phase = false;
+ vector<string> hints;
+ bool finished = false;
+
+ Hints hint_finder(film);
+ hint_finder.Progress.connect([prefix](string progress) {
+ std::cout << UP_ONE_LINE_AND_ERASE << prefix << ": " << progress << "\n";
+ std::cout.flush();
+ });
+ hint_finder.Pulse.connect([prefix, &pulse_phase]() {
+ std::cout << UP_ONE_LINE_AND_ERASE << prefix << ": " << (pulse_phase ? "X" : "x") << "\n";
+ std::cout.flush();
+ pulse_phase = !pulse_phase;
+ });
+ hint_finder.Hint.connect([&hints](string hint) {
+ hints.push_back(hint);
+ });
+ hint_finder.Finished.connect([&finished]() {
+ finished = true;
+ });
+
+ std::cout << prefix << ":\n";
+ std::cout.flush();
+
+ hint_finder.start();
+ while (!finished) {
+ signal_manager->ui_idle();
+ dcpomatic_sleep_milliseconds(200);
+ }
+
+ std::cout << UP_ONE_LINE_AND_ERASE;
+
+ if (!hints.empty()) {
+ std::cerr << "Hints:\n\n";
+ for (auto hint: hints) {
+ std::cerr << word_wrap("* " + hint, 70) << "\n";
+ }
+ std::cerr << "*** Encoding aborted because hints were found ***\n\n";
+ std::cerr << "Modify your settings and run the command again, or run without\n";
+ std::cerr << "the `--hints' option to ignore these hints and encode anyway.\n";
+ exit(EXIT_FAILURE);
+ }
+ }
+
if (progress) {
if (export_format) {
cout << "\nExporting " << film->name() << "\n";
}
}
- TranscodeJob::ChangedBehaviour behaviour = check ? TranscodeJob::ChangedBehaviour::STOP : TranscodeJob::ChangedBehaviour::IGNORE;
+ TranscodeJob::ChangedBehaviour const behaviour = check ? TranscodeJob::ChangedBehaviour::STOP : TranscodeJob::ChangedBehaviour::IGNORE;
if (export_format) {
auto job = std::make_shared<TranscodeJob>(film, behaviour);
job->set_encoder (
std::make_shared<FFmpegEncoder> (
- film, job, *export_filename, *export_format == "mp4" ? ExportFormat::H264_AAC : ExportFormat::PRORES, false, false, false, 23
+ film, job, *export_filename, *export_format == "mp4" ? ExportFormat::H264_AAC : ExportFormat::PRORES_HQ, false, false, false, 23
)
);
JobManager::instance()->add (job);
} else {
try {
- film->make_dcp (behaviour);
+ make_dcp (film, behaviour);
} catch (runtime_error& e) {
std::cerr << "Could not make DCP: " << e.what() << "\n";
exit(EXIT_FAILURE);