/
/
/
1"""Constants for Sonos S1 Player Provider."""
2
3from __future__ import annotations
4
5from music_assistant_models.enums import PlaybackState, PlayerFeature
6from soco.core import MUSIC_SRC_LINE_IN, MUSIC_SRC_TV
7
8from music_assistant.models.player import PlayerSource
9
10# Configuration Keys
11CONF_NETWORK_SCAN = "network_scan"
12CONF_HOUSEHOLD_ID = "household_id"
13
14# Player Features
15# PAUSE is advertised unconditionally: whether a speaker can pause depends on what it has
16# loaded rather than on the model, so pause() reads that back from the speaker itself and
17# falls back to stop when it is refused.
18# The volume features are deliberately absent here: they depend on the individual speaker
19# and are added by SonosPlayer.
20PLAYER_FEATURES = (
21 PlayerFeature.PLAY_MEDIA,
22 PlayerFeature.PAUSE,
23 PlayerFeature.SET_MEMBERS,
24 PlayerFeature.ENQUEUE,
25 PlayerFeature.GAPLESS_PLAYBACK,
26 PlayerFeature.SELECT_SOURCE,
27)
28
29# Source Mapping
30SOURCE_LINEIN = "Line-in"
31SOURCE_TV = "TV"
32
33# Line-in and TV are the only sources this provider can report or switch to.
34LINEIN_SOURCE_MAPPING = {
35 MUSIC_SRC_TV: SOURCE_TV,
36 MUSIC_SRC_LINE_IN: SOURCE_LINEIN,
37}
38
39LINEIN_SOURCE_IDS = (SOURCE_TV, SOURCE_LINEIN)
40
41PLAYER_SOURCE_MAP = {
42 SOURCE_LINEIN: PlayerSource(
43 id=SOURCE_LINEIN,
44 name="Line-in",
45 passive=False,
46 can_play_pause=False,
47 can_next_previous=False,
48 can_seek=False,
49 ),
50 SOURCE_TV: PlayerSource(
51 id=SOURCE_TV,
52 name="TV",
53 passive=False,
54 can_play_pause=False,
55 can_next_previous=False,
56 can_seek=False,
57 ),
58}
59
60# Playback State Mapping
61PLAYBACK_STATE_MAP = {
62 "PLAYING": PlaybackState.PLAYING,
63 "PAUSED_PLAYBACK": PlaybackState.PAUSED,
64 "STOPPED": PlaybackState.IDLE,
65 "TRANSITIONING": PlaybackState.PLAYING,
66}
67
68# Sonos State Constants
69SONOS_STATE_PLAYING = "PLAYING"
70SONOS_STATE_TRANSITIONING = "TRANSITIONING"
71
72POLL_INTERVAL = 5
73# A speaker that reports TRANSITIONING carries no usable transport state (the coordinator of a
74# group that is still forming reports it for several seconds), so that report is discarded. It is
75# watched closely until it reports a usable state again, instead of leaving the player stale for a
76# full poll interval.
77TRANSITION_POLL_INTERVAL = 1
78
79# Subscription Settings
80SUBSCRIPTION_TIMEOUT = 1200
81SUBSCRIPTION_SERVICES = {
82 "avTransport",
83 "deviceProperties",
84 "renderingControl",
85 "zoneGroupTopology",
86}
87
88# Timing Constants
89DISCOVERY_INTERVAL = 1800
90NEVER_TIME = 0
91RESUB_COOLDOWN_SECONDS = 10.0
92# S1 speakers often drop or delay control requests while busy, so a single failed request
93# is not enough to mark a speaker offline. A failing ping is only trusted once events and
94# polls have both been silent for this long.
95AVAILABILITY_TIMEOUT = 60.0
96# S1 speakers apply a command a moment after acknowledging it, so the resulting state is
97# read back with a short delay instead of trusting the response to the command itself.
98COMMAND_POLL_DELAY = 2
99
100# Position/Duration Keys
101DURATION_SECONDS = "duration_in_s"
102POSITION_SECONDS = "position_in_s"
103
104# UID Constants
105UID_PREFIX = "RINCON_"
106UID_POSTFIX = "01400"
107