refactor: remove builtin player (in favor of sendspin) (#2752)
authorMaxim Raznatovski <nda.mr43@gmail.com>
Fri, 5 Dec 2025 16:39:22 +0000 (17:39 +0100)
committerGitHub <noreply@github.com>
Fri, 5 Dec 2025 16:39:22 +0000 (17:39 +0100)
music_assistant/providers/builtin_player/__init__.py [deleted file]
music_assistant/providers/builtin_player/icon.svg [deleted file]
music_assistant/providers/builtin_player/icon_monochrome.svg [deleted file]
music_assistant/providers/builtin_player/manifest.json [deleted file]
music_assistant/providers/builtin_player/player.py [deleted file]
music_assistant/providers/builtin_player/provider.py [deleted file]

diff --git a/music_assistant/providers/builtin_player/__init__.py b/music_assistant/providers/builtin_player/__init__.py
deleted file mode 100644 (file)
index 4c5d6be..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-"""Built-in HTTP-based Player Provider for Music Assistant.
-
-This provider creates a standards HTTP audio streaming endpoint that can be utilized
-by the MA web interface, accessed directly as a URL, consumed by Home Assistant media
-browser, or integrated with other plugins without requiring third-party protocols.
-
-Usage requires registering a player through the 'builtin_player/register' API command.
-The registered player must regularly update its state via 'builtin_player/update_state'
-to maintain the connection. Players can be manually disconnected with 'builtin_player/unregister'
-when no longer needed.
-
-Communication with the player occurs via events. The provider sends commands (play media url, pause,
-stop, volume changes, etc.) through the BUILTIN_PLAYER event type. Client implementations must
-listen for these events and respond accordingly to control playback and handle media changes.
-"""
-
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from music_assistant_models.enums import ProviderFeature
-
-from music_assistant.mass import MusicAssistant
-from music_assistant.models import ProviderInstanceType
-
-from .provider import BuiltinPlayerProvider
-
-if TYPE_CHECKING:
-    from music_assistant_models.config_entries import ConfigEntry, ConfigValueType, ProviderConfig
-    from music_assistant_models.provider import ProviderManifest
-
-SUPPORTED_FEATURES = {ProviderFeature.REMOVE_PLAYER}
-
-
-async def setup(
-    mass: MusicAssistant, manifest: ProviderManifest, config: ProviderConfig
-) -> ProviderInstanceType:
-    """Initialize provider(instance) with given configuration."""
-    return BuiltinPlayerProvider(mass, manifest, config, SUPPORTED_FEATURES)
-
-
-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
-    return ()
diff --git a/music_assistant/providers/builtin_player/icon.svg b/music_assistant/providers/builtin_player/icon.svg
deleted file mode 100644 (file)
index a843b01..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   width="240"
-   height="240"
-   viewBox="0 0 240 240"
-   fill="none"
-   version="1.1"
-   id="svg18"
-   sodipodi:docname="icon.svg"
-   inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)"
-   inkscape:export-filename="icon.svg"
-   inkscape:export-xdpi="96"
-   inkscape:export-ydpi="96"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:svg="http://www.w3.org/2000/svg">
-  <sodipodi:namedview
-     id="namedview18"
-     pagecolor="#ffffff"
-     bordercolor="#000000"
-     borderopacity="0.25"
-     inkscape:showpageshadow="2"
-     inkscape:pageopacity="0.0"
-     inkscape:pagecheckerboard="0"
-     inkscape:deskcolor="#d1d1d1"
-     inkscape:zoom="2.8284271"
-     inkscape:cx="94.575532"
-     inkscape:cy="119.32427"
-     inkscape:window-width="1920"
-     inkscape:window-height="1129"
-     inkscape:window-x="-8"
-     inkscape:window-y="-8"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="svg18" />
-  <g
-     clip-path="url(#clipPath19)"
-     id="g17"
-     transform="translate(0,2)">
-    <path
-       d="m 109.394,4.3814 c 5.848,-5.84187 15.394,-5.84187 21.212,0 l 98.788,98.8876 c 5.848,5.842 10.606,17.374 10.606,25.638 v 90.11 l -0.005,0.356 c -0.206,8.086 -6.881,14.628 -14.995,14.628 H 15 C 6.75759,234.001 2.40473e-5,227.22 0,218.987 v -90.11 c 1.20331e-4,-8.264 4.78834,-19.796 10.6064,-25.638 z"
-       fill="#f2f4f9"
-       id="path1" />
-    <path
-       d="m 109.394,4.3814 c 5.848,-5.84187 15.394,-5.84187 21.212,0 l 98.788,98.8876 c 5.848,5.842 10.606,17.374 10.606,25.638 v 90.11 l -0.005,0.356 c -0.206,8.086 -6.881,14.628 -14.995,14.628 H 15 C 6.75759,234.001 2.40473e-5,227.22 0,218.987 v -90.11 c 1.20331e-4,-8.264 4.78834,-19.796 10.6064,-25.638 z M 36,120.001 c -4.4183,0 -8,3.581 -8,8 v 78 h 16 v -78 c 0,-4.419 -3.5817,-8 -8,-8 z m 32,0 c -4.4183,0 -8,3.581 -8,8 v 78 h 16 v -78 c 0,-4.419 -3.5817,-8 -8,-8 z m 32,0 c -4.4183,0 -8,3.581 -8,8 v 78 h 16 v -78 c 0,-4.419 -3.582,-8 -8,-8 z m 58.393,0.426 c -4.193,-1.395 -8.722,0.873 -10.118,5.065 l -26.796,80.509 h 16.863 l 25.114,-75.457 c 1.395,-4.192 -0.872,-8.721 -5.063,-10.117 z m 30.315,5.065 c -1.395,-4.192 -5.925,-6.46 -10.117,-5.065 -4.192,1.396 -6.46,5.925 -5.065,10.117 l 25.116,75.457 h 16.862 z"
-       fill="#18bcf2"
-       id="path2" />
-    <g
-       clip-path="url(#clip1_3_51)"
-       id="g16">
-      <path
-         d="m 482.363,47.06 v 146.89 h -26.91 v -85.83 l -33.86,85.82 h -26.03 l -33.47,-85.14 v 85.14 h -26.23 V 47.06 h 26.23 l 46.48,114.99 46.88,-114.99 z"
-         fill="#f2f4f9"
-         id="path3" />
-      <path
-         d="m 581.292,193.94 c -0.85,-2.74 -1.47,-6.07 -1.86,-9.98 -5.94,8.42 -15.46,12.62 -28.58,12.62 -10.96,0 -20.65,-3.16 -29.06,-9.49 -8.02,-6.46 -12.04,-17.12 -12.04,-32 V 94.51 h 26.23 v 55.29 c 0,8.94 2.09,15.1 6.26,18.5 4.11,3.33 8.84,4.99 14.19,4.99 5.74,0 10.89,-1.79 15.46,-5.38 4.63,-3.65 6.95,-9.75 6.95,-18.3 V 94.52 h 26.32 v 81.03 c 0,6.65 0.65,12.79 1.96,18.4 h -25.83 z"
-         fill="#f2f4f9"
-         id="path4" />
-      <path
-         d="m 663.403,175.74 c 4.44,0 7.93,-0.86 10.47,-2.59 2.54,-1.73 3.82,-4.22 3.82,-7.49 0,-4.83 -3.23,-8.03 -9.69,-9.59 l -13.21,-3.62 c -10.05,-2.61 -17.37,-6.36 -21.97,-11.25 -4.6,-4.89 -6.9,-10.89 -6.9,-18.01 0,-9.39 3.39,-17.03 10.18,-22.9 6.78,-5.87 15.95,-8.81 27.5,-8.81 10.18,0 18.69,2.33 25.54,7 6.85,4.67 11.02,11.11 12.53,19.33 l -23.39,5.38 c -0.39,-3.26 -1.86,-5.84 -4.4,-7.73 -2.54,-1.89 -5.71,-2.84 -9.49,-2.84 -3.98,0 -7.11,0.9 -9.39,2.69 -2.28,1.79 -3.42,4.29 -3.42,7.49 0,2.41 0.88,4.4 2.64,5.97 1.76,1.57 4.63,2.9 8.61,4.01 l 13.02,3.43 c 9.2,2.41 16.18,6.13 20.94,11.16 4.76,5.02 7.14,11.12 7.14,18.3 0,9.39 -3.59,16.9 -10.76,22.51 -7.18,5.61 -16.96,8.42 -29.36,8.42 -12.4,0 -21.22,-2.53 -28.23,-7.58 -7.01,-5.05 -11.14,-11.95 -12.38,-20.7 l 23.98,-4.01 c 0.33,3.52 1.92,6.31 4.8,8.37 2.87,2.05 6.69,3.08 11.45,3.08 z"
-         fill="#f2f4f9"
-         id="path5" />
-      <path
-         d="m 720.062,60.66 c 0,-4.37 1.53,-8.07 4.6,-11.11 3.07,-3.03 6.82,-4.55 11.25,-4.55 4.43,0 8.19,1.52 11.25,4.55 3.07,3.03 4.6,6.74 4.6,11.11 0,4.37 -1.53,8.27 -4.6,11.3 -3.07,3.03 -6.82,4.55 -11.25,4.55 -4.43,0 -8.19,-1.52 -11.25,-4.55 -3.07,-3.03 -4.6,-6.8 -4.6,-11.3 z m 29.06,33.86 v 99.43 h -26.23 V 94.52 Z"
-         fill="#f2f4f9"
-         id="path6" />
-      <path
-         d="m 818.513,91.48 c 11.42,0 21.28,2.84 29.6,8.51 8.32,5.67 13.88,13.21 16.69,22.61 l -22.41,9 c -1.63,-4.96 -4.58,-8.94 -8.86,-11.94 -4.27,-3 -9.15,-4.5 -14.63,-4.5 -7.9,0 -14.11,2.63 -18.64,7.88 -4.54,5.25 -6.8,12.31 -6.8,21.19 0,8.88 2.3,15.87 6.9,20.99 4.6,5.12 10.78,7.68 18.54,7.68 5.61,0 10.57,-1.43 14.87,-4.31 4.31,-2.87 7.31,-6.72 9,-11.55 l 22.02,8.22 c -3.2,9.59 -9,17.21 -17.42,22.85 -8.42,5.64 -18.1,8.46 -29.06,8.46 -15.2,0 -27.52,-4.83 -36.94,-14.48 -9.43,-9.66 -14.14,-22.28 -14.14,-37.87 0,-15.59 4.73,-28.36 14.19,-38.12 9.46,-9.75 21.82,-14.63 37.09,-14.63 z"
-         fill="#f2f4f9"
-         id="path7" />
-      <path
-         d="m 1020.39,160.67 h -53.137 l -11.65,33.27 h -28.48 l 52.95,-146.88 h 27.687 l 52.84,146.89 h -29.06 l -11.16,-33.27 z m -8.02,-22.8 -18.497,-53.72 -18.59,53.72 z"
-         fill="#f2f4f9"
-         id="path8" />
-      <path
-         d="m 1109.45,175.74 c 4.44,0 7.93,-0.86 10.47,-2.59 2.54,-1.73 3.82,-4.22 3.82,-7.49 0,-4.83 -3.23,-8.03 -9.69,-9.59 l -13.21,-3.62 c -10.05,-2.61 -17.37,-6.36 -21.97,-11.25 -4.6,-4.89 -6.9,-10.89 -6.9,-18.01 0,-9.39 3.39,-17.03 10.18,-22.9 6.78,-5.87 15.95,-8.81 27.5,-8.81 10.18,0 18.69,2.33 25.54,7 6.85,4.67 11.02,11.11 12.53,19.33 l -23.39,5.38 c -0.39,-3.26 -1.86,-5.84 -4.4,-7.73 -2.54,-1.89 -5.71,-2.84 -9.49,-2.84 -3.98,0 -7.11,0.9 -9.39,2.69 -2.28,1.79 -3.42,4.29 -3.42,7.49 0,2.41 0.88,4.4 2.64,5.97 1.76,1.57 4.63,2.9 8.61,4.01 l 13.02,3.43 c 9.2,2.41 16.18,6.13 20.94,11.16 4.76,5.02 7.14,11.12 7.14,18.3 0,9.39 -3.59,16.9 -10.76,22.51 -7.18,5.61 -16.96,8.42 -29.36,8.42 -12.4,0 -21.22,-2.53 -28.23,-7.58 -7.01,-5.05 -11.14,-11.95 -12.38,-20.7 l 23.98,-4.01 c 0.33,3.52 1.92,6.31 4.8,8.37 2.87,2.05 6.69,3.08 11.45,3.08 z"
-         fill="#f2f4f9"
-         id="path9" />
-      <path
-         d="m 1202.41,175.74 c 4.44,0 7.93,-0.86 10.47,-2.59 2.54,-1.73 3.82,-4.22 3.82,-7.49 0,-4.83 -3.23,-8.03 -9.69,-9.59 l -13.21,-3.62 c -10.05,-2.61 -17.37,-6.36 -21.97,-11.25 -4.6,-4.89 -6.9,-10.89 -6.9,-18.01 0,-9.39 3.39,-17.03 10.18,-22.9 6.78,-5.87 15.95,-8.81 27.5,-8.81 10.18,0 18.69,2.33 25.54,7 6.85,4.67 11.02,11.11 12.53,19.33 l -23.39,5.38 c -0.39,-3.26 -1.86,-5.84 -4.4,-7.73 -2.54,-1.89 -5.71,-2.84 -9.49,-2.84 -3.98,0 -7.11,0.9 -9.39,2.69 -2.28,1.79 -3.42,4.29 -3.42,7.49 0,2.41 0.88,4.4 2.64,5.97 1.76,1.57 4.63,2.9 8.61,4.01 l 13.02,3.43 c 9.2,2.41 16.18,6.13 20.94,11.16 4.76,5.02 7.14,11.12 7.14,18.3 0,9.39 -3.59,16.9 -10.76,22.51 -7.18,5.61 -16.96,8.42 -29.36,8.42 -12.4,0 -21.22,-2.53 -28.23,-7.58 -7.01,-5.05 -11.14,-11.95 -12.38,-20.7 l 23.98,-4.01 c 0.33,3.52 1.92,6.31 4.8,8.37 2.87,2.05 6.69,3.08 11.45,3.08 z"
-         fill="#f2f4f9"
-         id="path10" />
-      <path
-         d="m 1259.07,60.66 c 0,-4.37 1.53,-8.07 4.6,-11.11 3.07,-3.03 6.82,-4.55 11.25,-4.55 4.43,0 8.19,1.52 11.25,4.55 3.07,3.03 4.6,6.74 4.6,11.11 0,4.37 -1.53,8.27 -4.6,11.3 -3.07,3.03 -6.82,4.55 -11.25,4.55 -4.43,0 -8.19,-1.52 -11.25,-4.55 -3.07,-3.03 -4.6,-6.8 -4.6,-11.3 z m 29.07,33.86 v 99.43 h -26.23 V 94.52 Z"
-         fill="#f2f4f9"
-         id="path11" />
-      <path
-         d="m 1347.25,175.74 c 4.44,0 7.93,-0.86 10.47,-2.59 2.54,-1.73 3.82,-4.22 3.82,-7.49 0,-4.83 -3.23,-8.03 -9.69,-9.59 l -13.21,-3.62 c -10.05,-2.61 -17.37,-6.36 -21.97,-11.25 -4.6,-4.89 -6.9,-10.89 -6.9,-18.01 0,-9.39 3.39,-17.03 10.18,-22.9 6.78,-5.87 15.95,-8.81 27.5,-8.81 10.18,0 18.69,2.33 25.54,7 6.85,4.67 11.02,11.11 12.53,19.33 l -23.39,5.38 c -0.39,-3.26 -1.86,-5.84 -4.4,-7.73 -2.54,-1.89 -5.71,-2.84 -9.49,-2.84 -3.98,0 -7.11,0.9 -9.39,2.69 -2.28,1.79 -3.42,4.29 -3.42,7.49 0,2.41 0.88,4.4 2.64,5.97 1.76,1.57 4.63,2.9 8.61,4.01 l 13.02,3.43 c 9.2,2.41 16.18,6.13 20.94,11.16 4.76,5.02 7.14,11.12 7.14,18.3 0,9.39 -3.59,16.9 -10.76,22.51 -7.18,5.61 -16.96,8.42 -29.36,8.42 -12.4,0 -21.22,-2.53 -28.23,-7.58 -7.01,-5.05 -11.14,-11.95 -12.38,-20.7 l 23.98,-4.01 c 0.33,3.52 1.92,6.31 4.8,8.37 2.87,2.05 6.69,3.08 11.45,3.08 z"
-         fill="#f2f4f9"
-         id="path12" />
-      <path
-         d="m 1462.53,193.94 c -6.39,1.63 -12.43,2.45 -18.1,2.45 -10.63,0 -18.87,-2.85 -24.71,-8.56 -5.84,-5.71 -8.76,-14.37 -8.76,-25.98 v -44.82 h -15.17 V 94.52 h 15.17 V 63.69 h 25.83 v 30.83 h 22.9 v 22.51 h -22.9 v 40.02 c -0.2,10.7 4.01,16.05 12.62,16.05 3.07,0 6.43,-0.59 10.08,-1.76 l 3.03,22.61 z"
-         fill="#f2f4f9"
-         id="path13" />
-      <path
-         d="m 1542.67,193.94 c -0.59,-3.13 -1.08,-6.52 -1.47,-10.18 -2.81,3.85 -6.77,6.95 -11.89,9.3 -5.12,2.35 -10.98,3.52 -17.57,3.52 -10.83,0 -19.56,-2.9 -26.18,-8.71 -6.62,-5.81 -9.93,-13.67 -9.93,-23.58 0,-9.91 3.21,-17.53 9.64,-23.05 6.42,-5.51 15.25,-8.27 26.47,-8.27 h 28.87 v -3.33 c 0,-5.74 -1.73,-10.01 -5.19,-12.82 -3.46,-2.8 -8.29,-4.21 -14.48,-4.21 -10.96,0 -18.82,4.67 -23.58,13.99 l -19.08,-10.86 c 8.55,-16.18 23.32,-24.27 44.33,-24.27 12.66,0 23.06,3.3 31.22,9.88 8.15,6.59 12.23,17.29 12.23,32.1 v 38.07 c 0,10.83 0.62,18.3 1.86,22.41 h -25.25 z m -1.86,-43.06 h -22.8 c -5.02,0 -8.92,1.16 -11.69,3.47 -2.77,2.32 -4.16,5.5 -4.16,9.54 0,4.04 1.45,7.31 4.35,9.59 2.9,2.29 7,3.43 12.28,3.43 6.46,0 11.74,-1.96 15.85,-5.87 4.11,-3.91 6.17,-9.98 6.17,-18.2 z"
-         fill="#f2f4f9"
-         id="path14" />
-      <path
-         d="m 1682.71,132.78 v 61.16 h -26.13 v -55.49 c 0,-9.07 -2.05,-15.17 -6.17,-18.3 -4.18,-3.2 -8.81,-4.79 -13.9,-4.79 -5.94,0 -11.19,1.79 -15.75,5.38 -4.7,3.72 -7.05,9.82 -7.05,18.3 v 54.9 h -26.03 V 94.52 h 24.66 l 0.78,9.88 c 2.8,-3.91 6.83,-7.05 12.09,-9.39 5.25,-2.35 10.91,-3.52 16.98,-3.52 12.85,0 22.82,3.61 29.9,10.81 7.08,7.21 10.62,17.37 10.62,30.48 z"
-         fill="#f2f4f9"
-         id="path15" />
-      <path
-         d="m 1762.08,193.94 c -6.39,1.63 -12.43,2.45 -18.1,2.45 -10.63,0 -18.87,-2.85 -24.71,-8.56 -5.84,-5.71 -8.76,-14.37 -8.76,-25.98 v -44.82 h -15.17 V 94.52 h 15.17 V 63.69 h 25.83 v 30.83 h 22.9 v 22.51 h -22.9 v 40.02 c -0.2,10.7 4.01,16.05 12.62,16.05 3.07,0 6.43,-0.59 10.08,-1.76 l 3.03,22.61 z"
-         fill="#f2f4f9"
-         id="path16" />
-    </g>
-  </g>
-  <defs
-     id="defs18">
-    <clipPath
-       id="clip0_3_51">
-      <rect
-         width="1762"
-         height="240"
-         fill="#ffffff"
-         id="rect17"
-         x="0"
-         y="0" />
-    </clipPath>
-    <clipPath
-       id="clip1_3_51">
-      <rect
-         width="1426"
-         height="154"
-         fill="#ffffff"
-         transform="translate(336,43)"
-         id="rect18"
-         x="0"
-         y="0" />
-    </clipPath>
-    <clipPath
-       clipPathUnits="userSpaceOnUse"
-       id="clipPath19">
-      <rect
-         style="fill:none;fill-opacity:1;stroke-width:0.904839"
-         id="rect20"
-         width="239.88728"
-         height="239.55457"
-         x="0.14213564"
-         y="0.010407645" />
-    </clipPath>
-  </defs>
-</svg>
diff --git a/music_assistant/providers/builtin_player/icon_monochrome.svg b/music_assistant/providers/builtin_player/icon_monochrome.svg
deleted file mode 100644 (file)
index 23c48c6..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg
-   width="240"
-   height="240"
-   viewBox="0 0 240 240"
-   fill="none"
-   version="1.1"
-   id="svg18"
-   sodipodi:docname="icon_monochrome.svg"
-   inkscape:version="1.3.2 (091e20e, 2023-11-25, custom)"
-   inkscape:export-filename="icon.svg"
-   inkscape:export-xdpi="96"
-   inkscape:export-ydpi="96"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:svg="http://www.w3.org/2000/svg">
-  <sodipodi:namedview
-     id="namedview18"
-     pagecolor="#000000"
-     bordercolor="#000000"
-     borderopacity="0.25"
-     inkscape:showpageshadow="2"
-     inkscape:pageopacity="0.0"
-     inkscape:pagecheckerboard="0"
-     inkscape:deskcolor="#d1d1d1"
-     inkscape:zoom="2.8284271"
-     inkscape:cx="120.38493"
-     inkscape:cy="119.32427"
-     inkscape:window-width="1920"
-     inkscape:window-height="1129"
-     inkscape:window-x="-8"
-     inkscape:window-y="-8"
-     inkscape:window-maximized="1"
-     inkscape:current-layer="svg18" />
-  <path
-     d="m 109.394,6.3814 c 5.848,-5.84187 15.394,-5.84187 21.212,0 l 98.788,98.8876 c 5.848,5.842 10.606,17.374 10.606,25.638 v 90.11 l -0.005,0.356 c -0.206,8.086 -6.881,14.628 -14.995,14.628 H 15 C 6.75759,236.001 2.40473e-5,229.22 0,220.987 v -90.11 c 1.20331e-4,-8.264 4.78834,-19.796 10.6064,-25.638 z M 36,122.001 c -4.4183,0 -8,3.581 -8,8 v 78 h 16 v -78 c 0,-4.419 -3.5817,-8 -8,-8 z m 32,0 c -4.4183,0 -8,3.581 -8,8 v 78 h 16 v -78 c 0,-4.419 -3.5817,-8 -8,-8 z m 32,0 c -4.4183,0 -8,3.581 -8,8 v 78 h 16 v -78 c 0,-4.419 -3.582,-8 -8,-8 z m 58.393,0.426 c -4.193,-1.395 -8.722,0.873 -10.118,5.065 l -26.796,80.509 h 16.863 l 25.114,-75.457 c 1.395,-4.192 -0.872,-8.721 -5.063,-10.117 z m 30.315,5.065 c -1.395,-4.192 -5.925,-6.46 -10.117,-5.065 -4.192,1.396 -6.46,5.925 -5.065,10.117 l 25.116,75.457 h 16.862 z"
-     fill="#18bcf2"
-     id="path2"
-     clip-path="none"
-     style="fill:#ffffff;fill-opacity:1" />
-  <g
-     id="g3">
-    <rect
-       style="fill:none;fill-opacity:1;stroke-width:0.904839"
-       id="rect2"
-       width="239.88728"
-       height="239.55457"
-       x="0.14213564"
-       y="2.0104077" />
-  </g>
-  <g
-     clip-path="url(#clipPath1)"
-     id="g16"
-     transform="translate(0,2)">
-    <path
-       d="m 482.363,47.06 v 146.89 h -26.91 v -85.83 l -33.86,85.82 h -26.03 l -33.47,-85.14 v 85.14 h -26.23 V 47.06 h 26.23 l 46.48,114.99 46.88,-114.99 z"
-       fill="#f2f4f9"
-       id="path3" />
-    <path
-       d="m 581.292,193.94 c -0.85,-2.74 -1.47,-6.07 -1.86,-9.98 -5.94,8.42 -15.46,12.62 -28.58,12.62 -10.96,0 -20.65,-3.16 -29.06,-9.49 -8.02,-6.46 -12.04,-17.12 -12.04,-32 V 94.51 h 26.23 v 55.29 c 0,8.94 2.09,15.1 6.26,18.5 4.11,3.33 8.84,4.99 14.19,4.99 5.74,0 10.89,-1.79 15.46,-5.38 4.63,-3.65 6.95,-9.75 6.95,-18.3 V 94.52 h 26.32 v 81.03 c 0,6.65 0.65,12.79 1.96,18.4 h -25.83 z"
-       fill="#f2f4f9"
-       id="path4" />
-    <path
-       d="m 663.403,175.74 c 4.44,0 7.93,-0.86 10.47,-2.59 2.54,-1.73 3.82,-4.22 3.82,-7.49 0,-4.83 -3.23,-8.03 -9.69,-9.59 l -13.21,-3.62 c -10.05,-2.61 -17.37,-6.36 -21.97,-11.25 -4.6,-4.89 -6.9,-10.89 -6.9,-18.01 0,-9.39 3.39,-17.03 10.18,-22.9 6.78,-5.87 15.95,-8.81 27.5,-8.81 10.18,0 18.69,2.33 25.54,7 6.85,4.67 11.02,11.11 12.53,19.33 l -23.39,5.38 c -0.39,-3.26 -1.86,-5.84 -4.4,-7.73 -2.54,-1.89 -5.71,-2.84 -9.49,-2.84 -3.98,0 -7.11,0.9 -9.39,2.69 -2.28,1.79 -3.42,4.29 -3.42,7.49 0,2.41 0.88,4.4 2.64,5.97 1.76,1.57 4.63,2.9 8.61,4.01 l 13.02,3.43 c 9.2,2.41 16.18,6.13 20.94,11.16 4.76,5.02 7.14,11.12 7.14,18.3 0,9.39 -3.59,16.9 -10.76,22.51 -7.18,5.61 -16.96,8.42 -29.36,8.42 -12.4,0 -21.22,-2.53 -28.23,-7.58 -7.01,-5.05 -11.14,-11.95 -12.38,-20.7 l 23.98,-4.01 c 0.33,3.52 1.92,6.31 4.8,8.37 2.87,2.05 6.69,3.08 11.45,3.08 z"
-       fill="#f2f4f9"
-       id="path5" />
-    <path
-       d="m 720.062,60.66 c 0,-4.37 1.53,-8.07 4.6,-11.11 3.07,-3.03 6.82,-4.55 11.25,-4.55 4.43,0 8.19,1.52 11.25,4.55 3.07,3.03 4.6,6.74 4.6,11.11 0,4.37 -1.53,8.27 -4.6,11.3 -3.07,3.03 -6.82,4.55 -11.25,4.55 -4.43,0 -8.19,-1.52 -11.25,-4.55 -3.07,-3.03 -4.6,-6.8 -4.6,-11.3 z m 29.06,33.86 v 99.43 h -26.23 V 94.52 Z"
-       fill="#f2f4f9"
-       id="path6" />
-    <path
-       d="m 818.513,91.48 c 11.42,0 21.28,2.84 29.6,8.51 8.32,5.67 13.88,13.21 16.69,22.61 l -22.41,9 c -1.63,-4.96 -4.58,-8.94 -8.86,-11.94 -4.27,-3 -9.15,-4.5 -14.63,-4.5 -7.9,0 -14.11,2.63 -18.64,7.88 -4.54,5.25 -6.8,12.31 -6.8,21.19 0,8.88 2.3,15.87 6.9,20.99 4.6,5.12 10.78,7.68 18.54,7.68 5.61,0 10.57,-1.43 14.87,-4.31 4.31,-2.87 7.31,-6.72 9,-11.55 l 22.02,8.22 c -3.2,9.59 -9,17.21 -17.42,22.85 -8.42,5.64 -18.1,8.46 -29.06,8.46 -15.2,0 -27.52,-4.83 -36.94,-14.48 -9.43,-9.66 -14.14,-22.28 -14.14,-37.87 0,-15.59 4.73,-28.36 14.19,-38.12 9.46,-9.75 21.82,-14.63 37.09,-14.63 z"
-       fill="#f2f4f9"
-       id="path7" />
-    <path
-       d="m 1020.39,160.67 h -53.137 l -11.65,33.27 h -28.48 l 52.95,-146.88 h 27.687 l 52.84,146.89 h -29.06 l -11.16,-33.27 z m -8.02,-22.8 -18.497,-53.72 -18.59,53.72 z"
-       fill="#f2f4f9"
-       id="path8" />
-    <path
-       d="m 1109.45,175.74 c 4.44,0 7.93,-0.86 10.47,-2.59 2.54,-1.73 3.82,-4.22 3.82,-7.49 0,-4.83 -3.23,-8.03 -9.69,-9.59 l -13.21,-3.62 c -10.05,-2.61 -17.37,-6.36 -21.97,-11.25 -4.6,-4.89 -6.9,-10.89 -6.9,-18.01 0,-9.39 3.39,-17.03 10.18,-22.9 6.78,-5.87 15.95,-8.81 27.5,-8.81 10.18,0 18.69,2.33 25.54,7 6.85,4.67 11.02,11.11 12.53,19.33 l -23.39,5.38 c -0.39,-3.26 -1.86,-5.84 -4.4,-7.73 -2.54,-1.89 -5.71,-2.84 -9.49,-2.84 -3.98,0 -7.11,0.9 -9.39,2.69 -2.28,1.79 -3.42,4.29 -3.42,7.49 0,2.41 0.88,4.4 2.64,5.97 1.76,1.57 4.63,2.9 8.61,4.01 l 13.02,3.43 c 9.2,2.41 16.18,6.13 20.94,11.16 4.76,5.02 7.14,11.12 7.14,18.3 0,9.39 -3.59,16.9 -10.76,22.51 -7.18,5.61 -16.96,8.42 -29.36,8.42 -12.4,0 -21.22,-2.53 -28.23,-7.58 -7.01,-5.05 -11.14,-11.95 -12.38,-20.7 l 23.98,-4.01 c 0.33,3.52 1.92,6.31 4.8,8.37 2.87,2.05 6.69,3.08 11.45,3.08 z"
-       fill="#f2f4f9"
-       id="path9" />
-    <path
-       d="m 1202.41,175.74 c 4.44,0 7.93,-0.86 10.47,-2.59 2.54,-1.73 3.82,-4.22 3.82,-7.49 0,-4.83 -3.23,-8.03 -9.69,-9.59 l -13.21,-3.62 c -10.05,-2.61 -17.37,-6.36 -21.97,-11.25 -4.6,-4.89 -6.9,-10.89 -6.9,-18.01 0,-9.39 3.39,-17.03 10.18,-22.9 6.78,-5.87 15.95,-8.81 27.5,-8.81 10.18,0 18.69,2.33 25.54,7 6.85,4.67 11.02,11.11 12.53,19.33 l -23.39,5.38 c -0.39,-3.26 -1.86,-5.84 -4.4,-7.73 -2.54,-1.89 -5.71,-2.84 -9.49,-2.84 -3.98,0 -7.11,0.9 -9.39,2.69 -2.28,1.79 -3.42,4.29 -3.42,7.49 0,2.41 0.88,4.4 2.64,5.97 1.76,1.57 4.63,2.9 8.61,4.01 l 13.02,3.43 c 9.2,2.41 16.18,6.13 20.94,11.16 4.76,5.02 7.14,11.12 7.14,18.3 0,9.39 -3.59,16.9 -10.76,22.51 -7.18,5.61 -16.96,8.42 -29.36,8.42 -12.4,0 -21.22,-2.53 -28.23,-7.58 -7.01,-5.05 -11.14,-11.95 -12.38,-20.7 l 23.98,-4.01 c 0.33,3.52 1.92,6.31 4.8,8.37 2.87,2.05 6.69,3.08 11.45,3.08 z"
-       fill="#f2f4f9"
-       id="path10" />
-    <path
-       d="m 1259.07,60.66 c 0,-4.37 1.53,-8.07 4.6,-11.11 3.07,-3.03 6.82,-4.55 11.25,-4.55 4.43,0 8.19,1.52 11.25,4.55 3.07,3.03 4.6,6.74 4.6,11.11 0,4.37 -1.53,8.27 -4.6,11.3 -3.07,3.03 -6.82,4.55 -11.25,4.55 -4.43,0 -8.19,-1.52 -11.25,-4.55 -3.07,-3.03 -4.6,-6.8 -4.6,-11.3 z m 29.07,33.86 v 99.43 h -26.23 V 94.52 Z"
-       fill="#f2f4f9"
-       id="path11" />
-    <path
-       d="m 1347.25,175.74 c 4.44,0 7.93,-0.86 10.47,-2.59 2.54,-1.73 3.82,-4.22 3.82,-7.49 0,-4.83 -3.23,-8.03 -9.69,-9.59 l -13.21,-3.62 c -10.05,-2.61 -17.37,-6.36 -21.97,-11.25 -4.6,-4.89 -6.9,-10.89 -6.9,-18.01 0,-9.39 3.39,-17.03 10.18,-22.9 6.78,-5.87 15.95,-8.81 27.5,-8.81 10.18,0 18.69,2.33 25.54,7 6.85,4.67 11.02,11.11 12.53,19.33 l -23.39,5.38 c -0.39,-3.26 -1.86,-5.84 -4.4,-7.73 -2.54,-1.89 -5.71,-2.84 -9.49,-2.84 -3.98,0 -7.11,0.9 -9.39,2.69 -2.28,1.79 -3.42,4.29 -3.42,7.49 0,2.41 0.88,4.4 2.64,5.97 1.76,1.57 4.63,2.9 8.61,4.01 l 13.02,3.43 c 9.2,2.41 16.18,6.13 20.94,11.16 4.76,5.02 7.14,11.12 7.14,18.3 0,9.39 -3.59,16.9 -10.76,22.51 -7.18,5.61 -16.96,8.42 -29.36,8.42 -12.4,0 -21.22,-2.53 -28.23,-7.58 -7.01,-5.05 -11.14,-11.95 -12.38,-20.7 l 23.98,-4.01 c 0.33,3.52 1.92,6.31 4.8,8.37 2.87,2.05 6.69,3.08 11.45,3.08 z"
-       fill="#f2f4f9"
-       id="path12" />
-    <path
-       d="m 1462.53,193.94 c -6.39,1.63 -12.43,2.45 -18.1,2.45 -10.63,0 -18.87,-2.85 -24.71,-8.56 -5.84,-5.71 -8.76,-14.37 -8.76,-25.98 v -44.82 h -15.17 V 94.52 h 15.17 V 63.69 h 25.83 v 30.83 h 22.9 v 22.51 h -22.9 v 40.02 c -0.2,10.7 4.01,16.05 12.62,16.05 3.07,0 6.43,-0.59 10.08,-1.76 l 3.03,22.61 z"
-       fill="#f2f4f9"
-       id="path13" />
-    <path
-       d="m 1542.67,193.94 c -0.59,-3.13 -1.08,-6.52 -1.47,-10.18 -2.81,3.85 -6.77,6.95 -11.89,9.3 -5.12,2.35 -10.98,3.52 -17.57,3.52 -10.83,0 -19.56,-2.9 -26.18,-8.71 -6.62,-5.81 -9.93,-13.67 -9.93,-23.58 0,-9.91 3.21,-17.53 9.64,-23.05 6.42,-5.51 15.25,-8.27 26.47,-8.27 h 28.87 v -3.33 c 0,-5.74 -1.73,-10.01 -5.19,-12.82 -3.46,-2.8 -8.29,-4.21 -14.48,-4.21 -10.96,0 -18.82,4.67 -23.58,13.99 l -19.08,-10.86 c 8.55,-16.18 23.32,-24.27 44.33,-24.27 12.66,0 23.06,3.3 31.22,9.88 8.15,6.59 12.23,17.29 12.23,32.1 v 38.07 c 0,10.83 0.62,18.3 1.86,22.41 h -25.25 z m -1.86,-43.06 h -22.8 c -5.02,0 -8.92,1.16 -11.69,3.47 -2.77,2.32 -4.16,5.5 -4.16,9.54 0,4.04 1.45,7.31 4.35,9.59 2.9,2.29 7,3.43 12.28,3.43 6.46,0 11.74,-1.96 15.85,-5.87 4.11,-3.91 6.17,-9.98 6.17,-18.2 z"
-       fill="#f2f4f9"
-       id="path14" />
-    <path
-       d="m 1682.71,132.78 v 61.16 h -26.13 v -55.49 c 0,-9.07 -2.05,-15.17 -6.17,-18.3 -4.18,-3.2 -8.81,-4.79 -13.9,-4.79 -5.94,0 -11.19,1.79 -15.75,5.38 -4.7,3.72 -7.05,9.82 -7.05,18.3 v 54.9 h -26.03 V 94.52 h 24.66 l 0.78,9.88 c 2.8,-3.91 6.83,-7.05 12.09,-9.39 5.25,-2.35 10.91,-3.52 16.98,-3.52 12.85,0 22.82,3.61 29.9,10.81 7.08,7.21 10.62,17.37 10.62,30.48 z"
-       fill="#f2f4f9"
-       id="path15" />
-    <path
-       d="m 1762.08,193.94 c -6.39,1.63 -12.43,2.45 -18.1,2.45 -10.63,0 -18.87,-2.85 -24.71,-8.56 -5.84,-5.71 -8.76,-14.37 -8.76,-25.98 v -44.82 h -15.17 V 94.52 h 15.17 V 63.69 h 25.83 v 30.83 h 22.9 v 22.51 h -22.9 v 40.02 c -0.2,10.7 4.01,16.05 12.62,16.05 3.07,0 6.43,-0.59 10.08,-1.76 l 3.03,22.61 z"
-       fill="#f2f4f9"
-       id="path16" />
-  </g>
-  <defs
-     id="defs18">
-    <clipPath
-       id="clip0_3_51">
-      <rect
-         width="1762"
-         height="240"
-         fill="#ffffff"
-         id="rect17"
-         x="0"
-         y="0" />
-    </clipPath>
-    <clipPath
-       id="clip1_3_51">
-      <rect
-         width="1426"
-         height="154"
-         fill="#ffffff"
-         transform="translate(336,43)"
-         id="rect18"
-         x="0"
-         y="0" />
-    </clipPath>
-    <clipPath
-       clipPathUnits="userSpaceOnUse"
-       id="clipPath1">
-      <g
-         id="g2"
-         transform="translate(0,-2)">
-        <rect
-           style="fill:none;fill-opacity:1;stroke-width:0.904839"
-           id="rect1"
-           width="239.88728"
-           height="239.55457"
-           x="0.14213564"
-           y="2.0104077" />
-      </g>
-    </clipPath>
-    <clipPath
-       clipPathUnits="userSpaceOnUse"
-       id="clipPath3">
-      <g
-         id="g4">
-        <rect
-           style="fill:none;fill-opacity:1;stroke-width:0.904839"
-           id="rect3"
-           width="239.88728"
-           height="239.55457"
-           x="0.14213564"
-           y="2.0104077" />
-      </g>
-    </clipPath>
-  </defs>
-</svg>
diff --git a/music_assistant/providers/builtin_player/manifest.json b/music_assistant/providers/builtin_player/manifest.json
deleted file mode 100644 (file)
index 7ee7a8a..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "type": "player",
-  "domain": "builtin_player",
-  "stage": "alpha",
-  "name": "Builtin Web Player",
-  "description": "Control playback and listen directly through the Music Assistant web interface.",
-  "codeowners": ["@music-assistant"],
-  "documentation": "https://music-assistant.io/player-support/builtin/",
-  "multi_instance": false,
-  "builtin": true,
-  "allow_disable": false
-}
diff --git a/music_assistant/providers/builtin_player/player.py b/music_assistant/providers/builtin_player/player.py
deleted file mode 100644 (file)
index 54f881f..0000000
+++ /dev/null
@@ -1,312 +0,0 @@
-"""Player model implementation for the Built-in Player."""
-
-from __future__ import annotations
-
-from collections.abc import Callable
-from time import time
-
-from aiohttp import web
-from music_assistant_models.builtin_player import BuiltinPlayerEvent, BuiltinPlayerState
-from music_assistant_models.config_entries import ConfigEntry, ConfigValueType
-from music_assistant_models.constants import PLAYER_CONTROL_NATIVE
-from music_assistant_models.enums import (
-    BuiltinPlayerEventType,
-    ConfigEntryType,
-    ContentType,
-    EventType,
-    PlaybackState,
-    PlayerFeature,
-    PlayerType,
-)
-from music_assistant_models.media_items import AudioFormat
-
-from music_assistant.constants import (
-    CONF_ENTRY_FLOW_MODE_ENFORCED,
-    CONF_ENTRY_HTTP_PROFILE_HIDDEN,
-    CONF_ENTRY_OUTPUT_CODEC_HIDDEN,
-    CONF_MUTE_CONTROL,
-    CONF_POWER_CONTROL,
-    CONF_VOLUME_CONTROL,
-    DEFAULT_STREAM_HEADERS,
-    INTERNAL_PCM_FORMAT,
-    create_sample_rates_config_entry,
-)
-from music_assistant.helpers.audio import get_player_filter_params
-from music_assistant.helpers.ffmpeg import get_ffmpeg_stream
-from music_assistant.models.player import DeviceInfo, Player, PlayerMedia
-from music_assistant.models.player_provider import PlayerProvider
-
-# If the player does not send an update within this time, it will be considered offline
-DURATION_UNTIL_TIMEOUT = 120  # 60 second extra headroom
-POLL_INTERVAL = 30
-
-
-class BuiltinPlayer(Player):
-    """Representation of a Builtin Player."""
-
-    last_update: float
-    unregister_cbs: list[Callable[[], None]] = []
-
-    def __init__(
-        self,
-        player_id: str,
-        provider: PlayerProvider,
-        name: str,
-        features: tuple[PlayerFeature, ...],
-    ) -> None:
-        """Initialize the Builtin Player."""
-        super().__init__(provider, player_id)
-        self._attr_type = PlayerType.PLAYER
-        self._attr_power_control = PLAYER_CONTROL_NATIVE
-        self._attr_device_info = DeviceInfo()
-        self._attr_supported_features = set(features)
-        self._attr_needs_poll = True
-        self._attr_poll_interval = POLL_INTERVAL
-        self._attr_hidden_by_default = True
-        self._attr_expose_to_ha_by_default = False
-        self.register(name, False)
-
-    def unregister_routes(self) -> None:
-        """Unregister all routes associated with this player."""
-        for cb in self.unregister_cbs:
-            cb()
-        self.unregister_cbs.clear()
-        self._attr_available = False
-        self._attr_playback_state = PlaybackState.IDLE
-        self._attr_powered = False
-        self._attr_needs_poll = False
-        self.update_state()
-
-    def register(self, player_name: str, update_state: bool = True) -> None:
-        """Register the player for playback."""
-        if not self.unregister_cbs:
-            self.unregister_cbs = [
-                self.mass.webserver.register_dynamic_route(
-                    f"/builtin_player/flow/{self.player_id}.mp3", self._serve_audio_stream
-                ),
-            ]
-
-        self._attr_playback_state = PlaybackState.IDLE
-        self._attr_name = player_name
-        self._attr_available = True
-        self._attr_powered = False
-        self._attr_needs_poll = True
-        self.last_update = time()
-        if update_state:
-            self.update_state()
-
-    async def get_config_entries(
-        self,
-        action: str | None = None,
-        values: dict[str, ConfigValueType] | None = None,
-    ) -> list[ConfigEntry]:
-        """Return all (provider/player specific) Config Entries for the player."""
-        base_entries = await super().get_config_entries(action=action, values=values)
-        return [
-            *base_entries,
-            CONF_ENTRY_FLOW_MODE_ENFORCED,
-            # Hide power/volume/mute control options since they are guaranteed to work
-            ConfigEntry(
-                key=CONF_POWER_CONTROL,
-                type=ConfigEntryType.STRING,
-                label=CONF_POWER_CONTROL,
-                default_value=PLAYER_CONTROL_NATIVE,
-                hidden=True,
-            ),
-            ConfigEntry(
-                key=CONF_VOLUME_CONTROL,
-                type=ConfigEntryType.STRING,
-                label=CONF_VOLUME_CONTROL,
-                default_value=PLAYER_CONTROL_NATIVE,
-                hidden=True,
-            ),
-            ConfigEntry(
-                key=CONF_MUTE_CONTROL,
-                type=ConfigEntryType.STRING,
-                label=CONF_MUTE_CONTROL,
-                default_value=PLAYER_CONTROL_NATIVE,
-                hidden=True,
-            ),
-            CONF_ENTRY_HTTP_PROFILE_HIDDEN,
-            CONF_ENTRY_OUTPUT_CODEC_HIDDEN,
-            create_sample_rates_config_entry([48000]),
-        ]
-
-    async def stop(self) -> None:
-        """Send STOP command to player."""
-        self.mass.signal_event(
-            EventType.BUILTIN_PLAYER,
-            self.player_id,
-            BuiltinPlayerEvent(type=BuiltinPlayerEventType.STOP),
-        )
-        self._attr_current_media = None
-        self.update_state()
-
-    async def play(self) -> None:
-        """Send PLAY command to player."""
-        self.mass.signal_event(
-            EventType.BUILTIN_PLAYER,
-            self.player_id,
-            BuiltinPlayerEvent(type=BuiltinPlayerEventType.PLAY),
-        )
-
-    async def pause(self) -> None:
-        """Send PAUSE command to player."""
-        self.mass.signal_event(
-            EventType.BUILTIN_PLAYER,
-            self.player_id,
-            BuiltinPlayerEvent(type=BuiltinPlayerEventType.PAUSE),
-        )
-
-    async def volume_set(self, volume_level: int) -> None:
-        """Send VOLUME_SET command to player."""
-        self.mass.signal_event(
-            EventType.BUILTIN_PLAYER,
-            self.player_id,
-            BuiltinPlayerEvent(type=BuiltinPlayerEventType.SET_VOLUME, volume=volume_level),
-        )
-
-    async def volume_mute(self, muted: bool) -> None:
-        """Send VOLUME MUTE command to player."""
-        self.mass.signal_event(
-            EventType.BUILTIN_PLAYER,
-            self.player_id,
-            BuiltinPlayerEvent(
-                type=BuiltinPlayerEventType.MUTE if muted else BuiltinPlayerEventType.UNMUTE
-            ),
-        )
-
-    async def play_media(self, media: PlayerMedia) -> None:
-        """Handle PLAY MEDIA on player."""
-        url = f"builtin_player/flow/{self.player_id}.mp3"
-        self._attr_current_media = media
-        self._attr_playback_state = PlaybackState.PLAYING
-        self.update_state()
-        self.mass.signal_event(
-            EventType.BUILTIN_PLAYER,
-            self.player_id,
-            BuiltinPlayerEvent(type=BuiltinPlayerEventType.PLAY_MEDIA, media_url=url),
-        )
-
-    async def power(self, powered: bool) -> None:
-        """Send POWER ON command to player."""
-        self.mass.signal_event(
-            EventType.BUILTIN_PLAYER,
-            self.player_id,
-            BuiltinPlayerEvent(
-                type=BuiltinPlayerEventType.POWER_ON
-                if powered
-                else BuiltinPlayerEventType.POWER_OFF
-            ),
-        )
-        if not powered:
-            self._attr_powered = False
-            self.update_state()
-
-    async def poll(self) -> None:
-        """
-        Poll player for state updates.
-
-        This is called by the Player Manager;
-        if the 'needs_poll' property is True.
-        """
-        last_updated = time() - self.last_update
-        if last_updated > DURATION_UNTIL_TIMEOUT:
-            self.mass.signal_event(
-                EventType.BUILTIN_PLAYER,
-                self.player_id,
-                BuiltinPlayerEvent(type=BuiltinPlayerEventType.TIMEOUT),
-            )
-            self.unregister_routes()
-
-    async def on_unload(self) -> None:
-        """Handle logic when the player is unloaded from the Player controller."""
-        self.unregister_routes()
-
-    async def _serve_audio_stream(self, request: web.Request) -> web.StreamResponse:
-        """Serve the flow stream audio to a player."""
-        player_id = request.path.rsplit(".")[0].rsplit("/")[-1]
-        format_str = request.path.rsplit(".")[-1]
-        self.logger.debug("Serving audio stream to %s", player_id)
-
-        if not (player := self.mass.players.get(player_id)):
-            raise web.HTTPNotFound(reason=f"Unknown player: {player_id}")
-
-        headers = {
-            **DEFAULT_STREAM_HEADERS,
-            "Content-Type": f"audio/{format_str}",
-            "Accept-Ranges": "none",
-        }
-
-        resp = web.StreamResponse(status=200, reason="OK", headers=headers)
-        resp.enable_chunked_encoding()
-
-        await resp.prepare(request)
-
-        # return early if this is not a GET request
-        if request.method != "GET":
-            return resp
-
-        # Check for a client probe request (from an iPhone/iPad)
-        if (range_header := request.headers.get("Range")) and range_header == "bytes=0-1":
-            self.logger.debug("Client is probing the stream.")
-            # We don't early exit here since playback would otherwise never start
-            # on iOS devices with Home Assistant OS installations.
-
-        media = player._current_media
-        if media is None:
-            raise web.HTTPNotFound(reason="No active media found!")
-
-        # TODO: set encoding quality using a bitrate parameter,
-        # maybe even dynamic with auto/semiauto switching with bad network?
-        if format_str == "mp3":
-            stream_format = AudioFormat(content_type=ContentType.MP3)
-        else:
-            stream_format = AudioFormat(content_type=ContentType.FLAC)
-
-        pcm_format = AudioFormat(
-            sample_rate=stream_format.sample_rate,
-            content_type=INTERNAL_PCM_FORMAT.content_type,
-            bit_depth=INTERNAL_PCM_FORMAT.bit_depth,
-            channels=INTERNAL_PCM_FORMAT.channels,
-        )
-
-        async for chunk in get_ffmpeg_stream(
-            # Use get_stream helper which handles all media types including UGP streams
-            audio_input=self.mass.streams.get_stream(media, pcm_format),
-            input_format=pcm_format,
-            output_format=stream_format,
-            # Apple ignores "Accept-Ranges=none" on iOS and iPadOS for some reason,
-            # so we need to slowly feed the music to avoid the Browser stopping and later
-            # restarting the audio stream (from a wrong position!) by keeping the buffer short.
-            extra_input_args=["-readrate", "1.02", "-readrate_initial_burst", "6"],
-            filter_params=get_player_filter_params(self.mass, player_id, pcm_format, stream_format),
-        ):
-            try:
-                await resp.write(chunk)
-            except (ConnectionError, ConnectionResetError):
-                break
-
-        return resp
-
-    def update_builtin_player_state(self, state: BuiltinPlayerState) -> None:
-        """Update the current state of the player."""
-        self._attr_elapsed_time_last_updated = time()
-        self.last_update = time()
-        self._attr_elapsed_time = float(state.position)
-        self._attr_volume_muted = state.muted
-        self._attr_volume_level = state.volume
-        if not state.powered:
-            self._attr_powered = False
-            self._attr_playback_state = PlaybackState.IDLE
-        elif state.playing:
-            self._attr_powered = True
-            self._attr_playback_state = PlaybackState.PLAYING
-        elif state.paused:
-            self._attr_powered = True
-            self._attr_playback_state = PlaybackState.PAUSED
-        else:
-            self._attr_powered = True
-            self._attr_playback_state = PlaybackState.IDLE
-
-        self.update_state()
diff --git a/music_assistant/providers/builtin_player/provider.py b/music_assistant/providers/builtin_player/provider.py
deleted file mode 100644 (file)
index 5d40589..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-"""Provider implementation for the Built-in Player."""
-
-from __future__ import annotations
-
-from collections.abc import Callable
-from typing import TYPE_CHECKING, cast
-
-import shortuuid
-from music_assistant_models.builtin_player import BuiltinPlayerEvent, BuiltinPlayerState
-from music_assistant_models.enums import BuiltinPlayerEventType, EventType, PlayerFeature
-
-from music_assistant.controllers.webserver.helpers.auth_middleware import get_current_user
-from music_assistant.models.player import Player
-from music_assistant.models.player_provider import PlayerProvider
-
-from .player import BuiltinPlayer
-
-
-class BuiltinPlayerProvider(PlayerProvider):
-    """Builtin Player Provider for playing to the Music Assistant Web Interface."""
-
-    _unregister_cbs: list[Callable[[], None]]
-
-    async def handle_async_init(self) -> None:
-        """Handle asynchronous initialization of the provider."""
-        self._unregister_cbs = [
-            self.mass.register_api_command("builtin_player/register", self.register_player),
-            self.mass.register_api_command("builtin_player/unregister", self.unregister_player),
-            self.mass.register_api_command("builtin_player/update_state", self.update_player_state),
-        ]
-
-    async def unload(self, is_removed: bool = False) -> None:
-        """
-        Handle unload/close of the provider.
-
-        Called when provider is deregistered (e.g. MA exiting or config reloading).
-        is_removed will be set to True when the provider is removed from the configuration.
-        """
-        for unload_cb in self._unregister_cbs:
-            unload_cb()
-
-    async def remove_player(self, player_id: str) -> None:
-        """Remove a player."""
-        self.mass.signal_event(
-            EventType.BUILTIN_PLAYER,
-            player_id,
-            BuiltinPlayerEvent(type=BuiltinPlayerEventType.TIMEOUT),
-        )
-        await self.unregister_player(player_id)
-
-    async def register_player(self, player_name: str, player_id: str | None) -> Player:
-        """Register a player.
-
-        Every player must first be registered through this `builtin_player/register` API command
-        before any playback can occur.
-        Since players queues can time out, this command either will create a new player queue,
-        or restore it from the last session.
-
-        - player_name: Human readable name of the player, will only be used in case this call
-                       creates a new queue.
-        - player_id: the id of the builtin player, set to None on new sessions. The returned player
-                     will have a new random player_id
-        """
-        if player_id is None:
-            player_id = f"ma_{shortuuid.random(10).lower()}"
-
-        player_features = {
-            PlayerFeature.VOLUME_SET,
-            PlayerFeature.VOLUME_MUTE,
-            PlayerFeature.PAUSE,
-            PlayerFeature.POWER,
-        }
-
-        # special case: user has player filter enabled but wants
-        # to use the builtin player on their device, so add it to their filter
-        current_user = get_current_user()
-        if (
-            current_user
-            and current_user.player_filter
-            and player_id not in current_user.player_filter
-        ):
-            current_user.player_filter.append(player_id)
-            await self.mass.webserver.auth.update_user_filters(
-                current_user, player_filter=current_user.player_filter, provider_filter=None
-            )
-
-        player = self.mass.players.get(player_id)
-
-        if player is None:
-            player = BuiltinPlayer(
-                player_id=player_id,
-                provider=self,
-                name=player_name,
-                features=tuple(player_features),
-            )
-            await self.mass.players.register_or_update(player)
-        else:
-            if TYPE_CHECKING:
-                player = cast("BuiltinPlayer", player)
-            player.register(player_name)
-
-        return player
-
-    async def unregister_player(self, player_id: str) -> None:
-        """Manually unregister a player with `builtin_player/unregister`."""
-        if player := self.mass.players.get(player_id):
-            if TYPE_CHECKING:
-                player = cast("BuiltinPlayer", player)
-            player.unregister_routes()
-
-    async def update_player_state(self, player_id: str, state: BuiltinPlayerState) -> bool:
-        """Update current state of a player.
-
-        A player must periodically update the state of through this `builtin_player/update_state`
-        API command.
-
-        Returns False in case the player already timed out or simply doesn't exist.
-        In that case, register the player first with `builtin_player/register`.
-        """
-        if not (player := self.mass.players.get(player_id)):
-            return False
-
-        if TYPE_CHECKING:
-            player = cast("BuiltinPlayer", player)
-
-        player.update_builtin_player_state(state)
-
-        return True