]> git.sesse.net Git - nageru/commitdiff
Expose the absolute path to the theme in Nageru.THEME_PATH.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 1 Mar 2018 19:08:59 +0000 (20:08 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Thu, 1 Mar 2018 19:08:59 +0000 (20:08 +0100)
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.

theme.cpp
theme.h

index 5fc5a7538cee288ae7e3fc335c1550bfdfe1dd2e..32a00ff7ec4ba639939bf34527b414a6ed120255 100644 (file)
--- a/theme.cpp
+++ b/theme.cpp
@@ -1090,24 +1090,7 @@ Theme::Theme(const string &filename, const vector<string> &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<string> &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<string> &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<string> &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<pair<string, int>> constants = {
+       const vector<pair<string, int>> num_constants = {
                { "VIDEO_FORMAT_BGRA", bmusb::PixelFormat_8BitBGRA },
                { "VIDEO_FORMAT_YCBCR", bmusb::PixelFormat_8BitYCbCrPlanar },
        };
+       const vector<pair<string, string>> str_constants = {
+               { "THEME_PATH", theme_path },
+       };
 
        lua_newtable(L);  // t = {}
 
-       for (const pair<string, int> &constant : constants) {
+       for (const pair<string, int> &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<string, string> &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 8712bf81542e9fb2df645f78ad0def61a475131c..d2f6d2c586a396199af736e6898b6ea0526a2641 100644 (file)
--- 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 <m>.
        const InputState *input_state = nullptr;  // Protected by <m>. Only set temporarily, during chain setup.