@@ -95,6 +95,7 @@ async def async_setup_entry(
9595 entities .append (NovastarBackgroundSelect (entry , coordinator , device_info ))
9696 entities .append (NovastarAudioInputSelect (entry , coordinator , device_info ))
9797 entities .append (NovastarAudioOutputSelect (entry , coordinator , device_info ))
98+ entities .append (NovastarAudioOutputModeSelect (entry , coordinator , device_info ))
9899 entities .extend (
99100 [
100101 NovastarLayerSourceSelect (entry , coordinator , device_info , layer_id )
@@ -600,3 +601,69 @@ async def async_select_option(self, option: str) -> None:
600601 if output_id is None :
601602 return
602603 await self .coordinator .async_set_audio_output (output_id )
604+
605+
606+ class NovastarAudioOutputModeSelect (_NovastarBaseAudioSelect ):
607+ """Select entity for audio output mode (audioOutputMode/outputChannelMode)."""
608+
609+ _attr_name = "Audio Output Mode"
610+ _attr_translation_key = "audio_output_mode"
611+
612+ def __init__ (
613+ self ,
614+ entry : ConfigEntry ,
615+ coordinator : NovastarCoordinator ,
616+ device_info : NovastarDeviceInfo ,
617+ ) -> None :
618+ """Initialize audio output mode select."""
619+ super ().__init__ (entry , coordinator , device_info )
620+ self ._attr_unique_id = f"{ entry .entry_id } _audio_output_mode"
621+
622+ @staticmethod
623+ def _audio_output_mode_map () -> dict [str , int ]:
624+ """Map documented audio output mode labels to ids."""
625+ return {
626+ "Embedded Mode" : 0 ,
627+ "Fixed Mode" : 1 ,
628+ }
629+
630+ @staticmethod
631+ def _audio_output_mode_label (mode_id : int ) -> str :
632+ """Return display label for one audio output mode id."""
633+ for label , option_id in NovastarAudioOutputModeSelect ._audio_output_mode_map ().items ():
634+ if option_id == mode_id :
635+ return label
636+ return f"Audio Output Mode { mode_id } "
637+
638+ @property
639+ def options (self ) -> list [str ]:
640+ """Return available audio output mode options."""
641+ options = list (self ._audio_output_mode_map ().keys ())
642+ current = self .current_option
643+ if current and current not in options :
644+ options .append (current )
645+ return options
646+
647+ @property
648+ def current_option (self ) -> str | None :
649+ """Return selected audio output mode option."""
650+ if not self .coordinator .data :
651+ return None
652+ current_id = _coerce_int (self .coordinator .data .audio_output_id )
653+ if current_id is None :
654+ return None
655+ return self ._audio_output_mode_label (current_id )
656+
657+ async def async_select_option (self , option : str ) -> None :
658+ """Set active audio output mode."""
659+ output_id = self ._audio_output_mode_map ().get (option )
660+ if output_id is None :
661+ text = option .strip ()
662+ if text .startswith ("Audio Output Mode " ):
663+ try :
664+ output_id = int (text .replace ("Audio Output Mode " , "" ).strip ())
665+ except ValueError :
666+ return
667+ if output_id is None :
668+ return
669+ await self .coordinator .async_set_audio_output (output_id )
0 commit comments