From: Lorenzo Imbastari Date: Tue, 24 Feb 2026 08:25:31 +0000 (+0100) Subject: Updated Artwork handling on AriaCast Receiver (#3226) X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=e430089a4b890101a026eabe7d406148f21680fd;p=music-assistant-server.git Updated Artwork handling on AriaCast Receiver (#3226) * Add AriaCast Receiver plugin for Music Assistant - Implemented AriaCast Receiver plugin to stream audio from Android devices to Music Assistant players. - Added README.md with features, installation, configuration, and usage instructions. - Created configuration classes for audio and server settings. - Developed metadata handling for AriaCast streams. - Implemented UDP discovery and WebSocket server for audio and metadata streaming. - Added helper functions for local IP retrieval and artwork downloading. - Included SVG icon for the plugin. - Updated manifest.json with documentation link and requirements. * Update README to simplify installation instructions Removed installation instructions and updated configuration step for clarity. * fixed mypy and pre-commit problems for my provider * Delete music_assistant/providers/ariacast_receiver/README.md * fixed pre-commit problems x2 * fixed icon * Merge remote-tracking branch 'origin/dev' into dev * Fixed Metadata and media controls after refactoring * copilot notes addressing * Addressing more copilot notes * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Addressing last notes * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: address code review feedback for ariacast_receiver * fix(ariacast): add playback ready event for audio/player sync - Add _playback_ready event to coordinate audio handler and player stream - Audio handler waits up to 2s for player to become ready after starting playback - get_audio_stream signals ready when it starts consuming frames - Clear ready state on cleanup in _clear_active_player and stream end This reduces audio frame loss during player setup by synchronizing the audio receiver with the player's readiness to consume frames. * Add multi-platform AriaCast receiver binaries (darwin/linux amd64/arm64/arm) * renamed receiver name * no redownload if same artwork Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/manifest.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: use shared http_session for ariacast websocket connection * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix in previous copilot commit messing up the way pipe was read (no loop) * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fixel last comments * Change multi_instance setting to false * Addressed latest comments after review - Switched from pipe to stdout - Dropped linux arm - Moved _get_binary_path() to helpers.py * Implemented stderr logging, robust WebSocket connection retries, improved artwork handling, and player switching control. Updated Manifest * Fix after PlayerController renamed all to all_players and players.get to get_player() * Update music_assistant/providers/ariacast_receiver/__init__.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update music_assistant/providers/ariacast_receiver/__init__.py Added suggested track change comments Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update documentation URL in manifest.json * Added README for the binary of AriaCast Receiver * updated receiver for artwork * final fixes * addressed copilot comment --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- diff --git a/music_assistant/providers/ariacast_receiver/__init__.py b/music_assistant/providers/ariacast_receiver/__init__.py index 3ef17ac6..75447106 100644 --- a/music_assistant/providers/ariacast_receiver/__init__.py +++ b/music_assistant/providers/ariacast_receiver/__init__.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio +import hashlib import time from collections import deque from collections.abc import AsyncGenerator @@ -262,13 +263,17 @@ class AriaCastBridge(PluginProvider): if not artwork_url: return + # The binary often sends a static local URL (like http://127.0.0.1/image/artwork). + # We combine it with the track title to detect actual song/artwork changes. + current_identifier = f"{artwork_url}_{meta.title}_{meta.artist}" + last_artwork_identifier = getattr(self, "_last_artwork_identifier", None) - if artwork_url != last_artwork_identifier: + if current_identifier != last_artwork_identifier: # New artwork detected self.logger.debug( - "New artwork detected: %s (was: %s)", artwork_url, last_artwork_identifier + "New artwork detected for track: %s (was: %s)", meta.title, last_artwork_identifier ) - self._last_artwork_identifier = artwork_url + self._last_artwork_identifier = current_identifier # Clear old artwork data to prevent serving stale image self._artwork_bytes = None if meta: @@ -402,18 +407,18 @@ class AriaCastBridge(PluginProvider): self.logger.info( "Artwork downloaded successfully, size: %d bytes", len(img_data) ) - + # Use a content-derived hash to prevent unbounded cache growth + img_hash = hashlib.md5(img_data).hexdigest()[:8] image = MediaItemImage( type=ImageType.THUMB, - path="artwork", + path=f"artwork_{img_hash}", provider=self.instance_id, remotely_accessible=False, ) - base_url = self.mass.metadata.get_image_url(image) if self._source_details.metadata: self._source_details.metadata.image_url = ( - f"{base_url}&t={self._artwork_timestamp}" + self.mass.metadata.get_image_url(image) ) if self._source_details.in_use_by: @@ -425,7 +430,7 @@ class AriaCastBridge(PluginProvider): async def resolve_image(self, path: str) -> bytes: """Return raw image bytes to Music Assistant.""" - if path == "artwork" and self._artwork_bytes: + if path.startswith("artwork") and self._artwork_bytes: return self._artwork_bytes return b"" diff --git a/music_assistant/providers/ariacast_receiver/bin/ariacast_darwin_amd64 b/music_assistant/providers/ariacast_receiver/bin/ariacast_darwin_amd64 index cccbda90..575651e6 100755 Binary files a/music_assistant/providers/ariacast_receiver/bin/ariacast_darwin_amd64 and b/music_assistant/providers/ariacast_receiver/bin/ariacast_darwin_amd64 differ diff --git a/music_assistant/providers/ariacast_receiver/bin/ariacast_darwin_arm64 b/music_assistant/providers/ariacast_receiver/bin/ariacast_darwin_arm64 index 89541d07..833380f5 100755 Binary files a/music_assistant/providers/ariacast_receiver/bin/ariacast_darwin_arm64 and b/music_assistant/providers/ariacast_receiver/bin/ariacast_darwin_arm64 differ diff --git a/music_assistant/providers/ariacast_receiver/bin/ariacast_linux_amd64 b/music_assistant/providers/ariacast_receiver/bin/ariacast_linux_amd64 index 26df90a5..a32e72e3 100755 Binary files a/music_assistant/providers/ariacast_receiver/bin/ariacast_linux_amd64 and b/music_assistant/providers/ariacast_receiver/bin/ariacast_linux_amd64 differ diff --git a/music_assistant/providers/ariacast_receiver/bin/ariacast_linux_arm64 b/music_assistant/providers/ariacast_receiver/bin/ariacast_linux_arm64 index f8f7d2ec..ec86be02 100755 Binary files a/music_assistant/providers/ariacast_receiver/bin/ariacast_linux_arm64 and b/music_assistant/providers/ariacast_receiver/bin/ariacast_linux_arm64 differ