From fc4ccfe65fe444f950918acfe38c584355c69210 Mon Sep 17 00:00:00 2001 From: MattMorgan <48740594+spycle@users.noreply.github.com> Date: Thu, 3 Jul 2025 21:37:41 +0100 Subject: [PATCH 1/7] Update README.md --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d8597e0..2ae0851 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,21 @@ -# TuneBlade Controller -Home Assistant custom integration for controlling AirPlay devices connected to a TuneBlade server. +TuneBlade is a simple Windows tray utility that lets you stream system-wide audio to AirPort Express, Apple TV, AirPlay enabled speakers and HiFi receivers, and to AirPlay audio receiving applications such as ShairPort, XBMC/Kodi. Connect an Alexa/Google/other speaker to the host and output via AirPlay. + +# TuneBlade Remote +Home Assistant custom integration for controlling AirPlay devices via TuneBlade Remote. ## Setup +Install TuneBlade on a Windows device. +Ensure Romote Control is set to on in the TuneBlade settings. + Search HACS for TuneBlade and download. Installation is then via the Integrations Page of Home Assistant. -Ensure Romote Control is on in TuneBlade settings. -Restart TuneBlade to ensure it's broadcasting. +Restart TuneBlade to ensure it's broadcasting (seems to stop advertising Bonjour after a while). TuneBlade should be automatically discovered however, manually configuration is possible with the host (without http://) and the port. The integration will add a simple switch for turning the connection on/off, and a media player which can be used in the same way but can also control volume (from TuneBlade). ## Master Volume Control -The Master control setting must be enabled in TuneBlade settings. +The Master control setting must be enabled in TuneBlade settings. A device named Master will then also be available. From a785db4e0a769fd85dc03d40eb3ffbc7ca2ec2bb Mon Sep 17 00:00:00 2001 From: MattMorgan <48740594+spycle@users.noreply.github.com> Date: Thu, 3 Jul 2025 21:38:07 +0100 Subject: [PATCH 2/7] Update manifest.json --- custom_components/tuneblade/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/tuneblade/manifest.json b/custom_components/tuneblade/manifest.json index 36c4f92..4a96879 100644 --- a/custom_components/tuneblade/manifest.json +++ b/custom_components/tuneblade/manifest.json @@ -13,7 +13,7 @@ "mqtt": [], "requirements": [], "usb": [], - "version": "2025.06.5", + "version": "2025.06.6", "zeroconf": [ { "type": "_http._tcp.local.", From 73ddec9e95399e7756483ddb1aa99e1131ed9138 Mon Sep 17 00:00:00 2001 From: MattMorgan <48740594+spycle@users.noreply.github.com> Date: Thu, 3 Jul 2025 21:38:25 +0100 Subject: [PATCH 3/7] Update const.py --- custom_components/tuneblade/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/tuneblade/const.py b/custom_components/tuneblade/const.py index a1a800b..7cd4d4c 100644 --- a/custom_components/tuneblade/const.py +++ b/custom_components/tuneblade/const.py @@ -4,7 +4,7 @@ NAME = "TuneBlade" DOMAIN = "tuneblade" DOMAIN_DATA = f"{DOMAIN}_data" -VERSION = "2025.06.5" +VERSION = "2025.06.6" ISSUE_URL = "https://github.com/spycle/tuneblade/issues" # Icons From ee4b2a817b316976cdcf7f3acc85935bbe29ec21 Mon Sep 17 00:00:00 2001 From: MattMorgan <48740594+spycle@users.noreply.github.com> Date: Thu, 3 Jul 2025 21:38:48 +0100 Subject: [PATCH 4/7] Update config_flow.py --- custom_components/tuneblade/config_flow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/tuneblade/config_flow.py b/custom_components/tuneblade/config_flow.py index fb6cb7b..5dcb3c3 100644 --- a/custom_components/tuneblade/config_flow.py +++ b/custom_components/tuneblade/config_flow.py @@ -43,8 +43,8 @@ async def async_step_user(self, user_input: dict[str, Any] | None = None) -> Flo data_schema = vol.Schema( { - vol.Required("host"): str, - vol.Required("port", default=443): int, + vol.Required("host", default='localhost'): str, + vol.Required("port", default=54412): int, vol.Optional("name", default="TuneBlade"): str, } ) From d763cf698b1e800517af95cdc8a5870ccca38f37 Mon Sep 17 00:00:00 2001 From: MattMorgan <48740594+spycle@users.noreply.github.com> Date: Thu, 3 Jul 2025 21:39:02 +0100 Subject: [PATCH 5/7] Update media_player.py --- custom_components/tuneblade/media_player.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/custom_components/tuneblade/media_player.py b/custom_components/tuneblade/media_player.py index d36f3c7..063f24c 100644 --- a/custom_components/tuneblade/media_player.py +++ b/custom_components/tuneblade/media_player.py @@ -51,8 +51,8 @@ class TuneBladeHubMediaPlayer(CoordinatorEntity, MediaPlayerEntity): def __init__(self, coordinator): super().__init__(coordinator) self.device_id = "MASTER" - self._attr_name = "TuneBlade Master" - self._attr_unique_id = "tuneblade_master" + self._attr_name = "Master" + self._attr_unique_id = "tuneblade_master_media_player" self._attr_volume_level = None self._attr_state = MediaPlayerState.OFF self._attr_supported_features = ( @@ -125,7 +125,7 @@ def extra_state_attributes(self): @property def device_info(self): return { - "identifiers": {(DOMAIN, self.device_id)}, + "identifiers": {(DOMAIN, "MASTER")}, "name": self._attr_name, "manufacturer": "TuneBlade", "entry_type": "service", # Mark as hub/service device From 0ffb247437b9d50bde73120371e1098a15ae83ca Mon Sep 17 00:00:00 2001 From: MattMorgan <48740594+spycle@users.noreply.github.com> Date: Thu, 3 Jul 2025 21:39:13 +0100 Subject: [PATCH 6/7] Update switch.py --- custom_components/tuneblade/switch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/tuneblade/switch.py b/custom_components/tuneblade/switch.py index fe9ac31..0452454 100644 --- a/custom_components/tuneblade/switch.py +++ b/custom_components/tuneblade/switch.py @@ -102,7 +102,7 @@ class TuneBladeHubSwitch(CoordinatorEntity, SwitchEntity): def __init__(self, coordinator): super().__init__(coordinator) - self._attr_name = "TuneBlade Master Switch" + self._attr_name = "Master" self._attr_unique_id = "tuneblade_master_switch" @property @@ -134,7 +134,7 @@ def available(self): def device_info(self): return { "identifiers": {(DOMAIN, "MASTER")}, - "name": "TuneBlade Hub", + "name": self._attr_name, "manufacturer": "TuneBlade", "entry_type": "service", } From a3c0e9a3cc80d4411ce850fe08421251ed440ae2 Mon Sep 17 00:00:00 2001 From: MattMorgan <48740594+spycle@users.noreply.github.com> Date: Thu, 3 Jul 2025 21:39:29 +0100 Subject: [PATCH 7/7] Update en.json --- custom_components/tuneblade/translations/en.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/custom_components/tuneblade/translations/en.json b/custom_components/tuneblade/translations/en.json index 4cf41ff..ed1067d 100644 --- a/custom_components/tuneblade/translations/en.json +++ b/custom_components/tuneblade/translations/en.json @@ -6,12 +6,13 @@ "description": "TuneBlade Remote", "data": { "host": "Host", - "port": "Port" + "port": "Port", + "name": "Name" } }, "confirm": { - "title": "Confirm TuneBlade Device", - "description": "TuneBlade was discovered at {ip}. Do you want to add it?" + "title": "Confirm TuneBlade Remote", + "description": "TuneBlade was discovered at {ip}. Do you want to add {name}?" } }, "abort": {