From 33d23f2216d14dbc53674ea28fd0a6375e6d7b5b Mon Sep 17 00:00:00 2001 From: Albaintor Date: Thu, 8 May 2025 19:05:36 +0200 Subject: [PATCH 01/17] Added configurable volume step --- src/config.py | 4 ++++ src/setup_flow.py | 26 ++++++++++++++++++++++++++ src/tv.py | 4 ++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/config.py b/src/config.py index b37b66f..6a66c28 100644 --- a/src/config.py +++ b/src/config.py @@ -38,6 +38,8 @@ class AtvDevice: """Enable External Metadata.""" use_chromecast: bool = False """Enable Chromecast features.""" + volume_step: float = 10 + """Volume step (1 to 100).""" class _EnhancedJSONEncoder(json.JSONEncoder): @@ -133,6 +135,7 @@ def update(self, atv: AtvDevice) -> bool: item.auth_error = atv.auth_error item.use_external_metadata = atv.use_external_metadata item.use_chromecast = atv.use_chromecast + item.volume_step = atv.volume_step if atv.volume_step else 10 return self.store() return False @@ -236,6 +239,7 @@ def load(self) -> bool: item.get("auth_error", False), item.get("use_external_metadata", False), item.get("use_chromecast", False), + item.get("volume_step", 10) ) self._config.append(atv) return True diff --git a/src/setup_flow.py b/src/setup_flow.py index 4fff16f..1ed2e48 100644 --- a/src/setup_flow.py +++ b/src/setup_flow.py @@ -48,6 +48,7 @@ class SetupSteps(IntEnum): _use_external_metadata: bool = False _reconfigured_device: AtvDevice | None = None _use_chromecast: bool = False +_volume_step: float = 10 # TODO #9 externalize language texts _user_input_discovery = RequestUserInput( @@ -300,6 +301,7 @@ async def handle_configuration_mode( use_external_metadata = ( selected_device.use_external_metadata if selected_device.use_external_metadata else False ) + volume_step = selected_device.volume_step if selected_device.volume_step else 10 return RequestUserInput( { @@ -325,6 +327,16 @@ async def handle_configuration_mode( }, "field": {"checkbox": {"value": use_external_metadata}}, }, + { + "id": "volume_step", + "label": { + "en": "Volume step in percent", + "fr": "Pallier de volume en pourcent", + }, + "field": { + "number": {"value": volume_step, "min": 1, "max": 50, "steps": 1, "decimals": 0} + }, + }, ], ) case "reset": @@ -446,6 +458,16 @@ async def _handle_discovery(msg: UserDataResponse) -> RequestUserInput | SetupEr }, "field": {"checkbox": {"value": False}}, }, + { + "id": "volume_step", + "label": { + "en": "Volume step in percent", + "fr": "Pallier de volume en pourcent", + }, + "field": { + "number": {"value": 10, "min": 1, "max": 50, "steps": 1, "decimals": 0} + }, + }, ], ) @@ -463,10 +485,12 @@ async def handle_device_choice(msg: UserDataResponse) -> RequestUserInput | Setu global _use_chromecast global _setup_step global _use_external_metadata + global _volume_step choice = msg.input_values["choice"] _use_external_metadata = msg.input_values.get("external_metadata", "false") == "true" _use_chromecast = msg.input_values.get("chromecast", "false") == "true" + _volume_step = msg.input_values.get("volume_step", 10) name = "" for discovered_tv in _discovered_android_tvs: @@ -484,6 +508,7 @@ async def handle_device_choice(msg: UserDataResponse) -> RequestUserInput | Setu id="", use_external_metadata=False, use_chromecast=False, + volume_step=_volume_step ), ) _LOG.info("Chosen Android TV: %s. Start pairing process...", choice) @@ -566,6 +591,7 @@ async def handle_user_data_pin(msg: UserDataResponse) -> SetupComplete | SetupEr use_chromecast=_use_chromecast, manufacturer=device_info.get("manufacturer", ""), model=device_info.get("model", ""), + volume_step=_volume_step ) config.devices.add_or_update(device) # triggers AndroidTv instance creation diff --git a/src/tv.py b/src/tv.py index fa3051d..a5a905e 100644 --- a/src/tv.py +++ b/src/tv.py @@ -964,7 +964,7 @@ async def volume_up(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: - self._chromecast.volume_up() + self._chromecast.volume_up(delta=self._device_config.volume_step/100) return ucapi.StatusCodes.OK except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) @@ -975,7 +975,7 @@ async def volume_down(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: - self._chromecast.volume_down() + self._chromecast.volume_down(delta=self._device_config.volume_step/100) return ucapi.StatusCodes.OK except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) From edf094d644a8e7e8396481d4bf1f3d7e5b01843c Mon Sep 17 00:00:00 2001 From: Albaintor Date: Thu, 8 May 2025 19:07:45 +0200 Subject: [PATCH 02/17] Linting --- src/config.py | 2 +- src/setup_flow.py | 12 ++++-------- src/tv.py | 4 ++-- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/config.py b/src/config.py index 6a66c28..d650754 100644 --- a/src/config.py +++ b/src/config.py @@ -239,7 +239,7 @@ def load(self) -> bool: item.get("auth_error", False), item.get("use_external_metadata", False), item.get("use_chromecast", False), - item.get("volume_step", 10) + item.get("volume_step", 10), ) self._config.append(atv) return True diff --git a/src/setup_flow.py b/src/setup_flow.py index 1ed2e48..e718603 100644 --- a/src/setup_flow.py +++ b/src/setup_flow.py @@ -333,9 +333,7 @@ async def handle_configuration_mode( "en": "Volume step in percent", "fr": "Pallier de volume en pourcent", }, - "field": { - "number": {"value": volume_step, "min": 1, "max": 50, "steps": 1, "decimals": 0} - }, + "field": {"number": {"value": volume_step, "min": 1, "max": 50, "steps": 1, "decimals": 0}}, }, ], ) @@ -464,9 +462,7 @@ async def _handle_discovery(msg: UserDataResponse) -> RequestUserInput | SetupEr "en": "Volume step in percent", "fr": "Pallier de volume en pourcent", }, - "field": { - "number": {"value": 10, "min": 1, "max": 50, "steps": 1, "decimals": 0} - }, + "field": {"number": {"value": 10, "min": 1, "max": 50, "steps": 1, "decimals": 0}}, }, ], ) @@ -508,7 +504,7 @@ async def handle_device_choice(msg: UserDataResponse) -> RequestUserInput | Setu id="", use_external_metadata=False, use_chromecast=False, - volume_step=_volume_step + volume_step=_volume_step, ), ) _LOG.info("Chosen Android TV: %s. Start pairing process...", choice) @@ -591,7 +587,7 @@ async def handle_user_data_pin(msg: UserDataResponse) -> SetupComplete | SetupEr use_chromecast=_use_chromecast, manufacturer=device_info.get("manufacturer", ""), model=device_info.get("model", ""), - volume_step=_volume_step + volume_step=_volume_step, ) config.devices.add_or_update(device) # triggers AndroidTv instance creation diff --git a/src/tv.py b/src/tv.py index a5a905e..23fc448 100644 --- a/src/tv.py +++ b/src/tv.py @@ -964,7 +964,7 @@ async def volume_up(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: - self._chromecast.volume_up(delta=self._device_config.volume_step/100) + self._chromecast.volume_up(delta=self._device_config.volume_step / 100) return ucapi.StatusCodes.OK except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) @@ -975,7 +975,7 @@ async def volume_down(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: - self._chromecast.volume_down(delta=self._device_config.volume_step/100) + self._chromecast.volume_down(delta=self._device_config.volume_step / 100) return ucapi.StatusCodes.OK except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) From d489b32ae7278420f6e1b0ae0e6bdbc49411530b Mon Sep 17 00:00:00 2001 From: Albaintor Date: Thu, 8 May 2025 19:18:25 +0200 Subject: [PATCH 03/17] Updated version --- driver.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/driver.json b/driver.json index 299ca47..5eca623 100644 --- a/driver.json +++ b/driver.json @@ -1,6 +1,6 @@ { "driver_id": "androidtv", - "version": "0.7.2", + "version": "0.7.3", "min_core_api": "0.20.0", "name": { "en": "Android TV" }, "icon": "uc:integration", @@ -41,5 +41,5 @@ } ] }, - "release_date": "2025-04-27" + "release_date": "2025-05-08" } From 5ff83c6d06ea11f88d85941e1e7f12e04ceedcee Mon Sep 17 00:00:00 2001 From: Albaintor Date: Fri, 9 May 2025 19:15:56 +0200 Subject: [PATCH 04/17] Removed duplicate volume/mute features --- .idea/runConfigurations/check_black.xml | 35 ------------------------- src/profiles.py | 3 --- 2 files changed, 38 deletions(-) delete mode 100644 .idea/runConfigurations/check_black.xml diff --git a/.idea/runConfigurations/check_black.xml b/.idea/runConfigurations/check_black.xml deleted file mode 100644 index 5925ed7..0000000 --- a/.idea/runConfigurations/check_black.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/profiles.py b/src/profiles.py index ac5eace..f4b261a 100644 --- a/src/profiles.py +++ b/src/profiles.py @@ -189,9 +189,6 @@ def __init__(self): media_player.Features.SUBTITLE, media_player.Features.RECORD, media_player.Features.STOP, - media_player.Features.VOLUME, - media_player.Features.VOLUME_UP_DOWN, - media_player.Features.MUTE_TOGGLE, ], [], {}, From f2fa96a38951013a2c01c79a17a8dfc69a5af3b9 Mon Sep 17 00:00:00 2001 From: Albaintor Date: Fri, 9 May 2025 19:20:02 +0200 Subject: [PATCH 05/17] Fixed wrong volume step management --- src/setup_flow.py | 2 +- src/tv.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/setup_flow.py b/src/setup_flow.py index e718603..add7d37 100644 --- a/src/setup_flow.py +++ b/src/setup_flow.py @@ -486,7 +486,7 @@ async def handle_device_choice(msg: UserDataResponse) -> RequestUserInput | Setu choice = msg.input_values["choice"] _use_external_metadata = msg.input_values.get("external_metadata", "false") == "true" _use_chromecast = msg.input_values.get("chromecast", "false") == "true" - _volume_step = msg.input_values.get("volume_step", 10) + _volume_step = float(msg.input_values.get("volume_step", 10)) name = "" for discovered_tv in _discovered_android_tvs: diff --git a/src/tv.py b/src/tv.py index 23fc448..d64a8ca 100644 --- a/src/tv.py +++ b/src/tv.py @@ -964,7 +964,7 @@ async def volume_up(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: - self._chromecast.volume_up(delta=self._device_config.volume_step / 100) + self._chromecast.volume_up(delta=float(self._device_config.volume_step/100)) return ucapi.StatusCodes.OK except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) @@ -975,7 +975,7 @@ async def volume_down(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: - self._chromecast.volume_down(delta=self._device_config.volume_step / 100) + self._chromecast.volume_down(delta=float(self._device_config.volume_step/100)) return ucapi.StatusCodes.OK except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) From 7f5b0441465579162073ee4cdf7530e90eb2f84f Mon Sep 17 00:00:00 2001 From: Albaintor Date: Fri, 9 May 2025 19:27:01 +0200 Subject: [PATCH 06/17] Fixed wrong volume step management --- src/tv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tv.py b/src/tv.py index d64a8ca..c68b5f1 100644 --- a/src/tv.py +++ b/src/tv.py @@ -964,7 +964,7 @@ async def volume_up(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: - self._chromecast.volume_up(delta=float(self._device_config.volume_step/100)) + self._chromecast.volume_up(delta=float(self._device_config.volume_step / 100)) return ucapi.StatusCodes.OK except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) @@ -975,7 +975,7 @@ async def volume_down(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: - self._chromecast.volume_down(delta=float(self._device_config.volume_step/100)) + self._chromecast.volume_down(delta=float(self._device_config.volume_step / 100)) return ucapi.StatusCodes.OK except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) From af816ca2e913f5b429b4f62c7ff3eb892254aaeb Mon Sep 17 00:00:00 2001 From: Albaintor Date: Fri, 9 May 2025 20:09:05 +0200 Subject: [PATCH 07/17] Fixed volume control replaced by chromecast volume commands even if not activated --- src/driver.py | 21 +++++++++++---------- src/tv.py | 5 +++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/driver.py b/src/driver.py index 50ee0e4..101d791 100644 --- a/src/driver.py +++ b/src/driver.py @@ -154,16 +154,17 @@ async def media_player_cmd_handler( if params is None or "source" not in params: return ucapi.StatusCodes.BAD_REQUEST return await android_tv.select_source(params["source"]) - if cmd_id == media_player.Commands.VOLUME_UP: - return await android_tv.volume_up() - if cmd_id == media_player.Commands.VOLUME_DOWN: - return await android_tv.volume_down() - if cmd_id == media_player.Commands.MUTE_TOGGLE: - return await android_tv.volume_mute_toggle() - if cmd_id == media_player.Commands.VOLUME: - return await android_tv.volume_set(params.get("volume")) - if cmd_id == media_player.Commands.SEEK: - return await android_tv.media_seek(params.get("media_position", 0)) + if android_tv.device_config.use_chromecast: + if cmd_id == media_player.Commands.VOLUME_UP: + return await android_tv.volume_up() + if cmd_id == media_player.Commands.VOLUME_DOWN: + return await android_tv.volume_down() + if cmd_id == media_player.Commands.MUTE_TOGGLE: + return await android_tv.volume_mute_toggle() + if cmd_id == media_player.Commands.VOLUME: + return await android_tv.volume_set(params.get("volume")) + if cmd_id == media_player.Commands.SEEK: + return await android_tv.media_seek(params.get("media_position", 0)) return await android_tv.send_media_player_command(cmd_id) diff --git a/src/tv.py b/src/tv.py index c68b5f1..3fc390a 100644 --- a/src/tv.py +++ b/src/tv.py @@ -346,6 +346,11 @@ def is_on(self) -> bool | None: """Whether the Android TV is on or off. Returns None if not connected.""" return self._atv.is_on + @property + def device_config(self) -> AtvDevice: + """Return current device configuration.""" + return self._device_config + @property def media_title(self) -> str | None: """Return media title.""" From a454aa0395231a3b22b951c771317aa40f69042d Mon Sep 17 00:00:00 2001 From: Albaintor Date: Sat, 10 May 2025 08:50:08 +0200 Subject: [PATCH 08/17] Added 3 simple commands for volume control because Chromecast when enabled will replace volume up/down and mute commands --- config/profiles/default.json | 14 +++++++++++++- src/driver.py | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/config/profiles/default.json b/config/profiles/default.json index 7db6d9e..75af037 100644 --- a/config/profiles/default.json +++ b/config/profiles/default.json @@ -91,7 +91,10 @@ "KEYCODE_F9", "KEYCODE_F10", "KEYCODE_F11", - "KEYCODE_F12" + "KEYCODE_F12", + "KEY_VOLUME_UP", + "KEY_VOLUME_DOWN", + "KEY_VOLUME_MUTE" ], "command_map": { "CURSOR_ENTER_LONG": { @@ -105,6 +108,15 @@ "MENU_LONG": { "keycode": "MENU", "action": "LONG" + }, + "KEY_VOLUME_UP": { + "keycode": "VOLUME_UP" + }, + "KEY_VOLUME_DOWN": { + "keycode": "VOLUME_DOWN" + }, + "KEY_VOLUME_MUTE": { + "keycode": "VOLUME_MUTE" } } } diff --git a/src/driver.py b/src/driver.py index 101d791..89a78ca 100644 --- a/src/driver.py +++ b/src/driver.py @@ -155,6 +155,7 @@ async def media_player_cmd_handler( return ucapi.StatusCodes.BAD_REQUEST return await android_tv.select_source(params["source"]) if android_tv.device_config.use_chromecast: + # If chromecast disabled, default mapping will be used if cmd_id == media_player.Commands.VOLUME_UP: return await android_tv.volume_up() if cmd_id == media_player.Commands.VOLUME_DOWN: From b54674f0ad6f8d63ac78c2c07f528a0d1ee0b0c5 Mon Sep 17 00:00:00 2001 From: Albaintor Date: Sat, 10 May 2025 10:24:29 +0200 Subject: [PATCH 09/17] Fixed bug in volume set --- src/tv.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tv.py b/src/tv.py index 3fc390a..788274d 100644 --- a/src/tv.py +++ b/src/tv.py @@ -998,14 +998,14 @@ async def volume_mute_toggle(self) -> ucapi.StatusCodes: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) return ucapi.StatusCodes.BAD_REQUEST - async def volume_set(self, volume: float | None) -> ucapi.StatusCodes: + async def volume_set(self, volume: int | None) -> ucapi.StatusCodes: """Set volume.""" if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED if volume is None: return ucapi.StatusCodes.BAD_REQUEST try: - await self._chromecast.set_volume(volume / 100) + self._chromecast.set_volume(float(volume) / 100) return ucapi.StatusCodes.OK except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) From 1e333bd199a5f1d00fc7db7fb2190300b625e4b3 Mon Sep 17 00:00:00 2001 From: Albaintor Date: Sat, 10 May 2025 10:41:04 +0200 Subject: [PATCH 10/17] Added new simple commands to other profiles where volume up/down is supported (all profiles actually) --- config/profiles/DUNE HD HOMATICS.json | 14 +++++++++++++- config/profiles/Google_Chromecast.json | 14 +++++++++++++- config/profiles/NVIDIA_SHIELD.json | 14 +++++++++++++- config/profiles/TPV.json | 14 +++++++++++++- config/profiles/onn_Streaming_Device.json | 12 ++++++++++++ 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/config/profiles/DUNE HD HOMATICS.json b/config/profiles/DUNE HD HOMATICS.json index cd9e1eb..4df0a17 100644 --- a/config/profiles/DUNE HD HOMATICS.json +++ b/config/profiles/DUNE HD HOMATICS.json @@ -46,7 +46,10 @@ "PRIMEVIDEO", "PLAYSTORE", "FACTORYTEST", - "DISNEY" + "DISNEY", + "KEY_VOLUME_UP", + "KEY_VOLUME_DOWN", + "KEY_VOLUME_MUTE" ], "command_map": { "CURSOR_ENTER_LONG": { @@ -84,6 +87,15 @@ "DISNEY": { "keycode": 142, "action": "SHORT" + }, + "KEY_VOLUME_UP": { + "keycode": "VOLUME_UP" + }, + "KEY_VOLUME_DOWN": { + "keycode": "VOLUME_DOWN" + }, + "KEY_VOLUME_MUTE": { + "keycode": "VOLUME_MUTE" } } } diff --git a/config/profiles/Google_Chromecast.json b/config/profiles/Google_Chromecast.json index 0848010..33522cc 100644 --- a/config/profiles/Google_Chromecast.json +++ b/config/profiles/Google_Chromecast.json @@ -25,7 +25,10 @@ "search" ], "simple_commands": [ - "SCREENSAVER" + "SCREENSAVER", + "KEY_VOLUME_UP", + "KEY_VOLUME_DOWN", + "KEY_VOLUME_MUTE" ], "command_map": { "context_menu": { @@ -39,6 +42,15 @@ "SCREENSAVER": { "keycode": "BACK", "action": "DOUBLE_CLICK" + }, + "KEY_VOLUME_UP": { + "keycode": "VOLUME_UP" + }, + "KEY_VOLUME_DOWN": { + "keycode": "VOLUME_DOWN" + }, + "KEY_VOLUME_MUTE": { + "keycode": "VOLUME_MUTE" } } } diff --git a/config/profiles/NVIDIA_SHIELD.json b/config/profiles/NVIDIA_SHIELD.json index a97fde5..cc73b46 100644 --- a/config/profiles/NVIDIA_SHIELD.json +++ b/config/profiles/NVIDIA_SHIELD.json @@ -25,7 +25,10 @@ ], "simple_commands": [ "APPS", - "APP_SWITCHER" + "APP_SWITCHER", + "KEY_VOLUME_UP", + "KEY_VOLUME_DOWN", + "KEY_VOLUME_MUTE" ], "command_map": { "context_menu": { @@ -43,6 +46,15 @@ "APP_SWITCHER": { "keycode": "HOME", "action": "DOUBLE_CLICK" + }, + "KEY_VOLUME_UP": { + "keycode": "VOLUME_UP" + }, + "KEY_VOLUME_DOWN": { + "keycode": "VOLUME_DOWN" + }, + "KEY_VOLUME_MUTE": { + "keycode": "VOLUME_MUTE" } } } diff --git a/config/profiles/TPV.json b/config/profiles/TPV.json index f356fe2..8d06e3c 100644 --- a/config/profiles/TPV.json +++ b/config/profiles/TPV.json @@ -42,7 +42,10 @@ "HOME_LONG", "MENU_LONG", "ENTER", - "TELETEXT" + "TELETEXT", + "KEY_VOLUME_UP", + "KEY_VOLUME_DOWN", + "KEY_VOLUME_MUTE" ], "command_map": { "CURSOR_ENTER_LONG": { @@ -64,6 +67,15 @@ "TELETEXT": { "keycode": 233, "action": "SHORT" + }, + "KEY_VOLUME_UP": { + "keycode": "VOLUME_UP" + }, + "KEY_VOLUME_DOWN": { + "keycode": "VOLUME_DOWN" + }, + "KEY_VOLUME_MUTE": { + "keycode": "VOLUME_MUTE" } } } diff --git a/config/profiles/onn_Streaming_Device.json b/config/profiles/onn_Streaming_Device.json index 76bb17c..15d5723 100644 --- a/config/profiles/onn_Streaming_Device.json +++ b/config/profiles/onn_Streaming_Device.json @@ -25,6 +25,9 @@ "search" ], "simple_commands": [ + "KEY_VOLUME_UP", + "KEY_VOLUME_DOWN", + "KEY_VOLUME_MUTE" ], "command_map": { "context_menu": { @@ -34,6 +37,15 @@ "settings": { "keycode": "HOME", "action": "LONG" + }, + "KEY_VOLUME_UP": { + "keycode": "VOLUME_UP" + }, + "KEY_VOLUME_DOWN": { + "keycode": "VOLUME_DOWN" + }, + "KEY_VOLUME_MUTE": { + "keycode": "VOLUME_MUTE" } } } From f8dc641f8137bfbdcd3c65087c8dcfb6f8a8ea06 Mon Sep 17 00:00:00 2001 From: Albaintor Date: Sat, 10 May 2025 16:38:38 +0200 Subject: [PATCH 11/17] Fixed volume step not updated in reconfiguration and added traces --- src/setup_flow.py | 9 ++++++++- src/tv.py | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/setup_flow.py b/src/setup_flow.py index add7d37..d73d468 100644 --- a/src/setup_flow.py +++ b/src/setup_flow.py @@ -618,14 +618,21 @@ async def _handle_device_reconfigure( use_chromecast = msg.input_values.get("chromecast", "false") == "true" use_external_metadata = msg.input_values.get("external_metadata", "false") == "true" + volume_step = float(msg.input_values.get("volume_step", 10)) _LOG.debug("User has changed configuration") _reconfigured_device.use_chromecast = use_chromecast _reconfigured_device.use_external_metadata = use_external_metadata + _reconfigured_device.volume_step = volume_step config.devices.add_or_update(_reconfigured_device) # triggers ATV instance update await asyncio.sleep(1) - _LOG.info("Setup successfully completed for %s", _reconfigured_device.name) + _LOG.info( + "Setup successfully completed for %s (chromecast %s, external metadata %s, volume step %s)", + _reconfigured_device.name, + _reconfigured_device.use_chromecast, + _reconfigured_device.volume_step, + ) return SetupComplete() diff --git a/src/tv.py b/src/tv.py index 788274d..874b6e5 100644 --- a/src/tv.py +++ b/src/tv.py @@ -969,6 +969,12 @@ async def volume_up(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: + _LOG.debug( + "[%s] Volume up : current %s + step %s", + self.log_id, + self._chromecast.status.volume_level, + self._device_config.volume_step / 100, + ) self._chromecast.volume_up(delta=float(self._device_config.volume_step / 100)) return ucapi.StatusCodes.OK except PyChromecastError as ex: @@ -980,6 +986,12 @@ async def volume_down(self) -> ucapi.StatusCodes: if self._chromecast is None: return ucapi.StatusCodes.NOT_IMPLEMENTED try: + _LOG.debug( + "[%s] Volume down : current %s - step %s", + self.log_id, + self._chromecast.status.volume_level, + self._device_config.volume_step / 100, + ) self._chromecast.volume_down(delta=float(self._device_config.volume_step / 100)) return ucapi.StatusCodes.OK except PyChromecastError as ex: @@ -992,6 +1004,7 @@ async def volume_mute_toggle(self) -> ucapi.StatusCodes: return ucapi.StatusCodes.NOT_IMPLEMENTED try: self._muted = not self._muted + _LOG.debug("[%s] Mute toggle : %s", self.log_id, self._muted) self._chromecast.set_volume_muted(self._muted) return ucapi.StatusCodes.OK except PyChromecastError as ex: @@ -1005,6 +1018,7 @@ async def volume_set(self, volume: int | None) -> ucapi.StatusCodes: if volume is None: return ucapi.StatusCodes.BAD_REQUEST try: + _LOG.debug("[%s] Set volume : %s", self.log_id, volume) self._chromecast.set_volume(float(volume) / 100) return ucapi.StatusCodes.OK except PyChromecastError as ex: From bb06ebce1e08ba682f9809b17d4ba2a832d8af18 Mon Sep 17 00:00:00 2001 From: Albaintor Date: Sat, 10 May 2025 16:45:18 +0200 Subject: [PATCH 12/17] Fixed volume step not updated in reconfiguration and added traces --- src/setup_flow.py | 1 + src/tv.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/setup_flow.py b/src/setup_flow.py index d73d468..64b6d1e 100644 --- a/src/setup_flow.py +++ b/src/setup_flow.py @@ -631,6 +631,7 @@ async def _handle_device_reconfigure( "Setup successfully completed for %s (chromecast %s, external metadata %s, volume step %s)", _reconfigured_device.name, _reconfigured_device.use_chromecast, + _reconfigured_device.use_external_metadata, _reconfigured_device.volume_step, ) diff --git a/src/tv.py b/src/tv.py index 874b6e5..2c46425 100644 --- a/src/tv.py +++ b/src/tv.py @@ -970,7 +970,7 @@ async def volume_up(self) -> ucapi.StatusCodes: return ucapi.StatusCodes.NOT_IMPLEMENTED try: _LOG.debug( - "[%s] Volume up : current %s + step %s", + "[%s] Volume up : current %.2f + step %s", self.log_id, self._chromecast.status.volume_level, self._device_config.volume_step / 100, @@ -987,7 +987,7 @@ async def volume_down(self) -> ucapi.StatusCodes: return ucapi.StatusCodes.NOT_IMPLEMENTED try: _LOG.debug( - "[%s] Volume down : current %s - step %s", + "[%s] Volume down : current %.2f - step %s", self.log_id, self._chromecast.status.volume_level, self._device_config.volume_step / 100, @@ -1018,7 +1018,7 @@ async def volume_set(self, volume: int | None) -> ucapi.StatusCodes: if volume is None: return ucapi.StatusCodes.BAD_REQUEST try: - _LOG.debug("[%s] Set volume : %s", self.log_id, volume) + _LOG.debug("[%s] Set volume : %%.2f", self.log_id, float(volume) / 100) self._chromecast.set_volume(float(volume) / 100) return ucapi.StatusCodes.OK except PyChromecastError as ex: From 800e7be06ad153d776ef9cb686afe50661a669d4 Mon Sep 17 00:00:00 2001 From: Albaintor Date: Sat, 10 May 2025 16:47:37 +0200 Subject: [PATCH 13/17] Fix --- src/tv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tv.py b/src/tv.py index 2c46425..eb88cc7 100644 --- a/src/tv.py +++ b/src/tv.py @@ -1018,7 +1018,7 @@ async def volume_set(self, volume: int | None) -> ucapi.StatusCodes: if volume is None: return ucapi.StatusCodes.BAD_REQUEST try: - _LOG.debug("[%s] Set volume : %%.2f", self.log_id, float(volume) / 100) + _LOG.debug("[%s] Set volume : %.2f", self.log_id, float(volume)/100) self._chromecast.set_volume(float(volume) / 100) return ucapi.StatusCodes.OK except PyChromecastError as ex: From 932793b906a9100d56ef25edf65aaac17a058682 Mon Sep 17 00:00:00 2001 From: Albaintor Date: Sat, 10 May 2025 16:49:16 +0200 Subject: [PATCH 14/17] Linting --- src/tv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tv.py b/src/tv.py index eb88cc7..1cff0c0 100644 --- a/src/tv.py +++ b/src/tv.py @@ -1018,7 +1018,7 @@ async def volume_set(self, volume: int | None) -> ucapi.StatusCodes: if volume is None: return ucapi.StatusCodes.BAD_REQUEST try: - _LOG.debug("[%s] Set volume : %.2f", self.log_id, float(volume)/100) + _LOG.debug("[%s] Set volume : %.2f", self.log_id, float(volume) / 100) self._chromecast.set_volume(float(volume) / 100) return ucapi.StatusCodes.OK except PyChromecastError as ex: From 85af0c6a49abe288e6b510a5bd13821727d272e4 Mon Sep 17 00:00:00 2001 From: Albaintor Date: Mon, 12 May 2025 17:38:53 +0200 Subject: [PATCH 15/17] Reverted simple commands and added configurable option for volume through chromecast --- config/profiles/DUNE HD HOMATICS.json | 14 +--------- config/profiles/Google_Chromecast.json | 14 +--------- config/profiles/NVIDIA_SHIELD.json | 14 +--------- config/profiles/TPV.json | 14 +--------- config/profiles/default.json | 14 +--------- config/profiles/onn_Streaming_Device.json | 12 -------- src/config.py | 4 +++ src/driver.py | 12 ++++---- src/setup_flow.py | 34 ++++++++++++++++++++--- 9 files changed, 45 insertions(+), 87 deletions(-) diff --git a/config/profiles/DUNE HD HOMATICS.json b/config/profiles/DUNE HD HOMATICS.json index 4df0a17..cd9e1eb 100644 --- a/config/profiles/DUNE HD HOMATICS.json +++ b/config/profiles/DUNE HD HOMATICS.json @@ -46,10 +46,7 @@ "PRIMEVIDEO", "PLAYSTORE", "FACTORYTEST", - "DISNEY", - "KEY_VOLUME_UP", - "KEY_VOLUME_DOWN", - "KEY_VOLUME_MUTE" + "DISNEY" ], "command_map": { "CURSOR_ENTER_LONG": { @@ -87,15 +84,6 @@ "DISNEY": { "keycode": 142, "action": "SHORT" - }, - "KEY_VOLUME_UP": { - "keycode": "VOLUME_UP" - }, - "KEY_VOLUME_DOWN": { - "keycode": "VOLUME_DOWN" - }, - "KEY_VOLUME_MUTE": { - "keycode": "VOLUME_MUTE" } } } diff --git a/config/profiles/Google_Chromecast.json b/config/profiles/Google_Chromecast.json index 33522cc..0848010 100644 --- a/config/profiles/Google_Chromecast.json +++ b/config/profiles/Google_Chromecast.json @@ -25,10 +25,7 @@ "search" ], "simple_commands": [ - "SCREENSAVER", - "KEY_VOLUME_UP", - "KEY_VOLUME_DOWN", - "KEY_VOLUME_MUTE" + "SCREENSAVER" ], "command_map": { "context_menu": { @@ -42,15 +39,6 @@ "SCREENSAVER": { "keycode": "BACK", "action": "DOUBLE_CLICK" - }, - "KEY_VOLUME_UP": { - "keycode": "VOLUME_UP" - }, - "KEY_VOLUME_DOWN": { - "keycode": "VOLUME_DOWN" - }, - "KEY_VOLUME_MUTE": { - "keycode": "VOLUME_MUTE" } } } diff --git a/config/profiles/NVIDIA_SHIELD.json b/config/profiles/NVIDIA_SHIELD.json index cc73b46..a97fde5 100644 --- a/config/profiles/NVIDIA_SHIELD.json +++ b/config/profiles/NVIDIA_SHIELD.json @@ -25,10 +25,7 @@ ], "simple_commands": [ "APPS", - "APP_SWITCHER", - "KEY_VOLUME_UP", - "KEY_VOLUME_DOWN", - "KEY_VOLUME_MUTE" + "APP_SWITCHER" ], "command_map": { "context_menu": { @@ -46,15 +43,6 @@ "APP_SWITCHER": { "keycode": "HOME", "action": "DOUBLE_CLICK" - }, - "KEY_VOLUME_UP": { - "keycode": "VOLUME_UP" - }, - "KEY_VOLUME_DOWN": { - "keycode": "VOLUME_DOWN" - }, - "KEY_VOLUME_MUTE": { - "keycode": "VOLUME_MUTE" } } } diff --git a/config/profiles/TPV.json b/config/profiles/TPV.json index 8d06e3c..f356fe2 100644 --- a/config/profiles/TPV.json +++ b/config/profiles/TPV.json @@ -42,10 +42,7 @@ "HOME_LONG", "MENU_LONG", "ENTER", - "TELETEXT", - "KEY_VOLUME_UP", - "KEY_VOLUME_DOWN", - "KEY_VOLUME_MUTE" + "TELETEXT" ], "command_map": { "CURSOR_ENTER_LONG": { @@ -67,15 +64,6 @@ "TELETEXT": { "keycode": 233, "action": "SHORT" - }, - "KEY_VOLUME_UP": { - "keycode": "VOLUME_UP" - }, - "KEY_VOLUME_DOWN": { - "keycode": "VOLUME_DOWN" - }, - "KEY_VOLUME_MUTE": { - "keycode": "VOLUME_MUTE" } } } diff --git a/config/profiles/default.json b/config/profiles/default.json index 75af037..7db6d9e 100644 --- a/config/profiles/default.json +++ b/config/profiles/default.json @@ -91,10 +91,7 @@ "KEYCODE_F9", "KEYCODE_F10", "KEYCODE_F11", - "KEYCODE_F12", - "KEY_VOLUME_UP", - "KEY_VOLUME_DOWN", - "KEY_VOLUME_MUTE" + "KEYCODE_F12" ], "command_map": { "CURSOR_ENTER_LONG": { @@ -108,15 +105,6 @@ "MENU_LONG": { "keycode": "MENU", "action": "LONG" - }, - "KEY_VOLUME_UP": { - "keycode": "VOLUME_UP" - }, - "KEY_VOLUME_DOWN": { - "keycode": "VOLUME_DOWN" - }, - "KEY_VOLUME_MUTE": { - "keycode": "VOLUME_MUTE" } } } diff --git a/config/profiles/onn_Streaming_Device.json b/config/profiles/onn_Streaming_Device.json index 15d5723..76bb17c 100644 --- a/config/profiles/onn_Streaming_Device.json +++ b/config/profiles/onn_Streaming_Device.json @@ -25,9 +25,6 @@ "search" ], "simple_commands": [ - "KEY_VOLUME_UP", - "KEY_VOLUME_DOWN", - "KEY_VOLUME_MUTE" ], "command_map": { "context_menu": { @@ -37,15 +34,6 @@ "settings": { "keycode": "HOME", "action": "LONG" - }, - "KEY_VOLUME_UP": { - "keycode": "VOLUME_UP" - }, - "KEY_VOLUME_DOWN": { - "keycode": "VOLUME_DOWN" - }, - "KEY_VOLUME_MUTE": { - "keycode": "VOLUME_MUTE" } } } diff --git a/src/config.py b/src/config.py index d650754..0397091 100644 --- a/src/config.py +++ b/src/config.py @@ -38,6 +38,8 @@ class AtvDevice: """Enable External Metadata.""" use_chromecast: bool = False """Enable Chromecast features.""" + use_chromecast_volume: bool = False + """Enable volume driven by Chromecast protocol.""" volume_step: float = 10 """Volume step (1 to 100).""" @@ -135,6 +137,7 @@ def update(self, atv: AtvDevice) -> bool: item.auth_error = atv.auth_error item.use_external_metadata = atv.use_external_metadata item.use_chromecast = atv.use_chromecast + item.use_chromecast_volume = atv.use_chromecast_volume item.volume_step = atv.volume_step if atv.volume_step else 10 return self.store() return False @@ -239,6 +242,7 @@ def load(self) -> bool: item.get("auth_error", False), item.get("use_external_metadata", False), item.get("use_chromecast", False), + item.get("use_chromecast_volume", False), item.get("volume_step", 10), ) self._config.append(atv) diff --git a/src/driver.py b/src/driver.py index 89a78ca..c4ae4bf 100644 --- a/src/driver.py +++ b/src/driver.py @@ -154,18 +154,18 @@ async def media_player_cmd_handler( if params is None or "source" not in params: return ucapi.StatusCodes.BAD_REQUEST return await android_tv.select_source(params["source"]) - if android_tv.device_config.use_chromecast: - # If chromecast disabled, default mapping will be used + if android_tv.device_config.use_chromecast_volume: + # If use_chromecast_volume disabled, default mapping will be used if cmd_id == media_player.Commands.VOLUME_UP: return await android_tv.volume_up() if cmd_id == media_player.Commands.VOLUME_DOWN: return await android_tv.volume_down() if cmd_id == media_player.Commands.MUTE_TOGGLE: return await android_tv.volume_mute_toggle() - if cmd_id == media_player.Commands.VOLUME: - return await android_tv.volume_set(params.get("volume")) - if cmd_id == media_player.Commands.SEEK: - return await android_tv.media_seek(params.get("media_position", 0)) + if cmd_id == media_player.Commands.VOLUME: + return await android_tv.volume_set(params.get("volume")) + if cmd_id == media_player.Commands.SEEK: + return await android_tv.media_seek(params.get("media_position", 0)) return await android_tv.send_media_player_command(cmd_id) diff --git a/src/setup_flow.py b/src/setup_flow.py index 64b6d1e..e59fb26 100644 --- a/src/setup_flow.py +++ b/src/setup_flow.py @@ -48,6 +48,7 @@ class SetupSteps(IntEnum): _use_external_metadata: bool = False _reconfigured_device: AtvDevice | None = None _use_chromecast: bool = False +_use_chromecast_volume: bool = False _volume_step: float = 10 # TODO #9 externalize language texts @@ -298,6 +299,9 @@ async def handle_configuration_mode( _setup_step = SetupSteps.RECONFIGURE _reconfigured_device = selected_device use_chromecast = selected_device.use_chromecast if selected_device.use_chromecast else False + use_chromecast_volume = ( + selected_device.use_chromecast_volume if selected_device.use_chromecast_volume else False + ) use_external_metadata = ( selected_device.use_external_metadata if selected_device.use_external_metadata else False ) @@ -318,6 +322,14 @@ async def handle_configuration_mode( }, "field": {"checkbox": {"value": use_chromecast}}, }, + { + "id": "chromecast_volume", + "label": { + "en": "Set volume through Chromecast", + "fr": "Régler le volume par Chromecast", + }, + "field": {"checkbox": {"value": use_chromecast_volume}}, + }, { "id": "external_metadata", "label": { @@ -330,8 +342,8 @@ async def handle_configuration_mode( { "id": "volume_step", "label": { - "en": "Volume step in percent", - "fr": "Pallier de volume en pourcent", + "en": "Volume step in percent (Chromecast only)", + "fr": "Pallier de volume en pourcentage (Chromecast uniquement)", }, "field": {"number": {"value": volume_step, "min": 1, "max": 50, "steps": 1, "decimals": 0}}, }, @@ -447,6 +459,14 @@ async def _handle_discovery(msg: UserDataResponse) -> RequestUserInput | SetupEr }, "field": {"checkbox": {"value": False}}, }, + { + "id": "chromecast_volume", + "label": { + "en": "Set volume through Chromecast", + "fr": "Régler le volume par Chromecast", + }, + "field": {"checkbox": {"value": False}}, + }, { "id": "external_metadata", "label": { @@ -459,8 +479,8 @@ async def _handle_discovery(msg: UserDataResponse) -> RequestUserInput | SetupEr { "id": "volume_step", "label": { - "en": "Volume step in percent", - "fr": "Pallier de volume en pourcent", + "en": "Volume step in percent (Chromecast only)", + "fr": "Pallier de volume en pourcent (Chromecast uniquement)", }, "field": {"number": {"value": 10, "min": 1, "max": 50, "steps": 1, "decimals": 0}}, }, @@ -479,6 +499,7 @@ async def handle_device_choice(msg: UserDataResponse) -> RequestUserInput | Setu """ global _pairing_android_tv global _use_chromecast + global _use_chromecast_volume global _setup_step global _use_external_metadata global _volume_step @@ -486,6 +507,7 @@ async def handle_device_choice(msg: UserDataResponse) -> RequestUserInput | Setu choice = msg.input_values["choice"] _use_external_metadata = msg.input_values.get("external_metadata", "false") == "true" _use_chromecast = msg.input_values.get("chromecast", "false") == "true" + _use_chromecast_volume = msg.input_values.get("chromecast_volume", "false") == "true" _volume_step = float(msg.input_values.get("volume_step", 10)) name = "" @@ -504,6 +526,7 @@ async def handle_device_choice(msg: UserDataResponse) -> RequestUserInput | Setu id="", use_external_metadata=False, use_chromecast=False, + use_chromecast_volume=_use_chromecast_volume, volume_step=_volume_step, ), ) @@ -585,6 +608,7 @@ async def handle_user_data_pin(msg: UserDataResponse) -> SetupComplete | SetupEr address=_pairing_android_tv.address, use_external_metadata=_use_external_metadata, use_chromecast=_use_chromecast, + use_chromecast_volume=_use_chromecast_volume, manufacturer=device_info.get("manufacturer", ""), model=device_info.get("model", ""), volume_step=_volume_step, @@ -617,11 +641,13 @@ async def _handle_device_reconfigure( return SetupError() use_chromecast = msg.input_values.get("chromecast", "false") == "true" + use_chromecast_volume = msg.input_values.get("chromecast_volume", "false") == "true" use_external_metadata = msg.input_values.get("external_metadata", "false") == "true" volume_step = float(msg.input_values.get("volume_step", 10)) _LOG.debug("User has changed configuration") _reconfigured_device.use_chromecast = use_chromecast + _reconfigured_device.use_chromecast_volume = use_chromecast_volume _reconfigured_device.use_external_metadata = use_external_metadata _reconfigured_device.volume_step = volume_step From 4eafd976539eaea5f8bd0c3e6fb2f6ffd7d373bf Mon Sep 17 00:00:00 2001 From: Albaintor Date: Mon, 12 May 2025 19:08:18 +0200 Subject: [PATCH 16/17] Last changes requested --- .idea/runConfigurations/check_black.xml | 35 ++++++++++ src/driver.py | 14 ++-- src/tv.py | 85 ++++++++++++++----------- 3 files changed, 88 insertions(+), 46 deletions(-) create mode 100644 .idea/runConfigurations/check_black.xml diff --git a/.idea/runConfigurations/check_black.xml b/.idea/runConfigurations/check_black.xml new file mode 100644 index 0000000..5925ed7 --- /dev/null +++ b/.idea/runConfigurations/check_black.xml @@ -0,0 +1,35 @@ + + + + + \ No newline at end of file diff --git a/src/driver.py b/src/driver.py index c4ae4bf..50ee0e4 100644 --- a/src/driver.py +++ b/src/driver.py @@ -154,14 +154,12 @@ async def media_player_cmd_handler( if params is None or "source" not in params: return ucapi.StatusCodes.BAD_REQUEST return await android_tv.select_source(params["source"]) - if android_tv.device_config.use_chromecast_volume: - # If use_chromecast_volume disabled, default mapping will be used - if cmd_id == media_player.Commands.VOLUME_UP: - return await android_tv.volume_up() - if cmd_id == media_player.Commands.VOLUME_DOWN: - return await android_tv.volume_down() - if cmd_id == media_player.Commands.MUTE_TOGGLE: - return await android_tv.volume_mute_toggle() + if cmd_id == media_player.Commands.VOLUME_UP: + return await android_tv.volume_up() + if cmd_id == media_player.Commands.VOLUME_DOWN: + return await android_tv.volume_down() + if cmd_id == media_player.Commands.MUTE_TOGGLE: + return await android_tv.volume_mute_toggle() if cmd_id == media_player.Commands.VOLUME: return await android_tv.volume_set(params.get("volume")) if cmd_id == media_player.Commands.SEEK: diff --git a/src/tv.py b/src/tv.py index 1cff0c0..057653b 100644 --- a/src/tv.py +++ b/src/tv.py @@ -966,50 +966,59 @@ async def media_seek(self, position: float) -> ucapi.StatusCodes: async def volume_up(self) -> ucapi.StatusCodes: """Change volume up.""" - if self._chromecast is None: - return ucapi.StatusCodes.NOT_IMPLEMENTED - try: - _LOG.debug( - "[%s] Volume up : current %.2f + step %s", - self.log_id, - self._chromecast.status.volume_level, - self._device_config.volume_step / 100, - ) - self._chromecast.volume_up(delta=float(self._device_config.volume_step / 100)) - return ucapi.StatusCodes.OK - except PyChromecastError as ex: - _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) - return ucapi.StatusCodes.BAD_REQUEST + if self.device_config.use_chromecast and self.device_config.use_chromecast_volume: + if self._chromecast is None: + return ucapi.StatusCodes.NOT_IMPLEMENTED + try: + _LOG.debug( + "[%s] Volume up : current %.2f + step %s", + self.log_id, + self._chromecast.status.volume_level, + self._device_config.volume_step / 100, + ) + self._chromecast.volume_up(delta=float(self._device_config.volume_step / 100)) + return ucapi.StatusCodes.OK + except PyChromecastError as ex: + _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) + return ucapi.StatusCodes.BAD_REQUEST + else: + return await self.send_media_player_command(media_player.Commands.VOLUME_UP) async def volume_down(self) -> ucapi.StatusCodes: """Change volume down.""" - if self._chromecast is None: - return ucapi.StatusCodes.NOT_IMPLEMENTED - try: - _LOG.debug( - "[%s] Volume down : current %.2f - step %s", - self.log_id, - self._chromecast.status.volume_level, - self._device_config.volume_step / 100, - ) - self._chromecast.volume_down(delta=float(self._device_config.volume_step / 100)) - return ucapi.StatusCodes.OK - except PyChromecastError as ex: - _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) - return ucapi.StatusCodes.BAD_REQUEST + if self.device_config.use_chromecast and self.device_config.use_chromecast_volume: + if self._chromecast is None: + return ucapi.StatusCodes.NOT_IMPLEMENTED + try: + _LOG.debug( + "[%s] Volume down : current %.2f - step %s", + self.log_id, + self._chromecast.status.volume_level, + self._device_config.volume_step / 100, + ) + self._chromecast.volume_down(delta=float(self._device_config.volume_step / 100)) + return ucapi.StatusCodes.OK + except PyChromecastError as ex: + _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) + return ucapi.StatusCodes.BAD_REQUEST + else: + return await self.send_media_player_command(media_player.Commands.VOLUME_DOWN) async def volume_mute_toggle(self) -> ucapi.StatusCodes: """Mute toggle.""" - if self._chromecast is None: - return ucapi.StatusCodes.NOT_IMPLEMENTED - try: - self._muted = not self._muted - _LOG.debug("[%s] Mute toggle : %s", self.log_id, self._muted) - self._chromecast.set_volume_muted(self._muted) - return ucapi.StatusCodes.OK - except PyChromecastError as ex: - _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) - return ucapi.StatusCodes.BAD_REQUEST + if self.device_config.use_chromecast and self.device_config.use_chromecast_volume: + if self._chromecast is None: + return ucapi.StatusCodes.NOT_IMPLEMENTED + try: + self._muted = not self._muted + _LOG.debug("[%s] Mute toggle : %s", self.log_id, self._muted) + self._chromecast.set_volume_muted(self._muted) + return ucapi.StatusCodes.OK + except PyChromecastError as ex: + _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) + return ucapi.StatusCodes.BAD_REQUEST + else: + return await self.send_media_player_command(media_player.Commands.MUTE_TOGGLE) async def volume_set(self, volume: int | None) -> ucapi.StatusCodes: """Set volume.""" From ef2d924e4c6888f3d0586f171294a7f305d0954f Mon Sep 17 00:00:00 2001 From: Albaintor Date: Mon, 12 May 2025 19:10:12 +0200 Subject: [PATCH 17/17] Linting --- src/tv.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/tv.py b/src/tv.py index 057653b..af46c7b 100644 --- a/src/tv.py +++ b/src/tv.py @@ -981,8 +981,7 @@ async def volume_up(self) -> ucapi.StatusCodes: except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) return ucapi.StatusCodes.BAD_REQUEST - else: - return await self.send_media_player_command(media_player.Commands.VOLUME_UP) + return await self.send_media_player_command(media_player.Commands.VOLUME_UP) async def volume_down(self) -> ucapi.StatusCodes: """Change volume down.""" @@ -1001,8 +1000,7 @@ async def volume_down(self) -> ucapi.StatusCodes: except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) return ucapi.StatusCodes.BAD_REQUEST - else: - return await self.send_media_player_command(media_player.Commands.VOLUME_DOWN) + return await self.send_media_player_command(media_player.Commands.VOLUME_DOWN) async def volume_mute_toggle(self) -> ucapi.StatusCodes: """Mute toggle.""" @@ -1017,8 +1015,7 @@ async def volume_mute_toggle(self) -> ucapi.StatusCodes: except PyChromecastError as ex: _LOG.error("[%s] Chromecast error sending command : %s", self.log_id, ex) return ucapi.StatusCodes.BAD_REQUEST - else: - return await self.send_media_player_command(media_player.Commands.MUTE_TOGGLE) + return await self.send_media_player_command(media_player.Commands.MUTE_TOGGLE) async def volume_set(self, volume: int | None) -> ucapi.StatusCodes: """Set volume."""