From f190ce5af38c87b2586cff0b49d6be0bb38f5b0d Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 00:07:32 +0100 Subject: Remove unnecessary new line. --- src/lib/encode_cli.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index a682fa4e3..6209d4c01 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -489,9 +489,9 @@ encode_cli(int argc, char* argv[], function out, functionname())); + out(fmt::format("Exporting {}\n", film->name())); } else { - out(fmt::format("\nMaking DCP for {}\n", film->name())); + out(fmt::format("Making DCP for {}\n", film->name())); } } -- cgit v1.2.3 From 3be10e6264ee8a817c4b6ed744a2a34cf99cecea Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 00:09:01 +0100 Subject: Add a basic test of the encode CLI. --- src/lib/encode_cli.cc | 3 ++ test/encode_cli_test.cc | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ test/wscript | 1 + 3 files changed, 92 insertions(+) create mode 100644 test/encode_cli_test.cc (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index 6209d4c01..d7c4541cb 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -271,6 +271,9 @@ encode_cli(int argc, char* argv[], function out, function export_filename; bool hints = false; + /* This makes it possible to call getopt several times in the same executable, for tests */ + optind = 0; + int option_index = 0; while (true) { static struct option long_options[] = { diff --git a/test/encode_cli_test.cc b/test/encode_cli_test.cc new file mode 100644 index 000000000..fc70c02d5 --- /dev/null +++ b/test/encode_cli_test.cc @@ -0,0 +1,88 @@ +/* + Copyright (C) 2025 Carl Hetherington + + 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 . + +*/ + + +#include "lib/content_factory.h" +#include "lib/encode_cli.h" +#include "lib/film.h" +#include "test.h" +#include +#include +#include +#include +#include + + +using std::cout; +using std::string; +using std::vector; +using boost::optional; + + +static +optional +run(vector const& args, vector& output) +{ + vector argv(args.size() + 1); + for (auto i = 0U; i < args.size(); ++i) { + argv[i] = const_cast(args[i].c_str()); + } + argv[args.size()] = nullptr; + + auto error = encode_cli(args.size(), argv.data(), [&output](string s) { output.push_back(s); }, []() { }); + if (error) { + std::cout << *error << "\n"; + } + + return error; +} + + +static +bool +find_in_order(vector const& output, vector const& check) +{ + BOOST_REQUIRE(!check.empty()); + + auto next = check.begin(); + for (auto line: output) { + if (line.find(*next) != string::npos) { + ++next; + if (next == check.end()) { + return true; + } + } + } + + return false; +} + + +BOOST_AUTO_TEST_CASE(basic_encode_cli_test) +{ + auto content = content_factory("test/data/flat_red.png"); + auto film = new_test_film("basic_encode_cli_test", content); + film->write_metadata(); + + vector output; + run({ "cli", "build/test/basic_encode_cli_test" }, output); + + BOOST_CHECK(find_in_order(output, { "Making DCP for", "Examining content", "OK", "Transcoding DCP", "OK" })); +} diff --git a/test/wscript b/test/wscript index 85bfccf56..714c237a4 100644 --- a/test/wscript +++ b/test/wscript @@ -85,6 +85,7 @@ def build(bld): email_test.cc empty_caption_test.cc empty_test.cc + encode_cli_test.cc encryption_test.cc file_extension_test.cc ffmpeg_audio_only_test.cc -- cgit v1.2.3 From 09471c55b24d5e69359675fe669397f031aa62d3 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 00:17:27 +0100 Subject: Preparation for offering command in the encode CLI. --- src/lib/encode_cli.cc | 10 +++++++++- test/encode_cli_test.cc | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index d7c4541cb..c321d5014 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -66,7 +66,9 @@ using boost::optional; static void help(function out) { - out(fmt::format("Syntax: {} [OPTION] []\n", program_name)); + out(fmt::format("Syntax: {} [OPTION] [COMMAND] []\n", program_name)); + out("Commands:\n"); + out("make-dcp make DCP from the given film; default if no other command is specified\n"); out(variant::insert_dcpomatic(" -v, --version show %1 version\n")); out(" -h, --help show this help\n"); out(" -f, --flags show flags passed to C++ compiler on build\n"); @@ -270,6 +272,7 @@ encode_cli(int argc, char* argv[], function out, function export_format; optional export_filename; bool hints = false; + string command = "make-dcp"; /* This makes it possible to call getopt several times in the same executable, for tests */ optind = 0; @@ -360,6 +363,11 @@ encode_cli(int argc, char* argv[], function out, functionwrite_metadata(); + + vector output; + run({ "cli", "make-dcp", "build/test/basic_encode_cli_test" }, output); + + BOOST_CHECK(find_in_order(output, { "Making DCP for", "Examining content", "OK", "Transcoding DCP", "OK" })); +} -- cgit v1.2.3 From 9325b94009dfe3ed02559303e6803e235299e151 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 00:24:01 +0100 Subject: Make --list-servers into a command. --- src/lib/encode_cli.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index c321d5014..fb307e019 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -68,7 +68,8 @@ help(function out) { out(fmt::format("Syntax: {} [OPTION] [COMMAND] []\n", program_name)); out("Commands:\n"); - out("make-dcp make DCP from the given film; default if no other command is specified\n"); + out("make-dcp make DCP from the given film; default if no other command is specified\n"); + out(variant::insert_dcpomatic("list-servers display a list of encoding servers that %1 can use (until Ctrl-C)\n")); out(variant::insert_dcpomatic(" -v, --version show %1 version\n")); out(" -h, --help show this help\n"); out(" -f, --flags show flags passed to C++ compiler on build\n"); @@ -79,6 +80,7 @@ help(function out) out(" -k, --keep-going keep running even when the job is complete\n"); out(" -s, --servers specify servers to use in a text file\n"); out(variant::insert_dcpomatic(" -l, --list-servers just display a list of encoding servers that %1 is configured to use; don't encode\n")); + out(" (deprecated - use the list-servers command instead)\n"); out(" -d, --dcp-path echo DCP's path to stdout on successful completion (implies -n)\n"); out(" -c, --config directory containing config.xml and cinemas.xml\n"); out(" --dump just dump a summary of the film's settings; don't encode\n"); @@ -363,9 +365,19 @@ encode_cli(int argc, char* argv[], function out, function commands = { + "make-dcp", + "list-servers" + }; + if (optind < argc - 1) { /* Command with a film specified afterwards */ command = argv[optind++]; + } else if (optind < argc) { + /* Look for a valid command, hoping that it's not the name of a film */ + if (std::find(commands.begin(), commands.end(), argv[optind]) != commands.end()) { + command = argv[optind++]; + } } if (config) { @@ -387,7 +399,7 @@ encode_cli(int argc, char* argv[], function out, functionset_servers(servers); } - if (list_servers_) { + if (command == "list-servers" || list_servers_) { list_servers(out); return {}; } -- cgit v1.2.3 From e662e5369a0aec59dbbd5763e999132c3fece565 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 00:28:29 +0100 Subject: Make --dump into a command. --- src/lib/encode_cli.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index fb307e019..4fd2feac5 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -70,6 +70,7 @@ help(function out) out("Commands:\n"); out("make-dcp make DCP from the given film; default if no other command is specified\n"); out(variant::insert_dcpomatic("list-servers display a list of encoding servers that %1 can use (until Ctrl-C)\n")); + out("dump show a summary of the film's settings\n"); out(variant::insert_dcpomatic(" -v, --version show %1 version\n")); out(" -h, --help show this help\n"); out(" -f, --flags show flags passed to C++ compiler on build\n"); @@ -84,6 +85,7 @@ help(function out) out(" -d, --dcp-path echo DCP's path to stdout on successful completion (implies -n)\n"); out(" -c, --config directory containing config.xml and cinemas.xml\n"); out(" --dump just dump a summary of the film's settings; don't encode\n"); + out(" (deprecated - use the dump command instead)\n"); out(" --no-check don't check project's content files for changes before making the DCP\n"); out(" --export-format export project to a file, rather than making a DCP: specify mov or mp4\n"); out(" --export-filename filename to export to with --export-format\n"); @@ -367,7 +369,8 @@ encode_cli(int argc, char* argv[], function out, function commands = { "make-dcp", - "list-servers" + "list-servers", + "dump" }; if (optind < argc - 1) { @@ -443,7 +446,7 @@ encode_cli(int argc, char* argv[], function out, function Date: Mon, 3 Mar 2025 00:42:15 +0100 Subject: Tweak help to suggest that the film is really a command parameter. --- src/lib/encode_cli.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index 4fd2feac5..77970ea2b 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -66,12 +66,14 @@ using boost::optional; static void help(function out) { - out(fmt::format("Syntax: {} [OPTION] [COMMAND] []\n", program_name)); - out("Commands:\n"); - out("make-dcp make DCP from the given film; default if no other command is specified\n"); - out(variant::insert_dcpomatic("list-servers display a list of encoding servers that %1 can use (until Ctrl-C)\n")); - out("dump show a summary of the film's settings\n"); - out(variant::insert_dcpomatic(" -v, --version show %1 version\n")); + out(fmt::format("Syntax: {} [OPTION] [COMMAND] []\n", program_name)); + + out("\nCommands:\n\n"); + out(" make-dcp make DCP from the given film; default if no other command is specified\n"); + out(variant::insert_dcpomatic(" list-servers display a list of encoding servers that %1 can use (until Ctrl-C)\n")); + out(" dump show a summary of the film's settings\n"); + + out(variant::insert_dcpomatic("\n -v, --version show %1 version\n")); out(" -h, --help show this help\n"); out(" -f, --flags show flags passed to C++ compiler on build\n"); out(" -n, --no-progress do not print progress to stdout\n"); @@ -91,7 +93,6 @@ help(function out) out(" --export-filename filename to export to with --export-format\n"); out(" --hints analyze film for hints before encoding and abort if any are found\n"); out("\n"); - out(" is the film directory.\n"); } -- cgit v1.2.3 From f180d199dcb0217ea9750ab0a788217689733c41 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 01:11:03 +0100 Subject: Further help clarification. --- src/lib/encode_cli.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index 77970ea2b..67c82c141 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -69,11 +69,12 @@ help(function out) out(fmt::format("Syntax: {} [OPTION] [COMMAND] []\n", program_name)); out("\nCommands:\n\n"); - out(" make-dcp make DCP from the given film; default if no other command is specified\n"); - out(variant::insert_dcpomatic(" list-servers display a list of encoding servers that %1 can use (until Ctrl-C)\n")); - out(" dump show a summary of the film's settings\n"); + out(" make-dcp make DCP from the given film; default if no other command is specified\n"); + out(variant::insert_dcpomatic(" list-servers display a list of encoding servers that %1 can use (until Ctrl-C)\n")); + out(" dump show a summary of the film's settings\n"); - out(variant::insert_dcpomatic("\n -v, --version show %1 version\n")); + out("\nOptions:\n\n"); + out(variant::insert_dcpomatic(" -v, --version show %1 version\n")); out(" -h, --help show this help\n"); out(" -f, --flags show flags passed to C++ compiler on build\n"); out(" -n, --no-progress do not print progress to stdout\n"); @@ -92,6 +93,8 @@ help(function out) out(" --export-format export project to a file, rather than making a DCP: specify mov or mp4\n"); out(" --export-filename filename to export to with --export-format\n"); out(" --hints analyze film for hints before encoding and abort if any are found\n"); + out("\ne.g.\n"); + out(fmt::format("\n {} -t 4 make-dcp my_great_movie\n", program_name)); out("\n"); } -- cgit v1.2.3 From 27f9ce96db8b800b301ad3b21fb81355e982941a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 20:52:47 +0100 Subject: Allow configuration of Grok licence via dcpomatic2_cli (#2981). --- src/lib/encode_cli.cc | 38 ++++++++++++++++++++++++++++++++++++++ test/encode_cli_test.cc | 26 +++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index 67c82c141..7e9c25a6a 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -72,6 +72,10 @@ help(function out) out(" make-dcp make DCP from the given film; default if no other command is specified\n"); out(variant::insert_dcpomatic(" list-servers display a list of encoding servers that %1 can use (until Ctrl-C)\n")); out(" dump show a summary of the film's settings\n"); +#ifdef DCPOMATIC_GROK + out(" config-params list the parameters that can be set with `config`\n"); + out(" config set a DCP-o-matic configuration value\n"); +#endif out("\nOptions:\n\n"); out(variant::insert_dcpomatic(" -v, --version show %1 version\n")); @@ -95,6 +99,7 @@ help(function out) out(" --hints analyze film for hints before encoding and abort if any are found\n"); out("\ne.g.\n"); out(fmt::format("\n {} -t 4 make-dcp my_great_movie\n", program_name)); + out(fmt::format("\n {} config grok-licence 12345ABCD\n", program_name)); out("\n"); } @@ -374,7 +379,13 @@ encode_cli(int argc, char* argv[], function out, function commands = { "make-dcp", "list-servers", +#ifdef DCPOMATIC_GROK + "dump", + "config-params", + "config" +#else "dump" +#endif }; if (optind < argc - 1) { @@ -387,6 +398,33 @@ encode_cli(int argc, char* argv[], function out, functiongrok(); + if (parameter == "grok-licence") { + grok.licence = value; + Config::instance()->set_grok(grok); + Config::instance()->write(); + } else { + return fmt::format("Unrecognised configuration parameter `{}'", parameter); + } + } else { + return fmt::format("Missing configuration parameter: use {} config ", program_name); + } + return {}; + } +#endif + if (config) { State::override_path = *config; } diff --git a/test/encode_cli_test.cc b/test/encode_cli_test.cc index d857476a6..8ee656277 100644 --- a/test/encode_cli_test.cc +++ b/test/encode_cli_test.cc @@ -47,8 +47,11 @@ run(vector const& args, vector& output) argv[args.size()] = nullptr; auto error = encode_cli(args.size(), argv.data(), [&output](string s) { output.push_back(s); }, []() { }); + for (auto i: output) { + std::cout << "O:" << i; + } if (error) { - std::cout << *error << "\n"; + std::cout << "E:" << *error << "\n"; } return error; @@ -99,3 +102,24 @@ BOOST_AUTO_TEST_CASE(encode_cli_with_explicit_encode_command_test) BOOST_CHECK(find_in_order(output, { "Making DCP for", "Examining content", "OK", "Transcoding DCP", "OK" })); } + + +#ifdef DCPOMATIC_GROK +BOOST_AUTO_TEST_CASE(encode_cli_set_grok_licence) +{ + boost::filesystem::path config = "build/encode_cli_set_grok_licence"; + boost::filesystem::remove_all(config); + boost::filesystem::create_directories(config); + ConfigRestorer cr(config); + + vector output; + auto error = run({ "cli", "config", "grok-licence", "12345678ABC" }, output); + BOOST_CHECK(output.empty()); + BOOST_CHECK(!error); + + cxml::Document check("Config"); + check.read_file(config / "2.18" / "config.xml"); + BOOST_CHECK_EQUAL(check.node_child("Grok")->string_child("Licence"), "12345678ABC"); +} +#endif + -- cgit v1.2.3 From 641f5f2f61b77d79cb1e8c737cda0766b1ee2de8 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 22:10:56 +0100 Subject: Support some more grok configuration in the dcpomatic2_cli. --- src/lib/encode_cli.cc | 18 +++++++++++++++--- test/encode_cli_test.cc | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index 7e9c25a6a..f28b93421 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -402,7 +402,9 @@ encode_cli(int argc, char* argv[], function out, function out, functiongrok(); if (parameter == "grok-licence") { grok.licence = value; - Config::instance()->set_grok(grok); - Config::instance()->write(); + } else if (parameter == "grok-enable") { + if (value == "1") { + grok.enable = true; + } else if (value == "0") { + grok.enable = false; + } else { + return fmt::format("Invalid value {} for grok-enable (use 1 to enable, 0 to disable)", value); + } + } else if (parameter == "grok-binary-location") { + grok.binary_location = value; } else { return fmt::format("Unrecognised configuration parameter `{}'", parameter); } + Config::instance()->set_grok(grok); + Config::instance()->write(); } else { return fmt::format("Missing configuration parameter: use {} config ", program_name); } diff --git a/test/encode_cli_test.cc b/test/encode_cli_test.cc index 8ee656277..0a0a17e3a 100644 --- a/test/encode_cli_test.cc +++ b/test/encode_cli_test.cc @@ -121,5 +121,43 @@ BOOST_AUTO_TEST_CASE(encode_cli_set_grok_licence) check.read_file(config / "2.18" / "config.xml"); BOOST_CHECK_EQUAL(check.node_child("Grok")->string_child("Licence"), "12345678ABC"); } + + +BOOST_AUTO_TEST_CASE(encode_cli_enable_grok) +{ + boost::filesystem::path config = "build/encode_cli_enable_grok"; + boost::filesystem::remove_all(config); + boost::filesystem::create_directories(config); + ConfigRestorer cr(config); + + for (auto value: vector{ "1", "0"}) { + vector output; + auto error = run({ "cli", "config", "grok-enable", value }, output); + BOOST_CHECK(output.empty()); + BOOST_CHECK(!error); + + cxml::Document check("Config"); + check.read_file(config / "2.18" / "config.xml"); + BOOST_CHECK_EQUAL(check.node_child("Grok")->string_child("Enable"), value); + } +} + + +BOOST_AUTO_TEST_CASE(encode_cli_set_grok_binary_location) +{ + boost::filesystem::path config = "build/encode_cli_set_grok_binary_location"; + boost::filesystem::remove_all(config); + boost::filesystem::create_directories(config); + ConfigRestorer cr(config); + + vector output; + auto error = run({ "cli", "config", "grok-binary-location", "foo/bar/baz" }, output); + BOOST_CHECK(output.empty()); + BOOST_CHECK(!error); + + cxml::Document check("Config"); + check.read_file(config / "2.18" / "config.xml"); + BOOST_CHECK_EQUAL(check.node_child("Grok")->string_child("BinaryLocation"), "foo/bar/baz"); +} #endif -- cgit v1.2.3 From 7ff15e15e08d0d8603633980bb128f447861c947 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 23:29:06 +0100 Subject: Add list-gpus command to dcpomatic2_cli. --- src/lib/encode_cli.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index f28b93421..7681252b2 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -30,6 +30,7 @@ #include "filter.h" #ifdef DCPOMATIC_GROK #include "grok/context.h" +#include "grok/util.h" #endif #include "hints.h" #include "job_manager.h" @@ -75,6 +76,7 @@ help(function out) #ifdef DCPOMATIC_GROK out(" config-params list the parameters that can be set with `config`\n"); out(" config set a DCP-o-matic configuration value\n"); + out(" list-gpus list available GPUs\n"); #endif out("\nOptions:\n\n"); @@ -382,7 +384,8 @@ encode_cli(int argc, char* argv[], function out, function out, function ", program_name); } return {}; + } else if (command == "list-gpus") { + int N = 0; + for (auto gpu: get_gpu_names()) { + out(fmt::format("{}: {}\n", N++, gpu)); + } + return {}; } #endif -- cgit v1.2.3 From 42b92cbe4518a170b217ab54a26b51f56246a50f Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 3 Mar 2025 23:40:33 +0100 Subject: Allow configuration of Grok GPU index. --- src/lib/encode_cli.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/lib/encode_cli.cc') diff --git a/src/lib/encode_cli.cc b/src/lib/encode_cli.cc index 7681252b2..fa304b6e0 100644 --- a/src/lib/encode_cli.cc +++ b/src/lib/encode_cli.cc @@ -44,6 +44,7 @@ #include "version.h" #include "video_content.h" #include +#include #include #include #include @@ -408,6 +409,7 @@ encode_cli(int argc, char* argv[], function out, function out, function(value); } else { return fmt::format("Unrecognised configuration parameter `{}'", parameter); } -- cgit v1.2.3