Skip to main content

sonos_api/services/group_rendering_control/
state.rs

1//! Canonical GroupRenderingControl service state type.
2//!
3//! Used by both UPnP event streaming (via `into_state()`) and polling (via `poll()`).
4
5use serde::{Deserialize, Serialize};
6
7use crate::SonosClient;
8
9/// Complete GroupRenderingControl service state.
10///
11/// Canonical type used by both UPnP event streaming and polling.
12/// Fields match the UPnP GroupRenderingControl event data 1:1.
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
14pub struct GroupRenderingControlState {
15    /// Current group volume level (0-100)
16    pub group_volume: Option<u16>,
17
18    /// Whether the group is muted
19    pub group_mute: Option<bool>,
20
21    /// Whether the group volume is changeable
22    pub group_volume_changeable: Option<bool>,
23}
24
25/// Poll a speaker for complete GroupRenderingControl state.
26///
27/// Calls GetGroupVolume (required), GetGroupMute (optional).
28/// GroupVolumeChangeable has no Get operation — always None when polled.
29pub fn poll(client: &SonosClient, ip: &str) -> crate::Result<GroupRenderingControlState> {
30    let volume = client.execute_enhanced(
31        ip,
32        super::get_group_volume_operation()
33            .build()
34            .map_err(|e| crate::ApiError::ParseError(e.to_string()))?,
35    )?;
36
37    let mute = super::get_group_mute_operation()
38        .build()
39        .ok()
40        .and_then(|op| client.execute_enhanced(ip, op).ok());
41
42    Ok(GroupRenderingControlState {
43        group_volume: Some(volume.current_volume),
44        group_mute: mute.map(|m| m.current_mute),
45        group_volume_changeable: None,
46    })
47}