]> git.sesse.net Git - nageru-docs/blobdiff - theme.rst
Document unsynchronized HDMI/SDI output.
[nageru-docs] / theme.rst
index 2e8b6663b0ccddd05fe1314502ff9c5d2cf040f5..8dbaf80b06b14d2aa09758348f2c0077b9b49a06 100644 (file)
--- a/theme.rst
+++ b/theme.rst
@@ -1,14 +1,6 @@
 The theme
 =========
 
-**NOTE**: Nageru 1.9.0 made significant improvements to themes
-and how scenes work. If you use an older version, you may want
-to look at `the 1.8.6 documentation <https://nageru.sesse.net/doc-1.8.6/>`_;
-themes written for older versions still work without modification in
-1.9.0, but are not documented here, and you are advised to change
-to use the new interfaces, as they are equally powerful and much simpler
-to work with.
-
 In Nageru, most of the business logic around how your stream
 ends up looking is governed by the **theme**, much like how a
 theme works on a blog or a CMS. Most importantly, the theme
@@ -303,18 +295,28 @@ The theme should return a CSS color (e.g. “#ff0000”, or “cyan”) for each
 channel when asked; it can vary from frame to frame. A typical use is to mark
 the currently playing input as red, or the preview as green.
 
-And finally, there are two entry points related to white balance::
+
+.. _white-balance:
+
+White balance
+.............
+
+Finally, there are two entry points related to white balance. The first one
+is::
 
   Nageru.set_supports_wb(2, true)
-  function set_wb(channel, red, green, blue)
 
 If the first function is called with a true value (at the start of the theme),
 the channel will get a “Set WB” button next to it, which will activate a color
-picker. When the user picks a color (ostensibly with a gray point), the second
-function will be called (with the RGB values in linear light—not sRGB!),
-and the theme can then use it to adjust the white balance for that channel.
-The typical way to to this is to have a *WhiteBalanceEffect* on each input
-and set its “neutral_color” parameter using the “set_vec3” function.
+picker, to select the gray point. To actually *apply* this white balance change,
+add the white balance element to the scene::
+
+  scene:add_white_balance()
+
+The white balance effect will automatically figure out which input it is
+connected to, and fetch its gray point if needed. (If it is connected to
+e.g. a mix of several inputs, such as a camera and an overlay, you will need to
+give the input to fetch white balance from as as a parameter.)
 
 
 More complicated channels: Composites
@@ -399,11 +401,21 @@ crop is. If so, you can do this::
 
    resample_effect:always_disable_if_disabled(crop_effect)
 
+Also, you can disable an optional effect if a given other
+effect is *enabled*::
+
+   overlay1_effect:promise_to_disable_if_enabled(overlay2_effect)
+   overlay2_effect:promise_to_disable_if_enabled(overlay1_effect)
+
+Note that the latter is a promise from the user, not automatic disabling; since
+it is mostly useful for mutual exclusions, Nageru wouldn't know which of the
+two to disable. (If you violate the promise, you will get an error message at
+runtime.) It can still be useful for reducing the number of alternatives, though.
+
 For more advanced exclusions, you may choose to split up the scenes into several
-distinct ones that you manage yourself; indeed, before Nageru 1.9.0, that was
-the only option. At some point, however, you may choose to simply accept the
-added startup time and a bit of extra RAM cost; ease of use and flexibility often
-trumps such concerns.
+distinct ones that you manage yourself. At some point, however, you may choose
+to simply accept the added startup time and a bit of extra RAM cost; ease of
+use and flexibility often trumps such concerns.
 
 
 .. _menus:
@@ -498,11 +510,60 @@ effect alternatives. In particular, you may want to disable scaling if
 the frame is already of the correct resolution.
 
 
+Audio control
+-------------
+
+Before you attempt to control audio from the theme, be sure to have read
+the documentation about :doc:`audio`.
+
+The theme has a certain amount of control over the audio
+mix, assuming that you are in multichannel mode. This is useful in particular
+to be able to set defaults, if e.g. one channel should always be muted at
+startup, or to switch in/out certain channels depending on whether they are
+visible or not.
+
+In particular, these operations are available::
+
+  # Returns number of buses in the mapping.
+  local num_buses = Nageru.get_num_audio_buses()
+
+  # Gets the name from the mapping. All indexes start at zero,
+  # so valid indexes are 0..(num_buses-1), inclusive.
+  local name = Nageru.get_audio_bus_name(N)
+
+  # 0.0 is zero amplification, as in the UI. Valid range is
+  # -inf to +6.0, inclusive.
+  local level = Nageru.get_audio_bus_fader_level_db(N)
+  set_audio_bus_fader_level_db(N, level)
+
+  # Similar as the above, but valid range is -15.0..+15.0 (dB).
+  # Valid bands are Nageru.EQ_BAND_{BASS, MID, TREBLE}.
+  local eq_level = Nageru.get_audio_bus_eq_level_db(N, Nageru.EQ_BAND_BASS)
+  Nageru.set_audio_bus_eq_level_db(N, Nageru.EQ_BAND_BASS, level)
+
+  # A boolean. Does not affect the bus levels set/returned above.
+  local muted = Nageru_get_audio_bus_mute(N)
+  Nageru_set_audio_bus_mute(N, false)
+
+Note that any audio operation is inherently unsynchronized with the UI,
+so if the user reduces the number of audio buses while
+the theme tries to access one that is going away, you may get unpredictable
+behavior, up to and including crashes. Thus, you will need to be careful
+with such operations.
+
+Also, you cannot do anything with audio before the first *get_scene()* call,
+since the audio mixer is initialized only after the theme has been loaded and
+initialized. Thus, for things that should be done only the first frame, the
+recommended method is to put code into get_scene() and have a guard variable
+that makes sure it is only run
+once, ever.
+
+
 Overriding the status line
 --------------------------
 
 Some users may wish to override the status line, e.g. with recording time.
-If so, it is possible (since Nageru 1.9.1) to declare a function **format_status_line**::
+If so, it is possible to declare a function **format_status_line**::
 
   function format_status_line(disk_space_text, file_length_seconds)
     if file_length_seconds > 86400.0 then