diff --git a/playout/libretime_playout/liquidsoap/templates/outputs.liq.j2 b/playout/libretime_playout/liquidsoap/templates/outputs.liq.j2 index 06b21efc1a..e8e79f53a3 100644 --- a/playout/libretime_playout/liquidsoap/templates/outputs.liq.j2 +++ b/playout/libretime_playout/liquidsoap/templates/outputs.liq.j2 @@ -117,20 +117,41 @@ output.shoutcast( ) {%- endmacro -%} -{% for output in config.stream.outputs.system -%} -{% if output.enabled -%} -# {{ output.kind.value }}:{{ loop.index }} +{#- + Build a system output configuration. +#} +{%- macro output_system(output_id, output) -%} +# {{ output.kind.value }}:{{ output_id }} %ifndef output.{{ output.kind.value }} log("output.{{ output.kind.value }} is not defined!") %endif %ifdef output.{{ output.kind.value }} -output.{{ output.kind.value }}(id="{{ output.kind.value }}:{{ loop.index }}", s) +output.{{ output.kind.value }}( + id="{{ output.kind.value }}:{{ output_id }}", +{%- if output.kind.value == "alsa" %} +{%- if output.device is not none %} + device="{{ output.device }}", +{%- endif %} +{%- elif output.kind.value == "pulseaudio" %} +{%- if output.device is not none %} + device="{{ output.device }}", +{%- endif %} +{%- endif %} + s +) %endif +{%- endmacro -%} + +{# ############################### #} + +{%- for output in config.stream.outputs.system -%} +{% if output.enabled -%} +{{ output_system(loop.index, output) }} {% endif -%} {% endfor -%} -{% for output in config.stream.outputs.icecast -%} +{%- for output in config.stream.outputs.icecast -%} {% if output.enabled -%} {{ output_icecast(loop.index, output) }} diff --git a/playout/tests/liquidsoap/__snapshots__/entrypoint_test.ambr b/playout/tests/liquidsoap/__snapshots__/entrypoint_test.ambr index 4735502f46..a0fba73faf 100644 --- a/playout/tests/liquidsoap/__snapshots__/entrypoint_test.ambr +++ b/playout/tests/liquidsoap/__snapshots__/entrypoint_test.ambr @@ -315,7 +315,10 @@ log("output.pulseaudio is not defined!") %endif %ifdef output.pulseaudio - output.pulseaudio(id="pulseaudio:1", s) + output.pulseaudio( + id="pulseaudio:1", + s + ) %endif @@ -355,6 +358,55 @@ %include "/fake/1.4/ls_script.liq" + # pulseaudio:1 + %ifndef output.pulseaudio + log("output.pulseaudio is not defined!") + %endif + %ifdef output.pulseaudio + output.pulseaudio( + id="pulseaudio:1", + device="alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink", + s + ) + %endif + + + + gateway("started") + + ''' +# --- +# name: test_generate_entrypoint[stream_config7-1.4] + ''' + # THIS FILE IS AUTO GENERATED. PLEASE DO NOT EDIT! + ########################################################### + # The ignore() lines are to squash unused variable warnings + + # Inputs + input_main_mount = "main" + input_main_port = 8001 + input_main_secure = false + input_show_mount = "show" + input_show_port = 8002 + input_show_secure = false + + # Settings + set("log.file.path", "/var/log/radio.log") + + set("server.telnet", true) + set("server.telnet.bind_addr", "127.0.0.1") + set("server.telnet.port", 1234) + + set("harbor.bind_addrs", ["0.0.0.0"]) + + station_name = interactive.string("station_name", "LibreTime") + + message_offline = interactive.string("message_offline", "LibreTime - offline") + message_format = interactive.string("message_format", "0") + input_fade_transition = interactive.float("input_fade_transition", 0.0) + + %include "/fake/1.4/ls_script.liq" + gateway("started") diff --git a/playout/tests/liquidsoap/fixtures/__init__.py b/playout/tests/liquidsoap/fixtures/__init__.py index 1675bbbb38..dad8d644e2 100644 --- a/playout/tests/liquidsoap/fixtures/__init__.py +++ b/playout/tests/liquidsoap/fixtures/__init__.py @@ -91,6 +91,17 @@ def make_config_with_stream(**kwargs) -> Config: "system": [{"enabled": True, "kind": "pulseaudio"}], } ), + make_config_with_stream( + outputs={ + "system": [ + { + "enabled": True, + "kind": "pulseaudio", + "device": "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink", + } + ], + } + ), make_config_with_stream( outputs={ "system": [{"enabled": False, "kind": "alsa"}], diff --git a/shared/libretime_shared/config/_models.py b/shared/libretime_shared/config/_models.py index 094d763c30..3229b50865 100644 --- a/shared/libretime_shared/config/_models.py +++ b/shared/libretime_shared/config/_models.py @@ -245,7 +245,7 @@ class ShoutcastOutput(BaseModel): genre: Optional[str] = None -class SystemOutputKind(str, Enum): +class SystemOutput(str, Enum): ALSA = "alsa" AO = "ao" OSS = "oss" @@ -253,16 +253,49 @@ class SystemOutputKind(str, Enum): PULSEAUDIO = "pulseaudio" -class SystemOutput(BaseModel): +class BaseSystemOutput(BaseModel): enabled: bool = False - kind: SystemOutputKind = SystemOutputKind.ALSA + + +class ALSASystemOutput(BaseSystemOutput): + kind: Literal[SystemOutput.ALSA] = SystemOutput.ALSA + device: Optional[str] = None + + +class AOSystemOutput(BaseSystemOutput): + kind: Literal[SystemOutput.AO] = SystemOutput.AO + + +class OSSSystemOutput(BaseSystemOutput): + kind: Literal[SystemOutput.OSS] = SystemOutput.OSS + + +class PortAudioSystemOutput(BaseSystemOutput): + kind: Literal[SystemOutput.PORTAUDIO] = SystemOutput.PORTAUDIO + + +class PulseAudioSystemOutput(BaseSystemOutput): + kind: Literal[SystemOutput.PULSEAUDIO] = SystemOutput.PULSEAUDIO + device: Optional[str] = None + + +AnySystemOutput = Annotated[ + Union[ + ALSASystemOutput, + AOSystemOutput, + OSSSystemOutput, + PortAudioSystemOutput, + PulseAudioSystemOutput, + ], + Field(discriminator="kind"), +] # pylint: disable=too-few-public-methods class Outputs(BaseModel): icecast: List[IcecastOutput] = Field([], max_items=3) shoutcast: List[ShoutcastOutput] = Field([], max_items=1) - system: List[SystemOutput] = Field([], max_items=1) + system: List[AnySystemOutput] = Field([], max_items=1) @property def merged(self) -> List[Union[IcecastOutput, ShoutcastOutput]]: