Skip to content

Let the player withdraw the server's volume and mute commands - #203

Merged
kahrendt merged 2 commits into
mainfrom
player-volume-mute-adjustable
Oct 13, 2026
Merged

kahrendt merged 2 commits into
mainfrom
player-volume-mute-adjustable

Conversation

@kahrendt

@kahrendt kahrendt commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Lets a player withdraw the server's volume and mute commands at runtime, for outputs whose level is set elsewhere (e.g. line out to an amplifier). The current spec carries supported_commands in client/state and lets a player change it mid-session (roles/player/v1.md "client/state player object"), so no reconnect is needed.

Closes #82.

Change

  • New PlayerRole::set_volume_adjustable(bool) and set_mute_adjustable(bool), main loop only, both enabled by default, mirroring set_output_delay_adjustable(). The flags are not persisted.
  • While one is disabled: its command leaves supported_commands, its volume/muted value is omitted from client/state, and a server command for it is ignored. The stored value is kept and reported again when re-enabled.
  • ClientPlayerStateObject::volume/muted become std::optional; the formatter writes them only when set.
  • Examples: basic_client and tui_client gain -F (the server cannot set the volume, which starts at 100) and -M (the server cannot set mute). Local volume and mute controls still work.
  • docs/integration-guide.md documents the setters.

Notes

  • Omitting the value is one compliant choice; the spec also allows reporting it read-only without the command. Read-only reporting is left for when a consumer needs it.

Tests

  • Table test over the knobs: supported_commands, presence of volume/muted, the defaults, and a disable/re-enable row.
  • Table test that an unadvertised volume or mute command reaches neither the listener nor the stored value.
  • Formatter test that unset keys are omitted while 0/false are still written.
  • Loopback test that withdrawing and restoring both knobs republishes client/state while connected; dropping either setter's publish hangs it.

Adds PlayerRole::set_volume_adjustable() and set_mute_adjustable(),
enabled by default. While one is disabled, its command leaves
client/state supported_commands, its value is omitted, and a server
command for it is ignored; the stored value is kept. The spec lets a
player change supported_commands mid-session, so no reconnect is
needed.

The basic and TUI examples gain -F (the server cannot set the volume,
which starts at full scale) and -M (the server cannot set mute).

Closes #82.
@kahrendt
kahrendt marked this pull request as ready for review October 13, 2026 14:58
@kahrendt
kahrendt requested a balanced review from Copilot October 13, 2026 14:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The central runtime publication behavior lacks effective coverage, and a new test unnecessarily bypasses the public API.

2 open findings
What changed in this PR

Adds runtime controls for withdrawing server volume and mute commands without reconnecting.

Changes:

  • Adds volume/mute adjustability APIs and conditional state serialization.
  • Ignores withdrawn commands while preserving local values.
  • Updates tests, documentation, and example CLI flags.
File Description
include/​sendspin/​player_role.h Declares and documents new setters.
src/​player_role.cpp Implements flags, state reporting, and command guards.
src/​player_role_impl.h Stores adjustability flags.
src/​protocol_messages.h Makes volume and mute optional.
src/​protocol.cpp Omits unset fields during serialization.
tests/​test_player_role.cpp Tests capabilities and ignored commands.
tests/​test_protocol.cpp Tests optional-field serialization.
docs/​integration-guide.md Documents runtime controls.
examples/​basic_client/​main.cpp Adds -F and -M options.
examples/​basic_client/​README.md Documents new options.
examples/​tui_client/​main.cpp Adds -F and -M options.
examples/​tui_client/​README.md Documents new options.

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/player_role.cpp
Comment thread tests/test_player_role.cpp Outdated
The command-gate test now builds the role with add_player() and sets
and reads it through the public setters and getters. A new loopback
test checks that withdrawing and restoring volume and mute republishes
client/state while connected; dropping either setter's publish hangs
it. The player test's access comment now names PlayerRole::impl_.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The implementation, API documentation, examples, and observable-behavior tests consistently cover the requested runtime withdrawal behavior.

0 open findings

2 resolved since last review

🧠 Review effort: Balanced

@kahrendt
kahrendt merged commit 7b312e8 into main Oct 13, 2026
17 checks passed
@kahrendt
kahrendt deleted the player-volume-mute-adjustable branch October 13, 2026 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle enabling/disabling volume

2 participants