From: Steinar H. Gunderson Date: Thu, 1 Mar 2018 19:08:59 +0000 (+0100) Subject: Expose the absolute path to the theme in Nageru.THEME_PATH. X-Git-Tag: 1.7.0~2 X-Git-Url: https://git.sesse.net/?p=nageru;a=commitdiff_plain;h=16e654819e2254ef045b60b7751a918558c4a13a Expose the absolute path to the theme in Nageru.THEME_PATH. Presumably useful if the theme wants to open up CEF stuff that is relative to its own path (perhaps even in the same directory). Also don't let themes return values (with LUA_MULTRET); they'd just hit the assert one line further down anyway. --- diff --git a/theme.cpp b/theme.cpp index 5fc5a75..32a00ff 100644 --- a/theme.cpp +++ b/theme.cpp @@ -1090,24 +1090,7 @@ Theme::Theme(const string &filename, const vector &search_dirs, Resource L = luaL_newstate(); luaL_openlibs(L); - register_constants(); - register_class("EffectChain", EffectChain_funcs); - register_class("LiveInputWrapper", LiveInputWrapper_funcs); - register_class("ImageInput", ImageInput_funcs); - register_class("VideoInput", VideoInput_funcs); - register_class("HTMLInput", HTMLInput_funcs); - register_class("WhiteBalanceEffect", WhiteBalanceEffect_funcs); - register_class("ResampleEffect", ResampleEffect_funcs); - register_class("PaddingEffect", PaddingEffect_funcs); - register_class("IntegralPaddingEffect", IntegralPaddingEffect_funcs); - register_class("OverlayEffect", OverlayEffect_funcs); - register_class("ResizeEffect", ResizeEffect_funcs); - register_class("MultiplyEffect", MultiplyEffect_funcs); - register_class("MixEffect", MixEffect_funcs); - register_class("InputStateInfo", InputStateInfo_funcs); - register_class("ThemeMenu", ThemeMenu_funcs); - - // Run script. Search through all directories until we find a file that will load + // 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); @@ -1121,8 +1104,9 @@ Theme::Theme(const string &filename, const vector &search_dirs, Resource real_search_dirs = search_dirs; } + string path; + int theme_code_ref; for (const string &dir : real_search_dirs) { - string path; if (dir.empty()) { path = filename; } else { @@ -1130,11 +1114,13 @@ Theme::Theme(const string &filename, const vector &search_dirs, Resource } 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); - } + // Save the theme for when we're actually going to run it + // (we need to set up the right environment below first, + // and we couldn't do that before, because we didn't know the + // path to put in Nageru.THEME_PATH). + theme_code_ref = luaL_ref(L, LUA_REGISTRYINDEX); + assert(lua_gettop(L) == 0); + success = true; break; } @@ -1154,6 +1140,46 @@ Theme::Theme(const string &filename, const vector &search_dirs, Resource } assert(lua_gettop(L) == 0); + // Make sure the path exposed to the theme (as Nageru.THEME_PATH; + // can be useful for locating files when talking to CEF) is absolute. + // In a sense, it would be nice if realpath() had a mode not to + // resolve symlinks, but it doesn't, so we only call it if we don't + // already have an absolute path (which may leave ../ elements etc.). + if (path[0] == '/') { + theme_path = path; + } else { + char *absolute_theme_path = realpath(path.c_str(), nullptr); + theme_path = absolute_theme_path; + free(absolute_theme_path); + } + + // Set up the API we provide. + register_constants(); + register_class("EffectChain", EffectChain_funcs); + register_class("LiveInputWrapper", LiveInputWrapper_funcs); + register_class("ImageInput", ImageInput_funcs); + register_class("VideoInput", VideoInput_funcs); + register_class("HTMLInput", HTMLInput_funcs); + register_class("WhiteBalanceEffect", WhiteBalanceEffect_funcs); + register_class("ResampleEffect", ResampleEffect_funcs); + register_class("PaddingEffect", PaddingEffect_funcs); + register_class("IntegralPaddingEffect", IntegralPaddingEffect_funcs); + register_class("OverlayEffect", OverlayEffect_funcs); + register_class("ResizeEffect", ResizeEffect_funcs); + register_class("MultiplyEffect", MultiplyEffect_funcs); + register_class("MixEffect", MixEffect_funcs); + register_class("InputStateInfo", InputStateInfo_funcs); + register_class("ThemeMenu", ThemeMenu_funcs); + + // Now actually run the theme to get everything set up. + lua_rawgeti(L, LUA_REGISTRYINDEX, theme_code_ref); + luaL_unref(L, LUA_REGISTRYINDEX, theme_code_ref); + if (lua_pcall(L, 0, 0, 0)) { + fprintf(stderr, "Error when running %s: %s\n", path.c_str(), lua_tostring(L, -1)); + exit(1); + } + assert(lua_gettop(L) == 0); + // Ask it for the number of channels. num_channels = call_num_channels(L); } @@ -1166,18 +1192,26 @@ Theme::~Theme() void Theme::register_constants() { // Set Nageru.VIDEO_FORMAT_BGRA = bmusb::PixelFormat_8BitBGRA, etc. - const vector> constants = { + const vector> num_constants = { { "VIDEO_FORMAT_BGRA", bmusb::PixelFormat_8BitBGRA }, { "VIDEO_FORMAT_YCBCR", bmusb::PixelFormat_8BitYCbCrPlanar }, }; + const vector> str_constants = { + { "THEME_PATH", theme_path }, + }; lua_newtable(L); // t = {} - for (const pair &constant : constants) { + for (const pair &constant : num_constants) { lua_pushstring(L, constant.first.c_str()); lua_pushinteger(L, constant.second); lua_settable(L, 1); // t[key] = value } + for (const pair &constant : str_constants) { + lua_pushstring(L, constant.first.c_str()); + lua_pushstring(L, constant.second.c_str()); + lua_settable(L, 1); // t[key] = value + } lua_setglobal(L, "Nageru"); // Nageru = t assert(lua_gettop(L) == 0); diff --git a/theme.h b/theme.h index 8712bf8..d2f6d2c 100644 --- a/theme.h +++ b/theme.h @@ -123,6 +123,8 @@ private: void register_class(const char *class_name, const luaL_Reg *funcs); int set_theme_menu(lua_State *L); + std::string theme_path; + std::mutex m; lua_State *L; // Protected by . const InputState *input_state = nullptr; // Protected by . Only set temporarily, during chain setup.