From b7398dd7960ddf07f03b9a9ebc669d29141c09d0 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Fri, 21 Jun 2019 19:31:28 +0200 Subject: [PATCH] Make it possible to set channel names imperatively instead of using a callback. channel_name() will still be used if it exists, for compatibility with older themes. --- nageru/simple.lua | 14 +++----------- nageru/theme.cpp | 32 ++++++++++++++++++++++++++++++-- nageru/theme.h | 5 ++++- nageru/theme.lua | 35 ++++++++--------------------------- 4 files changed, 45 insertions(+), 41 deletions(-) diff --git a/nageru/simple.lua b/nageru/simple.lua index 3960505..8d5b3e6 100644 --- a/nageru/simple.lua +++ b/nageru/simple.lua @@ -32,17 +32,9 @@ function num_channels() return 2 end --- API ENTRY POINT --- Returns the name for each additional channel (starting from 2). --- Called at the start of the program, and then each frame for live --- channels in case they change resolution. -function channel_name(channel) - if channel == 2 then - return "First input" - elseif channel == 3 then - return "Second input" - end -end +-- Set some global state. +Nageru.set_channel_name(2, "First input") +Nageru.set_channel_name(3, "Second input") -- API ENTRY POINT -- Returns, given a channel number, which signal it corresponds to (starting from 0). diff --git a/nageru/theme.cpp b/nageru/theme.cpp index 8050003..6a4de4b 100644 --- a/nageru/theme.cpp +++ b/nageru/theme.cpp @@ -1223,6 +1223,17 @@ int call_num_channels(lua_State *L) } // namespace +int Nageru_set_channel_name(lua_State *L) +{ + // NOTE: m is already locked. + Theme *theme = get_theme_updata(L); + unsigned channel = luaL_checknumber(L, 1); + const string text = checkstdstring(L, 2); + theme->channel_names[channel] = text; + lua_pop(L, 2); + return 0; +} + 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) { @@ -1293,7 +1304,7 @@ Theme::Theme(const string &filename, const vector &search_dirs, Resource } // Set up the API we provide. - register_constants(); + register_globals(); register_class("Scene", Scene_funcs); register_class("Block", Block_funcs); register_class("EffectBlueprint", EffectBlueprint_funcs); @@ -1334,7 +1345,7 @@ Theme::~Theme() lua_close(L); } -void Theme::register_constants() +void Theme::register_globals() { // Set Nageru.VIDEO_FORMAT_BGRA = bmusb::PixelFormat_8BitBGRA, etc. const vector> num_constants = { @@ -1358,6 +1369,13 @@ void Theme::register_constants() lua_settable(L, 1); // t[key] = value } + const luaL_Reg Nageru_funcs[] = { + { "set_channel_name", Nageru_set_channel_name }, + { NULL, NULL } + }; + lua_pushlightuserdata(L, this); + luaL_setfuncs(L, Nageru_funcs, 1); // for (name,f in funcs) { mt[name] = f, with upvalue {theme} } + lua_setglobal(L, "Nageru"); // Nageru = t assert(lua_gettop(L) == 0); } @@ -1484,7 +1502,17 @@ Theme::Chain Theme::get_chain(unsigned num, float t, unsigned width, unsigned he string Theme::get_channel_name(unsigned channel) { lock_guard lock(m); + lua_getglobal(L, "channel_name"); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + if (channel_names.count(channel)) { + return channel_names[channel]; + } else { + return "(no title)"; + } + } + lua_pushnumber(L, channel); if (lua_pcall(L, 1, 1, 0) != 0) { fprintf(stderr, "error running function `channel_name': %s\n", lua_tostring(L, -1)); diff --git a/nageru/theme.h b/nageru/theme.h index 2fac796..7945425 100644 --- a/nageru/theme.h +++ b/nageru/theme.h @@ -180,7 +180,7 @@ public: } private: - void register_constants(); + void register_globals(); void register_class(const char *class_name, const luaL_Reg *funcs, EffectType effect_type = NO_EFFECT_TYPE); int set_theme_menu(lua_State *L); Chain get_chain_from_effect_chain(movit::EffectChain *effect_chain, unsigned num, const InputState &input_state); @@ -217,9 +217,12 @@ private: std::unique_ptr theme_menu; std::function theme_menu_callback; + std::map channel_names; // Set using Nageru.set_theme(). Protected by . + friend class LiveInputWrapper; friend class Scene; friend int ThemeMenu_set(lua_State *L); + friend int Nageru_set_channel_name(lua_State *L); }; // LiveInputWrapper is a facade on top of an YCbCrInput, exposed to diff --git a/nageru/theme.lua b/nageru/theme.lua index de8d252..c762a3f 100644 --- a/nageru/theme.lua +++ b/nageru/theme.lua @@ -36,11 +36,6 @@ local NO_TRANSITION = 0 local ZOOM_TRANSITION = 1 -- Also for slides. local FADE_TRANSITION = 2 --- Last width/height/frame rate for each channel, if we have it. --- Note that unlike the values we get from Nageru, the resolution is per --- frame and not per field, since we deinterlace. -local last_resolution = {} - function make_sbs_input(scene) return { input = scene:add_input(), @@ -115,6 +110,10 @@ local static_scene = Scene.new(16, 9) static_scene:add_input(static_image) -- Note: Locks this input to images only. static_scene:finalize() +-- Set some global state. +Nageru.set_channel_name(SBS_SIGNAL_NUM + 2, "Side-by-side") +Nageru.set_channel_name(STATIC_SIGNAL_NUM + 2, "Static picture") + -- API ENTRY POINT -- Returns the number of outputs in addition to the live (0) and preview (1). -- Called only once, at the start of the program. @@ -126,25 +125,6 @@ function is_plain_signal(num) return num == INPUT0_SIGNAL_NUM or num == INPUT1_SIGNAL_NUM end --- API ENTRY POINT --- Returns the name for each additional channel (starting from 2). --- Called at the start of the program, and then each frame for live --- channels in case they change resolution. -function channel_name(channel) - local signal_num = channel - 2 - if is_plain_signal(signal_num) then - if last_resolution[signal_num] then - return "Input " .. (signal_num + 1) .. " (" .. last_resolution[signal_num].human_readable_resolution .. ")" - else - return "Input " .. (signal_num + 1) - end - elseif signal_num == SBS_SIGNAL_NUM then - return "Side-by-side" - elseif signal_num == STATIC_SIGNAL_NUM then - return "Static picture" - end -end - -- API ENTRY POINT -- Returns, given a channel number, which signal it corresponds to (starting from 0). -- Should return -1 if the channel does not correspond to a simple signal @@ -397,8 +377,7 @@ function get_scene(num, t, width, height, signals) is_connected = signals:get_is_connected(signal_num), has_signal = signals:get_has_signal(signal_num), frame_rate_nom = signals:get_frame_rate_nom(signal_num), - frame_rate_den = signals:get_frame_rate_den(signal_num), - human_readable_resolution = signals:get_human_readable_resolution(signal_num) + frame_rate_den = signals:get_frame_rate_den(signal_num) } if res.interlaced then @@ -413,8 +392,10 @@ function get_scene(num, t, width, height, signals) end input_resolution[signal_num] = res + + local text_res = signals:get_human_readable_resolution(signal_num) + Nageru.set_channel_name(signal_num + 2, "Input " .. (signal_num + 1) .. " (" .. text_res .. ")") end - last_resolution = input_resolution if num == 0 then -- Live. finish_transitions(t) -- 2.39.2