Add system mute control via setMute action

Introduce a setMute protocol action and an NAudio-backed
AudioControlService so the Android client can toggle the Windows
render endpoint mute state over WebSocket.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Misaka
2026-06-17 22:12:13 +08:00
parent ad9a9021cc
commit 30da1680f2
9 changed files with 126 additions and 5 deletions

View File

@@ -46,7 +46,7 @@ public sealed class SyncMessageTests
public void ReplaceAllAppendsSubmittedText()
{
var keyboard = new RecordingKeyboardInjectionService();
var handler = new SyncMessageHandler(keyboard);
var handler = new SyncMessageHandler(keyboard, new RecordingAudioControlService());
handler.Handle(new SyncMessage
{
@@ -59,6 +59,33 @@ public sealed class SyncMessageTests
keyboard.Calls);
}
[TestMethod]
public void DeserializeAndroidSetMuteMessage()
{
var message = JsonSerializer.Deserialize<SyncMessage>(
"""{"action":"setMute","muted":true}""",
new JsonSerializerOptions(JsonSerializerDefaults.Web));
Assert.IsNotNull(message);
Assert.AreEqual(SyncAction.SetMute, message.Action);
Assert.AreEqual(true, message.Muted);
}
[TestMethod]
public void SetMuteForwardsToAudioService()
{
var audio = new RecordingAudioControlService();
var handler = new SyncMessageHandler(new RecordingKeyboardInjectionService(), audio);
handler.Handle(new SyncMessage
{
Action = SyncAction.SetMute,
Muted = true
});
CollectionAssert.AreEqual(new[] { "mute:True" }, audio.Calls);
}
[TestMethod]
public void DiscoveryResponseContainsServiceEndpoint()
{
@@ -77,7 +104,7 @@ public sealed class SyncMessageTests
[TestMethod]
public void WebSocketServiceInfoContainsDeviceName()
{
using var server = new WebSocketServerService(new SyncMessageHandler(new RecordingKeyboardInjectionService()), "Desktop-WIN11");
using var server = new WebSocketServerService(new SyncMessageHandler(new RecordingKeyboardInjectionService(), new RecordingAudioControlService()), "Desktop-WIN11");
using var document = JsonDocument.Parse(server.BuildServiceInfoJson());
var root = document.RootElement;
@@ -112,4 +139,16 @@ public sealed class SyncMessageTests
Calls.Add("enter");
}
}
private sealed class RecordingAudioControlService : IAudioControlService
{
public List<string> Calls { get; } = [];
public bool IsMuted => Calls.Count > 0 && Calls[^1] == "mute:True";
public void SetMute(bool muted)
{
Calls.Add($"mute:{muted}");
}
}
}