/
/
/
1"""Model/base for a Metadata Provider implementation."""
2
3from __future__ import annotations
4
5from typing import TYPE_CHECKING
6
7from .provider import Provider
8
9if TYPE_CHECKING:
10 from music_assistant.models.player import Player
11
12
13class PlayerProvider(Provider):
14 """
15 Base representation of a Player Provider (controller).
16
17 Player Provider implementations should inherit from this base model.
18 """
19
20 async def loaded_in_mass(self) -> None:
21 """Call after the provider has been loaded."""
22
23 def on_player_enabled(self, player_id: str) -> None:
24 """Call (by config manager) when a player gets enabled."""
25 # default implementation: trigger discovery - feel free to override
26 task_id = f"discover_players_{self.instance_id}"
27 self.mass.call_later(5, self.mass.run_provider_discovery, self.instance_id, task_id=task_id)
28
29 def on_player_disabled(self, player_id: str) -> None:
30 """Call (by config manager) when a player gets disabled."""
31 # default implementation: unregister player from player controller
32 # which will also trigger an unload on the player instance
33 # feel free to override with a better implementation
34 self.mass.create_task(self.mass.players.unregister(player_id))
35
36 async def remove_player(self, player_id: str) -> None:
37 """Remove a player from this provider."""
38 # will only be called for providers with REMOVE_PLAYER feature set.
39 raise NotImplementedError
40
41 async def create_group_player(
42 self, name: str, members: list[str], dynamic: bool = True
43 ) -> Player:
44 """
45 Create new Group Player.
46
47 Only called for providers that support CREATE_GROUP_PLAYER feature.
48
49 :param name: Name of the group player
50 :param members: List of player ids to add to the group
51 :param dynamic: Whether the group is dynamic (members can change)
52 """
53 raise NotImplementedError
54
55 async def remove_group_player(self, player_id: str) -> None:
56 """
57 Remove a group player.
58
59 Only called for providers that support REMOVE_GROUP_PLAYER feature.
60
61 :param player_id: ID of the group player to remove.
62 """
63 raise NotImplementedError
64
65 async def discover_players(self) -> None:
66 """Discover players for this provider."""
67 # This will be called when the player provider is (re)loaded into MA.
68 # For providers that support dynamic discovery of players via mdns,
69 # there is no need to implement this method.
70
71 @property
72 def players(self) -> list[Player]:
73 """Return all players belonging to this provider."""
74 return self.mass.players.all_players(
75 provider_filter=self.instance_id, return_protocol_players=True
76 )
77