X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=theme.lua;h=709797c4878b1a64fc616e41f384a7433774dc7d;hb=f65089f8f99aa42e2dec6396a13e797aaafde903;hp=0f390f426aadb8503f374b0bca77046a73db4f56;hpb=2b806ed340112b4b464b6f2b9c34e4873de5f1c5;p=nageru diff --git a/theme.lua b/theme.lua index 0f390f4..709797c 100644 --- a/theme.lua +++ b/theme.lua @@ -29,99 +29,145 @@ local INPUT1_SIGNAL_NUM = 1 local SBS_SIGNAL_NUM = 2 local STATIC_SIGNAL_NUM = 3 --- “fake” signal numbers that signifies that we are fading from one input +-- “fake” signal number that signifies that we are fading from one input -- to the next. -local FADE_VTV_SIGNAL_NUM = 4 -- Video to/from video. -local FADE_VTP_SIGNAL_NUM = 5 -- Video to/from static picture. +local FADE_SIGNAL_NUM = 4 --- The main live chain. -function make_sbs_chain(hq) - local chain = EffectChain.new(16, 9) - local input0 = chain:add_live_input(true) - input0:connect_signal(0) - local input0_wb_effect = chain:add_effect(WhiteBalanceEffect.new()) - local input1 = chain:add_live_input(true) - input1:connect_signal(1) - local input1_wb_effect = chain:add_effect(WhiteBalanceEffect.new()) +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 if (hq) then - resample_effect = chain:add_effect(ResampleEffect.new(), input0_wb_effect) + resample_effect = chain:add_effect(ResampleEffect.new()) else - resize_effect = chain:add_effect(ResizeEffect.new(), input0_wb_effect) + resize_effect = chain:add_effect(ResizeEffect.new()) end local padding_effect = chain:add_effect(IntegralPaddingEffect.new()) - padding_effect:set_vec4("border_color", 0.0, 0.0, 0.0, 1.0) - local resample2_effect = nil - local resize2_effect = nil - if (hq) then - resample2_effect = chain:add_effect(ResampleEffect.new(), input1_wb_effect) + return { + input = input, + wb_effect = wb_effect, + resample_effect = resample_effect, + resize_effect = resize_effect, + padding_effect = padding_effect + } +end + +-- The main live chain. +function make_sbs_chain(input0_deint, input1_deint, hq) + local chain = EffectChain.new(16, 9) + + local input0 = make_sbs_input(chain, INPUT0_SIGNAL_NUM, input0_deint, hq) + local input1 = make_sbs_input(chain, INPUT1_SIGNAL_NUM, input1_deint, hq) + + input0.padding_effect:set_vec4("border_color", 0.0, 0.0, 0.0, 1.0) + input1.padding_effect:set_vec4("border_color", 0.0, 0.0, 0.0, 0.0) + + chain:add_effect(OverlayEffect.new(), input0.padding_effect, input1.padding_effect) + chain:finalize(hq) + + return { + chain = chain, + input0 = input0, + input1 = input1 + } +end + +-- Make all possible combinations of side-by-side chains. +local sbs_chains = {} +for input0_type, input0_deint in pairs({live = false, livedeint = true}) do + sbs_chains[input0_type] = {} + for input1_type, input1_deint in pairs({live = false, livedeint = true}) do + sbs_chains[input0_type][input1_type] = {} + for _, hq in pairs({true, false}) do + sbs_chains[input0_type][input1_type][hq] = + make_sbs_chain(input0_deint, input1_deint, hq) + end + end +end + +function make_fade_input(chain, signal, live, deint) + local input, wb_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 else - resize2_effect = chain:add_effect(ResizeEffect.new(), input1_wb_effect) + input = chain:add_effect(ImageInput.new("bg.jpeg")) + last = input + end + + return { + input = input, + wb_effect = wb_effect, + last = last + } +end + +-- A chain to fade between two inputs, of which either can be a picture +-- or a live input. In practice only used live, but we still support the +-- hq parameter. +function make_fade_chain(input0_live, input0_deint, input1_live, input1_deint, hq) + local chain = EffectChain.new(16, 9) + + local input0 = make_fade_input(chain, INPUT0_SIGNAL_NUM, input0_live, input0_deint) + local input1 = make_fade_input(chain, INPUT1_SIGNAL_NUM, input1_live, input1_deint) + + local mix_effect = chain:add_effect(MixEffect.new(), input0.last, input1.last) + chain:finalize(hq) + + return { + chain = chain, + input0 = input0, + input1 = input1, + mix_effect = mix_effect + } +end + +-- Chains to fade between two inputs, in various configurations. +local fade_chains = {} +for input0_type, input0_live in pairs({static = false, live = true, livedeint = true}) do + local input0_deint = (input0_live == "livedeint") + fade_chains[input0_type] = {} + for input1_type, input1_live in pairs({static = false, live = true, livedeint = true}) do + local input1_deint = (input1_live == "livedeint") + fade_chains[input0_type][input1_type] = {} + for _, hq in pairs({true, false}) do + fade_chains[input0_type][input1_type][hq] = + make_fade_chain(input0_live, input0_deint, input1_live, input1_deint, hq) + end end - local padding2_effect = chain:add_effect(IntegralPaddingEffect.new()) +end + +-- A chain to show a single input on screen. +function make_simple_chain(input_deint, hq) + local chain = EffectChain.new(16, 9) - chain:add_effect(OverlayEffect.new(), padding_effect, padding2_effect) + 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) return { chain = chain, - input0 = { - input = input0, - white_balance_effect = input0_wb_effect, - resample_effect = resample_effect, - resize_effect = resize_effect, - padding_effect = padding_effect - }, - input1 = { - input = input1, - white_balance_effect = input1_wb_effect, - resample_effect = resample2_effect, - resize_effect = resize2_effect, - padding_effect = padding2_effect - } + input = input, + wb_effect = wb_effect } end -local main_chain_hq = make_sbs_chain(true) -local main_chain_lq = make_sbs_chain(false) - --- A chain to fade between two inputs (live chain only) -local fade_vtv_chain_hq = EffectChain.new(16, 9) -local fade_vtv_chain_hq_input0 = fade_vtv_chain_hq:add_live_input(true) -local fade_vtv_chain_hq_wb0_effect = fade_vtv_chain_hq:add_effect(WhiteBalanceEffect.new()) -local fade_vtv_chain_hq_input1 = fade_vtv_chain_hq:add_live_input(true) -local fade_vtv_chain_hq_wb1_effect = fade_vtv_chain_hq:add_effect(WhiteBalanceEffect.new()) -fade_vtv_chain_hq_input0:connect_signal(0) -fade_vtv_chain_hq_input1:connect_signal(1) -local fade_vtv_chain_mix_effect = fade_vtv_chain_hq:add_effect(MixEffect.new(), fade_vtv_chain_hq_wb0_effect, fade_vtv_chain_hq_wb1_effect) -fade_vtv_chain_hq:finalize(true) - --- A chain to fade between an inputs and a picture (live chain only) -local fade_vtp_chain_hq = EffectChain.new(16, 9) -local fade_vtp_chain_hq_input0 = fade_vtp_chain_hq:add_live_input(true) -local fade_vtp_chain_hq_wb0_effect = fade_vtp_chain_hq:add_effect(WhiteBalanceEffect.new()) -local fade_vtp_chain_hq_input1 = fade_vtp_chain_hq:add_effect(ImageInput.new("bg.jpeg")) -fade_vtp_chain_hq_input0:connect_signal(0) -local fade_vtp_chain_mix_effect = fade_vtp_chain_hq:add_effect(MixEffect.new(), fade_vtp_chain_hq_wb0_effect, fade_vtp_chain_hq_input1) -fade_vtp_chain_hq:finalize(true) - --- A chain to show a single input on screen (HQ version). -local simple_chain_hq = EffectChain.new(16, 9) -local simple_chain_hq_input = simple_chain_hq:add_live_input(true) -simple_chain_hq_input:connect_signal(0) -- First input card. Can be changed whenever you want. -local simple_chain_hq_wb_effect = simple_chain_hq:add_effect(WhiteBalanceEffect.new()) -simple_chain_hq:finalize(true) - --- A chain to show a single input on screen (LQ version). -local simple_chain_lq = EffectChain.new(16, 9) -local simple_chain_lq_input = simple_chain_lq:add_live_input(true) -simple_chain_lq_input:connect_signal(0) -- First input card. Can be changed whenever you want. -local simple_chain_lq_wb_effect = simple_chain_lq:add_effect(WhiteBalanceEffect.new()) -simple_chain_lq:finalize(false) +-- Make all possible combinations of single-input chains. +local simple_chains = {} +for input_type, input_deint in pairs({live = false, livedeint = true}) do + simple_chains[input_type] = {} + for _, hq in pairs({true, false}) do + simple_chains[input_type][hq] = make_simple_chain(input_deint, hq) + end +end -- A chain to show a single static picture on screen (HQ version). local static_chain_hq = EffectChain.new(16, 9) @@ -133,6 +179,17 @@ local static_chain_lq = EffectChain.new(16, 9) local static_chain_lq_input = static_chain_lq:add_effect(ImageInput.new("bg.jpeg")) static_chain_lq:finalize(false) +-- Used for indexing into the tables of chains. +function get_input_type(signals, signal_num) + if signal_num == STATIC_SIGNAL_NUM then + return "static" + elseif signals:get_interlaced(signal_num) then + return "livedeint" + else + return "live" + end +end + -- 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() @@ -176,7 +233,7 @@ function finish_transitions(t) end -- If live is fade but de-facto single, make it so. - if (live_signal_num == FADE_VTV_SIGNAL_NUM or live_signal_num == FADE_VTP_SIGNAL_NUM) and t >= transition_end then + if live_signal_num == FADE_SIGNAL_NUM and t >= transition_end then live_signal_num = fade_dst_signal end end @@ -218,7 +275,7 @@ end function transition_clicked(num, t) if num == 0 then -- Cut. - if live_signal_num == FADE_VTV_SIGNAL_NUM or live_signal_num == FADE_VTP_SIGNAL_NUM then + if live_signal_num == FADE_SIGNAL_NUM then -- Ongoing fade; finish it immediately. finish_transitions(transition_end) end @@ -278,24 +335,19 @@ function transition_clicked(num, t) finish_transitions(t) -- Fade. - if (live_signal_num == INPUT0_SIGNAL_NUM and preview_signal_num == INPUT1_SIGNAL_NUM) or - (live_signal_num == INPUT1_SIGNAL_NUM and preview_signal_num == INPUT0_SIGNAL_NUM) then + if (live_signal_num ~= preview_signal_num) and + (live_signal_num == INPUT0_SIGNAL_NUM or + live_signal_num == INPUT1_SIGNAL_NUM or + live_signal_num == STATIC_SIGNAL_NUM) and + (preview_signal_num == INPUT0_SIGNAL_NUM or + preview_signal_num == INPUT1_SIGNAL_NUM or + preview_signal_num == STATIC_SIGNAL_NUM) then transition_start = t transition_end = t + 1.0 fade_src_signal = live_signal_num fade_dst_signal = preview_signal_num preview_signal_num = live_signal_num - live_signal_num = FADE_VTV_SIGNAL_NUM - elseif ((live_signal_num == INPUT0_SIGNAL_NUM or live_signal_num == INPUT1_SIGNAL_NUM) and - preview_signal_num == STATIC_SIGNAL_NUM) or - ((preview_signal_num == INPUT0_SIGNAL_NUM or preview_signal_num == INPUT1_SIGNAL_NUM) and - live_signal_num == STATIC_SIGNAL_NUM) then - transition_start = t - transition_end = t + 1.0 - fade_src_signal = live_signal_num - fade_dst_signal = preview_signal_num - preview_signal_num = live_signal_num - live_signal_num = FADE_VTP_SIGNAL_NUM + live_signal_num = FADE_SIGNAL_NUM else -- Fades involving SBS are ignored (we have no chain for it). end @@ -332,90 +384,96 @@ end function get_chain(num, t, width, height, signals) if num == 0 then -- Live. if live_signal_num == INPUT0_SIGNAL_NUM or live_signal_num == INPUT1_SIGNAL_NUM then -- Plain input. + local input_type = get_input_type(signals, live_signal_num) + local chain = simple_chains[input_type][true] prepare = function() - simple_chain_hq_input:connect_signal(live_signal_num) - set_neutral_color_from_signal(simple_chain_hq_wb_effect, live_signal_num) + chain.input:connect_signal(live_signal_num) + set_neutral_color_from_signal(chain.wb_effect, live_signal_num) end - return simple_chain_hq, prepare + return chain.chain, prepare elseif live_signal_num == STATIC_SIGNAL_NUM then -- Static picture. prepare = function() end return static_chain_hq, prepare - elseif live_signal_num == FADE_VTV_SIGNAL_NUM then -- Fade video-to-video. + elseif live_signal_num == FADE_SIGNAL_NUM then -- Fade. + local input0_type = get_input_type(signals, fade_src_signal) + local input1_type = get_input_type(signals, fade_dst_signal) + local chain = fade_chains[input0_type][input1_type][true] prepare = function() - fade_vtv_chain_hq_input0:connect_signal(fade_src_signal) - set_neutral_color_from_signal(fade_vtv_chain_hq_wb0_effect, fade_src_signal) - fade_vtv_chain_hq_input1:connect_signal(fade_dst_signal) - set_neutral_color_from_signal(fade_vtv_chain_hq_wb1_effect, fade_dst_signal) + if input0_type == "live" then + chain.input0.input:connect_signal(fade_src_signal) + set_neutral_color_from_signal(chain.input0.wb_effect, fade_src_signal) + end + if input1_type == "live" then + chain.input1.input:connect_signal(fade_dst_signal) + set_neutral_color_from_signal(chain.input1.wb_effect, fade_dst_signal) + end local tt = calc_fade_progress(t, transition_start, transition_end) - fade_vtv_chain_mix_effect:set_float("strength_first", 1.0 - tt) - fade_vtv_chain_mix_effect:set_float("strength_second", tt) + chain.mix_effect:set_float("strength_first", 1.0 - tt) + chain.mix_effect:set_float("strength_second", tt) end - return fade_vtv_chain_hq, prepare - elseif live_signal_num == FADE_VTP_SIGNAL_NUM then -- Fade video-to-picture (or picture-to-video). - prepare = function() - local tt - if fade_src_signal == STATIC_SIGNAL_NUM then - fade_vtp_chain_hq_input0:connect_signal(fade_dst_signal) - set_neutral_color_from_signal(fade_vtp_chain_hq_wb0_effect, fade_dst_signal) - tt = 1.0 - calc_fade_progress(t, transition_start, transition_end) - else - fade_vtp_chain_hq_input0:connect_signal(fade_src_signal) - set_neutral_color_from_signal(fade_vtp_chain_hq_wb0_effect, fade_src_signal) - tt = calc_fade_progress(t, transition_start, transition_end) - end - fade_vtp_chain_mix_effect:set_float("strength_first", 1.0 - tt) - fade_vtp_chain_mix_effect:set_float("strength_second", tt) - end - return fade_vtp_chain_hq, prepare + return chain.chain, prepare end -- SBS code (live_signal_num == SBS_SIGNAL_NUM). + local input0_type = get_input_type(signals, INPUT0_SIGNAL_NUM) + local input1_type = get_input_type(signals, INPUT1_SIGNAL_NUM) if t > transition_end and zoom_dst == 1.0 then -- Special case: Show only the single image on screen. + local chain = simple_chains[input0_type][true] prepare = function() - simple_chain_hq_input:connect_signal(INPUT0_SIGNAL_NUM) - set_neutral_color(simple_chain_hq_wb_effect, input0_neutral_color) + chain.input:connect_signal(INPUT0_SIGNAL_NUM) + set_neutral_color(chain.wb_effect, input0_neutral_color) end - return simple_chain_hq, prepare + return chain.chain, prepare end + local chain = sbs_chains[input0_type][input1_type][true] prepare = function() if t < transition_start then - prepare_sbs_chain(main_chain_hq, zoom_src, width, height) + prepare_sbs_chain(chain, zoom_src, width, height) elseif t > transition_end then - prepare_sbs_chain(main_chain_hq, zoom_dst, width, height) + prepare_sbs_chain(chain, zoom_dst, width, height) else local tt = (t - transition_start) / (transition_end - transition_start) -- Smooth it a bit. tt = math.sin(tt * 3.14159265358 * 0.5) - prepare_sbs_chain(main_chain_hq, zoom_src + (zoom_dst - zoom_src) * tt, width, height) + prepare_sbs_chain(chain, zoom_src + (zoom_dst - zoom_src) * tt, width, height) end end - return main_chain_hq.chain, prepare + return chain.chain, prepare end if num == 1 then -- Preview. num = preview_signal_num + 2 end + + -- Individual preview inputs. if num == INPUT0_SIGNAL_NUM + 2 then + local input_type = get_input_type(signals, INPUT0_SIGNAL_NUM) + local chain = simple_chains[input_type][false] prepare = function() - simple_chain_lq_input:connect_signal(0) - set_neutral_color(simple_chain_lq_wb_effect, input0_neutral_color) + chain.input:connect_signal(INPUT0_SIGNAL_NUM) + set_neutral_color(chain.wb_effect, input0_neutral_color) end - return simple_chain_lq, prepare + return chain.chain, prepare end if num == INPUT1_SIGNAL_NUM + 2 then + local input_type = get_input_type(signals, INPUT1_SIGNAL_NUM) + local chain = simple_chains[input_type][false] prepare = function() - simple_chain_lq_input:connect_signal(1) - set_neutral_color(simple_chain_lq_wb_effect, input1_neutral_color) + chain.input:connect_signal(INPUT1_SIGNAL_NUM) + set_neutral_color(chain.wb_effect, input1_neutral_color) end - return simple_chain_lq, prepare + return chain.chain, prepare end if num == SBS_SIGNAL_NUM + 2 then + local input0_type = get_input_type(signals, INPUT0_SIGNAL_NUM) + local input1_type = get_input_type(signals, INPUT1_SIGNAL_NUM) + local chain = sbs_chains[input0_type][input1_type][false] prepare = function() - prepare_sbs_chain(main_chain_lq, 0.0, width, height) + prepare_sbs_chain(chain, 0.0, width, height) end - return main_chain_lq.chain, prepare + return chain.chain, prepare end if num == STATIC_SIGNAL_NUM + 2 then prepare = function() @@ -518,8 +576,8 @@ end function prepare_sbs_chain(chain, t, screen_width, screen_height) chain.input0.input:connect_signal(0) chain.input1.input:connect_signal(1) - set_neutral_color(chain.input0.white_balance_effect, input0_neutral_color) - set_neutral_color(chain.input1.white_balance_effect, input1_neutral_color) + set_neutral_color(chain.input0.wb_effect, input0_neutral_color) + set_neutral_color(chain.input1.wb_effect, input1_neutral_color) -- First input is positioned (16,48) from top-left. local width0 = round(848 * screen_width/1280.0)