X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=theme.lua;h=bbc086a4e86f478dde7c2b66eabe8f64e78a0aee;hb=f006b5b162841dbc764fb620025b87a3272ac79a;hp=e59ccc86cb0ed0ef4d6cc29f352f3c510ffdea95;hpb=4d07ca58601c7c6ec9bb51f561d1b23601a47637;p=nageru diff --git a/theme.lua b/theme.lua index e59ccc8..bbc086a 100644 --- a/theme.lua +++ b/theme.lua @@ -31,7 +31,7 @@ local STATIC_SIGNAL_NUM = 3 -- to the next. local FADE_SIGNAL_NUM = 4 --- Last width/height/resolution for each channel, if we have it. +-- 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 = {} @@ -57,7 +57,6 @@ end function make_sbs_input(chain, signal, deint, hq) local input = chain:add_live_input(not deint, deint) -- Override bounce only if not deinterlacing. input:connect_signal(signal) - local wb_effect = chain:add_effect(WhiteBalanceEffect.new()) local resample_effect = nil local resize_effect = nil @@ -66,6 +65,7 @@ function make_sbs_input(chain, signal, deint, hq) else resize_effect = chain:add_effect(ResizeEffect.new()) end + local wb_effect = chain:add_effect(WhiteBalanceEffect.new()) local padding_effect = chain:add_effect(IntegralPaddingEffect.new()) @@ -113,9 +113,8 @@ function make_fade_input(chain, signal, live, deint, scale) local input, wb_effect, resample_effect, last if live then input = chain:add_live_input(false, deint) - wb_effect = chain:add_effect(WhiteBalanceEffect.new()) input:connect_signal(signal) - last = wb_effect + last = input else input = chain:add_effect(ImageInput.new("bg.jpeg")) last = input @@ -128,6 +127,12 @@ function make_fade_input(chain, signal, live, deint, scale) last = resample_effect end + -- Make sure to put the white balance after the scaling (usually more efficient). + if live then + wb_effect = chain:add_effect(WhiteBalanceEffect.new()) + last = wb_effect + end + return { input = input, wb_effect = wb_effect, @@ -177,8 +182,6 @@ function make_simple_chain(input_deint, input_scale, hq) local input = chain:add_live_input(false, input_deint) input:connect_signal(0) -- First input card. Can be changed whenever you want. - local wb_effect = chain:add_effect(WhiteBalanceEffect.new()) - chain:finalize(hq) local resample_effect, resize_effect if scale then @@ -189,6 +192,9 @@ function make_simple_chain(input_deint, input_scale, hq) end end + local wb_effect = chain:add_effect(WhiteBalanceEffect.new()) + chain:finalize(hq) + return { chain = chain, input = input, @@ -248,16 +254,36 @@ function set_scale_parameters_if_needed(chain_or_input, width, height) end end +-- 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. function num_channels() return 4 end +-- Helper function to write e.g. “720p60”. The difference between this +-- and get_channel_resolution_raw() is that this one also can say that +-- there's no signal. +function get_channel_resolution(signal_num) + res = last_resolution[signal_num] + if (not res) or res.height <= 0 then + return "no signal" + end + if not res.has_signal then + if res.height == 525 then + -- Special mode for the USB3 cards. + return "no signal" + end + return get_channel_resolution_raw(res) .. ", no signal" + else + return get_channel_resolution_raw(res) + end +end + -- Helper function to write e.g. “60” or “59.94”. -function get_frame_rate(signal_num) - local nom = last_resolution[signal_num].frame_rate_nom - local den = last_resolution[signal_num].frame_rate_den +function get_frame_rate(res) + local nom = res.frame_rate_nom + local den = res.frame_rate_den if nom % den == 0 then return nom / den else @@ -266,21 +292,15 @@ function get_frame_rate(signal_num) end -- Helper function to write e.g. “720p60”. -function get_channel_resolution(signal_num) - if last_resolution[signal_num] then - if last_resolution[signal_num].height == 0 or - last_resolution[signal_num].height == 525 then - return "no signal" - elseif last_resolution[signal_num].interlaced then - return last_resolution[signal_num].height .. "i" .. get_frame_rate(signal_num) - else - return last_resolution[signal_num].height .. "p" .. get_frame_rate(signal_num) - end +function get_channel_resolution_raw(res) + if res.interlaced then + return res.height .. "i" .. get_frame_rate(res) else - return "no signal" + return res.height .. "p" .. get_frame_rate(res) end 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. @@ -296,12 +316,66 @@ function channel_name(channel) 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. +-- (The information is used for whether right-click on the channel should bring up +-- an input selector or not.) +-- Called once for each channel, at the start of the program. +-- Will never be called for live (0) or preview (1). +function channel_signal(channel) + if channel == 2 then + return 0 + elseif channel == 3 then + return 1 + else + return -1 + end +end + +-- API ENTRY POINT +-- Called every frame. Returns the color (if any) to paint around the given +-- channel. Returns a CSS color (typically to mark live and preview signals); +-- "transparent" is allowed. +-- Will never be called for live (0) or preview (1). +function channel_color(channel) + if channel_involved_in(channel, live_signal_num) then + return "#f00" + end + if channel_involved_in(channel, preview_signal_num) then + return "#0f0" + end + return "transparent" +end + +function channel_involved_in(channel, signal_num) + if signal_num == INPUT0_SIGNAL_NUM then + return channel == 2 + end + if signal_num == INPUT1_SIGNAL_NUM then + return channel == 3 + end + if signal_num == SBS_SIGNAL_NUM then + return (channel == 2 or channel == 3) + end + if signal_num == STATIC_SIGNAL_NUM then + return (channel == 5) + end + if signal_num == FADE_SIGNAL_NUM then + return (channel_involved_in(channel, fade_src_signal) or + channel_involved_in(channel, fade_dst_signal)) + end + return false +end + +-- API ENTRY POINT -- Returns if a given channel supports setting white balance (starting from 2). -- Called only once for each channel, at the start of the program. function supports_set_wb(channel) return channel == 2 or channel == 3 end +-- API ENTRY POINT -- Gets called with a new gray point when the white balance is changing. -- The color is in linear light (not sRGB gamma). function set_wb(channel, red, green, blue) @@ -324,11 +398,13 @@ function finish_transitions(t) end end +-- API ENTRY POINT -- Called every frame. function get_transitions(t) finish_transitions(t) if live_signal_num == preview_signal_num then + -- No transitions possible. return {} end @@ -358,6 +434,8 @@ function get_transitions(t) return {"Cut"} end +-- API ENTRY POINT +-- Called when the user clicks a transition button. function transition_clicked(num, t) if num == 0 then -- Cut. @@ -440,10 +518,12 @@ function transition_clicked(num, t) end end +-- API ENTRY POINT function channel_clicked(num) preview_signal_num = num end +-- API ENTRY POINT -- Called every frame. Get the chain for displaying at input , -- where 0 is live, 1 is preview, 2 is the first channel to display -- in the bottom bar, and so on up to num_channels()+1. t is the @@ -474,6 +554,7 @@ function get_chain(num, t, width, height, signals) width = signals:get_width(signal_num), height = signals:get_height(signal_num), interlaced = signals:get_interlaced(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) } @@ -515,12 +596,12 @@ function get_chain(num, t, width, height, signals) local input1_scale = needs_scale(signals, fade_dst_signal, width, height) local chain = fade_chains[input0_type][input0_scale][input1_type][input1_scale][true] prepare = function() - if input0_type == "live" then + if input0_type == "live" or input0_type == "livedeint" then chain.input0.input:connect_signal(fade_src_signal) set_neutral_color_from_signal(chain.input0.wb_effect, fade_src_signal) end set_scale_parameters_if_needed(chain.input0, width, height) - if input1_type == "live" then + if input1_type == "live" or input1_type == "livedeint" then chain.input1.input:connect_signal(fade_dst_signal) set_neutral_color_from_signal(chain.input1.wb_effect, fade_dst_signal) end @@ -611,6 +692,9 @@ function place_rectangle(resample_effect, resize_effect, padding_effect, x0, y0, local srcy0 = 0.0 local srcy1 = 1.0 + padding_effect:set_int("width", screen_width) + padding_effect:set_int("height", screen_height) + -- Cull. if x0 > screen_width or x1 < 0.0 or y0 > screen_height or y1 < 0.0 then resample_effect:set_int("width", 1)