Add Alexa player provider (#2210)
authorSameer Alam <31905246+alams154@users.noreply.github.com>
Tue, 24 Jun 2025 11:14:49 +0000 (06:14 -0500)
committerGitHub <noreply@github.com>
Tue, 24 Jun 2025 11:14:49 +0000 (13:14 +0200)
music_assistant/providers/alexa/__init__.py [new file with mode: 0644]
music_assistant/providers/alexa/icon.svg [new file with mode: 0644]
music_assistant/providers/alexa/icon_monochrome.svg [new file with mode: 0644]
music_assistant/providers/alexa/manifest.json [new file with mode: 0644]
requirements_all.txt

diff --git a/music_assistant/providers/alexa/__init__.py b/music_assistant/providers/alexa/__init__.py
new file mode 100644 (file)
index 0000000..1fe0ae2
--- /dev/null
@@ -0,0 +1,378 @@
+"""Alexa player provider support for Music Assistant."""
+
+from __future__ import annotations
+
+import asyncio
+import logging
+import os
+import time
+from typing import TYPE_CHECKING, Any
+
+import aiohttp
+from aiohttp import web
+from alexapy import AlexaAPI, AlexaLogin, AlexaProxy
+from music_assistant_models.config_entries import ConfigEntry
+from music_assistant_models.enums import (
+    ConfigEntryType,
+    PlayerFeature,
+    PlayerState,
+    PlayerType,
+    ProviderFeature,
+)
+from music_assistant_models.errors import LoginFailed
+from music_assistant_models.player import DeviceInfo, Player, PlayerMedia
+
+from music_assistant.constants import (
+    CONF_ENTRY_CROSSFADE,
+    CONF_ENTRY_CROSSFADE_DURATION,
+    CONF_ENTRY_FLOW_MODE_ENFORCED,
+    CONF_ENTRY_HTTP_PROFILE,
+    CONF_PASSWORD,
+    CONF_USERNAME,
+)
+from music_assistant.helpers.auth import AuthenticationHelper
+from music_assistant.models.player_provider import PlayerProvider
+
+_LOGGER = logging.getLogger(__name__)
+
+if TYPE_CHECKING:
+    from music_assistant_models.config_entries import (
+        ConfigValueType,
+        ProviderConfig,
+    )
+    from music_assistant_models.provider import ProviderManifest
+
+    from music_assistant.mass import MusicAssistant
+    from music_assistant.models import ProviderInstanceType
+
+CONF_URL = "url"
+CONF_ACTION_AUTH = "auth"
+CONF_AUTH_TOKEN = "token"
+
+SUPPORTED_FEATURES: set[ProviderFeature] = set()
+
+
+async def setup(
+    mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
+) -> ProviderInstanceType:
+    """Initialize provider(instance) with given configuration."""
+    return AlexaProvider(mass, manifest, config)
+
+
+async def get_config_entries(
+    mass: MusicAssistant,
+    instance_id: str | None = None,
+    action: str | None = None,
+    values: dict[str, ConfigValueType] | None = None,
+) -> tuple[ConfigEntry, ...]:
+    """
+    Return Config entries to setup this provider.
+
+    instance_id: id of an existing provider instance (None if new instance setup).
+    action: [optional] action key called from config entries UI.
+    values: the (intermediate) raw values for config entries sent with the action.
+    """
+    # ruff: noqa: ARG001
+    # config flow auth action/step (authenticate button clicked)
+    if action == CONF_ACTION_AUTH and values:
+        async with AuthenticationHelper(mass, str(values["session_id"])) as auth_helper:
+            login = AlexaLogin(
+                url=str(values[CONF_URL]),
+                email=str(values[CONF_USERNAME]),
+                password=str(values[CONF_PASSWORD]),
+                outputpath=lambda x: x,
+            )
+
+            # --- Proxy authentication logic using AlexaProxy ---
+            # Build the proxy path and URL
+            proxy_path = "/alexa/auth/proxy/"
+            post_path = "/alexa/auth/proxy/ap/signin"
+            base_url = mass.webserver.base_url.rstrip("/")
+            proxy_url = f"{base_url}{proxy_path}"
+
+            # Create AlexaProxy instance
+            proxy = AlexaProxy(login, proxy_url)
+
+            # Handler that delegates to AlexaProxy's all_handler
+            async def proxy_handler(request: web.Request) -> Any:
+                response = await proxy.all_handler(request)
+                if "Successfully logged in" in getattr(response, "text", ""):
+                    # Notify the callback URL
+                    async with aiohttp.ClientSession() as session:
+                        await session.get(auth_helper.callback_url)
+                    return web.Response(
+                        text="""
+                        <html>
+                            <body>
+                                <h2>Login successful!</h2>
+                                <p>You may now close this window.</p>
+                            </body>
+                        </html>
+                        """,
+                        content_type="text/html",
+                    )
+                return response
+
+            # Register GET for the base proxy path
+            mass.webserver.register_dynamic_route(proxy_path, proxy_handler, "GET")
+            # Register POST for the specific signin helper path
+            mass.webserver.register_dynamic_route(post_path, proxy_handler, "POST")
+
+            try:
+                await auth_helper.authenticate(proxy_url, timeout=300)
+                await save_cookie(login, str(values[CONF_USERNAME]), mass)
+            except KeyError:
+                # no URL param was found so user probably cancelled the auth
+                pass
+            except Exception as error:
+                raise LoginFailed(f"Failed to authenticate with Amazon '{error}'.")
+            finally:
+                mass.webserver.unregister_dynamic_route(proxy_path)
+                mass.webserver.unregister_dynamic_route(post_path)
+
+    return (
+        ConfigEntry(
+            key=CONF_URL,
+            type=ConfigEntryType.STRING,
+            label="URL",
+            required=True,
+            default_value="amazon.com",
+        ),
+        ConfigEntry(
+            key=CONF_USERNAME,
+            type=ConfigEntryType.STRING,
+            label="E-Mail",
+            required=True,
+        ),
+        ConfigEntry(
+            key=CONF_PASSWORD,
+            type=ConfigEntryType.SECURE_STRING,
+            label="Password",
+            required=True,
+        ),
+        ConfigEntry(
+            key=CONF_ACTION_AUTH,
+            type=ConfigEntryType.ACTION,
+            label="Authenticate with Amazon",
+            description="Click to start the authentication process.",
+            action=CONF_ACTION_AUTH,
+            depends_on=CONF_URL,
+        ),
+    )
+
+
+async def save_cookie(login: AlexaLogin, username: str, mass: MusicAssistant) -> None:
+    """Save the cookie file for the Alexa login."""
+    if login._session is None:
+        _LOGGER.error("AlexaLogin session is not initialized.")
+        return
+
+    cookie_dir = os.path.join(mass.storage_path, ".alexa")
+    await asyncio.to_thread(os.makedirs, cookie_dir, exist_ok=True)
+    cookie_path = os.path.join(cookie_dir, f"alexa_media.{username}.pickle")
+    login._cookiefile = [login._outputpath(cookie_path)]
+    if (login._cookiefile[0]) and await asyncio.to_thread(os.path.exists, login._cookiefile[0]):
+        _LOGGER.debug("Removing outdated cookiefile %s", login._cookiefile[0])
+        await delete_cookie(login._cookiefile[0])
+    cookie_jar = login._session.cookie_jar
+    assert isinstance(cookie_jar, aiohttp.CookieJar)
+    if login._debug:
+        _LOGGER.debug("Saving cookie to %s", login._cookiefile[0])
+    try:
+        await asyncio.to_thread(cookie_jar.save, login._cookiefile[0])
+    except (OSError, EOFError, TypeError, AttributeError):
+        _LOGGER.debug("Error saving pickled cookie to %s", login._cookiefile[0])
+
+
+async def delete_cookie(cookiefile: str) -> None:
+    """Delete the specified cookie file."""
+    if await asyncio.to_thread(os.path.exists, cookiefile):
+        try:
+            await asyncio.to_thread(os.remove, cookiefile)
+            _LOGGER.debug("Deleted cookie file: %s", cookiefile)
+        except OSError as e:
+            _LOGGER.error("Failed to delete cookie file %s: %s", cookiefile, e)
+    else:
+        _LOGGER.debug("Cookie file %s does not exist, nothing to delete.", cookiefile)
+
+
+class AlexaProvider(PlayerProvider):
+    """Implementation of an Alexa Device Provider."""
+
+    class AlexaDevice:
+        """Representation of an Alexa Device."""
+
+        _device_type: str
+        device_serial_number: str
+        _device_family: str
+        _cluster_members: str
+        _locale: str
+
+    login: AlexaLogin
+    devices: dict[str, AlexaProvider.AlexaDevice]
+
+    @property
+    def supported_features(self) -> set[ProviderFeature]:
+        """Return the features supported by this Provider."""
+        return SUPPORTED_FEATURES
+
+    def __init__(
+        self, mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
+    ) -> None:
+        """Initialize AlexaProvider and its device mapping."""
+        super().__init__(mass, manifest, config)
+        self.devices = {}
+
+    async def loaded_in_mass(self) -> None:
+        """Call after the provider has been loaded."""
+        self.login = AlexaLogin(
+            url=str(self.config.get_value(CONF_URL)),
+            email=str(self.config.get_value(CONF_USERNAME)),
+            password=str(self.config.get_value(CONF_PASSWORD)),
+            outputpath=lambda x: x,
+        )
+
+        cookie_dir = os.path.join(self.mass.storage_path, ".alexa")
+        await asyncio.to_thread(os.makedirs, cookie_dir, exist_ok=True)
+        cookie_path = os.path.join(
+            cookie_dir, f"alexa_media.{self.config.get_value(CONF_USERNAME)}.pickle"
+        )
+        self.login._cookiefile = [self.login._outputpath(cookie_path)]
+
+        await self.login.login(cookies=await self.login.load_cookie())
+
+        devices = await AlexaAPI.get_devices(self.login)
+
+        if devices is None:
+            return
+
+        for device in devices:
+            if device.get("capabilities") and "MUSIC_SKILL" in device.get("capabilities"):
+                dev_name = device["accountName"]
+                player_id = dev_name
+                player = Player(
+                    player_id=player_id,
+                    provider=self.instance_id,
+                    type=PlayerType.PLAYER,
+                    name=player_id,
+                    available=True,
+                    powered=False,
+                    device_info=DeviceInfo(),
+                    supported_features={
+                        PlayerFeature.VOLUME_SET,
+                        PlayerFeature.PAUSE,
+                        PlayerFeature.VOLUME_MUTE,
+                    },
+                )
+                await self.mass.players.register_or_update(player)
+                # Initialize AlexaDevice and store in self.devices
+                device_object = self.AlexaDevice()
+                device_object._device_type = device["deviceType"]
+                device_object.device_serial_number = device["serialNumber"]
+                device_object._device_family = device["deviceOwnerCustomerId"]
+                device_object._cluster_members = device["clusterMembers"]
+                device_object._locale = "en-US"
+                self.devices[player_id] = device_object
+
+    async def get_player_config_entries(self, player_id: str) -> tuple[ConfigEntry, ...]:
+        """Return all (provider/player specific) Config Entries for the given player (if any)."""
+        base_entries = await super().get_player_config_entries(player_id)
+        return (
+            *base_entries,
+            CONF_ENTRY_FLOW_MODE_ENFORCED,
+            CONF_ENTRY_CROSSFADE,
+            CONF_ENTRY_CROSSFADE_DURATION,
+            CONF_ENTRY_HTTP_PROFILE,
+        )
+
+    async def cmd_stop(self, player_id: str) -> None:
+        """Send STOP command to given player."""
+        if not (player := self.mass.players.get(player_id, raise_unavailable=False)):
+            return
+        device_object = self.devices[player_id]
+        api = AlexaAPI(device_object, self.login)
+        await api.stop()
+
+        player.state = PlayerState.IDLE
+        self.mass.players.update(player_id)
+
+    async def cmd_play(self, player_id: str) -> None:
+        """Send PLAY command to given player."""
+        if not (player := self.mass.players.get(player_id, raise_unavailable=False)):
+            return
+        device_object = self.devices[player_id]
+        api = AlexaAPI(device_object, self.login)
+        await api.play()
+
+        player.state = PlayerState.PLAYING
+        self.mass.players.update(player_id)
+
+    async def cmd_pause(self, player_id: str) -> None:
+        """Send PAUSE command to given player."""
+        if not (player := self.mass.players.get(player_id, raise_unavailable=False)):
+            return
+        device_object = self.devices[player_id]
+        api = AlexaAPI(device_object, self.login)
+        await api.pause()
+
+        player.state = PlayerState.PLAYING
+        self.mass.players.update(player_id)
+
+    async def cmd_volume_set(self, player_id: str, volume_level: int) -> None:
+        """Send VOLUME_SET command to given player."""
+        if not (player := self.mass.players.get(player_id, raise_unavailable=False)):
+            return
+        device_object = self.devices[player_id]
+        api = AlexaAPI(device_object, self.login)
+        await api.set_volume(volume_level / 100)
+
+        player.volume_level = volume_level
+        self.mass.players.update(player_id)
+
+    async def cmd_volume_mute(self, player_id: str, muted: bool) -> None:
+        """Send VOLUME MUTE command to given player."""
+        if not (player := self.mass.players.get(player_id, raise_unavailable=False)):
+            return
+        device_object = self.devices[player_id]
+        api = AlexaAPI(device_object, self.login)
+        await api.set_volume(0)
+
+        player.volume_level = 0
+        self.mass.players.update(player_id)
+
+    async def play_media(
+        self,
+        player_id: str,
+        media: PlayerMedia,
+    ) -> None:
+        """Handle PLAY MEDIA on given player.
+
+        This is called by the Players controller to start playing a mediaitem on the given player.
+        The provider's own implementation should work out how to handle this request.
+
+            - player_id: player_id of the player to handle the command.
+            - media: Details of the item that needs to be played on the player.
+        """
+        if not (player := self.mass.players.get(player_id)):
+            return
+
+        async with aiohttp.ClientSession() as session:
+            try:
+                async with session.post(
+                    "http://localhost:3000/ma/push-url",
+                    json={"streamUrl": media.uri},
+                    timeout=aiohttp.ClientTimeout(total=10),
+                ) as resp:
+                    await resp.text()
+            except Exception as exc:
+                _LOGGER.error("Failed to push URL to Alexa: %s", exc)
+                return
+        device_object = self.devices[player_id]
+        api = AlexaAPI(device_object, self.login)
+        await api.run_custom("Ask music assistant to play audio")
+
+        player.current_media = media
+        player.elapsed_time = 0
+        player.elapsed_time_last_updated = time.time()
+        player.state = PlayerState.PLAYING
+        self.mass.players.update(player_id)
diff --git a/music_assistant/providers/alexa/icon.svg b/music_assistant/providers/alexa/icon.svg
new file mode 100644 (file)
index 0000000..20db3de
--- /dev/null
@@ -0,0 +1,286 @@
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+        width="100%" viewBox="0 0 471 320" enable-background="new 0 0 471 320" xml:space="preserve">
+<path fill="#FFFFFF" opacity="1.000000" stroke="none"
+       d="
+M252.000000,321.000000
+       C168.000000,321.000000 84.500000,321.000000 1.000000,321.000000
+       C1.000000,214.333328 1.000000,107.666664 1.000000,1.000000
+       C158.000000,1.000000 315.000000,1.000000 472.000000,1.000000
+       C472.000000,107.666664 472.000000,214.333328 472.000000,321.000000
+       C398.833344,321.000000 325.666656,321.000000 252.000000,321.000000
+M132.674255,194.936462
+       C129.750748,193.196274 126.827248,191.456085 123.903748,189.715897
+       C123.382484,189.910019 122.861221,190.104126 122.339966,190.298248
+       C122.686920,192.168167 122.475426,194.467758 123.508179,195.810028
+       C125.169853,197.969727 127.649689,199.501373 129.789658,201.291443
+       C145.735291,214.629837 163.721878,224.532745 183.479233,230.573761
+       C204.683884,237.057297 226.382736,240.448639 248.857193,238.189590
+       C263.558411,236.711884 277.870178,234.228760 291.890228,229.621231
+       C304.964844,225.324432 317.220428,219.451309 328.600067,211.743301
+       C331.052826,210.081940 333.296844,207.634888 331.611481,204.794159
+       C330.934357,203.652832 327.270905,203.457596 325.325897,204.037216
+       C316.938202,206.536667 308.847961,210.226120 300.345154,212.105835
+       C284.631165,215.579681 268.808594,219.303070 252.837875,220.681107
+       C234.307770,222.280029 215.671768,220.766968 197.237137,217.116592
+       C174.898849,212.693207 153.617844,205.525391 132.674255,194.936462
+M325.009338,136.041565
+       C324.428314,136.336014 323.849152,136.634186 323.266022,136.924377
+       C314.419464,141.326782 310.074066,149.711731 312.166962,158.343582
+       C314.388153,167.504486 320.848175,172.620819 331.448944,171.778214
+       C337.577087,171.291122 343.528687,168.583481 349.587708,166.867294
+       C351.523376,173.037857 356.787018,168.816177 360.996826,170.131409
+       C360.996826,154.372833 361.169189,139.395325 360.923096,124.424690
+       C360.802612,117.096924 356.831726,111.144165 349.677856,110.309685
+       C340.865692,109.281754 331.693237,109.631516 322.880341,110.854744
+       C315.638092,111.859970 315.142944,113.922653 316.656494,122.267784
+       C318.377289,121.868019 320.057373,121.329361 321.778381,121.104927
+       C327.614746,120.343842 333.451202,119.351593 339.315247,119.106102
+       C344.312836,118.896873 348.473724,122.344917 348.916077,126.513443
+       C349.241913,129.584259 348.980011,132.717422 348.980011,136.001831
+       C340.850372,136.001831 333.347015,136.001831 325.009338,136.041565
+M111.407669,156.902222
+       C113.308113,167.283493 119.563362,171.092606 126.897125,171.914474
+       C134.954834,172.817505 142.247879,170.252029 148.759354,165.206711
+       C149.615585,170.461060 152.079178,171.276596 159.999191,169.186676
+       C159.999191,154.105118 160.103333,138.974716 159.945587,123.847038
+       C159.886276,118.158936 156.924438,113.480980 151.952011,111.177841
+       C144.070053,107.527031 135.478607,108.737801 127.144043,109.476624
+       C123.989868,109.756233 120.833679,110.902931 117.859688,112.103470
+       C114.006866,113.658760 114.586754,117.296455 115.410477,120.196518
+       C115.626579,120.957336 119.167160,121.131348 121.132027,120.971756
+       C127.313194,120.469688 133.460831,119.294930 139.641373,119.130875
+       C144.186768,119.010216 147.150742,122.113701 147.882919,126.542610
+       C148.381760,129.560013 147.978317,132.726578 147.978317,135.844315
+       C142.104126,135.541199 136.850601,134.925858 131.617767,135.068741
+       C119.102882,135.410477 110.922241,142.758881 111.407669,156.902222
+M251.000000,127.427681
+       C251.604309,120.637886 248.226318,115.188354 242.945694,112.331398
+       C237.528961,109.400772 231.093674,108.433052 224.501740,108.864578
+       C215.531891,109.451775 206.489487,115.592957 202.885101,123.996735
+       C198.725174,133.695786 199.155960,143.633362 201.362061,153.422791
+       C203.237442,161.744659 208.352798,168.390884 217.072311,170.368820
+       C223.081100,171.731842 229.501801,172.161926 235.646835,171.724045
+       C239.596069,171.442627 243.682693,169.288498 247.089554,167.037979
+       C248.482101,166.118057 248.242203,162.726944 248.744965,160.460068
+       C247.021240,160.298401 245.268677,159.854843 243.579147,160.027603
+       C238.391434,160.557999 233.225220,161.902832 228.055435,161.879379
+       C217.172882,161.830017 210.236038,153.667175 211.470261,143.997528
+       C219.644104,143.997528 227.759171,144.538025 235.770187,143.856110
+       C245.078110,143.063782 250.338928,137.133926 251.000000,127.427681
+M305.511200,162.988770
+       C300.050690,154.921082 294.590179,146.853409 289.119843,138.771194
+       C294.844147,130.908707 300.649048,123.043961 306.320038,115.083817
+       C308.158966,112.502647 306.953491,110.299255 303.731842,110.014679
+       C298.875305,109.585693 294.912476,110.736244 292.156555,115.355179
+       C289.226837,120.265396 285.723419,124.833313 282.143158,130.025421
+       C278.369446,124.532623 275.031464,120.282593 272.379791,115.640541
+       C269.810669,111.143028 266.249359,109.428642 261.365387,110.039963
+       C259.994507,110.211571 257.854187,110.546982 257.541443,111.368584
+       C257.083221,112.572426 257.540710,114.558189 258.325500,115.730316
+       C262.851410,122.489822 267.761292,128.997742 272.131409,135.852066
+       C273.212677,137.547943 273.722137,140.729065 272.849274,142.331100
+       C270.607727,146.445221 267.342285,149.987396 264.672424,153.885773
+       C261.343933,158.745758 258.202179,163.733627 254.868698,168.836304
+       C263.339203,171.609909 266.976593,170.515015 271.129578,164.355042
+       C274.547638,159.285187 277.904968,154.174362 281.541595,148.701889
+       C286.226501,155.396591 290.568115,161.689209 295.036743,167.890320
+       C295.700958,168.812027 296.927673,169.827209 297.955841,169.897537
+       C301.542969,170.142853 305.157166,169.992462 310.169739,169.992462
+       C308.375671,167.193405 307.202850,165.363647 305.511200,162.988770
+M173.000000,95.527779
+       C173.000000,116.348511 172.964066,137.169342 173.015518,157.989929
+       C173.040390,168.052216 182.473022,174.196548 191.951355,170.602356
+       C196.172623,169.001617 195.071198,165.575241 194.772018,162.696594
+       C194.690704,161.914322 192.020706,161.486603 190.627350,160.732544
+       C189.043686,159.875488 186.895966,159.173203 186.192001,157.792526
+       C185.211548,155.869614 185.053406,153.380371 185.045227,151.131683
+       C184.968842,130.144653 185.056732,109.156807 184.894287,88.170761
+       C184.881012,86.453903 183.716324,83.586288 182.504089,83.228821
+       C175.279327,81.098343 173.000595,83.036652 173.000015,90.541359
+       C172.999908,91.873886 173.000000,93.206413 173.000000,95.527779
+M350.008545,208.357910
+       C350.966156,203.602005 352.443237,198.871841 352.680573,194.080261
+       C352.816284,191.341034 352.089111,187.726303 348.019409,187.043686
+       C335.630493,184.965698 323.514404,185.359497 312.190399,191.479614
+       C310.392761,192.451157 309.175446,194.496429 306.774536,196.999527
+       C309.374573,196.999527 310.200500,197.030640 311.023499,196.994690
+       C318.449280,196.670334 325.872894,196.131500 333.300568,196.070267
+       C338.566010,196.026871 341.949707,199.401642 340.853973,203.315613
+       C339.283478,208.925644 337.326141,214.428024 335.507446,219.967651
+       C334.580109,222.792221 333.594910,225.597839 332.635895,228.412033
+       C333.147705,228.870132 333.659515,229.328232 334.171295,229.786346
+       C336.428009,228.286346 339.397125,227.267685 340.800323,225.190994
+       C344.232635,220.111176 346.941315,214.542435 350.008545,208.357910
+z"/>
+<path fill="#05A0D1" opacity="1.000000" stroke="none"
+       d="
+M133.044678,195.005905
+       C153.617844,205.525391 174.898849,212.693207 197.237137,217.116592
+       C215.671768,220.766968 234.307770,222.280029 252.837875,220.681107
+       C268.808594,219.303070 284.631165,215.579681 300.345154,212.105835
+       C308.847961,210.226120 316.938202,206.536667 325.325897,204.037216
+       C327.270905,203.457596 330.934357,203.652832 331.611481,204.794159
+       C333.296844,207.634888 331.052826,210.081940 328.600067,211.743301
+       C317.220428,219.451309 304.964844,225.324432 291.890228,229.621231
+       C277.870178,234.228760 263.558411,236.711884 248.857193,238.189590
+       C226.382736,240.448639 204.683884,237.057297 183.479233,230.573761
+       C163.721878,224.532745 145.735291,214.629837 129.789658,201.291443
+       C127.649689,199.501373 125.169853,197.969727 123.508179,195.810028
+       C122.475426,194.467758 122.686920,192.168167 122.339966,190.298248
+       C122.861221,190.104126 123.382484,189.910019 123.903748,189.715897
+       C126.827248,191.456085 129.750748,193.196274 133.044678,195.005905
+z"/>
+<path fill="#05A0D1" opacity="1.000000" stroke="none"
+       d="
+M325.426483,136.021698
+       C333.347015,136.001831 340.850372,136.001831 348.980011,136.001831
+       C348.980011,132.717422 349.241913,129.584259 348.916077,126.513443
+       C348.473724,122.344917 344.312836,118.896873 339.315247,119.106102
+       C333.451202,119.351593 327.614746,120.343842 321.778381,121.104927
+       C320.057373,121.329361 318.377289,121.868019 316.656494,122.267784
+       C315.142944,113.922653 315.638092,111.859970 322.880341,110.854744
+       C331.693237,109.631516 340.865692,109.281754 349.677856,110.309685
+       C356.831726,111.144165 360.802612,117.096924 360.923096,124.424690
+       C361.169189,139.395325 360.996826,154.372833 360.996826,170.131409
+       C356.787018,168.816177 351.523376,173.037857 349.587708,166.867294
+       C343.528687,168.583481 337.577087,171.291122 331.448944,171.778214
+       C320.848175,172.620819 314.388153,167.504486 312.166962,158.343582
+       C310.074066,149.711731 314.419464,141.326782 323.266022,136.924377
+       C323.849152,136.634186 324.428314,136.336014 325.426483,136.021698
+M349.000000,152.287567
+       C349.000000,149.990402 349.000000,147.693222 349.000000,144.736740
+       C343.874084,144.478485 339.142700,143.918350 334.435883,144.078964
+       C327.512390,144.315216 324.510468,148.156418 325.001404,155.354919
+       C325.308533,159.858597 329.759369,162.917465 335.767059,161.863815
+       C339.503571,161.208511 343.165771,159.554596 346.549957,157.761322
+       C347.819885,157.088364 348.209198,154.753571 349.000000,152.287567
+z"/>
+<path fill="#05A0D1" opacity="1.000000" stroke="none"
+       d="
+M111.235481,156.512482
+       C110.922241,142.758881 119.102882,135.410477 131.617767,135.068741
+       C136.850601,134.925858 142.104126,135.541199 147.978317,135.844315
+       C147.978317,132.726578 148.381760,129.560013 147.882919,126.542610
+       C147.150742,122.113701 144.186768,119.010216 139.641373,119.130875
+       C133.460831,119.294930 127.313194,120.469688 121.132027,120.971756
+       C119.167160,121.131348 115.626579,120.957336 115.410477,120.196518
+       C114.586754,117.296455 114.006866,113.658760 117.859688,112.103470
+       C120.833679,110.902931 123.989868,109.756233 127.144043,109.476624
+       C135.478607,108.737801 144.070053,107.527031 151.952011,111.177841
+       C156.924438,113.480980 159.886276,118.158936 159.945587,123.847038
+       C160.103333,138.974716 159.999191,154.105118 159.999191,169.186676
+       C152.079178,171.276596 149.615585,170.461060 148.759354,165.206711
+       C142.247879,170.252029 134.954834,172.817505 126.897125,171.914474
+       C119.563362,171.092606 113.308113,167.283493 111.235481,156.512482
+M129.304321,161.758820
+       C143.886307,162.864822 148.370697,159.143051 147.922806,146.287720
+       C147.912247,145.984726 147.691788,145.689056 147.287445,144.702347
+       C142.867615,144.479202 138.120926,143.834030 133.431854,144.123199
+       C129.211273,144.383499 125.185081,146.313644 124.211395,150.902023
+       C123.333275,155.040115 123.752449,159.274567 129.304321,161.758820
+z"/>
+<path fill="#05A0D1" opacity="1.000000" stroke="none"
+       d="
+M250.999969,127.867981
+       C250.338928,137.133926 245.078110,143.063782 235.770187,143.856110
+       C227.759171,144.538025 219.644104,143.997528 211.470261,143.997528
+       C210.236038,153.667175 217.172882,161.830017 228.055435,161.879379
+       C233.225220,161.902832 238.391434,160.557999 243.579147,160.027603
+       C245.268677,159.854843 247.021240,160.298401 248.744965,160.460068
+       C248.242203,162.726944 248.482101,166.118057 247.089554,167.037979
+       C243.682693,169.288498 239.596069,171.442627 235.646835,171.724045
+       C229.501801,172.161926 223.081100,171.731842 217.072311,170.368820
+       C208.352798,168.390884 203.237442,161.744659 201.362061,153.422791
+       C199.155960,143.633362 198.725174,133.695786 202.885101,123.996735
+       C206.489487,115.592957 215.531891,109.451775 224.501740,108.864578
+       C231.093674,108.433052 237.528961,109.400772 242.945694,112.331398
+       C248.226318,115.188354 251.604309,120.637886 250.999969,127.867981
+M237.940445,131.154510
+       C240.048218,127.250107 238.941589,123.111465 236.044189,121.020882
+       C233.407089,119.118103 229.154648,118.589249 225.713104,118.835625
+       C216.975342,119.461166 213.316727,125.454582 212.234512,133.571243
+       C213.073364,133.844513 213.969940,134.217499 214.903198,134.427902
+       C222.761597,136.199814 230.621704,137.897842 237.940445,131.154510
+z"/>
+<path fill="#05A0D1" opacity="1.000000" stroke="none"
+       d="
+M305.770630,163.261322
+       C307.202850,165.363647 308.375671,167.193405 310.169739,169.992462
+       C305.157166,169.992462 301.542969,170.142853 297.955841,169.897537
+       C296.927673,169.827209 295.700958,168.812027 295.036743,167.890320
+       C290.568115,161.689209 286.226501,155.396591 281.541595,148.701889
+       C277.904968,154.174362 274.547638,159.285187 271.129578,164.355042
+       C266.976593,170.515015 263.339203,171.609909 254.868698,168.836304
+       C258.202179,163.733627 261.343933,158.745758 264.672424,153.885773
+       C267.342285,149.987396 270.607727,146.445221 272.849274,142.331100
+       C273.722137,140.729065 273.212677,137.547943 272.131409,135.852066
+       C267.761292,128.997742 262.851410,122.489822 258.325500,115.730316
+       C257.540710,114.558189 257.083221,112.572426 257.541443,111.368584
+       C257.854187,110.546982 259.994507,110.211571 261.365387,110.039963
+       C266.249359,109.428642 269.810669,111.143028 272.379791,115.640541
+       C275.031464,120.282593 278.369446,124.532623 282.143158,130.025421
+       C285.723419,124.833313 289.226837,120.265396 292.156555,115.355179
+       C294.912476,110.736244 298.875305,109.585693 303.731842,110.014679
+       C306.953491,110.299255 308.158966,112.502647 306.320038,115.083817
+       C300.649048,123.043961 294.844147,130.908707 289.119843,138.771194
+       C294.590179,146.853409 300.050690,154.921082 305.770630,163.261322
+z"/>
+<path fill="#05A0D1" opacity="1.000000" stroke="none"
+       d="
+M173.000000,95.033356
+       C173.000000,93.206413 172.999908,91.873886 173.000015,90.541359
+       C173.000595,83.036652 175.279327,81.098343 182.504089,83.228821
+       C183.716324,83.586288 184.881012,86.453903 184.894287,88.170761
+       C185.056732,109.156807 184.968842,130.144653 185.045227,151.131683
+       C185.053406,153.380371 185.211548,155.869614 186.192001,157.792526
+       C186.895966,159.173203 189.043686,159.875488 190.627350,160.732544
+       C192.020706,161.486603 194.690704,161.914322 194.772018,162.696594
+       C195.071198,165.575241 196.172623,169.001617 191.951355,170.602356
+       C182.473022,174.196548 173.040390,168.052216 173.015518,157.989929
+       C172.964066,137.169342 173.000000,116.348511 173.000000,95.033356
+z"/>
+<path fill="#05A0D1" opacity="1.000000" stroke="none"
+       d="
+M349.974884,208.764191
+       C346.941315,214.542435 344.232635,220.111176 340.800323,225.190994
+       C339.397125,227.267685 336.428009,228.286346 334.171295,229.786346
+       C333.659515,229.328232 333.147705,228.870132 332.635895,228.412033
+       C333.594910,225.597839 334.580109,222.792221 335.507446,219.967651
+       C337.326141,214.428024 339.283478,208.925644 340.853973,203.315613
+       C341.949707,199.401642 338.566010,196.026871 333.300568,196.070267
+       C325.872894,196.131500 318.449280,196.670334 311.023499,196.994690
+       C310.200500,197.030640 309.374573,196.999527 306.774536,196.999527
+       C309.175446,194.496429 310.392761,192.451157 312.190399,191.479614
+       C323.514404,185.359497 335.630493,184.965698 348.019409,187.043686
+       C352.089111,187.726303 352.816284,191.341034 352.680573,194.080261
+       C352.443237,198.871841 350.966156,203.602005 349.974884,208.764191
+z"/>
+<path fill="#FFFFFF" opacity="1.000000" stroke="none"
+       d="
+M349.000000,152.731995
+       C348.209198,154.753571 347.819885,157.088364 346.549957,157.761322
+       C343.165771,159.554596 339.503571,161.208511 335.767059,161.863815
+       C329.759369,162.917465 325.308533,159.858597 325.001404,155.354919
+       C324.510468,148.156418 327.512390,144.315216 334.435883,144.078964
+       C339.142700,143.918350 343.874084,144.478485 349.000000,144.736740
+       C349.000000,147.693222 349.000000,149.990402 349.000000,152.731995
+z"/>
+<path fill="#FFFFFF" opacity="1.000000" stroke="none"
+       d="
+M128.994263,161.481964
+       C123.752449,159.274567 123.333275,155.040115 124.211395,150.902023
+       C125.185081,146.313644 129.211273,144.383499 133.431854,144.123199
+       C138.120926,143.834030 142.867615,144.479202 147.287445,144.702347
+       C147.691788,145.689056 147.912247,145.984726 147.922806,146.287720
+       C148.370697,159.143051 143.886307,162.864822 128.994263,161.481964
+z"/>
+<path fill="#FFFFFF" opacity="1.000000" stroke="none"
+       d="
+M237.773071,131.513702
+       C230.621704,137.897842 222.761597,136.199814 214.903198,134.427902
+       C213.969940,134.217499 213.073364,133.844513 212.234512,133.571243
+       C213.316727,125.454582 216.975342,119.461166 225.713104,118.835625
+       C229.154648,118.589249 233.407089,119.118103 236.044189,121.020882
+       C238.941589,123.111465 240.048218,127.250107 237.773071,131.513702
+z"/>
+</svg>
diff --git a/music_assistant/providers/alexa/icon_monochrome.svg b/music_assistant/providers/alexa/icon_monochrome.svg
new file mode 100644 (file)
index 0000000..1de0726
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="1080" height="1080" viewBox="0 0 1080 1080" xml:space="preserve">
+<desc>Created with Fabric.js 5.2.4</desc>
+<defs>
+</defs>
+<g transform="matrix(1 0 0 1 540 540)" id="fadab756-2020-4796-aed7-b425a5ac6873"  >
+<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke"  x="-540" y="-540" rx="0" ry="0" width="1080" height="1080" />
+</g>
+<g transform="matrix(1 0 0 1 540 540)" id="79ff0c74-2519-4d91-9d45-fb360f242543"  >
+</g>
+<g transform="matrix(1 0 0 1 505.2 518.25)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-236.5, -161)" d="M 252 321 C 168 321 84.5 321 1 321 C 1 214.333328 1 107.666664 1 1 C 158 1 315 1 472 1 C 472 107.666664 472 214.333328 472 321 C 398.833344 321 325.666656 321 252 321 M 132.674255 194.936462 C 129.750748 193.196274 126.827248 191.456085 123.903748 189.715897 C 123.382484 189.910019 122.861221 190.104126 122.339966 190.298248 C 122.68692 192.168167 122.475426 194.467758 123.508179 195.810028 C 125.169853 197.969727 127.649689 199.501373 129.789658 201.291443 C 145.735291 214.629837 163.721878 224.532745 183.479233 230.573761 C 204.683884 237.057297 226.382736 240.448639 248.857193 238.18959 C 263.558411 236.711884 277.870178 234.22876 291.890228 229.621231 C 304.964844 225.324432 317.220428 219.451309 328.600067 211.743301 C 331.052826 210.08194 333.296844 207.634888 331.611481 204.794159 C 330.934357 203.652832 327.270905 203.457596 325.325897 204.037216 C 316.938202 206.536667 308.847961 210.22612 300.345154 212.105835 C 284.631165 215.579681 268.808594 219.30307 252.837875 220.681107 C 234.30777 222.280029 215.671768 220.766968 197.237137 217.116592 C 174.898849 212.693207 153.617844 205.525391 132.674255 194.936462 M 325.009338 136.041565 C 324.428314 136.336014 323.849152 136.634186 323.266022 136.924377 C 314.419464 141.326782 310.074066 149.711731 312.166962 158.343582 C 314.388153 167.504486 320.848175 172.620819 331.448944 171.778214 C 337.577087 171.291122 343.528687 168.583481 349.587708 166.867294 C 351.523376 173.037857 356.787018 168.816177 360.996826 170.131409 C 360.996826 154.372833 361.169189 139.395325 360.923096 124.42469 C 360.802612 117.096924 356.831726 111.144165 349.677856 110.309685 C 340.865692 109.281754 331.693237 109.631516 322.880341 110.854744 C 315.638092 111.85997 315.142944 113.922653 316.656494 122.267784 C 318.377289 121.868019 320.057373 121.329361 321.778381 121.104927 C 327.614746 120.343842 333.451202 119.351593 339.315247 119.106102 C 344.312836 118.896873 348.473724 122.344917 348.916077 126.513443 C 349.241913 129.584259 348.980011 132.717422 348.980011 136.001831 C 340.850372 136.001831 333.347015 136.001831 325.009338 136.041565 M 111.407669 156.902222 C 113.308113 167.283493 119.563362 171.092606 126.897125 171.914474 C 134.954834 172.817505 142.247879 170.252029 148.759354 165.206711 C 149.615585 170.46106 152.079178 171.276596 159.999191 169.186676 C 159.999191 154.105118 160.103333 138.974716 159.945587 123.847038 C 159.886276 118.158936 156.924438 113.48098 151.952011 111.177841 C 144.070053 107.527031 135.478607 108.737801 127.144043 109.476624 C 123.989868 109.756233 120.833679 110.902931 117.859688 112.10347 C 114.006866 113.65876 114.586754 117.296455 115.410477 120.196518 C 115.626579 120.957336 119.16716 121.131348 121.132027 120.971756 C 127.313194 120.469688 133.460831 119.29493 139.641373 119.130875 C 144.186768 119.010216 147.150742 122.113701 147.882919 126.54261 C 148.38176 129.560013 147.978317 132.726578 147.978317 135.844315 C 142.104126 135.541199 136.850601 134.925858 131.617767 135.068741 C 119.102882 135.410477 110.922241 142.758881 111.407669 156.902222 M 251 127.427681 C 251.604309 120.637886 248.226318 115.188354 242.945694 112.331398 C 237.528961 109.400772 231.093674 108.433052 224.50174 108.864578 C 215.531891 109.451775 206.489487 115.592957 202.885101 123.996735 C 198.725174 133.695786 199.15596 143.633362 201.362061 153.422791 C 203.237442 161.744659 208.352798 168.390884 217.072311 170.36882 C 223.0811 171.731842 229.501801 172.161926 235.646835 171.724045 C 239.596069 171.442627 243.682693 169.288498 247.089554 167.037979 C 248.482101 166.118057 248.242203 162.726944 248.744965 160.460068 C 247.02124 160.298401 245.268677 159.854843 243.579147 160.027603 C 238.391434 160.557999 233.22522 161.902832 228.055435 161.879379 C 217.172882 161.830017 210.236038 153.667175 211.470261 143.997528 C 219.644104 143.997528 227.759171 144.538025 235.770187 143.85611 C 245.07811 143.063782 250.338928 137.133926 251 127.427681 M 305.5112 162.98877 C 300.05069 154.921082 294.590179 146.853409 289.119843 138.771194 C 294.844147 130.908707 300.649048 123.043961 306.320038 115.083817 C 308.158966 112.502647 306.953491 110.299255 303.731842 110.014679 C 298.875305 109.585693 294.912476 110.736244 292.156555 115.355179 C 289.226837 120.265396 285.723419 124.833313 282.143158 130.025421 C 278.369446 124.532623 275.031464 120.282593 272.379791 115.640541 C 269.810669 111.143028 266.249359 109.428642 261.365387 110.039963 C 259.994507 110.211571 257.854187 110.546982 257.541443 111.368584 C 257.083221 112.572426 257.54071 114.558189 258.3255 115.730316 C 262.85141 122.489822 267.761292 128.997742 272.131409 135.852066 C 273.212677 137.547943 273.722137 140.729065 272.849274 142.3311 C 270.607727 146.445221 267.342285 149.987396 264.672424 153.885773 C 261.343933 158.745758 258.202179 163.733627 254.868698 168.836304 C 263.339203 171.609909 266.976593 170.515015 271.129578 164.355042 C 274.547638 159.285187 277.904968 154.174362 281.541595 148.701889 C 286.226501 155.396591 290.568115 161.689209 295.036743 167.89032 C 295.700958 168.812027 296.927673 169.827209 297.955841 169.897537 C 301.542969 170.142853 305.157166 169.992462 310.169739 169.992462 C 308.375671 167.193405 307.20285 165.363647 305.5112 162.98877 M 173 95.527779 C 173 116.348511 172.964066 137.169342 173.015518 157.989929 C 173.04039 168.052216 182.473022 174.196548 191.951355 170.602356 C 196.172623 169.001617 195.071198 165.575241 194.772018 162.696594 C 194.690704 161.914322 192.020706 161.486603 190.62735 160.732544 C 189.043686 159.875488 186.895966 159.173203 186.192001 157.792526 C 185.211548 155.869614 185.053406 153.380371 185.045227 151.131683 C 184.968842 130.144653 185.056732 109.156807 184.894287 88.170761 C 184.881012 86.453903 183.716324 83.586288 182.504089 83.228821 C 175.279327 81.098343 173.000595 83.036652 173.000015 90.541359 C 172.999908 91.873886 173 93.206413 173 95.527779 M 350.008545 208.35791 C 350.966156 203.602005 352.443237 198.871841 352.680573 194.080261 C 352.816284 191.341034 352.089111 187.726303 348.019409 187.043686 C 335.630493 184.965698 323.514404 185.359497 312.190399 191.479614 C 310.392761 192.451157 309.175446 194.496429 306.774536 196.999527 C 309.374573 196.999527 310.2005 197.03064 311.023499 196.99469 C 318.44928 196.670334 325.872894 196.1315 333.300568 196.070267 C 338.56601 196.026871 341.949707 199.401642 340.853973 203.315613 C 339.283478 208.925644 337.326141 214.428024 335.507446 219.967651 C 334.580109 222.792221 333.59491 225.597839 332.635895 228.412033 C 333.147705 228.870132 333.659515 229.328232 334.171295 229.786346 C 336.428009 228.286346 339.397125 227.267685 340.800323 225.190994 C 344.232635 220.111176 346.941315 214.542435 350.008545 208.35791 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 495.97 571.55)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-227.27, -214.3)" d="M 133.044678 195.005905 C 153.617844 205.525391 174.898849 212.693207 197.237137 217.116592 C 215.671768 220.766968 234.30777 222.280029 252.837875 220.681107 C 268.808594 219.30307 284.631165 215.579681 300.345154 212.105835 C 308.847961 210.22612 316.938202 206.536667 325.325897 204.037216 C 327.270905 203.457596 330.934357 203.652832 331.611481 204.794159 C 333.296844 207.634888 331.052826 210.08194 328.600067 211.743301 C 317.220428 219.451309 304.964844 225.324432 291.890228 229.621231 C 277.870178 234.22876 263.558411 236.711884 248.857193 238.18959 C 226.382736 240.448639 204.683884 237.057297 183.479233 230.573761 C 163.721878 224.532745 145.735291 214.629837 129.789658 201.291443 C 127.649689 199.501373 125.169853 197.969727 123.508179 195.810028 C 122.475426 194.467758 122.68692 192.168167 122.339966 190.298248 C 122.861221 190.104126 123.382484 189.910019 123.903748 189.715897 C 126.827248 191.456085 129.750748 193.196274 133.044678 195.005905 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 605.05 498.03)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-336.35, -140.79)" d="M 325.426483 136.021698 C 333.347015 136.001831 340.850372 136.001831 348.980011 136.001831 C 348.980011 132.717422 349.241913 129.584259 348.916077 126.513443 C 348.473724 122.344917 344.312836 118.896873 339.315247 119.106102 C 333.451202 119.351593 327.614746 120.343842 321.778381 121.104927 C 320.057373 121.329361 318.377289 121.868019 316.656494 122.267784 C 315.142944 113.922653 315.638092 111.85997 322.880341 110.854744 C 331.693237 109.631516 340.865692 109.281754 349.677856 110.309685 C 356.831726 111.144165 360.802612 117.096924 360.923096 124.42469 C 361.169189 139.395325 360.996826 154.372833 360.996826 170.131409 C 356.787018 168.816177 351.523376 173.037857 349.587708 166.867294 C 343.528687 168.583481 337.577087 171.291122 331.448944 171.778214 C 320.848175 172.620819 314.388153 167.504486 312.166962 158.343582 C 310.074066 149.711731 314.419464 141.326782 323.266022 136.924377 C 323.849152 136.634186 324.428314 136.336014 325.426483 136.021698 M 349 152.287567 C 349 149.990402 349 147.693222 349 144.73674 C 343.874084 144.478485 339.1427 143.91835 334.435883 144.078964 C 327.51239 144.315216 324.510468 148.156418 325.001404 155.354919 C 325.308533 159.858597 329.759369 162.917465 335.767059 161.863815 C 339.503571 161.208511 343.165771 159.554596 346.549957 157.761322 C 347.819885 157.088364 348.209198 154.753571 349 152.287567 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 404.33 497.63)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-135.63, -140.38)" d="M 111.235481 156.512482 C 110.922241 142.758881 119.102882 135.410477 131.617767 135.068741 C 136.850601 134.925858 142.104126 135.541199 147.978317 135.844315 C 147.978317 132.726578 148.38176 129.560013 147.882919 126.54261 C 147.150742 122.113701 144.186768 119.010216 139.641373 119.130875 C 133.460831 119.29493 127.313194 120.469688 121.132027 120.971756 C 119.16716 121.131348 115.626579 120.957336 115.410477 120.196518 C 114.586754 117.296455 114.006866 113.65876 117.859688 112.10347 C 120.833679 110.902931 123.989868 109.756233 127.144043 109.476624 C 135.478607 108.737801 144.070053 107.527031 151.952011 111.177841 C 156.924438 113.48098 159.886276 118.158936 159.945587 123.847038 C 160.103333 138.974716 159.999191 154.105118 159.999191 169.186676 C 152.079178 171.276596 149.615585 170.46106 148.759354 165.206711 C 142.247879 170.252029 134.954834 172.817505 126.897125 171.914474 C 119.563362 171.092606 113.308113 167.283493 111.235481 156.512482 M 129.304321 161.75882 C 143.886307 162.864822 148.370697 159.143051 147.922806 146.28772 C 147.912247 145.984726 147.691788 145.689056 147.287445 144.702347 C 142.867615 144.479202 138.120926 143.83403 133.431854 144.123199 C 129.211273 144.383499 125.185081 146.313644 124.211395 150.902023 C 123.333275 155.040115 123.752449 159.274567 129.304321 161.75882 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 494.09 497.58)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-225.39, -140.33)" d="M 250.999969 127.867981 C 250.338928 137.133926 245.07811 143.063782 235.770187 143.85611 C 227.759171 144.538025 219.644104 143.997528 211.470261 143.997528 C 210.236038 153.667175 217.172882 161.830017 228.055435 161.879379 C 233.22522 161.902832 238.391434 160.557999 243.579147 160.027603 C 245.268677 159.854843 247.02124 160.298401 248.744965 160.460068 C 248.242203 162.726944 248.482101 166.118057 247.089554 167.037979 C 243.682693 169.288498 239.596069 171.442627 235.646835 171.724045 C 229.501801 172.161926 223.0811 171.731842 217.072311 170.36882 C 208.352798 168.390884 203.237442 161.744659 201.362061 153.422791 C 199.15596 143.633362 198.725174 133.695786 202.885101 123.996735 C 206.489487 115.592957 215.531891 109.451775 224.50174 108.864578 C 231.093674 108.433052 237.528961 109.400772 242.945694 112.331398 C 248.226318 115.188354 251.604309 120.637886 250.999969 127.867981 M 237.940445 131.15451 C 240.048218 127.250107 238.941589 123.111465 236.044189 121.020882 C 233.407089 119.118103 229.154648 118.589249 225.713104 118.835625 C 216.975342 119.461166 213.316727 125.454582 212.234512 133.571243 C 213.073364 133.844513 213.96994 134.217499 214.903198 134.427902 C 222.761597 136.199814 230.621704 137.897842 237.940445 131.15451 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 551.22 497.35)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-282.52, -140.1)" d="M 305.77063 163.261322 C 307.20285 165.363647 308.375671 167.193405 310.169739 169.992462 C 305.157166 169.992462 301.542969 170.142853 297.955841 169.897537 C 296.927673 169.827209 295.700958 168.812027 295.036743 167.89032 C 290.568115 161.689209 286.226501 155.396591 281.541595 148.701889 C 277.904968 154.174362 274.547638 159.285187 271.129578 164.355042 C 266.976593 170.515015 263.339203 171.609909 254.868698 168.836304 C 258.202179 163.733627 261.343933 158.745758 264.672424 153.885773 C 267.342285 149.987396 270.607727 146.445221 272.849274 142.3311 C 273.722137 140.729065 273.212677 137.547943 272.131409 135.852066 C 267.761292 128.997742 262.85141 122.489822 258.3255 115.730316 C 257.54071 114.558189 257.083221 112.572426 257.541443 111.368584 C 257.854187 110.546982 259.994507 110.211571 261.365387 110.039963 C 266.249359 109.428642 269.810669 111.143028 272.379791 115.640541 C 275.031464 120.282593 278.369446 124.532623 282.143158 130.025421 C 285.723419 124.833313 289.226837 120.265396 292.156555 115.355179 C 294.912476 110.736244 298.875305 109.585693 303.731842 110.014679 C 306.953491 110.299255 308.158966 112.502647 306.320038 115.083817 C 300.649048 123.043961 294.844147 130.908707 289.119843 138.771194 C 294.590179 146.853409 300.05069 154.921082 305.77063 163.261322 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 452.75 484.27)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-184.06, -127.03)" d="M 173 95.033356 C 173 93.206413 172.999908 91.873886 173.000015 90.541359 C 173.000595 83.036652 175.279327 81.098343 182.504089 83.228821 C 183.716324 83.586288 184.881012 86.453903 184.894287 88.170761 C 185.056732 109.156807 184.968842 130.144653 185.045227 151.131683 C 185.053406 153.380371 185.211548 155.869614 186.192001 157.792526 C 186.895966 159.173203 189.043686 159.875488 190.62735 160.732544 C 192.020706 161.486603 194.690704 161.914322 194.772018 162.696594 C 195.071198 165.575241 196.172623 169.001617 191.951355 170.602356 C 182.473022 174.196548 173.04039 168.052216 173.015518 157.989929 C 172.964066 137.169342 173 116.348511 173 95.033356 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 598.43 565.1)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-329.74, -207.85)" d="M 349.974884 208.764191 C 346.941315 214.542435 344.232635 220.111176 340.800323 225.190994 C 339.397125 227.267685 336.428009 228.286346 334.171295 229.786346 C 333.659515 229.328232 333.147705 228.870132 332.635895 228.412033 C 333.59491 225.597839 334.580109 222.792221 335.507446 219.967651 C 337.326141 214.428024 339.283478 208.925644 340.853973 203.315613 C 341.949707 199.401642 338.56601 196.026871 333.300568 196.070267 C 325.872894 196.1315 318.44928 196.670334 311.023499 196.99469 C 310.2005 197.03064 309.374573 196.999527 306.774536 196.999527 C 309.175446 194.496429 310.392761 192.451157 312.190399 191.479614 C 323.514404 185.359497 335.630493 184.965698 348.019409 187.043686 C 352.089111 187.726303 352.816284 191.341034 352.680573 194.080261 C 352.443237 198.871841 350.966156 203.602005 349.974884 208.764191 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 605.67 510.31)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-336.97, -153.06)" d="M 349 152.731995 C 348.209198 154.753571 347.819885 157.088364 346.549957 157.761322 C 343.165771 159.554596 339.503571 161.208511 335.767059 161.863815 C 329.759369 162.917465 325.308533 159.858597 325.001404 155.354919 C 324.510468 148.156418 327.51239 144.315216 334.435883 144.078964 C 339.1427 143.91835 343.874084 144.478485 349 144.73674 C 349 147.693222 349 149.990402 349 152.731995 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 404.6 510.15)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-135.9, -152.9)" d="M 128.994263 161.481964 C 123.752449 159.274567 123.333275 155.040115 124.211395 150.902023 C 125.185081 146.313644 129.211273 144.383499 133.431854 144.123199 C 138.120926 143.83403 142.867615 144.479202 147.287445 144.702347 C 147.691788 145.689056 147.912247 145.984726 147.922806 146.28772 C 148.370697 159.143051 143.886307 162.864822 128.994263 161.481964 z" stroke-linecap="round" />
+</g>
+<g transform="matrix(1 0 0 1 494.31 484.66)"  >
+<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-225.61, -127.41)" d="M 237.773071 131.513702 C 230.621704 137.897842 222.761597 136.199814 214.903198 134.427902 C 213.96994 134.217499 213.073364 133.844513 212.234512 133.571243 C 213.316727 125.454582 216.975342 119.461166 225.713104 118.835625 C 229.154648 118.589249 233.407089 119.118103 236.044189 121.020882 C 238.941589 123.111465 240.048218 127.250107 237.773071 131.513702 z" stroke-linecap="round" />
+</g>
+</svg>
diff --git a/music_assistant/providers/alexa/manifest.json b/music_assistant/providers/alexa/manifest.json
new file mode 100644 (file)
index 0000000..e0d2a85
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "type": "player",
+  "domain": "alexa",
+  "name": "Alexa",
+  "description": "Support Echo devices as players in Music Assistant.",
+  "codeowners": ["@alams154"],
+  "requirements": ["alexapy==1.29.5"],
+  "documentation": "https://www.music-assistant.io/player-support/alexa/"
+}
index 309a2153ef82a3e25ccd2521a2d00569c971c31c..f1166903c979ac540986a8ab732fa33813d12b46 100644 (file)
@@ -12,6 +12,7 @@ aiorun==2025.1.1
 aioslimproto==3.1.0
 aiosonos==0.1.9
 aiosqlite==0.21.0
+alexapy==1.29.5
 async-upnp-client==0.44.0
 audible==0.10.0
 bgutil-ytdlp-pot-provider==1.1.0