Fix iOS voice capture and screen sharing
Build and test / test (macos-latest) (push) Canceled after 0s
Build and test / test (ubuntu-24.04) (push) Canceled after 0s
Build and test / test (windows-latest) (push) Canceled after 0s
Build and test / apple-client (push) Canceled after 0s

This commit is contained in:
2026-09-21 14:14:15 +02:00
parent 35617e9708
commit 0372baf589
13 changed files with 389 additions and 66 deletions
@@ -81,6 +81,58 @@ public class PublishServerScriptTests
Assert.Contains("<string>$(CURRENT_PROJECT_VERSION)</string>", extensionManifest);
}
[Fact]
public async Task IosScreenSharingDeclaresBackgroundCaptureAndKeepsReplayKitFallback()
{
string root = FindRoot();
string manifest = await File.ReadAllTextAsync(Path.Combine(
root, "clients", "apple", "VoiceCat.iOS", "Info.plist"));
string settings = await File.ReadAllTextAsync(Path.Combine(
root, "clients", "apple", "VoiceCat.iOS", "SettingsController.cs"));
Assert.Contains("<string>screen-capture</string>", manifest);
Assert.Contains("if (IosScreenCapture.IsAvailable)", settings);
Assert.Contains("new RPSystemBroadcastPickerView", settings);
Assert.DoesNotContain("if (OperatingSystem.IsIOSVersionAtLeast(27)) { model.ToggleScreenAudio();", settings);
}
[Fact]
public async Task IosCaptureDoesNotDependOnCoalescedManagedTimers()
{
string root = FindRoot();
string microphone = await File.ReadAllTextAsync(Path.Combine(
root, "clients", "apple", "VoiceCat.iOS", "IosAudioEngine.cs"));
string screen = await File.ReadAllTextAsync(Path.Combine(
root, "clients", "apple", "VoiceCat.iOS", "BroadcastAudioPump.cs"));
Assert.DoesNotContain("PeriodicTimer", microphone);
Assert.Contains("owner.Audio.FeedPcm(route.StreamId", microphone);
Assert.Contains("new Thread(Run)", screen);
Assert.DoesNotContain("Task.Delay(10", screen);
Assert.Contains("MaximumCaptureCallbackFrames = 16_384", microphone);
Assert.DoesNotContain("Math.Ceiling(4_096 * 48_000", microphone);
}
[Fact]
public async Task IosAudioCommitsInputRouteBeforeChannelsAndVoiceProcessingBeforeConnections()
{
string root = FindRoot();
string router = await File.ReadAllTextAsync(Path.Combine(root, "clients", "apple", "VoiceCat.iOS", "IosAudioRouter.cs"));
string engine = await File.ReadAllTextAsync(Path.Combine(root, "clients", "apple", "VoiceCat.iOS", "IosAudioEngine.cs"));
Assert.True(router.IndexOf("ApplyInputSelection(session)", StringComparison.Ordinal) <
router.IndexOf("SetActive(true", StringComparison.Ordinal));
Assert.DoesNotContain("session.SetPreferredInputNumberOfChannels", router);
Assert.DoesNotContain("MaximumInputNumberOfChannels", router);
Assert.Contains("SelectedDataSourceId = null; SelectedPolarPattern = AVAudioDataSourcePolarPattern.Unknown", router);
Assert.Contains("ClearStereoPolarPattern(session)", router);
Assert.Contains("CaptureChannels == 2\n ? port.DataSources?.FirstOrDefault", router);
Assert.True(engine.IndexOf("SetVoiceProcessingEnabled", StringComparison.Ordinal) <
engine.IndexOf("next.Connect(source", StringComparison.Ordinal));
Assert.Contains("AVAudioEngine.ConfigurationChangeNotification", engine);
Assert.Contains("ReferenceEquals(engine, next) && !next.Running", engine);
}
[Fact]
public async Task DefaultPublishTargetsWindowsAndLinuxWhileRuntimeCanSelectOne()
{