From cfb6e27f0331084a35efdcd4e8cec1f2c9949875 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Wed, 27 Jul 2016 01:21:24 +0200 Subject: [PATCH] Support searching for the theme in multiple directories. --- flags.cpp | 9 +++++++++ flags.h | 1 + mixer.cpp | 2 +- theme.cpp | 33 +++++++++++++++++++++++++++++---- theme.h | 2 +- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/flags.cpp b/flags.cpp index 5f20f48..5c57df7 100644 --- a/flags.cpp +++ b/flags.cpp @@ -52,6 +52,7 @@ void usage() fprintf(stderr, " -c, --num-cards set number of input cards, including fake cards (default 2)\n"); fprintf(stderr, " -C, --num-fake-cards set number of fake cards (default 0)\n"); fprintf(stderr, " -t, --theme=FILE choose theme (default theme.lua)\n"); + fprintf(stderr, " -I, --theme-dir=DIR search for theme in this directory (can be given multiple times)\n"); fprintf(stderr, " -v, --va-display=SPEC VA-API device for H.264 encoding\n"); fprintf(stderr, " ($DISPLAY spec or /dev/dri/render* path)\n"); fprintf(stderr, " -m, --map-signal=SIGNAL,CARD set a default card mapping (can be given multiple times)\n"); @@ -98,6 +99,7 @@ void parse_flags(int argc, char * const argv[]) { "num-cards", required_argument, 0, 'c' }, { "num-fake-cards", required_argument, 0, 'C' }, { "theme", required_argument, 0, 't' }, + { "theme-dir", required_argument, 0, 'I' }, { "map-signal", required_argument, 0, 'm' }, { "va-display", required_argument, 0, OPTION_VA_DISPLAY }, { "http-uncompressed-video", no_argument, 0, OPTION_HTTP_UNCOMPRESSED_VIDEO }, @@ -130,6 +132,7 @@ void parse_flags(int argc, char * const argv[]) { "no-flush-pbos", no_argument, 0, OPTION_NO_FLUSH_PBOS }, { 0, 0, 0, 0 } }; + vector theme_dirs; for ( ;; ) { int option_index = 0; int c = getopt_long(argc, argv, "c:C:t:v:m:", long_options, &option_index); @@ -147,6 +150,9 @@ void parse_flags(int argc, char * const argv[]) case 't': global_flags.theme_filename = optarg; break; + case 'I': + theme_dirs.push_back(optarg); + break; case 'm': { char *ptr = strchr(optarg, ','); if (ptr == nullptr) { @@ -293,6 +299,9 @@ void parse_flags(int argc, char * const argv[]) } else if (global_flags.x264_preset.empty()) { global_flags.x264_preset = X264_DEFAULT_PRESET; } + if (!theme_dirs.empty()) { + global_flags.theme_dirs = theme_dirs; + } for (pair mapping : global_flags.default_stream_mapping) { if (mapping.second >= global_flags.num_cards) { diff --git a/flags.h b/flags.h index 7d4abd2..beddab7 100644 --- a/flags.h +++ b/flags.h @@ -13,6 +13,7 @@ struct Flags { std::string va_display; bool uncompressed_video_to_http = false; bool x264_video_to_http = false; + std::vector theme_dirs { ".", "/usr/local/share/nageru" }; std::string theme_filename = "theme.lua"; bool locut_enabled = true; bool gain_staging_auto = true; diff --git a/mixer.cpp b/mixer.cpp index e087796..ff1f83c 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -144,7 +144,7 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards) movit_texel_subpixel_precision /= 2.0; resource_pool.reset(new ResourcePool); - theme.reset(new Theme(global_flags.theme_filename.c_str(), resource_pool.get(), num_cards)); + theme.reset(new Theme(global_flags.theme_filename, global_flags.theme_dirs, resource_pool.get(), num_cards)); for (unsigned i = 0; i < NUM_OUTPUTS; ++i) { output_channel[i].parent = this; output_channel[i].channel = i; diff --git a/theme.cpp b/theme.cpp index a73b607..1434d98 100644 --- a/theme.cpp +++ b/theme.cpp @@ -708,7 +708,7 @@ int call_num_channels(lua_State *L) } // namespace -Theme::Theme(const char *filename, ResourcePool *resource_pool, unsigned num_cards) +Theme::Theme(const string &filename, const vector &search_dirs, ResourcePool *resource_pool, unsigned num_cards) : resource_pool(resource_pool), num_cards(num_cards), signal_to_card_mapping(global_flags.default_stream_mapping) { L = luaL_newstate(); @@ -727,11 +727,36 @@ Theme::Theme(const char *filename, ResourcePool *resource_pool, unsigned num_car register_class("MixEffect", MixEffect_funcs); register_class("InputStateInfo", InputStateInfo_funcs); - // Run script. + // Run script. Search through all directories until we find a file that will load + // (as in, does not return LUA_ERRFILE); then run it. We store load errors + // from all the attempts, and show them once we know we can't find any of them. lua_settop(L, 0); - if (luaL_dofile(L, filename)) { - fprintf(stderr, "error: %s\n", lua_tostring(L, -1)); + vector errors; + bool success = false; + for (size_t i = 0; i < search_dirs.size(); ++i) { + string path = search_dirs[i] + "/" + filename; + int err = luaL_loadfile(L, path.c_str()); + if (err == 0) { + // Success; actually call the code. + if (lua_pcall(L, 0, LUA_MULTRET, 0)) { + fprintf(stderr, "Error when running %s: %s\n", path.c_str(), lua_tostring(L, -1)); + exit(1); + } + success = true; + break; + } + errors.push_back(lua_tostring(L, -1)); lua_pop(L, 1); + if (err != LUA_ERRFILE) { + // The file actually loaded, but failed to parse somehow. Abort; don't try the next one. + break; + } + } + + if (!success) { + for (const string &error : errors) { + fprintf(stderr, "%s\n", error.c_str()); + } exit(1); } assert(lua_gettop(L) == 0); diff --git a/theme.h b/theme.h index 264b5ac..91c5c2e 100644 --- a/theme.h +++ b/theme.h @@ -38,7 +38,7 @@ public: class Theme { public: - Theme(const char *filename, movit::ResourcePool *resource_pool, unsigned num_cards); + Theme(const std::string &filename, const std::vector &search_dirs, movit::ResourcePool *resource_pool, unsigned num_cards); ~Theme(); struct Chain { -- 2.39.2