]> git.sesse.net Git - nageru/blobdiff - theme.cpp
Open up for inputs that are different from the native resolution. No deinterlacing...
[nageru] / theme.cpp
index 4ea8cd73b6eaf12ea23da9e363f8b8a2220ee4cd..61e149c3320c9256d0985d51a3db26dc913e99f2 100644 (file)
--- a/theme.cpp
+++ b/theme.cpp
 #include <cstddef>
 #include <new>
 #include <utility>
+#include <memory>
+
+#include "defs.h"
+#include "image_input.h"
 
 namespace movit {
 class ResourcePool;
 }  // namespace movit
 
-#define WIDTH 1280  // FIXME
-#define HEIGHT 720  // FIXME
-
 using namespace std;
 using namespace movit;
 
@@ -35,6 +36,23 @@ namespace {
 
 vector<LiveInputWrapper *> live_inputs;
 
+class LuaRefWithDeleter {
+public:
+       LuaRefWithDeleter(mutex *m, lua_State *L, int ref) : m(m), L(L), ref(ref) {}
+       ~LuaRefWithDeleter() {
+               unique_lock<mutex> lock(*m);
+               luaL_unref(L, LUA_REGISTRYINDEX, ref);
+       }
+       int get() const { return ref; }
+
+private:
+       LuaRefWithDeleter(const LuaRefWithDeleter &) = delete;
+
+       mutex *m;
+       lua_State *L;
+       int ref;
+};
+
 template<class T, class... Args>
 int wrap_lua_object(lua_State* L, const char *class_name, Args&&... args)
 {
@@ -63,7 +81,8 @@ Effect *get_effect(lua_State *L, int idx)
            luaL_testudata(L, idx, "IntegralPaddingEffect") ||
            luaL_testudata(L, idx, "OverlayEffect") ||
            luaL_testudata(L, idx, "ResizeEffect") ||
-           luaL_testudata(L, idx, "MixEffect")) {
+           luaL_testudata(L, idx, "MixEffect") ||
+           luaL_testudata(L, idx, "ImageInput")) {
                return (Effect *)lua_touserdata(L, idx);
        }
        luaL_error(L, "Error: Index #%d was not an Effect type\n", idx);
@@ -76,6 +95,13 @@ bool checkbool(lua_State* L, int idx)
        return lua_toboolean(L, idx);
 }
 
+std::string checkstdstring(lua_State *L, int index)
+{
+       size_t len;
+       const char* cstr = lua_tolstring(L, index, &len);
+       return std::string(cstr, len);
+}
+
 int EffectChain_new(lua_State* L)
 {
        assert(lua_gettop(L) == 2);
@@ -102,7 +128,11 @@ int EffectChain_add_effect(lua_State* L)
        // TODO: Better error reporting.
        Effect *effect = get_effect(L, 2);
        if (lua_gettop(L) == 2) {
-               chain->add_effect(effect);
+               if (effect->num_inputs() == 0) {
+                       chain->add_input((Input *)effect);
+               } else {
+                       chain->add_effect(effect);
+               }
        } else {
                vector<Effect *> inputs;
                for (int idx = 3; idx <= lua_gettop(L); ++idx) {
@@ -179,6 +209,13 @@ int LiveInputWrapper_connect_signal(lua_State* L)
        return 0;
 }
 
+int ImageInput_new(lua_State* L)
+{
+       assert(lua_gettop(L) == 1);
+       std::string filename = checkstdstring(L, 1);
+       return wrap_lua_object<ImageInput>(L, "ImageInput", filename);
+}
+
 int WhiteBalanceEffect_new(lua_State* L)
 {
        assert(lua_gettop(L) == 0);
@@ -225,12 +262,10 @@ int Effect_set_float(lua_State *L)
 {
        assert(lua_gettop(L) == 3);
        Effect *effect = (Effect *)get_effect(L, 1);
-       size_t len;
-       const char* cstr = lua_tolstring(L, 2, &len);
-       std::string key(cstr, len);
+       std::string key = checkstdstring(L, 2);
        float value = luaL_checknumber(L, 3);
        if (!effect->set_float(key, value)) {
-               luaL_error(L, "Effect refused set_float(\"%s\", %d) (invalid key?)", cstr, int(value));
+               luaL_error(L, "Effect refused set_float(\"%s\", %d) (invalid key?)", key.c_str(), int(value));
        }
        return 0;
 }
@@ -239,12 +274,10 @@ int Effect_set_int(lua_State *L)
 {
        assert(lua_gettop(L) == 3);
        Effect *effect = (Effect *)get_effect(L, 1);
-       size_t len;
-       const char* cstr = lua_tolstring(L, 2, &len);
-       std::string key(cstr, len);
+       std::string key = checkstdstring(L, 2);
        float value = luaL_checknumber(L, 3);
        if (!effect->set_int(key, value)) {
-               luaL_error(L, "Effect refused set_int(\"%s\", %d) (invalid key?)", cstr, int(value));
+               luaL_error(L, "Effect refused set_int(\"%s\", %d) (invalid key?)", key.c_str(), int(value));
        }
        return 0;
 }
@@ -253,15 +286,13 @@ int Effect_set_vec3(lua_State *L)
 {
        assert(lua_gettop(L) == 5);
        Effect *effect = (Effect *)get_effect(L, 1);
-       size_t len;
-       const char* cstr = lua_tolstring(L, 2, &len);
-       std::string key(cstr, len);
+       std::string key = checkstdstring(L, 2);
        float v[3];
        v[0] = luaL_checknumber(L, 3);
        v[1] = luaL_checknumber(L, 4);
        v[2] = luaL_checknumber(L, 5);
        if (!effect->set_vec3(key, v)) {
-               luaL_error(L, "Effect refused set_vec3(\"%s\", %f, %f, %f) (invalid key?)", cstr,
+               luaL_error(L, "Effect refused set_vec3(\"%s\", %f, %f, %f) (invalid key?)", key.c_str(),
                        v[0], v[1], v[2]);
        }
        return 0;
@@ -271,16 +302,14 @@ int Effect_set_vec4(lua_State *L)
 {
        assert(lua_gettop(L) == 6);
        Effect *effect = (Effect *)get_effect(L, 1);
-       size_t len;
-       const char* cstr = lua_tolstring(L, 2, &len);
-       std::string key(cstr, len);
+       std::string key = checkstdstring(L, 2);
        float v[4];
        v[0] = luaL_checknumber(L, 3);
        v[1] = luaL_checknumber(L, 4);
        v[2] = luaL_checknumber(L, 5);
        v[3] = luaL_checknumber(L, 6);
        if (!effect->set_vec4(key, v)) {
-               luaL_error(L, "Effect refused set_vec4(\"%s\", %f, %f, %f, %f) (invalid key?)", cstr,
+               luaL_error(L, "Effect refused set_vec4(\"%s\", %f, %f, %f, %f) (invalid key?)", key.c_str(),
                        v[0], v[1], v[2], v[3]);
        }
        return 0;
@@ -299,6 +328,15 @@ const luaL_Reg LiveInputWrapper_funcs[] = {
        { NULL, NULL }
 };
 
+const luaL_Reg ImageInput_funcs[] = {
+       { "new", ImageInput_new },
+       { "set_float", Effect_set_float },
+       { "set_int", Effect_set_int },
+       { "set_vec3", Effect_set_vec3 },
+       { "set_vec4", Effect_set_vec4 },
+       { NULL, NULL }
+};
+
 const luaL_Reg WhiteBalanceEffect_funcs[] = {
        { "new", WhiteBalanceEffect_new },
        { "set_float", Effect_set_float },
@@ -414,6 +452,7 @@ Theme::Theme(const char *filename, ResourcePool *resource_pool, unsigned num_car
 
        register_class("EffectChain", EffectChain_funcs); 
        register_class("LiveInputWrapper", LiveInputWrapper_funcs); 
+       register_class("ImageInput", ImageInput_funcs);
        register_class("WhiteBalanceEffect", WhiteBalanceEffect_funcs);
        register_class("ResampleEffect", ResampleEffect_funcs);
        register_class("PaddingEffect", PaddingEffect_funcs);
@@ -478,14 +517,14 @@ Theme::get_chain(unsigned num, float t, unsigned width, unsigned height)
                exit(1);
        }
        lua_pushvalue(L, -1);
-       int funcref = luaL_ref(L, LUA_REGISTRYINDEX);  // TODO: leak!
+       shared_ptr<LuaRefWithDeleter> funcref(new LuaRefWithDeleter(&m, L, luaL_ref(L, LUA_REGISTRYINDEX)));
        lua_pop(L, 2);
        assert(lua_gettop(L) == 0);
        return make_pair(chain, [this, funcref]{
                unique_lock<mutex> lock(m);
 
                // Set up state, including connecting signals.
-               lua_rawgeti(L, LUA_REGISTRYINDEX, funcref);
+               lua_rawgeti(L, LUA_REGISTRYINDEX, funcref->get());
                if (lua_pcall(L, 0, 0, 0) != 0) {
                        fprintf(stderr, "error running chain setup callback: %s\n", lua_tostring(L, -1));
                        exit(1);
@@ -574,6 +613,8 @@ void Theme::connect_signal(YCbCrInput *input, int signal_num)
        }
        input->set_texture_num(0, input_textures[signal_num].tex_y);
        input->set_texture_num(1, input_textures[signal_num].tex_cbcr);
+       input->set_width(input_textures[signal_num].width);
+       input->set_height(input_textures[signal_num].height);
 }
 
 void Theme::transition_clicked(int transition_num, float t)