@@ -71,6 +71,10 @@ if not is_pw_disabled():
with st . form ( " signin_form " ) :
pw = st . text_input ( " Password " , type = " password " )
submitted = st . form_submit_button ( " Sign in " )
st . components . v1 . html (
" <script>setTimeout(()=>window.parent.document.querySelector( ' input[type= \" password \" ] ' )?.focus(),100)</script> " ,
height = 0
)
if submitted :
if verify_password ( pw , pw_rec ) :
st . session_state [ ' frontend_authenticated ' ] = True
@@ -490,13 +494,43 @@ else:
disabled = is_streaming
)
# Use analog-specific defaults (not from saved settings which may have Dante values)
default_name = " Analog_Radio_1 "
default_program_info = " Analog Radio Broadcast "
default_lang = " deu "
quality_options = list ( QUALITY_MAP . keys ( ) )
default_quality = " Medium (24kHz) " if " Medium (24kHz) " in quality_options else quality_options [ 0 ]
# Use saved settings if audio_mode matches, otherwise use analog-specific defaults
saved_audio_mode = saved_settings . get ( ' audio_mode ' )
if saved_audio_mode == ' Analog ' :
default_name = saved_settings . get ( ' channel_names ' , [ " Analog_Radio_1 " ] ) [ 0 ]
raw_program_info = saved_settings . get ( ' program_info ' , default_name )
if isinstance ( raw_program_info , list ) and raw_program_info :
default_program_info = raw_program_info [ 0 ]
else :
default_program_info = raw_program_info
default_lang = saved_settings . get ( ' languages ' , [ " deu " ] ) [ 0 ]
# Map saved sampling rate to quality label
saved_rate = saved_settings . get ( ' auracast_sampling_rate_hz ' )
if saved_rate == 48000 :
default_quality = " High (48kHz) "
elif saved_rate == 32000 :
default_quality = " Good (32kHz) "
elif saved_rate == 24000 :
default_quality = " Medium (24kHz) "
elif saved_rate == 16000 :
default_quality = " Fair (16kHz) "
else :
default_quality = " Medium (24kHz) "
saved_pwd = saved_settings . get ( ' stream_password ' , ' ' )
else :
# Use analog-specific defaults when switching from another mode
default_name = " Analog_Radio_1 "
default_program_info = " Analog Radio Broadcast "
default_lang = " deu "
default_quality = " Medium (24kHz) " if " Medium (24kHz) " in quality_options else quality_options [ 0 ]
saved_pwd = ' '
if default_quality not in quality_options :
default_quality = quality_options [ 0 ]
quality1 = st . selectbox (
" Stream Quality (Radio 1) " ,
quality_options ,
@@ -507,7 +541,7 @@ else:
stream_passwort1 = st . text_input (
" Stream Passwort (Radio 1) " ,
value = " " ,
value = saved_pwd ,
type = " password " ,
disabled = is_streaming ,
help = " Optional: Set a broadcast code for Radio 1. "
@@ -621,7 +655,10 @@ else:
input_device1 = None
else :
# Mono mode: show all available channels
saved_input_device = saved_settings . get ( ' input_device ' )
default_r1_idx = 0
if saved_input_device in analog_names :
default_r1_idx = analog_names . index ( saved_input_device )
input_device1 = st . selectbox (
" Input Device (Radio 1) " ,
analog_names ,
@@ -670,22 +707,53 @@ else:
)
if radio2_enabled and not stereo_enabled :
# Use analog-specific defaults for Radio 2
default_name_r2 = " Analog_Radio_2 "
default_program_info_r2 = " Analog Radio Broadcast "
default_lang_r2 = " deu "
# Use saved settings if audio_mode matches, otherwise use analog-specific defaults for Radio 2
secondary_settings = saved_settings . get ( ' secondary ' , { } )
saved_audio_mode = saved_settings . get ( ' audio_mode ' )
if saved_audio_mode == ' Analog ' and secondary_settings :
default_name_r2 = secondary_settings . get ( ' channel_names ' , [ " Analog_Radio_2 " ] ) [ 0 ] if isinstance ( secondary_settings . get ( ' channel_names ' ) , list ) else secondary_settings . get ( ' channel_names ' , " Analog_Radio_2 " )
raw_program_info_r2 = secondary_settings . get ( ' program_info ' , default_name_r2 )
if isinstance ( raw_program_info_r2 , list ) and raw_program_info_r2 :
default_program_info_r2 = raw_program_info_r2 [ 0 ]
else :
default_program_info_r2 = raw_program_info_r2
default_lang_r2 = secondary_settings . get ( ' languages ' , [ " deu " ] ) [ 0 ] if isinstance ( secondary_settings . get ( ' languages ' ) , list ) else secondary_settings . get ( ' languages ' , ' deu ' )
# Map saved sampling rate to quality label
saved_rate_r2 = secondary_settings . get ( ' auracast_sampling_rate_hz ' )
if saved_rate_r2 == 48000 :
default_quality_r2 = " High (48kHz) "
elif saved_rate_r2 == 32000 :
default_quality_r2 = " Good (32kHz) "
elif saved_rate_r2 == 24000 :
default_quality_r2 = " Medium (24kHz) "
elif saved_rate_r2 == 16000 :
default_quality_r2 = " Fair (16kHz) "
else :
default_quality_r2 = " Medium (24kHz) "
saved_pwd_r2 = secondary_settings . get ( ' stream_password ' , ' ' )
else :
# Use analog-specific defaults when switching from another mode
default_name_r2 = " Analog_Radio_2 "
default_program_info_r2 = " Analog Radio Broadcast "
default_lang_r2 = " deu "
default_quality_r2 = " Medium (24kHz) " if " Medium (24kHz) " in quality_options else quality_options [ 0 ]
saved_pwd_r2 = ' '
if default_quality_r2 not in quality_options :
default_quality_r2 = quality_options [ 0 ]
quality2 = st . selectbox (
" Stream Quality (Radio 2) " ,
quality_options ,
index = quality_options . index ( default_quality ) ,
index = quality_options . index ( default_quality_r2 ) ,
disabled = is_streaming ,
help = " Select the audio sampling rate for Radio 2. "
)
stream_passwort2 = st . text_input (
" Stream Passwort (Radio 2) " ,
value = " " ,
value = saved_pwd_r2 ,
type = " password " ,
disabled = is_streaming ,
help = " Optional: Set a broadcast code for Radio 2. "
@@ -753,7 +821,11 @@ else:
if not is_streaming :
if analog_names :
secondary_settings = saved_settings . get ( ' secondary ' , { } )
saved_input_device2 = secondary_settings . get ( ' input_device ' )
default_r2_idx = 1 if len ( analog_names ) > 1 else 0
if saved_input_device2 in analog_names :
default_r2_idx = analog_names . index ( saved_input_device2 )
input_device2 = st . selectbox (
" Input Device (Radio 2) " ,
analog_names ,
@@ -847,10 +919,15 @@ else:
)
# Dante stereo mode toggle
saved_r1_config = saved_settings . get ( ' dante_radio1 ' , { } )
saved_audio_mode = saved_settings . get ( ' audio_mode ' )
dante_stereo_enabled = False
if saved_audio_mode == ' Network - Dante ' :
# Check if any input device starts with dante_stereo_ to detect stereo mode
input_device = saved_settings . get ( ' input_device ' , ' ' )
dante_stereo_enabled = input_device . startswith ( ' dante_stereo_ ' )
dante_stereo_enabled = st . checkbox (
" 🎧 Stereo Mode " ,
value = bool ( saved_r1_config . get ( ' dante_stereo_mode ' , False ) ) ,
value = dante_stereo_enabled ,
help = " Enable stereo streaming for Dante inputs. Select left and right channels from ASRC channels 1-6. Radio 2 and multi-stream configurations will be disabled in stereo mode. " ,
disabled = is_streaming
)
@@ -859,13 +936,23 @@ else:
dante_left_channel = None
dante_right_channel = None
if dante_stereo_enabled :
dante_channel_options = [ " dante_asrc_ch1 " , " dante_asrc_ch2 " , " dante_asrc_ch3 " ,
dante_channel_options = [ " dante_asrc_ch1 " , " dante_asrc_ch2 " , " dante_asrc_ch3 " ,
" dante_asrc_ch4 " , " dante_asrc_ch5 " , " dante_asrc_ch6 " ]
dante_channel_labels = [ " CH1 " , " CH2 " , " CH3 " , " CH4 " , " CH5 " , " CH6 " ]
# Parse saved stereo device name to extract left and right channels
input_device = saved_settings . get ( ' input_device ' , ' ' )
saved_left = ' dante_asrc_ch1 '
saved_right = ' dante_asrc_ch2 '
if input_device . startswith ( ' dante_stereo_ ' ) :
# Format: dante_stereo_<left>_<right>
parts = input_device . split ( ' _ ' )
if len ( parts ) > = 4 :
saved_left = f " dante_asrc_ch { parts [ 2 ] } "
saved_right = f " dante_asrc_ch { parts [ 3 ] } "
col_left , col_right = st . columns ( 2 )
with col_left :
saved_left = saved_r1_config . get ( ' dante_stereo_left ' , ' dante_asrc_ch1 ' )
left_idx = dante_channel_options . index ( saved_left ) if saved_left in dante_channel_options else 0
dante_left_channel = st . selectbox (
" Left Channel " ,
@@ -876,7 +963,6 @@ else:
help = " Select the Dante ASRC channel for the left stereo channel "
)
with col_right :
saved_right = saved_r1_config . get ( ' dante_stereo_right ' , ' dante_asrc_ch2 ' )
right_idx = dante_channel_options . index ( saved_right ) if saved_right in dante_channel_options else 1
dante_right_channel = st . selectbox (
" Right Channel " ,
@@ -886,7 +972,7 @@ else:
disabled = is_streaming ,
help = " Select the Dante ASRC channel for the right stereo channel "
)
if dante_left_channel == dante_right_channel :
st . warning ( " ⚠️ Left and right channels are the same. Select different channels for true stereo. " )
else :
@@ -894,7 +980,22 @@ else:
# Stream count dropdown for Radio 1 (disabled in stereo mode - forced to 1 stream at 48kHz)
r1_stream_options = list ( dante_stream_options . keys ( ) )
saved_r1_streams = saved_r1_config . get ( ' stream_config ' , ' 1x48 ' )
# Infer stream configuration from saved sampling rate
saved_rate = saved_settings . get ( ' auracast_sampling_rate_hz ' )
saved_r1_streams = ' 1 × 48kHz ' # default
if saved_rate :
if saved_rate == 48000 :
channel_names = saved_settings . get ( ' channel_names ' , [ ] )
if len ( channel_names ) == 2 :
saved_r1_streams = ' 2 × 24kHz '
elif len ( channel_names ) == 3 :
saved_r1_streams = ' 3 × 16kHz '
else :
saved_r1_streams = ' 1 × 48kHz '
elif saved_rate == 24000 :
saved_r1_streams = ' 2 × 24kHz '
elif saved_rate == 16000 :
saved_r1_streams = ' 3 × 16kHz '
default_r1_idx = r1_stream_options . index ( saved_r1_streams ) if saved_r1_streams in r1_stream_options else 0
if dante_stereo_enabled :
@@ -924,15 +1025,25 @@ else:
r1_available_qualities = [ ]
for quality in [ " High (48kHz) " , " Good (32kHz) " , " Medium (24kHz) " , " Fair (16kHz) " ] :
# Check if this quality is equal to or lower than the max
if ( r1_max_quality == " High (48kHz) " or
if ( r1_max_quality == " High (48kHz) " or
( r1_max_quality == " Medium (24kHz) " and quality in [ " Medium (24kHz) " , " Fair (16kHz) " ] ) or
( r1_max_quality == " Fair (16kHz) " and quality == " Fair (16kHz) " ) ) :
r1_available_qualities . append ( quality )
saved_r1_quality = saved_r1_config . get ( ' radio_quality ' , r1_max_quality )
# Map saved sampling rate to quality label
saved_r1_quality = r1_max_quality
saved_rate = saved_settings . get ( ' auracast_sampling_rate_hz ' )
if saved_rate == 48000 :
saved_r1_quality = " High (48kHz) "
elif saved_rate == 32000 :
saved_r1_quality = " Good (32kHz) "
elif saved_rate == 24000 :
saved_r1_quality = " Medium (24kHz) "
elif saved_rate == 16000 :
saved_r1_quality = " Fair (16kHz) "
if saved_r1_quality not in r1_available_qualities :
saved_r1_quality = r1_max_quality
r1_radio_quality = st . selectbox (
" Stream Quality (Radio 1) " ,
r1_available_qualities ,
@@ -940,29 +1051,29 @@ else:
disabled = is_streaming ,
help = f " Select stream quality for Radio 1. Maximum quality based on configuration: { r1_max_quality } "
)
# Radio-level settings for Radio 1
# First row: Assistive listening, immediate rendering, presentation delay, QoS
col_r1_flags1 , col_r1_flags2 , col_r1_pdelay , col_r1_qos = st . columns ( [ 1 , 1 , 0.7 , 0.6 ] , gap = " small " )
with col_r1_flags1 :
r1_assisted_listening = st . checkbox (
" Assistive (R1) " ,
value = bool ( saved_r1_config . get ( ' assisted_listening ' , False ) ) ,
value = bool ( saved_settings . get ( ' assisted_listening_stream ' , False ) ) ,
disabled = is_streaming ,
help = " Assistive listening stream "
)
with col_r1_flags2 :
r1_immediate_rendering = st . checkbox (
" Immediate (R1) " ,
value = bool ( saved_r1_config . get ( ' immediate_rendering ' , False ) ) ,
value = bool ( saved_settings . get ( ' immediate_rendering ' , False ) ) ,
disabled = is_streaming ,
help = " Ignore presentation delay "
)
with col_r1_pdelay :
default_pdelay = int ( saved_r1_config . get ( ' presentation_delay_us ' , 40000 ) or 40000 )
default_pdelay = int ( saved_settings . get ( ' presentation_delay_us ' , 40000 ) or 40000 )
default_pdelay_ms = max ( 10 , min ( 200 , default_pdelay / / 1000 ) )
r1_presentation_delay_ms = st . number_input (
" Delay (ms, R1) " ,
@@ -970,10 +1081,10 @@ else:
disabled = is_streaming ,
help = " Presentation delay for Radio 1 "
)
with col_r1_qos :
qos_options = list ( QOS_PRESET_MAP . keys ( ) )
saved_qos = saved_r1_config . get ( ' qos_preset ' , ' Fast ' )
saved_qos = saved_settings . get ( ' qos_preset ' , ' Fast ' )
default_qos_idx = qos_options . index ( saved_qos ) if saved_qos in qos_options else 0
r1_qos_preset = st . selectbox (
" QoS (R1) " , options = qos_options , index = default_qos_idx ,
@@ -998,24 +1109,31 @@ else:
if dante_stereo_enabled :
# Stereo mode: single stream with combined L+R channels
with st . expander ( " Stereo Stream - Radio 1 " , expanded = True ) :
saved_streams = saved_r1_config . get ( ' streams ' , [ ] )
saved_stream = saved_streams [ 0 ] if saved_streams else { }
# Read from flat settings structure
channel_names = saved_settings . get ( ' channel_names ' , [ ] )
program_infos = saved_settings . get ( ' program_info ' , [ ] )
languages = saved_settings . get ( ' languages ' , [ ] )
saved_name = channel_names [ 0 ] if channel_names else ' Dante_Stereo '
saved_program_info = program_infos [ 0 ] if program_infos else saved_name
saved_language = languages [ 0 ] if languages else ' eng '
saved_password = saved_settings . get ( ' stream_password ' , ' ' )
# First row: Channel name and password
col_name , col_pwd = st . columns ( [ 2 , 1 ] )
with col_name :
stream_name = st . text_input (
" Channel Name " ,
value = saved_stream . get ( ' name ' , ' Dante_Stereo ' ) ,
value = saved_name ,
disabled = is_streaming ,
key = " r1_stereo_name "
)
with col_pwd :
stream_password = st . text_input (
" Stream Password " ,
value = saved_stream . get ( ' stream_password ' , ' ' ) ,
value = saved_password ,
type = " password " ,
disabled = is_streaming ,
key = " r1_stereo_password " ,
@@ -1024,19 +1142,19 @@ else:
# Second row: Program info and language
col_prog , col_lang_code = st . columns ( [ 2 , 1 ] )
with col_prog :
program_info = st . text_input (
" Program Info " ,
value = saved_stream . get ( ' program_info ' , ' Dante Stereo Broadcast ' ) ,
value = saved_program_info ,
disabled = is_streaming ,
key = " r1_stereo_program "
)
with col_lang_code :
language = st . text_input (
" Language " ,
value = saved_stream . get ( ' language ' , ' eng ' ) ,
value = saved_language ,
disabled = is_streaming ,
key = " r1_stereo_lang " ,
help = " ISO 639-3 language code "
@@ -1070,47 +1188,58 @@ else:
} )
else :
# Normal mono mode: multiple streams with individual channels
# Read from flat settings structure
channel_names = saved_settings . get ( ' channel_names ' , [ ] )
program_infos = saved_settings . get ( ' program_info ' , [ ] )
languages = saved_settings . get ( ' languages ' , [ ] )
input_devices = saved_settings . get ( ' input_devices ' , [ ] )
stream_passwords = saved_settings . get ( ' stream_passwords ' , [ ] ) if ' stream_passwords ' in saved_settings else [ ]
for i in range ( r1_num_streams ) :
with st . expander ( f " Stream { i + 1 } - Radio 1 " , expanded = True ) :
saved_streams = saved_r1_config . get ( ' streams ' , [ ] )
saved_stream = saved_streams [ i ] if i < len ( saved_streams ) else { }
# Get saved values from flat structure
saved_name = channel_names [ i ] if i < len ( channel_names ) else f ' Dante_R1_S { i + 1 } '
saved_program_info = program_infos [ i ] if i < len ( program_infos ) else f ' Dante Radio 1 Stream { i + 1 } '
saved_language = languages [ i ] if i < len ( languages ) else ' eng '
saved_password = stream_passwords [ i ] if i < len ( stream_passwords ) else ' '
saved_input_device = input_devices [ i ] if i < len ( input_devices ) else None
# First row: Channel name and language
col_name , col_lang = st . columns ( [ 2 , 1 ] )
with col_name :
stream_name = st . text_input (
f " Channel Name " ,
value = saved_stream . get ( ' name ' , f ' Dante_R1_S { i + 1 } ' ) ,
value = saved_name ,
disabled = is_streaming ,
key = f " r1_stream_ { i } _name "
)
with col_lang :
stream_password = st . text_input (
f " Stream Password " ,
value = saved_stream . get ( ' stream_password ' , ' ' ) ,
value = saved_password ,
type = " password " ,
disabled = is_streaming ,
key = f " r1_stream_ { i } _password " ,
help = " Optional: Set a broadcast code for this stream "
)
# Second row: Program info and language
col_prog , col_lang_code = st . columns ( [ 2 , 1 ] )
with col_prog :
program_info = st . text_input (
f " Program Info " ,
value = saved_stream . get ( ' program_info ' , f ' Dante Radio 1 Stream { i + 1 } ' ) ,
value = saved_program_info ,
disabled = is_streaming ,
key = f " r1_stream_ { i } _program "
)
with col_lang_code :
language = st . text_input (
f " Language " ,
value = saved_stream . get ( ' language ' , ' eng ' ) ,
value = saved_language ,
disabled = is_streaming ,
key = f " r1_stream_ { i } _lang " ,
help = " ISO 639-3 language code "
@@ -1122,10 +1251,10 @@ else:
with col_device :
# Session state key for persisting the selection
device_session_key = f " r1_stream_ { i } _device_saved "
if not is_streaming and input_options :
# Get default from session state first, then from saved settings
default_input_name = st . session_state . get ( device_session_key , saved_stream . get ( ' input_device ' ) )
default_input_name = st . session_state . get ( device_session_key , saved_input_device )
default_input_label = None
for label , name in option_name_map . items ( ) :
if name == default_input_name :
@@ -1133,7 +1262,7 @@ else:
break
if default_input_label not in input_options and input_options :
default_input_label = input_options [ 0 ]
selected_option = st . selectbox (
f " Input Device " ,
input_options ,
@@ -1146,7 +1275,7 @@ else:
st . session_state [ device_session_key ] = input_device
else :
# When streaming, get the device from session state
current_device = st . session_state . get ( device_session_key , saved_stream . get ( ' input_device ' , ' No device ' ) )
current_device = st . session_state . get ( device_session_key , saved_input_device or ' No device ' )
# Convert internal name to display label
display_label = current_device
@@ -1175,26 +1304,45 @@ else:
# --- Radio 2 Section ---
with st . container ( border = True ) :
st . subheader ( " Radio 2 " )
# Disable Radio 2 in stereo mode
saved_r2_config = saved_settings . get ( ' dante_radio2 ' , { } )
secondary_settings = saved_settings . get ( ' secondary ' , { } )
if dante_stereo_enabled :
st . info ( " 🎧 Radio 2 is automatically disabled in stereo mode " )
radio2_enabled = False
else :
# Enable/disable checkbox for Radio 2
# Use saved settings or streaming state to determine default
radio2_enabled_default = secondary_is_streaming
# Check if secondary radio has saved settings (indicates it was enabled)
if secondary_settings . get ( ' auracast_sampling_rate_hz ' ) or secondary_settings . get ( ' channel_names ' ) :
radio2_enabled_default = True
radio2_enabled = st . checkbox (
" Enable Radio 2 " ,
value = radio2_enabled_default ,
disabled = is_streaming ,
help = " Activate a second Dante radio with its own quality and timing settings. "
)
if radio2_enabled :
# Stream count dropdown for Radio 2
r2_stream_options = r1_stream_options
saved_r2_streams = saved_r2_config . get ( ' stream_config ' , ' 1x48 ' )
# Infer stream configuration from saved secondary sampling rate
saved_rate2 = secondary_settings . get ( ' auracast_sampling_rate_hz ' )
saved_r2_streams = ' 1 × 48kHz ' # default
if saved_rate2 :
if saved_rate2 == 48000 :
channel_names2 = secondary_settings . get ( ' channel_names ' , [ ] )
if len ( channel_names2 ) == 2 :
saved_r2_streams = ' 2 × 24kHz '
elif len ( channel_names2 ) == 3 :
saved_r2_streams = ' 3 × 16kHz '
else :
saved_r2_streams = ' 1 × 48kHz '
elif saved_rate2 == 24000 :
saved_r2_streams = ' 2 × 24kHz '
elif saved_rate2 == 16000 :
saved_r2_streams = ' 3 × 16kHz '
default_r2_idx = r2_stream_options . index ( saved_r2_streams ) if saved_r2_streams in r2_stream_options else 0
r2_stream_config = st . selectbox (
@@ -1216,11 +1364,20 @@ else:
( r2_max_quality == " Medium (24kHz) " and quality in [ " Medium (24kHz) " , " Fair (16kHz) " ] ) or
( r2_max_quality == " Fair (16kHz) " and quality == " Fair (16kHz) " ) ) :
r2_available_qualities . append ( quality )
saved_r2_quality = saved_r2_config . get ( ' radio_quality ' , r2_max_quality )
# Map saved secondary sampling rate to quality label
saved_r2_quality = r2_max_quality
if saved_rate2 == 48000 :
saved_r2_quality = " High (48kHz) "
elif saved_rate2 == 32000 :
saved_r2_quality = " Good (32kHz) "
elif saved_rate2 == 24000 :
saved_r2_quality = " Medium (24kHz) "
elif saved_rate2 == 16000 :
saved_r2_quality = " Fair (16kHz) "
if saved_r2_quality not in r2_available_qualities :
saved_r2_quality = r2_max_quality
r2_radio_quality = st . selectbox (
" Stream Quality (Radio 2) " ,
r2_available_qualities ,
@@ -1228,29 +1385,28 @@ else:
disabled = is_streaming ,
help = f " Select stream quality for Radio 2. Maximum quality based on configuration: { r2_max_quality } "
)
# Radio-level settings for Radio 2
# First row: Assistive listening, immediate rendering, presentation delay, QoS
col_r2_flags1 , col_r2_flags2 , col_r2_pdelay , col_r2_qos = st . columns ( [ 1 , 1 , 0.7 , 0.6 ] , gap = " small " )
with col_r2_flags1 :
r2_assisted_listening = st . checkbox (
" Assistive (R2) " ,
value = bool ( saved_r2_config . get ( ' assisted_listening ' , False ) ) ,
value = bool ( secondary_settings . get ( ' assisted_listening_stream ' , False ) ) ,
disabled = is_streaming ,
help = " Assistive listening stream "
)
with col_r2_flags2 :
r2_immediate_rendering = st . checkbox (
" Immediate (R2) " ,
value = bool ( saved_r2_config . get ( ' immediate_rendering ' , False ) ) ,
value = bool ( secondary_settings . get ( ' immediate_rendering ' , False ) ) ,
disabled = is_streaming ,
help = " Ignore presentation delay "
)
with col_r2_pdelay :
default_pdelay = int ( saved_r2_config . get ( ' presentation_delay_us ' , 40000 ) or 40000 )
default_pdelay = int ( secondary_settings . get ( ' presentation_delay_us ' , 40000 ) or 40000 )
default_pdelay_ms = max ( 10 , min ( 200 , default_pdelay / / 1000 ) )
r2_presentation_delay_ms = st . number_input (
" Delay (ms, R2) " ,
@@ -1258,13 +1414,13 @@ else:
disabled = is_streaming ,
help = " Presentation delay for Radio 2 "
)
with col_r2_qos :
qos_options = list ( QOS_PRESET_MAP . keys ( ) )
saved_qos = saved_r2_config . get ( ' qos_preset ' , ' Fast ' )
default_qos_idx = qos_options . index ( saved_qos ) if saved_qos in qos_options else 0
saved_qos = secondary_settings . get ( ' qos_preset ' , ' Fast ' )
default_qos_idx2 = qos_options . index ( saved_qos ) if saved_qos in qos_options else 0
r2_qos_preset = st . selectbox (
" QoS (R2) " , options = qos_options , index = default_qos_idx ,
" QoS (R2) " , options = qos_options , index = default_qos_idx2 ,
disabled = is_streaming ,
help = " Quality of Service preset for Radio 2 "
)
@@ -1279,48 +1435,59 @@ else:
# Per-stream configuration for Radio 2
st . write ( " **Stream Configuration (Radio 2)** " )
r2_streams = [ ]
# Read from flat secondary settings structure
channel_names2 = secondary_settings . get ( ' channel_names ' , [ ] )
program_infos2 = secondary_settings . get ( ' program_info ' , [ ] )
languages2 = secondary_settings . get ( ' languages ' , [ ] )
input_devices2 = secondary_settings . get ( ' input_devices ' , [ ] )
stream_passwords2 = secondary_settings . get ( ' stream_passwords ' , [ ] ) if ' stream_passwords ' in secondary_settings else [ ]
for i in range ( r2_num_streams ) :
with st . expander ( f " Stream { i + 1 } - Radio 2 " , expanded = True ) :
saved_streams = saved_r2_config . get ( ' streams ' , [ ] )
saved_stream = saved_streams [ i ] if i < len ( saved_streams ) else { }
# Get saved values from flat secondary structure
saved_name2 = channel_names2 [ i ] if i < len ( channel_names2 ) else f ' Dante_R2_S { i + 1 } '
saved_program_info2 = program_infos2 [ i ] if i < len ( program_infos2 ) else f ' Dante Radio 2 Stream { i + 1 } '
saved_language2 = languages2 [ i ] if i < len ( languages2 ) else ' eng '
saved_password2 = stream_passwords2 [ i ] if i < len ( stream_passwords2 ) else ' '
saved_input_device2 = input_devices2 [ i ] if i < len ( input_devices2 ) else None
# First row: Channel name and password
col_name , col_pwd = st . columns ( [ 2 , 1 ] )
with col_name :
stream_name = st . text_input (
f " Channel Name " ,
value = saved_stream . get ( ' name ' , f ' Dante_R2_S { i + 1 } ' ) ,
value = saved_name2 ,
disabled = is_streaming ,
key = f " r2_stream_ { i } _name "
)
with col_pwd :
stream_password = st . text_input (
f " Stream Password " ,
value = saved_stream . get ( ' stream_password ' , ' ' ) ,
value = saved_password2 ,
type = " password " ,
disabled = is_streaming ,
key = f " r2_stream_ { i } _password " ,
help = " Optional: Set a broadcast code for this stream "
)
# Second row: Program info and language
col_prog , col_lang = st . columns ( [ 2 , 1 ] )
with col_prog :
program_info = st . text_input (
f " Program Info " ,
value = saved_stream . get ( ' program_info ' , f ' Dante Radio 2 Stream { i + 1 } ' ) ,
value = saved_program_info2 ,
disabled = is_streaming ,
key = f " r2_stream_ { i } _program "
)
with col_lang :
language = st . text_input (
f " Language " ,
value = saved_stream . get ( ' language ' , ' eng ' ) ,
value = saved_language2 ,
disabled = is_streaming ,
key = f " r2_stream_ { i } _lang " ,
help = " ISO 639-3 language code "
@@ -1332,10 +1499,10 @@ else:
with col_device :
# Session state key for persisting the selection
device_session_key = f " r2_stream_ { i } _device_saved "
if not is_streaming and input_options :
# Get default from session state first, then from saved settings
default_input_name = st . session_state . get ( device_session_key , saved_stream . get ( ' input_device ' ) )
default_input_name = st . session_state . get ( device_session_key , saved_input_device2 )
default_input_label = None
for label , name in option_name_map . items ( ) :
if name == default_input_name :
@@ -1343,7 +1510,7 @@ else:
break
if default_input_label not in input_options and input_options :
default_input_label = input_options [ 0 ]
selected_option = st . selectbox (
f " Input Device " ,
input_options ,
@@ -1356,7 +1523,7 @@ else:
st . session_state [ device_session_key ] = input_device
else :
# When streaming, get the device from session state
current_device = st . session_state . get ( device_session_key , saved_stream . get ( ' input_device ' , ' No device ' ) )
current_device = st . session_state . get ( device_session_key , saved_input_device2 or ' No device ' )
# Convert internal name to display label
display_label = current_device
@@ -1444,8 +1611,30 @@ else:
if audio_mode in ( " USB " , " Network " ) :
# USB/Network: single set of controls shared with the single channel
# Use saved settings if audio_mode matches, otherwise use defaults
saved_audio_mode = saved_settings . get ( ' audio_mode ' )
if saved_audio_mode in ( " USB " , " Network " ) :
# Map saved sampling rate to quality label
saved_rate = saved_settings . get ( ' auracast_sampling_rate_hz ' )
if saved_rate == 48000 :
default_quality = " High (48kHz) "
elif saved_rate == 32000 :
default_quality = " Good (32kHz) "
elif saved_rate == 24000 :
default_quality = " Medium (24kHz) "
elif saved_rate == 16000 :
default_quality = " Fair (16kHz) "
else :
default_quality = " Medium (24kHz) "
saved_pwd = saved_settings . get ( ' stream_password ' , ' ' )
else :
# Use defaults when switching from another mode
default_quality = " Medium (24kHz) " if " Medium (24kHz) " in quality_options else quality_options [ 0 ]
saved_pwd = ' '
quality_options = list ( QUALITY_MAP . keys ( ) )
default_quality = " Medium (24kHz) " if " Medium (24kHz) " in quality_options else quality_options [ 0 ]
if default_quality not in quality_options :
default_quality = quality_options [ 0 ]
quality = st . selectbox (
" Stream Quality (Sampling Rate) " ,
quality_options ,
@@ -1456,7 +1645,7 @@ else:
stream_passwort = st . text_input (
" Stream Passwort " ,
value = " " ,
value = saved_pwd ,
type = " password " ,
disabled = is_streaming ,
help = " Optional: Set a broadcast code to protect your stream. Leave empty for an open (uncoded) broadcast. "
@@ -1728,7 +1917,7 @@ if start_stream:
analog_gain_db_right = cfg . get ( ' analog_gain_db_right ' , 0.0 ) ,
bigs = [
auracast_config . AuracastBigConfig (
code = ( cfg [ ' stream_passwort ' ] . strip ( ) or None ) ,
code = ( ( cfg [ ' stream_passwort ' ] or ' ' ) . strip ( ) or None ) ,
name = cfg [ ' name ' ] ,
program_info = cfg [ ' program_info ' ] ,
language = cfg [ ' language ' ] ,