denonavr 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
denonavr/soundmode.py CHANGED
@@ -11,14 +11,33 @@ import asyncio
11
11
  import logging
12
12
  from collections.abc import Hashable
13
13
  from copy import deepcopy
14
- from typing import Dict, List, Optional
14
+ from typing import Dict, List, Literal, Optional, get_args
15
15
 
16
16
  import attr
17
17
 
18
18
  from .appcommand import AppCommands
19
- from .const import ALL_ZONE_STEREO, DENON_ATTR_SETATTR, SOUND_MODE_MAPPING
19
+ from .const import (
20
+ ALL_ZONE_STEREO,
21
+ AURO_3D_MODE_MAP,
22
+ AURO_3D_MODE_MAP_MAP_LABELS,
23
+ AURO_MATIC_3D_PRESET_MAP,
24
+ AURO_MATIC_3D_PRESET_MAP_LABELS,
25
+ DENON_ATTR_SETATTR,
26
+ DIALOG_ENHANCER_LEVEL_MAP,
27
+ DIALOG_ENHANCER_LEVEL_MAP_LABELS,
28
+ EFFECT_SPEAKER_SELECTION_MAP,
29
+ EFFECT_SPEAKER_SELECTION_MAP_LABELS,
30
+ SOUND_MODE_MAPPING,
31
+ Auro3DModes,
32
+ AuroMatic3DPresets,
33
+ DialogEnhancerLevels,
34
+ DRCs,
35
+ EffectSpeakers,
36
+ IMAXHPFs,
37
+ IMAXLPFs,
38
+ )
20
39
  from .exceptions import AvrCommandError, AvrIncompleteResponseError, AvrProcessingError
21
- from .foundation import DenonAVRFoundation
40
+ from .foundation import DenonAVRFoundation, convert_on_off_bool
22
41
 
23
42
  _LOGGER = logging.getLogger(__name__)
24
43
 
@@ -67,6 +86,65 @@ class DenonAVRSoundMode(DenonAVRFoundation):
67
86
  _sound_mode_raw: Optional[str] = attr.ib(
68
87
  converter=attr.converters.optional(convert_sound_mode), default=None
69
88
  )
89
+ _neural_x: Optional[bool] = attr.ib(
90
+ converter=attr.converters.optional(convert_on_off_bool), default=None
91
+ )
92
+ _imax_auto_off: Optional[str] = attr.ib(
93
+ converter=attr.converters.optional(str), default=None
94
+ )
95
+ _imax_audio_settings: Optional[str] = attr.ib(
96
+ converter=attr.converters.optional(str), default=None
97
+ )
98
+ _imax_hpf: Optional[int] = attr.ib(
99
+ converter=attr.converters.optional(int), default=None
100
+ )
101
+ _imax_hpfs = get_args(IMAXHPFs)
102
+ _imax_lpf: Optional[int] = attr.ib(
103
+ converter=attr.converters.optional(int), default=None
104
+ )
105
+ _imax_lpfs = get_args(IMAXLPFs)
106
+ _imax_subwoofer_mode: Optional[str] = attr.ib(
107
+ converter=attr.converters.optional(str), default=None
108
+ )
109
+ _imax_subwoofer_output: Optional[str] = attr.ib(
110
+ converter=attr.converters.optional(str), default=None
111
+ )
112
+ _cinema_eq: Optional[bool] = attr.ib(
113
+ converter=attr.converters.optional(convert_on_off_bool), default=None
114
+ )
115
+ _center_spread: Optional[bool] = attr.ib(
116
+ converter=attr.converters.optional(convert_on_off_bool), default=None
117
+ )
118
+ _loudness_management: Optional[bool] = attr.ib(
119
+ converter=attr.converters.optional(convert_on_off_bool), default=None
120
+ )
121
+ _dialog_enhancer_level: Optional[str] = attr.ib(
122
+ converter=attr.converters.optional(str), default=None
123
+ )
124
+ _dialog_enhancer_levels = get_args(DialogEnhancerLevels)
125
+ _auromatic_3d_preset: Optional[str] = attr.ib(
126
+ converter=attr.converters.optional(str), default=None
127
+ )
128
+ _auromatic_3d_presets = get_args(AuroMatic3DPresets)
129
+ _auromatic_3d_strength: Optional[int] = attr.ib(
130
+ converter=attr.converters.optional(int), default=None
131
+ )
132
+ _auro_3d_mode: Optional[str] = attr.ib(
133
+ converter=attr.converters.optional(str), default=None
134
+ )
135
+ _auro_3d_modes = get_args(Auro3DModes)
136
+ _dialog_control: Optional[int] = attr.ib(
137
+ converter=attr.converters.optional(int), default=None
138
+ )
139
+ _speaker_virtualizer: Optional[bool] = attr.ib(
140
+ converter=attr.converters.optional(convert_on_off_bool), default=None
141
+ )
142
+ _effect_speaker_selection: Optional[str] = attr.ib(
143
+ converter=attr.converters.optional(str), default=None
144
+ )
145
+ _effect_speakers = get_args(EffectSpeakers)
146
+ _drc: Optional[str] = attr.ib(converter=attr.converters.optional(str), default=None)
147
+ _drcs = get_args(DRCs)
70
148
  _sound_mode_map: Dict[str, list] = attr.ib(
71
149
  validator=attr.validators.deep_mapping(
72
150
  attr.validators.instance_of(str),
@@ -113,6 +191,33 @@ class DenonAVRSoundMode(DenonAVRFoundation):
113
191
  self._device.telnet_api.register_callback(
114
192
  "MS", self._async_soundmode_callback
115
193
  )
194
+ self._device.telnet_api.register_callback(
195
+ "PS", self._async_neural_x_callback
196
+ )
197
+ self._device.telnet_api.register_callback("PS", self._async_imax_callback)
198
+ self._device.telnet_api.register_callback(
199
+ "PS", self._async_cinema_eq_callback
200
+ )
201
+ self._device.telnet_api.register_callback(
202
+ "PS", self._async_center_spread_callback
203
+ )
204
+ self._device.telnet_api.register_callback(
205
+ "PS", self._async_loudness_management_callback
206
+ )
207
+ self._device.telnet_api.register_callback(
208
+ "PS", self._async_dialog_enhancer_callback
209
+ )
210
+ self._device.telnet_api.register_callback("PS", self._async_auro_callback)
211
+ self._device.telnet_api.register_callback(
212
+ "PS", self._async_dialog_control_callback
213
+ )
214
+ self._device.telnet_api.register_callback(
215
+ "PS", self._async_speaker_virtualizer_callback
216
+ )
217
+ self._device.telnet_api.register_callback(
218
+ "PS", self._async_effect_speaker_selection_callback
219
+ )
220
+ self._device.telnet_api.register_callback("PS", self._async_drc_callback)
116
221
 
117
222
  self._is_setup = True
118
223
  _LOGGER.debug("Finished sound mode setup")
@@ -126,6 +231,116 @@ class DenonAVRSoundMode(DenonAVRFoundation):
126
231
 
127
232
  self._sound_mode_raw = parameter
128
233
 
234
+ async def _async_neural_x_callback(
235
+ self, zone: str, event: str, parameter: str
236
+ ) -> None:
237
+ """Handle a Neural X:change event."""
238
+ parameter_name_length = len("NEURAL")
239
+ if parameter[:parameter_name_length] == "NEURAL":
240
+ self._neural_x = parameter[parameter_name_length + 1 :]
241
+
242
+ async def _async_imax_callback(self, zone: str, event: str, parameter: str) -> None:
243
+ """Handle an IMAX change event."""
244
+ key_value = parameter.split()
245
+ if len(key_value) != 2 or key_value[0][:4] != "IMAX":
246
+ return
247
+
248
+ if key_value[0] == "IMAX":
249
+ self._imax_auto_off = parameter[5:]
250
+ elif key_value[0] == "IMAXAUD":
251
+ self._imax_audio_settings = parameter[8:]
252
+ elif key_value[0] == "IMAXHPF":
253
+ self._imax_hpf = int(parameter[8:])
254
+ elif key_value[0] == "IMAXLPF":
255
+ self._imax_lpf = int(parameter[8:])
256
+ elif key_value[0] == "IMAXSWM":
257
+ self._imax_subwoofer_mode = parameter[8:]
258
+ elif key_value[0] == "IMAXSWO":
259
+ self._imax_subwoofer_output = parameter[8:]
260
+
261
+ async def _async_cinema_eq_callback(
262
+ self, zone: str, event: str, parameter: str
263
+ ) -> None:
264
+ """Handle a Cinema EQ change event."""
265
+ if parameter[:10] == "CINEMA EQ.":
266
+ self._cinema_eq = parameter[10:]
267
+
268
+ async def _async_center_spread_callback(
269
+ self, zone: str, event: str, parameter: str
270
+ ) -> None:
271
+ """Handle a Center Spread change event."""
272
+ if parameter[:3] == "CES":
273
+ self._center_spread = parameter[4:]
274
+
275
+ async def _async_loudness_management_callback(
276
+ self, zone: str, event: str, parameter: str
277
+ ) -> None:
278
+ """Handle a Loudness Management change event."""
279
+ if parameter[:3] == "LOM":
280
+ self._loudness_management = parameter[4:]
281
+
282
+ async def _async_dialog_enhancer_callback(
283
+ self, zone: str, event: str, parameter: str
284
+ ) -> None:
285
+ """Handle a Dialog Enhancer change event."""
286
+ if parameter[:3] == "DEH":
287
+ self._dialog_enhancer_level = DIALOG_ENHANCER_LEVEL_MAP_LABELS[
288
+ parameter[4:]
289
+ ]
290
+
291
+ async def _async_auro_callback(self, zone: str, event: str, parameter: str) -> None:
292
+ """Handle a Auro change event."""
293
+ key_value = parameter.split()
294
+ if len(key_value) != 2 or key_value[0][:4] != "AURO":
295
+ return
296
+
297
+ if key_value[0] == "AUROPR":
298
+ self._auromatic_3d_preset = AURO_MATIC_3D_PRESET_MAP_LABELS[parameter[7:]]
299
+ elif key_value[0] == "AUROST":
300
+ self._auromatic_3d_strength = int(parameter[7:])
301
+ elif key_value[0] == "AUROMODE":
302
+ self._auro_3d_mode = AURO_3D_MODE_MAP_MAP_LABELS[parameter[9:]]
303
+
304
+ async def _async_dialog_control_callback(
305
+ self, zone: str, event: str, parameter: str
306
+ ) -> None:
307
+ """Handle a Dialog Control change event."""
308
+ key_value = parameter.split()
309
+ if len(key_value) != 2 or key_value[0] != "DIC":
310
+ return
311
+
312
+ self._dialog_control = int(key_value[1])
313
+
314
+ async def _async_speaker_virtualizer_callback(
315
+ self, zone: str, event: str, parameter: str
316
+ ) -> None:
317
+ """Handle a Speaker Virtualizer change event."""
318
+ key_value = parameter.split()
319
+ if len(key_value) != 2 or key_value[0] != "SPV":
320
+ return
321
+
322
+ self._speaker_virtualizer = key_value[1]
323
+
324
+ async def _async_effect_speaker_selection_callback(
325
+ self, zone: str, event: str, parameter: str
326
+ ) -> None:
327
+ """Handle a Effect Speaker Selection change event."""
328
+ key_value = parameter.split(":")
329
+ if len(key_value) != 2 or key_value[0] != "SP":
330
+ return
331
+
332
+ self._effect_speaker_selection = EFFECT_SPEAKER_SELECTION_MAP_LABELS[
333
+ key_value[1]
334
+ ]
335
+
336
+ async def _async_drc_callback(self, zone: str, event: str, parameter: str) -> None:
337
+ """Handle a DRC change event."""
338
+ key_value = parameter.split()
339
+ if len(key_value) != 2 or key_value[0] != "DRC":
340
+ return
341
+
342
+ self._drc = key_value[1]
343
+
129
344
  async def async_update(
130
345
  self, global_update: bool = False, cache_id: Optional[Hashable] = None
131
346
  ) -> None:
@@ -292,6 +507,186 @@ class DenonAVRSoundMode(DenonAVRFoundation):
292
507
  """Return the current sound mode as string as received from the AVR."""
293
508
  return self._sound_mode_raw
294
509
 
510
+ @property
511
+ def neural_x(self) -> Optional[bool]:
512
+ """
513
+ Return the current Neural:X status.
514
+
515
+ Only available if using Telnet.
516
+ """
517
+ return self._neural_x
518
+
519
+ @property
520
+ def imax(self) -> Optional[str]:
521
+ """
522
+ Return the current IMAX status.
523
+
524
+ Only available if using Telnet.
525
+
526
+ Possible values are: "AUTO", "OFF"
527
+ """
528
+ return self._imax_auto_off
529
+
530
+ @property
531
+ def imax_audio_settings(self) -> Optional[str]:
532
+ """
533
+ Return the current IMAX Audio Settings.
534
+
535
+ Only available if using Telnet.
536
+
537
+ Possible values are: "AUTO", "MANUAL"
538
+ """
539
+ return self._imax_audio_settings
540
+
541
+ @property
542
+ def imax_hpf(self) -> Optional[int]:
543
+ """
544
+ Return the current IMAX High Pass Filter.
545
+
546
+ Only available if using Telnet.
547
+ """
548
+ return self._imax_hpf
549
+
550
+ @property
551
+ def imax_lpf(self) -> Optional[int]:
552
+ """
553
+ Return the current IMAX Low Pass Filter.
554
+
555
+ Only available if using Telnet.
556
+ """
557
+ return self._imax_lpf
558
+
559
+ @property
560
+ def imax_subwoofer_mode(self) -> Optional[str]:
561
+ """
562
+ Return the current IMAX Subwoofer Mode.
563
+
564
+ Only available if using Telnet.
565
+ """
566
+ return self._imax_subwoofer_mode
567
+
568
+ @property
569
+ def imax_subwoofer_output(self) -> Optional[str]:
570
+ """
571
+ Return the current IMAX Subwoofer Output Mode.
572
+
573
+ Only available if using Telnet.
574
+ """
575
+ return self._imax_subwoofer_output
576
+
577
+ @property
578
+ def cinema_eq(self) -> Optional[bool]:
579
+ """
580
+ Return the current Cinema EQ status.
581
+
582
+ Only available if using Telnet.
583
+ """
584
+ return self._cinema_eq
585
+
586
+ @property
587
+ def center_spread(self) -> Optional[bool]:
588
+ """
589
+ Return the current Center Spread status.
590
+
591
+ Only available if using Telnet.
592
+ """
593
+ return self._center_spread
594
+
595
+ @property
596
+ def loudness_management(self) -> Optional[bool]:
597
+ """
598
+ Return the current Loudness Management status.
599
+
600
+ Only available if using Telnet.
601
+ """
602
+ return self._loudness_management
603
+
604
+ @property
605
+ def dialog_enhancer(self) -> Optional[str]:
606
+ """
607
+ Return the current Dialog Enhancer level.
608
+
609
+ Only available if using Telnet.
610
+
611
+ Possible values are: "Off", "Low", "Medium", "High"
612
+ """
613
+ return self._dialog_enhancer_level
614
+
615
+ @property
616
+ def auromatic_3d_preset(self) -> Optional[str]:
617
+ """
618
+ Return the current Auro-Matic 3D Preset.
619
+
620
+ Only available if using Telnet.
621
+
622
+ Possible values are: "Small, "Medium", "Large", "Speech", "Movie"
623
+ """
624
+ return self._auromatic_3d_preset
625
+
626
+ @property
627
+ def auromatic_3d_strength(self) -> Optional[int]:
628
+ """
629
+ Return the current Auro-Matic 3D Strength.
630
+
631
+ Only available if using Telnet.
632
+
633
+ Possible values are: 1-16
634
+ """
635
+ return self._auromatic_3d_strength
636
+
637
+ @property
638
+ def auro_3d_mode(self) -> Optional[str]:
639
+ """
640
+ Return the current Auro 3D mode.
641
+
642
+ Only available if using Telnet.
643
+
644
+ Possible values are: "Direct", "Channel Expansion"
645
+ """
646
+ return self._auro_3d_mode
647
+
648
+ @property
649
+ def dialog_control(self) -> Optional[int]:
650
+ """
651
+ Return the current Dialog Control level.
652
+
653
+ Only available if using Telnet.
654
+
655
+ Possible values are: 0-6
656
+ """
657
+ return self._dialog_control
658
+
659
+ @property
660
+ def speaker_virtualizer(self) -> Optional[bool]:
661
+ """
662
+ Return the current Speaker Virtualizer status.
663
+
664
+ Only available if using Telnet.
665
+ """
666
+ return self._speaker_virtualizer
667
+
668
+ @property
669
+ def effect_speaker_selection(self) -> Optional[str]:
670
+ """
671
+ Return the current Effect Speaker Selection.
672
+
673
+ Only available if using Telnet.
674
+
675
+ Possible values are: "Floor", "Height + Floor"
676
+ """
677
+ return self._effect_speaker_selection
678
+
679
+ @property
680
+ def drc(self) -> Optional[str]:
681
+ """
682
+ Return the current DRC status.
683
+
684
+ Only available if using Telnet.
685
+
686
+ Possible values are: "AUTO", "LOW", "MID", "HI", "OFF"
687
+ """
688
+ return self._drc
689
+
295
690
  ##########
296
691
  # Setter #
297
692
  ##########
@@ -325,6 +720,520 @@ class DenonAVRSoundMode(DenonAVRFoundation):
325
720
  else:
326
721
  await self._device.api.async_get_command(command_url)
327
722
 
723
+ async def async_sound_mode_next(self):
724
+ """Select next sound mode."""
725
+ if self._device.telnet_available:
726
+ await self._device.telnet_api.async_send_commands(
727
+ self._device.telnet_commands.command_sel_sound_mode + "RIGHT"
728
+ )
729
+ else:
730
+ await self._device.api.async_get_command(
731
+ self._device.urls.command_sel_sound_mode + "RIGHT"
732
+ )
733
+
734
+ async def async_sound_mode_previous(self):
735
+ """Select previous sound mode."""
736
+ if self._device.telnet_available:
737
+ await self._device.telnet_api.async_send_commands(
738
+ self._device.telnet_commands.command_sel_sound_mode + "LEFT"
739
+ )
740
+ else:
741
+ await self._device.api.async_get_command(
742
+ self._device.urls.command_sel_sound_mode + "LEFT"
743
+ )
744
+
745
+ async def async_neural_x_on(self):
746
+ """Turn on Neural:X sound mode."""
747
+ if self._device.telnet_available:
748
+ await self._device.telnet_api.async_send_commands(
749
+ self._device.telnet_commands.command_neural_x_on_off.format(mode="ON")
750
+ )
751
+ else:
752
+ await self._device.api.async_get_command(
753
+ self._device.urls.command_neural_x_on_off.format(mode="ON")
754
+ )
755
+
756
+ async def async_neural_x_off(self):
757
+ """Turn off Neural:X sound mode."""
758
+ if self._device.telnet_available:
759
+ await self._device.telnet_api.async_send_commands(
760
+ self._device.telnet_commands.command_neural_x_on_off.format(mode="OFF")
761
+ )
762
+ else:
763
+ await self._device.api.async_get_command(
764
+ self._device.urls.command_neural_x_on_off.format(mode="OFF")
765
+ )
766
+
767
+ async def async_neural_x_toggle(self):
768
+ """
769
+ Toggle Neural:X sound mode.
770
+
771
+ Only available if using Telnet.
772
+ """
773
+ if self._neural_x:
774
+ await self.async_neural_x_off()
775
+ else:
776
+ await self.async_neural_x_on()
777
+
778
+ async def async_imax_auto(self):
779
+ """Set IMAX sound mode to Auto."""
780
+ if self._device.telnet_available:
781
+ await self._device.telnet_api.async_send_commands(
782
+ self._device.telnet_commands.command_imax_auto_off.format(mode="AUTO")
783
+ )
784
+ else:
785
+ await self._device.api.async_get_command(
786
+ self._device.urls.command_imax_auto_off.format(mode="AUTO")
787
+ )
788
+
789
+ async def async_imax_off(self):
790
+ """Turn off IMAX sound mode."""
791
+ if self._device.telnet_available:
792
+ await self._device.telnet_api.async_send_commands(
793
+ self._device.telnet_commands.command_imax_auto_off.format(mode="OFF")
794
+ )
795
+ else:
796
+ await self._device.api.async_get_command(
797
+ self._device.urls.command_imax_auto_off.format(mode="OFF")
798
+ )
799
+
800
+ async def async_imax_toggle(self):
801
+ """
802
+ Toggle IMAX sound mode between auto and off.
803
+
804
+ Only available if using Telnet.
805
+ """
806
+ if self._imax_auto_off != "OFF":
807
+ await self.async_imax_off()
808
+ else:
809
+ await self.async_imax_auto()
810
+
811
+ async def async_imax_audio_settings(self, mode: Literal["AUTO", "MANUAL"]):
812
+ """Set IMAX audio settings."""
813
+ if mode not in ["AUTO", "MANUAL"]:
814
+ raise AvrCommandError(f"{mode} is not a valid IMAX audio setting")
815
+
816
+ if self._device.telnet_available:
817
+ await self._device.telnet_api.async_send_commands(
818
+ self._device.telnet_commands.command_imax_audio_settings.format(
819
+ mode=mode
820
+ )
821
+ )
822
+ else:
823
+ await self._device.api.async_get_command(
824
+ self._device.urls.command_imax_audio_settings.format(mode=mode)
825
+ )
826
+
827
+ async def async_imax_audio_settings_toggle(self) -> None:
828
+ """
829
+ Toggle IMAX audio settings between auto and manual.
830
+
831
+ Only available if using Telnet.
832
+ """
833
+ if self._imax_audio_settings == "AUTO":
834
+ await self.async_imax_audio_settings("MANUAL")
835
+ else:
836
+ await self.async_imax_audio_settings("AUTO")
837
+
838
+ async def async_imax_hpf(self, hpf: IMAXHPFs) -> None:
839
+ """Set IMAX High Pass Filter."""
840
+ if hpf not in self._imax_hpfs:
841
+ raise AvrCommandError(f"{hpf} is not a valid IMAX high pass filter")
842
+
843
+ local_hpf = self._padded_pass_filter(hpf)
844
+ if self._device.telnet_available:
845
+ await self._device.telnet_api.async_send_commands(
846
+ self._device.telnet_commands.command_imax_hpf.format(
847
+ frequency=local_hpf
848
+ )
849
+ )
850
+ else:
851
+ await self._device.api.async_get_command(
852
+ self._device.urls.command_imax_hpf.format(frequency=local_hpf)
853
+ )
854
+
855
+ async def async_imax_lpf(self, lpf: IMAXLPFs) -> None:
856
+ """Set IMAX Low Pass Filter."""
857
+ if lpf not in self._imax_lpfs:
858
+ raise AvrCommandError(f"{lpf} is not a valid IMAX low pass filter")
859
+
860
+ local_lpf = self._padded_pass_filter(lpf)
861
+ if self._device.telnet_available:
862
+ await self._device.telnet_api.async_send_commands(
863
+ self._device.telnet_commands.command_imax_lpf.format(
864
+ frequency=local_lpf
865
+ )
866
+ )
867
+ else:
868
+ await self._device.api.async_get_command(
869
+ self._device.urls.command_imax_lpf.format(frequency=local_lpf)
870
+ )
871
+
872
+ @staticmethod
873
+ def _padded_pass_filter(pass_filter: str) -> str:
874
+ return f"0{pass_filter}" if len(str(pass_filter)) == 2 else str(pass_filter)
875
+
876
+ async def async_imax_subwoofer_mode(self, mode: Literal["ON", "OFF"]) -> None:
877
+ """Set IMAX Subwoofer Mode."""
878
+ if mode not in ["ON", "OFF"]:
879
+ raise AvrCommandError(f"{mode} is not a valid IMAX subwoofer mode")
880
+
881
+ if self._device.telnet_available:
882
+ await self._device.telnet_api.async_send_commands(
883
+ self._device.telnet_commands.command_imax_subwoofer_mode.format(
884
+ mode=mode
885
+ )
886
+ )
887
+ else:
888
+ await self._device.api.async_get_command(
889
+ self._device.urls.command_imax_subwoofer_mode.format(mode=mode)
890
+ )
891
+
892
+ async def async_imax_subwoofer_output(self, mode: Literal["L+M", "LFE"]) -> None:
893
+ """Set IMAX Subwoofer Output Mode."""
894
+ if mode not in ["L+M", "LFE"]:
895
+ raise AvrCommandError(f"{mode} is not a valid IMAX subwoofer output mode")
896
+
897
+ if self._device.telnet_available:
898
+ await self._device.telnet_api.async_send_commands(
899
+ self._device.telnet_commands.command_imax_subwoofer_output.format(
900
+ mode=mode
901
+ )
902
+ )
903
+ else:
904
+ await self._device.api.async_get_command(
905
+ self._device.urls.command_imax_subwoofer_output.format(mode=mode)
906
+ )
907
+
908
+ async def async_cinema_eq_on(self):
909
+ """Set Cinema EQ to ON."""
910
+ if self._device.telnet_available:
911
+ await self._device.telnet_api.async_send_commands(
912
+ self._device.telnet_commands.command_cinema_eq.format(mode="ON")
913
+ )
914
+ else:
915
+ await self._device.api.async_get_command(
916
+ self._device.urls.command_cinema_eq.format(mode="ON")
917
+ )
918
+
919
+ async def async_cinema_eq_off(self):
920
+ """Set Cinema EQ to OFF."""
921
+ if self._device.telnet_available:
922
+ await self._device.telnet_api.async_send_commands(
923
+ self._device.telnet_commands.command_cinema_eq.format(mode="OFF")
924
+ )
925
+ else:
926
+ await self._device.api.async_get_command(
927
+ self._device.urls.command_cinema_eq.format(mode="OFF")
928
+ )
929
+
930
+ async def async_cinema_eq_toggle(self):
931
+ """
932
+ Toggle Cinema EQ.
933
+
934
+ Only available if using Telnet.
935
+ """
936
+ if self._cinema_eq:
937
+ await self.async_cinema_eq_off()
938
+ else:
939
+ await self.async_cinema_eq_on()
940
+
941
+ async def async_center_spread_on(self):
942
+ """Set Center Spread to ON."""
943
+ if self._device.telnet_available:
944
+ await self._device.telnet_api.async_send_commands(
945
+ self._device.telnet_commands.command_center_spread.format(mode="ON")
946
+ )
947
+ else:
948
+ await self._device.api.async_get_command(
949
+ self._device.urls.command_center_spread.format(mode="ON")
950
+ )
951
+
952
+ async def async_center_spread_off(self):
953
+ """Set Center Spread to ON."""
954
+ if self._device.telnet_available:
955
+ await self._device.telnet_api.async_send_commands(
956
+ self._device.telnet_commands.command_center_spread.format(mode="OFF")
957
+ )
958
+ else:
959
+ await self._device.api.async_get_command(
960
+ self._device.urls.command_center_spread.format(mode="OFF")
961
+ )
962
+
963
+ async def async_center_spread_toggle(self):
964
+ """
965
+ Toggle Center Spread.
966
+
967
+ Only available if using Telnet.
968
+ """
969
+ if self._center_spread:
970
+ await self.async_center_spread_off()
971
+ else:
972
+ await self.async_center_spread_on()
973
+
974
+ async def async_loudness_management_on(self):
975
+ """Set Loudness Management to ON."""
976
+ if self._device.telnet_available:
977
+ await self._device.telnet_api.async_send_commands(
978
+ self._device.telnet_commands.command_loudness_management.format(
979
+ mode="ON"
980
+ )
981
+ )
982
+ else:
983
+ await self._device.api.async_get_command(
984
+ self._device.urls.command_loudness_management.format(mode="ON")
985
+ )
986
+
987
+ async def async_loudness_management_off(self):
988
+ """Set Loudness Management to OFF."""
989
+ if self._device.telnet_available:
990
+ await self._device.telnet_api.async_send_commands(
991
+ self._device.telnet_commands.command_loudness_management.format(
992
+ mode="OFF"
993
+ )
994
+ )
995
+ else:
996
+ await self._device.api.async_get_command(
997
+ self._device.urls.command_loudness_management.format(mode="OFF")
998
+ )
999
+
1000
+ async def async_loudness_management_toggle(self):
1001
+ """
1002
+ Toggle Loudness Management.
1003
+
1004
+ Only available if using Telnet.
1005
+ """
1006
+ if self._loudness_management:
1007
+ await self.async_loudness_management_off()
1008
+ else:
1009
+ await self.async_loudness_management_on()
1010
+
1011
+ async def async_dialog_enhancer(self, level: DialogEnhancerLevels) -> None:
1012
+ """Set Dialog Enhancer level."""
1013
+ if level not in self._dialog_enhancer_levels:
1014
+ raise AvrCommandError(f"{level} is not a valid dialog enhancer level")
1015
+
1016
+ level_mapped = DIALOG_ENHANCER_LEVEL_MAP[level]
1017
+ if self._device.telnet_available:
1018
+ await self._device.telnet_api.async_send_commands(
1019
+ self._device.telnet_commands.command_dialog_enhancer.format(
1020
+ level=level_mapped
1021
+ )
1022
+ )
1023
+ else:
1024
+ await self._device.api.async_get_command(
1025
+ self._device.urls.command_dialog_enhancer.format(level=level_mapped)
1026
+ )
1027
+
1028
+ async def async_auromatic_3d_preset(self, preset: AuroMatic3DPresets) -> None:
1029
+ """Set Auro-Matic 3D Preset."""
1030
+ if preset not in self._auromatic_3d_presets:
1031
+ raise AvrCommandError(f"{preset} is not a valid Auro-Matic 3D Preset")
1032
+
1033
+ local_preset = AURO_MATIC_3D_PRESET_MAP[preset]
1034
+ if self._device.telnet_available:
1035
+ await self._device.telnet_api.async_send_commands(
1036
+ self._device.telnet_commands.command_auromatic_3d_preset.format(
1037
+ preset=local_preset
1038
+ )
1039
+ )
1040
+ else:
1041
+ await self._device.api.async_get_command(
1042
+ self._device.urls.command_auromatic_3d_preset.format(
1043
+ preset=local_preset
1044
+ )
1045
+ )
1046
+
1047
+ async def async_auromatic_3d_strength_up(self) -> None:
1048
+ """Increase Auro-Matic 3D Strength."""
1049
+ if self._device.telnet_available:
1050
+ await self._device.telnet_api.async_send_commands(
1051
+ self._device.telnet_commands.command_auromatic_3d_strength.format(
1052
+ value="UP"
1053
+ )
1054
+ )
1055
+ else:
1056
+ await self._device.api.async_get_command(
1057
+ self._device.urls.command_auromatic_3d_strength.format(value="UP")
1058
+ )
1059
+
1060
+ async def async_auromatic_3d_strength_down(self) -> None:
1061
+ """Decrease Auro-Matic 3D Strength."""
1062
+ if self._device.telnet_available:
1063
+ await self._device.telnet_api.async_send_commands(
1064
+ self._device.telnet_commands.command_auromatic_3d_strength.format(
1065
+ value="DOWN"
1066
+ )
1067
+ )
1068
+ else:
1069
+ await self._device.api.async_get_command(
1070
+ self._device.urls.command_auromatic_3d_strength.format(value="DOWN")
1071
+ )
1072
+
1073
+ async def async_auromatic_3d_strength(self, strength: int) -> None:
1074
+ """
1075
+ Set Auro-Matic 3D Strength.
1076
+
1077
+ :param strength: Strength value to set. Valid values are 1-16.
1078
+ """
1079
+ if strength < 1 or strength > 16:
1080
+ raise AvrCommandError(f"{strength} is not a valid Auro-Matic 3D Strength")
1081
+
1082
+ local_strength = f"{strength:02}"
1083
+ if self._device.telnet_available:
1084
+ await self._device.telnet_api.async_send_commands(
1085
+ self._device.telnet_commands.command_auromatic_3d_strength.format(
1086
+ value=local_strength
1087
+ )
1088
+ )
1089
+ else:
1090
+ await self._device.api.async_get_command(
1091
+ self._device.urls.command_auromatic_3d_strength.format(
1092
+ value=local_strength
1093
+ )
1094
+ )
1095
+
1096
+ async def async_auro_3d_mode(self, mode: Auro3DModes) -> None:
1097
+ """Set Auro 3D Mode."""
1098
+ if mode not in self._auro_3d_modes:
1099
+ raise AvrCommandError(f"{mode} is not a valid Auro 3D Mode")
1100
+
1101
+ local_mode = AURO_3D_MODE_MAP[mode]
1102
+ if self._device.telnet_available:
1103
+ await self._device.telnet_api.async_send_commands(
1104
+ self._device.telnet_commands.command_auro_3d_mode.format(
1105
+ mode=local_mode
1106
+ )
1107
+ )
1108
+ else:
1109
+ await self._device.api.async_get_command(
1110
+ self._device.urls.command_auro_3d_mode.format(mode=local_mode)
1111
+ )
1112
+
1113
+ async def async_dialog_control_up(self) -> None:
1114
+ """Increase Dialog Control level."""
1115
+ if self._device.telnet_available:
1116
+ await self._device.telnet_api.async_send_commands(
1117
+ self._device.telnet_commands.command_dialog_control.format(value="UP")
1118
+ )
1119
+ else:
1120
+ await self._device.api.async_get_command(
1121
+ self._device.urls.command_dialog_control.format(value="UP")
1122
+ )
1123
+
1124
+ async def async_dialog_control_down(self) -> None:
1125
+ """Decrease Dialog Control level."""
1126
+ if self._device.telnet_available:
1127
+ await self._device.telnet_api.async_send_commands(
1128
+ self._device.telnet_commands.command_dialog_control.format(value="DOWN")
1129
+ )
1130
+ else:
1131
+ await self._device.api.async_get_command(
1132
+ self._device.urls.command_dialog_control.format(value="DOWN")
1133
+ )
1134
+
1135
+ async def async_dialog_control(self, level: int) -> None:
1136
+ """
1137
+ Set Dialog Control level.
1138
+
1139
+ :param level: Level to set. Valid values are 0-6.
1140
+ """
1141
+ if level < 0 or level > 6:
1142
+ raise AvrCommandError(f"{level} is not a valid dialog control level")
1143
+
1144
+ local_level = f"{level:02}"
1145
+ if self._device.telnet_available:
1146
+ await self._device.telnet_api.async_send_commands(
1147
+ self._device.telnet_commands.command_dialog_control.format(
1148
+ value=local_level
1149
+ )
1150
+ )
1151
+ else:
1152
+ await self._device.api.async_get_command(
1153
+ self._device.urls.command_dialog_control.format(value=local_level)
1154
+ )
1155
+
1156
+ async def async_speaker_virtualizer_on(self) -> None:
1157
+ """Set Speaker Virtualizer to ON."""
1158
+ if self._device.telnet_available:
1159
+ await self._device.telnet_api.async_send_commands(
1160
+ self._device.telnet_commands.command_speaker_virtualizer.format(
1161
+ mode="ON"
1162
+ )
1163
+ )
1164
+ else:
1165
+ await self._device.api.async_get_command(
1166
+ self._device.urls.command_speaker_virtualizer.format(mode="ON")
1167
+ )
1168
+
1169
+ async def async_speaker_virtualizer_off(self) -> None:
1170
+ """Set Speaker Virtualizer to OFF."""
1171
+ if self._device.telnet_available:
1172
+ await self._device.telnet_api.async_send_commands(
1173
+ self._device.telnet_commands.command_speaker_virtualizer.format(
1174
+ mode="OFF"
1175
+ )
1176
+ )
1177
+ else:
1178
+ await self._device.api.async_get_command(
1179
+ self._device.urls.command_speaker_virtualizer.format(mode="OFF")
1180
+ )
1181
+
1182
+ async def async_speaker_virtualizer_toggle(self) -> None:
1183
+ """
1184
+ Toggle Speaker Virtualizer.
1185
+
1186
+ Only available if using Telnet.
1187
+ """
1188
+ if self._speaker_virtualizer:
1189
+ await self.async_speaker_virtualizer_off()
1190
+ else:
1191
+ await self.async_speaker_virtualizer_on()
1192
+
1193
+ async def async_effect_speaker_selection(self, mode: EffectSpeakers) -> None:
1194
+ """Set Effect Speaker."""
1195
+ if mode not in self._effect_speakers:
1196
+ raise AvrCommandError(f"{mode} is not a valid effect speaker selection")
1197
+
1198
+ local_mode = EFFECT_SPEAKER_SELECTION_MAP[mode]
1199
+ if self._device.telnet_available:
1200
+ await self._device.telnet_api.async_send_commands(
1201
+ self._device.telnet_commands.command_effect_speaker_selection.format(
1202
+ mode=local_mode
1203
+ )
1204
+ )
1205
+ else:
1206
+ await self._device.api.async_get_command(
1207
+ self._device.urls.command_effect_speaker_selection.format(
1208
+ mode=local_mode
1209
+ )
1210
+ )
1211
+
1212
+ async def async_effect_speaker_selection_toggle(self) -> None:
1213
+ """
1214
+ Toggle Effect Speaker Selection.
1215
+
1216
+ Only available if using Telnet.
1217
+ """
1218
+ if self._effect_speaker_selection == "Floor":
1219
+ await self.async_effect_speaker_selection("Height + Floor")
1220
+ else:
1221
+ await self.async_effect_speaker_selection("Floor")
1222
+
1223
+ async def async_drc(self, mode: DRCs) -> None:
1224
+ """Set DRC mode."""
1225
+ if mode not in self._drcs:
1226
+ raise AvrCommandError(f"{mode} is not a valid DRC mode")
1227
+
1228
+ if self._device.telnet_available:
1229
+ await self._device.telnet_api.async_send_commands(
1230
+ self._device.telnet_commands.command_drc.format(mode=mode)
1231
+ )
1232
+ else:
1233
+ await self._device.api.async_get_command(
1234
+ self._device.urls.command_drc.format(mode=mode)
1235
+ )
1236
+
328
1237
 
329
1238
  def sound_mode_factory(instance: DenonAVRFoundation) -> DenonAVRSoundMode:
330
1239
  """Create DenonAVRSoundMode at receiver instances."""