/
/
1"""Constants for Chromecast Player provider."""
2
3from __future__ import annotations
4
5from music_assistant_models.config_entries import ConfigEntry
6from music_assistant_models.enums import ConfigEntryType
7
8from music_assistant.constants import (
9 CONF_ENTRY_FLOW_MODE,
10 CONF_ENTRY_HTTP_PROFILE_DEFAULT_3,
11 CONF_ENTRY_OUTPUT_CODEC,
12 CONF_ENTRY_PREFER_WAV_FOR_LIVE_SOURCES_DEFAULT_ENABLED,
13 create_sample_rates_config_entry,
14)
15
16MASS_APP_ID = "C35B0678"
17APP_MEDIA_RECEIVER = "CC1AD845"
18SENDSPIN_CAST_APP_ID = "DD107DDB"
19SENDSPIN_CAST_NAMESPACE = "urn:x-cast:sendspin"
20CONF_USE_MASS_APP = "use_mass_app"
21DASHBOARD_NAMESPACE = "urn:x-cast:io.music-assistant.cast"
22
23# Seconds to wait for a Cast receiver to acknowledge an app launch.
24APP_LAUNCH_TIMEOUT = 30.0
25
26# Seconds the receiver app is kept running after playback stopped, so a
27# follow-up command can reuse the Cast session instead of starting a new one.
28APP_QUIT_DELAY = 10.0
29
30# keepalive media the cast receiver plays while showing a dashboard
31DASHBOARD_KEEPALIVE_SUFFIXES = ("/dashboard-keepalive.mp4", "/keepalive.png")
32
33# Interval (seconds) before an unavailable player is re-evaluated as a possible
34# passive multichannel endpoint that should be removed from the setup.
35MULTICHANNEL_RECHECK_INTERVAL = 600
36
37# Devices known to not work with the Sendspin Cast bridge.
38# Tuple of (manufacturer, model) where "*" is a wildcard.
39# These devices will not get a Sendspin bridge, allowing other protocols
40# (e.g. AirPlay bridge) to handle them instead.
41SENDSPIN_CAST_BLOCKLIST: set[tuple[str, str]] = {
42 ("Harman Luxury Audio", "*"),
43 ("*", "HK OMNI ADAPT+AMP"),
44}
45
46CAST_PLAYER_CONFIG_ENTRIES = (
47 CONF_ENTRY_OUTPUT_CODEC,
48 CONF_ENTRY_PREFER_WAV_FOR_LIVE_SOURCES_DEFAULT_ENABLED,
49 CONF_ENTRY_HTTP_PROFILE_DEFAULT_3,
50 # enable flow mode by default as cast devices handle a continuous
51 # flow stream more reliably than enqueueing individual tracks
52 ConfigEntry.from_dict({**CONF_ENTRY_FLOW_MODE.to_dict(), "default_value": True}),
53 ConfigEntry(
54 key=CONF_USE_MASS_APP,
55 type=ConfigEntryType.BOOLEAN,
56 default_value=True,
57 advanced=True,
58 ),
59)
60
61# originally/officially cast supports 96k sample rate (even for groups)
62# but it seems a (recent?) update broke this ?!
63# For now only set safe default values and let the user try out higher values
64CONF_ENTRY_SAMPLE_RATES_CAST = create_sample_rates_config_entry(
65 max_sample_rate=192000,
66 max_bit_depth=24,
67 safe_max_sample_rate=48000,
68 safe_max_bit_depth=16,
69)
70CONF_ENTRY_SAMPLE_RATES_CAST_GROUP = create_sample_rates_config_entry(
71 max_sample_rate=96000,
72 max_bit_depth=24,
73 safe_max_sample_rate=48000,
74 safe_max_bit_depth=16,
75)
76
77# Measured defaults for known Cast models.
78CAST_MODEL_STATIC_DELAY: dict[tuple[str, str], int] = {
79 ("Google Inc.", "Google Home Mini"): 330,
80 ("Google Inc.", "Google Nest Mini"): 427,
81 ("Google Inc.", "Chromecast Audio"): 335,
82 ("Google Inc.", "Google Nest Hub"): 188,
83}
84CAST_FALLBACK_STATIC_DELAY = 330
85
86
87def get_cast_model_static_delay(manufacturer: str, model: str) -> int:
88 """
89 Look up the default static delay for a Cast device model.
90
91 :param manufacturer: Device manufacturer (e.g., "Google Inc.").
92 :param model: Device model name (e.g., "Google Nest Mini").
93 """
94 return CAST_MODEL_STATIC_DELAY.get((manufacturer, model), CAST_FALLBACK_STATIC_DELAY)
95