ConfigEntry,
ConfigValueOption,
)
-from music_assistant_models.enums import ConfigEntryType, ContentType
+from music_assistant_models.enums import ConfigEntryType, ContentType, HidePlayerOption
from music_assistant_models.media_items import AudioFormat
API_SCHEMA_VERSION: Final[int] = 26
CONF_AUTO_PLAY: Final[str] = "auto_play"
CONF_CROSSFADE: Final[str] = "crossfade"
CONF_GROUP_MEMBERS: Final[str] = "group_members"
-CONF_HIDE_PLAYER: Final[str] = "hide_player"
+CONF_HIDE_PLAYER_IN_UI: Final[str] = "hide_player_in_ui"
+CONF_EXPOSE_PLAYER_TO_HA: Final[str] = "expose_player_to_ha"
CONF_SYNC_ADJUST: Final[str] = "sync_adjust"
CONF_TTS_PRE_ANNOUNCE: Final[str] = "tts_pre_announce"
CONF_ANNOUNCE_VOLUME_STRATEGY: Final[str] = "announce_volume_strategy"
default_value=False,
description="When this player is turned ON, automatically start playing "
"(if there are items in the queue).",
+ depends_on=CONF_POWER_CONTROL,
+ depends_on_value_not="none",
+ category="player_controls",
)
CONF_ENTRY_OUTPUT_CHANNELS = ConfigEntry(
category="advanced",
)
-CONF_ENTRY_HIDE_PLAYER = ConfigEntry(
- key=CONF_HIDE_PLAYER,
- type=ConfigEntryType.BOOLEAN,
+CONF_ENTRY_CROSSFADE_DURATION_HIDDEN = ConfigEntry.from_dict(
+ {**CONF_ENTRY_CROSSFADE_DURATION.to_dict(), "hidden": True}
+)
+
+CONF_ENTRY_HIDE_PLAYER_IN_UI = ConfigEntry(
+ key=CONF_HIDE_PLAYER_IN_UI,
+ type=ConfigEntryType.STRING,
label="Hide this player in the user interface",
- default_value=False,
+ multi_value=True,
+ options=[
+ ConfigValueOption("Always", HidePlayerOption.ALWAYS.value),
+ ConfigValueOption("When powered off", HidePlayerOption.WHEN_OFF.value),
+ ConfigValueOption("When group active", HidePlayerOption.WHEN_GROUP_ACTIVE.value),
+ ConfigValueOption("When synced", HidePlayerOption.WHEN_SYNCED.value),
+ ConfigValueOption("When unavailable", HidePlayerOption.WHEN_UNAVAILABLE.value),
+ ],
+ default_value=[
+ HidePlayerOption.WHEN_UNAVAILABLE.value,
+ HidePlayerOption.WHEN_GROUP_ACTIVE.value,
+ HidePlayerOption.WHEN_SYNCED.value,
+ ],
+)
+CONF_ENTRY_HIDE_PLAYER_IN_UI_ALWAYS_DEFAULT = ConfigEntry.from_dict(
+ {**CONF_ENTRY_HIDE_PLAYER_IN_UI.to_dict(), "default_value": [HidePlayerOption.ALWAYS.value]}
+)
+
+CONF_ENTRY_HIDE_PLAYER_IN_UI_GROUP_PLAYER = ConfigEntry.from_dict(
+ {
+ **CONF_ENTRY_HIDE_PLAYER_IN_UI.to_dict(),
+ "default_value": [HidePlayerOption.WHEN_UNAVAILABLE.value],
+ "options": [
+ ConfigValueOption("Always", HidePlayerOption.ALWAYS.value).to_dict(),
+ ConfigValueOption("When powered off", HidePlayerOption.WHEN_OFF.value).to_dict(),
+ ConfigValueOption(
+ "When unavailable", HidePlayerOption.WHEN_UNAVAILABLE.value
+ ).to_dict(),
+ ],
+ }
)
+CONF_ENTRY_EXPOSE_PLAYER_TO_HA = ConfigEntry(
+ key=CONF_EXPOSE_PLAYER_TO_HA,
+ type=ConfigEntryType.BOOLEAN,
+ label="Expose this player to Home Assistant",
+ default_value=True,
+ description="Expose this player to the Home Assistant integration. \n"
+ "If disabled, this player will not be imported into Home Assistant.",
+ category="advanced",
+ # NOTE: This setting is hidden for now, until the HA integration has been updated
+ hidden=True,
+)
+CONF_ENTRY_EXPOSE_PLAYER_TO_HA_DEFAULT_DISABLED = ConfigEntry.from_dict(
+ {**CONF_ENTRY_EXPOSE_PLAYER_TO_HA.to_dict(), "default_value": False}
+)
+
+
CONF_ENTRY_OUTPUT_CODEC = ConfigEntry(
key=CONF_OUTPUT_CODEC,
type=ConfigEntryType.STRING,
"other playback related issues. In most cases the default setting is fine.",
)
+CONF_ENTRY_HTTP_PROFILE_DEFAULT_1 = ConfigEntry.from_dict(
+ {**CONF_ENTRY_HTTP_PROFILE.to_dict(), "default_value": "chunked"}
+)
+
CONF_ENTRY_HTTP_PROFILE_FORCED_1 = ConfigEntry.from_dict(
- {**CONF_ENTRY_HTTP_PROFILE.to_dict(), "default_value": "chunked", "hidden": True}
+ {**CONF_ENTRY_HTTP_PROFILE_DEFAULT_1.to_dict(), "hidden": True}
)
CONF_ENTRY_HTTP_PROFILE_FORCED_2 = ConfigEntry.from_dict(
{
"hidden": True,
}
)
+CONF_ENTRY_HTTP_PROFILE_HIDDEN = ConfigEntry.from_dict(
+ {**CONF_ENTRY_HTTP_PROFILE.to_dict(), "hidden": True}
+)
+
CONF_ENTRY_ENABLE_ICY_METADATA = ConfigEntry(
key=CONF_ENABLE_ICY_METADATA,
return conf_entry
-BASE_PLAYER_CONFIG_ENTRIES = (
- # config entries that are valid for all players
- CONF_ENTRY_PLAYER_ICON,
- CONF_ENTRY_FLOW_MODE,
- CONF_ENTRY_VOLUME_NORMALIZATION,
- CONF_ENTRY_OUTPUT_LIMITER,
- CONF_ENTRY_AUTO_PLAY,
- CONF_ENTRY_VOLUME_NORMALIZATION_TARGET,
- CONF_ENTRY_HIDE_PLAYER,
- CONF_ENTRY_TTS_PRE_ANNOUNCE,
- CONF_ENTRY_SAMPLE_RATES,
- CONF_ENTRY_HTTP_PROFILE_FORCED_2,
- CONF_ENTRY_OUTPUT_CODEC,
-)
-
-
DEFAULT_STREAM_HEADERS = {
"Server": "Music Assistant",
"transferMode.dlna.org": "Streaming",
LOGGER.exception("Error while reading persistent storage file %s", filename)
LOGGER.debug("Started with empty storage: No persistent storage file found.")
- async def _migrate(self) -> None:
+ async def _migrate(self) -> None: # noqa: PLR0915
changed = False
# Older versions of MA can create corrupt entries with no domain if retrying
self._data[CONF_PROVIDERS][new_instance_id] = provider_config
changed = True
+ # migrate "hide_player" --> "hide_player_in_ui"
+ for player_id, player_config in list(self._data.get(CONF_PLAYERS, {}).items()):
+ if not (values := player_config.get("values")):
+ continue
+ if values.pop("hide_player", None):
+ player_config["values"]["hide_player_in_ui"] = ["always"]
+ changed = True
+
if changed:
await self._async_save()
)
from music_assistant_models.enums import (
EventType,
+ HidePlayerOption,
MediaType,
PlayerFeature,
PlayerState,
CONF_ENTRY_ANNOUNCE_VOLUME_MIN,
CONF_ENTRY_ANNOUNCE_VOLUME_STRATEGY,
CONF_ENTRY_PLAYER_ICON,
- CONF_HIDE_PLAYER,
+ CONF_HIDE_PLAYER_IN_UI,
CONF_MUTE_CONTROL,
CONF_PLAYERS,
CONF_POWER_CONTROL,
async def _set_player_state_from_config(self, player: Player, config: PlayerConfig) -> None:
"""Set player state from config."""
player.display_name = config.name or player.name or config.default_name or player.player_id
- player.hidden = config.get_value(CONF_HIDE_PLAYER)
+ player.hide_player_in_ui = {
+ HidePlayerOption(x) for x in config.get_value(CONF_HIDE_PLAYER_IN_UI)
+ }
player.icon = config.get_value(CONF_ENTRY_PLAYER_ICON.key)
player.power_control = config.get_value(CONF_POWER_CONTROL)
if player.power_control == PLAYER_CONTROL_FAKE:
PLAYER_CONTROL_NATIVE,
PLAYER_CONTROL_NONE,
)
-from music_assistant_models.enums import ConfigEntryType, PlayerFeature
+from music_assistant_models.enums import ConfigEntryType, PlayerFeature, PlayerType
from music_assistant_models.errors import UnsupportedFeaturedException
from zeroconf import ServiceStateChange
from zeroconf.asyncio import AsyncServiceInfo
from music_assistant.constants import (
- BASE_PLAYER_CONFIG_ENTRIES,
CONF_ENTRY_ANNOUNCE_VOLUME,
CONF_ENTRY_ANNOUNCE_VOLUME_MAX,
CONF_ENTRY_ANNOUNCE_VOLUME_MIN,
CONF_ENTRY_ANNOUNCE_VOLUME_STRATEGY,
+ CONF_ENTRY_AUTO_PLAY,
+ CONF_ENTRY_CROSSFADE_DURATION,
+ CONF_ENTRY_CROSSFADE_FLOW_MODE_REQUIRED,
+ CONF_ENTRY_EXPOSE_PLAYER_TO_HA,
+ CONF_ENTRY_EXPOSE_PLAYER_TO_HA_DEFAULT_DISABLED,
+ CONF_ENTRY_FLOW_MODE,
+ CONF_ENTRY_HIDE_PLAYER_IN_UI,
+ CONF_ENTRY_HIDE_PLAYER_IN_UI_ALWAYS_DEFAULT,
+ CONF_ENTRY_HIDE_PLAYER_IN_UI_GROUP_PLAYER,
+ CONF_ENTRY_OUTPUT_CHANNELS,
+ CONF_ENTRY_OUTPUT_CODEC,
+ CONF_ENTRY_OUTPUT_LIMITER,
+ CONF_ENTRY_PLAYER_ICON,
+ CONF_ENTRY_PLAYER_ICON_GROUP,
+ CONF_ENTRY_SAMPLE_RATES,
+ CONF_ENTRY_TTS_PRE_ANNOUNCE,
+ CONF_ENTRY_VOLUME_NORMALIZATION,
+ CONF_ENTRY_VOLUME_NORMALIZATION_TARGET,
CONF_MUTE_CONTROL,
CONF_POWER_CONTROL,
CONF_VOLUME_CONTROL,
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 = (
+ # config entries that are valid for all/most players
+ CONF_ENTRY_PLAYER_ICON,
+ CONF_ENTRY_FLOW_MODE,
+ CONF_ENTRY_CROSSFADE_FLOW_MODE_REQUIRED,
+ CONF_ENTRY_CROSSFADE_DURATION,
+ CONF_ENTRY_VOLUME_NORMALIZATION,
+ CONF_ENTRY_OUTPUT_LIMITER,
+ CONF_ENTRY_VOLUME_NORMALIZATION_TARGET,
+ CONF_ENTRY_TTS_PRE_ANNOUNCE,
+ )
+ if not (player := self.mass.players.get(player_id)):
+ return base_entries
+
+ if player.type == PlayerType.GROUP:
+ # return group player specific entries
+ return (
+ *base_entries,
+ CONF_ENTRY_PLAYER_ICON_GROUP,
+ CONF_ENTRY_HIDE_PLAYER_IN_UI_GROUP_PLAYER,
+ # add player control entries as hidden entries
+ 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,
+ # disable mute control for group players for now
+ # TODO: work out if all child players support mute control
+ default_value=PLAYER_CONTROL_NONE,
+ hidden=True,
+ ),
+ CONF_ENTRY_AUTO_PLAY,
+ )
return (
- *BASE_PLAYER_CONFIG_ENTRIES,
+ # config entries that are valid for all players
+ *base_entries,
+ (
+ CONF_ENTRY_HIDE_PLAYER_IN_UI_ALWAYS_DEFAULT
+ if player and player.hidden_by_default
+ else CONF_ENTRY_HIDE_PLAYER_IN_UI
+ ),
+ (
+ CONF_ENTRY_EXPOSE_PLAYER_TO_HA
+ if player and player.expose_to_ha_by_default
+ else CONF_ENTRY_EXPOSE_PLAYER_TO_HA_DEFAULT_DISABLED
+ ),
+ # add player control entries
+ *self._create_player_control_config_entries(player),
+ CONF_ENTRY_AUTO_PLAY,
+ CONF_ENTRY_SAMPLE_RATES,
+ CONF_ENTRY_OUTPUT_CODEC,
+ CONF_ENTRY_OUTPUT_CHANNELS,
# add default entries for announce feature
CONF_ENTRY_ANNOUNCE_VOLUME_STRATEGY,
CONF_ENTRY_ANNOUNCE_VOLUME,
CONF_ENTRY_ANNOUNCE_VOLUME_MIN,
CONF_ENTRY_ANNOUNCE_VOLUME_MAX,
+ CONF_ENTRY_HIDE_PLAYER_IN_UI_ALWAYS_DEFAULT
+ if player and player.hidden_by_default
+ else CONF_ENTRY_HIDE_PLAYER_IN_UI,
+ CONF_ENTRY_EXPOSE_PLAYER_TO_HA
+ if player and player.expose_to_ha_by_default
+ else CONF_ENTRY_EXPOSE_PLAYER_TO_HA_DEFAULT_DISABLED,
# add player control entries
- *self._create_player_control_config_entries(self.mass.players.get(player_id)),
+ *self._create_player_control_config_entries(player),
+ CONF_ENTRY_AUTO_PLAY,
)
async def on_player_config_change(self, config: PlayerConfig, changed_keys: set[str]) -> None:
# configuration entries. If you do not need player specific configuration entries,
# you can leave this method out completely to accept the default implementation.
# Please note that you need to call the super() method to get the default entries.
- return ()
+ return await super().get_player_config_entries(player_id)
async def on_player_config_change(self, config: PlayerConfig, changed_keys: set[str]) -> None:
"""Call (by config manager) when the configuration of a player changes."""
CONF_ENTRY_DEPRECATED_EQ_MID,
CONF_ENTRY_DEPRECATED_EQ_TREBLE,
CONF_ENTRY_FLOW_MODE_ENFORCED,
- CONF_ENTRY_OUTPUT_CHANNELS,
CONF_ENTRY_OUTPUT_CODEC_HIDDEN,
CONF_ENTRY_SYNC_ADJUST,
create_sample_rates_config_entry,
CONF_ENTRY_DEPRECATED_EQ_BASS,
CONF_ENTRY_DEPRECATED_EQ_MID,
CONF_ENTRY_DEPRECATED_EQ_TREBLE,
- CONF_ENTRY_OUTPUT_CHANNELS,
CONF_ENTRY_OUTPUT_CODEC_HIDDEN,
ConfigEntry(
key=CONF_ENCRYPTION,
import shortuuid
from aiohttp import web
-from music_assistant_models.builtin_player import (
- BuiltinPlayerEvent,
- BuiltinPlayerState,
-)
+from music_assistant_models.builtin_player import BuiltinPlayerEvent, BuiltinPlayerState
from music_assistant_models.constants import PLAYER_CONTROL_NONE
from music_assistant_models.enums import (
BuiltinPlayerEventType,
)
from music_assistant_models.errors import PlayerUnavailableError
from music_assistant_models.media_items import AudioFormat
-from music_assistant_models.player import (
- DeviceInfo,
- Player,
- PlayerMedia,
-)
+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,
DEFAULT_PCM_FORMAT,
DEFAULT_STREAM_HEADERS,
)
from music_assistant.models.player_provider import PlayerProvider
if TYPE_CHECKING:
- from music_assistant_models.config_entries import (
- ConfigEntry,
- ConfigValueType,
- ProviderConfig,
- )
+ from music_assistant_models.config_entries import ConfigEntry, ConfigValueType, ProviderConfig
from music_assistant_models.provider import ProviderManifest
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:
from uuid import UUID
import pychromecast
-from music_assistant_models.config_entries import ConfigEntry
-from music_assistant_models.constants import PLAYER_CONTROL_NATIVE
-from music_assistant_models.enums import (
- ConfigEntryType,
- MediaType,
- PlayerFeature,
- PlayerState,
- PlayerType,
-)
+from music_assistant_models.enums import MediaType, PlayerFeature, PlayerState, PlayerType
from music_assistant_models.errors import PlayerUnavailableError
from music_assistant_models.player import DeviceInfo, Player, PlayerMedia
from pychromecast.controllers.media import STREAM_TYPE_BUFFERED, STREAM_TYPE_LIVE, MediaController
from pychromecast.socket_client import CONNECTION_STATUS_CONNECTED, CONNECTION_STATUS_DISCONNECTED
from music_assistant.constants import (
- BASE_PLAYER_CONFIG_ENTRIES,
CONF_ENTRY_CROSSFADE_DURATION,
CONF_ENTRY_CROSSFADE_FLOW_MODE_REQUIRED,
+ CONF_ENTRY_HTTP_PROFILE,
CONF_ENTRY_MANUAL_DISCOVERY_IPS,
CONF_ENTRY_OUTPUT_CODEC,
- CONF_MUTE_CONTROL,
CONF_PLAYERS,
- CONF_POWER_CONTROL,
- CONF_VOLUME_CONTROL,
MASS_LOGO_ONLINE,
VERBOSE_LOG_LEVEL,
create_sample_rates_config_entry,
from .helpers import CastStatusListener, ChromecastInfo
if TYPE_CHECKING:
- from music_assistant_models.config_entries import ConfigValueType, ProviderConfig
+ from music_assistant_models.config_entries import ConfigEntry, ConfigValueType, ProviderConfig
from music_assistant_models.provider import ProviderManifest
from pychromecast.controllers.media import MediaStatus
from pychromecast.controllers.receiver import CastStatus
from music_assistant.models import ProviderInstanceType
-PLAYER_CONFIG_ENTRIES = (
+CAST_PLAYER_CONFIG_ENTRIES = (
CONF_ENTRY_CROSSFADE_FLOW_MODE_REQUIRED,
CONF_ENTRY_CROSSFADE_DURATION,
CONF_ENTRY_OUTPUT_CODEC,
+ CONF_ENTRY_HTTP_PROFILE,
)
# originally/officially cast supports 96k sample rate (even for groups)
CONF_ENTRY_SAMPLE_RATES_CAST = create_sample_rates_config_entry(
max_sample_rate=192000,
max_bit_depth=24,
+ safe_max_sample_rate=48000,
+ safe_max_bit_depth=16,
)
CONF_ENTRY_SAMPLE_RATES_CAST_GROUP = create_sample_rates_config_entry(
max_sample_rate=96000,
max_bit_depth=24,
+ safe_max_sample_rate=48000,
+ safe_max_bit_depth=16,
)
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)."""
cast_player = self.castplayers.get(player_id)
+ base_entries = await super().get_player_config_entries(player_id)
if cast_player and cast_player.player.type == PlayerType.GROUP:
return (
- *BASE_PLAYER_CONFIG_ENTRIES,
- *PLAYER_CONFIG_ENTRIES,
+ *base_entries,
+ *CAST_PLAYER_CONFIG_ENTRIES,
CONF_ENTRY_SAMPLE_RATES_CAST_GROUP,
- # add player control entries as hidden entries
- 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,
- ),
)
- base_entries = await super().get_player_config_entries(player_id)
- return (*base_entries, *PLAYER_CONFIG_ENTRIES, CONF_ENTRY_SAMPLE_RATES_CAST)
+
+ return (*base_entries, *CAST_PLAYER_CONFIG_ENTRIES, CONF_ENTRY_SAMPLE_RATES_CAST)
async def cmd_stop(self, player_id: str) -> None:
"""Send STOP command to given player."""
CONF_ENTRY_CROSSFADE,
CONF_ENTRY_CROSSFADE_DURATION,
CONF_ENTRY_FLOW_MODE_ENFORCED,
+ CONF_ENTRY_HTTP_PROFILE,
CONF_ENTRY_OUTPUT_CODEC_DEFAULT_MP3,
CONF_IP_ADDRESS,
CONF_PASSWORD,
CONF_ENTRY_CROSSFADE,
CONF_ENTRY_CROSSFADE_DURATION,
CONF_ENTRY_OUTPUT_CODEC_DEFAULT_MP3,
+ CONF_ENTRY_HTTP_PROFILE,
)
async def cmd_volume_set(self, player_id: str, volume_level: int) -> None:
from music_assistant_models.player import DeviceInfo, Player, PlayerMedia
from music_assistant.constants import (
- CONF_ENTRY_CROSSFADE,
- CONF_ENTRY_CROSSFADE_DURATION,
CONF_ENTRY_ENABLE_ICY_METADATA,
CONF_ENTRY_ENABLE_ICY_METADATA_HIDDEN,
CONF_ENTRY_FLOW_MODE_DEFAULT_ENABLED,
DEFAULT_PLAYER_CONFIG_ENTRIES = (
- CONF_ENTRY_CROSSFADE,
- CONF_ENTRY_CROSSFADE_DURATION,
CONF_ENTRY_OUTPUT_CODEC_DEFAULT_MP3,
CONF_ENTRY_HTTP_PROFILE,
CONF_ENTRY_ENABLE_ICY_METADATA,
player.powered = state["state"] not in OFF_STATES
player.extra_data["hass_supported_features"] = hass_supported_features
- self._update_player_attributes(player, state["attributes"])
await self.mass.players.register_or_update(player)
+ self._update_player_attributes(player, state["attributes"])
def _on_entity_state_update(self, event: EntityStateEvent) -> None:
"""Handle Entity State event."""
ConfigValueType,
PlayerConfig,
)
-from music_assistant_models.constants import PLAYER_CONTROL_NATIVE, PLAYER_CONTROL_NONE
+from music_assistant_models.constants import PLAYER_CONTROL_NONE
from music_assistant_models.enums import (
ConfigEntryType,
ContentType,
from music_assistant_models.player import DeviceInfo, Player, PlayerMedia
from music_assistant.constants import (
- BASE_PLAYER_CONFIG_ENTRIES,
CONF_CROSSFADE,
CONF_CROSSFADE_DURATION,
CONF_ENABLE_ICY_METADATA,
CONF_ENTRY_CROSSFADE,
CONF_ENTRY_CROSSFADE_DURATION,
CONF_ENTRY_FLOW_MODE_ENFORCED,
- CONF_ENTRY_PLAYER_ICON_GROUP,
CONF_FLOW_MODE,
CONF_GROUP_MEMBERS,
CONF_HTTP_PROFILE,
- CONF_MUTE_CONTROL,
CONF_OUTPUT_CODEC,
- CONF_POWER_CONTROL,
CONF_SAMPLE_RATES,
- CONF_VOLUME_CONTROL,
DEFAULT_PCM_FORMAT,
create_sample_rates_config_entry,
)
"""Return all (provider/player specific) Config Entries for the given player (if any)."""
# default entries for player groups
base_entries = (
- *BASE_PLAYER_CONFIG_ENTRIES,
- CONF_ENTRY_PLAYER_ICON_GROUP,
+ *await super().get_player_config_entries(player_id),
CONF_ENTRY_GROUP_TYPE,
CONF_ENTRY_GROUP_MEMBERS,
CONFIG_ENTRY_DYNAMIC_MEMBERS,
- # add player control entries as hidden entries
- 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,
- # disable mute control for group players for now
- # TODO: work out if all child players support mute control
- default_value=PLAYER_CONTROL_NONE,
- hidden=True,
- ),
)
# group type is static and can not be changed. we just grab the existing, stored value
group_type: str = self.mass.config.get_raw_player_config_value(
required=False,
category=CONF_CATEGORY_BUILT_IN,
hidden=not local_snapserver_present,
+ depends_on=CONF_USE_EXTERNAL_SERVER,
+ depends_on_value_not=True,
help_link=CONF_HELP_LINK,
),
ConfigEntry(
required=False,
category=CONF_CATEGORY_BUILT_IN,
hidden=not local_snapserver_present,
+ depends_on=CONF_USE_EXTERNAL_SERVER,
+ depends_on_value_not=True,
help_link=CONF_HELP_LINK,
),
ConfigEntry(
required=False,
category=CONF_CATEGORY_BUILT_IN,
hidden=not local_snapserver_present,
+ depends_on=CONF_USE_EXTERNAL_SERVER,
+ depends_on_value_not=True,
help_link=CONF_HELP_LINK,
),
ConfigEntry(
required=False,
category=CONF_CATEGORY_BUILT_IN,
hidden=not local_snapserver_present,
+ depends_on=CONF_USE_EXTERNAL_SERVER,
+ depends_on_value_not=True,
help_link=CONF_HELP_LINK,
),
ConfigEntry(
required=False,
category=CONF_CATEGORY_BUILT_IN,
hidden=not local_snapserver_present,
+ depends_on=CONF_USE_EXTERNAL_SERVER,
+ depends_on_value_not=True,
help_link=CONF_HELP_LINK,
),
ConfigEntry(
from music_assistant.constants import (
CONF_ENTRY_CROSSFADE,
+ CONF_ENTRY_CROSSFADE_DURATION_HIDDEN,
CONF_ENTRY_FLOW_MODE_HIDDEN_DISABLED,
+ CONF_ENTRY_HTTP_PROFILE_DEFAULT_1,
CONF_ENTRY_MANUAL_DISCOVERY_IPS,
CONF_ENTRY_OUTPUT_CODEC,
MASS_LOGO_ONLINE,
base_entries = (
*await super().get_player_config_entries(player_id),
CONF_ENTRY_CROSSFADE,
+ CONF_ENTRY_CROSSFADE_DURATION_HIDDEN,
CONF_ENTRY_FLOW_MODE_HIDDEN_DISABLED,
CONF_ENTRY_OUTPUT_CODEC,
+ CONF_ENTRY_HTTP_PROFILE_DEFAULT_1,
create_sample_rates_config_entry(
max_sample_rate=48000, max_bit_depth=24, safe_max_bit_depth=24, hidden=True
),
from music_assistant.constants import (
CONF_CROSSFADE,
CONF_ENTRY_CROSSFADE,
+ CONF_ENTRY_CROSSFADE_DURATION_HIDDEN,
CONF_ENTRY_FLOW_MODE_HIDDEN_DISABLED,
- CONF_ENTRY_HTTP_PROFILE_FORCED_1,
+ CONF_ENTRY_HTTP_PROFILE_DEFAULT_1,
CONF_ENTRY_MANUAL_DISCOVERY_IPS,
CONF_ENTRY_OUTPUT_CODEC,
VERBOSE_LOG_LEVEL,
) -> tuple[ConfigEntry, ...]:
"""Return Config Entries for the given player."""
base_entries = await super().get_player_config_entries(player_id)
- if not (self.sonosplayers.get(player_id)):
- # most probably a syncgroup
- return (
- *base_entries,
- CONF_ENTRY_CROSSFADE,
- CONF_ENTRY_OUTPUT_CODEC,
- CONF_ENTRY_FLOW_MODE_HIDDEN_DISABLED,
- )
return (
*base_entries,
CONF_ENTRY_CROSSFADE,
+ CONF_ENTRY_CROSSFADE_DURATION_HIDDEN,
CONF_ENTRY_SAMPLE_RATES,
CONF_ENTRY_OUTPUT_CODEC,
CONF_ENTRY_FLOW_MODE_HIDDEN_DISABLED,
- CONF_ENTRY_HTTP_PROFILE_FORCED_1,
+ CONF_ENTRY_HTTP_PROFILE_DEFAULT_1,
)
def is_device_invisible(self, ip_address: str) -> bool:
CONF_ENTRY_DEPRECATED_EQ_MID,
CONF_ENTRY_DEPRECATED_EQ_TREBLE,
CONF_ENTRY_HTTP_PROFILE_FORCED_2,
- CONF_ENTRY_OUTPUT_CHANNELS,
CONF_ENTRY_OUTPUT_CODEC,
CONF_ENTRY_SYNC_ADJUST,
CONF_PORT,
CONF_ENTRY_DEPRECATED_EQ_BASS,
CONF_ENTRY_DEPRECATED_EQ_MID,
CONF_ENTRY_DEPRECATED_EQ_TREBLE,
- CONF_ENTRY_OUTPUT_CHANNELS,
CONF_ENTRY_CROSSFADE_DURATION,
CONF_ENTRY_OUTPUT_CODEC,
CONF_ENTRY_SYNC_ADJUST,