mirror of
https://github.com/fluxerapp/fluxer.git
synced 2026-09-02 21:04:06 +03:00
fix(voice): abort screen share when its audio cannot start (#2394)
This commit is contained in:
@@ -101,6 +101,7 @@ vi.mock('@app/features/voice/state/VoiceSettings', () => ({
|
|||||||
const {startConfiguredDisplayScreenShare, switchConfiguredDisplayScreenShare} = await import(
|
const {startConfiguredDisplayScreenShare, switchConfiguredDisplayScreenShare} = await import(
|
||||||
'@app/features/voice/utils/ScreenShareStartFlow'
|
'@app/features/voice/utils/ScreenShareStartFlow'
|
||||||
);
|
);
|
||||||
|
const {isScreenShareAudioCaptureError} = await import('@app/features/voice/utils/ScreenShareAudioCaptureError');
|
||||||
const ActiveScreenShareSource = (await import('@app/features/voice/state/ActiveScreenShareSource')).default;
|
const ActiveScreenShareSource = (await import('@app/features/voice/state/ActiveScreenShareSource')).default;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -132,6 +133,18 @@ describe('sharing a Fluxer-owned window while app audio is enabled', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('sharing another application window while app audio is enabled', () => {
|
||||||
|
test('arms native per-window audio and hard-fails when it cannot be armed', async () => {
|
||||||
|
armNativeAudioForNextCapture.mockResolvedValue(false);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
startConfiguredDisplayScreenShare('window:42:0', {preferredDisplaySurface: 'window'}),
|
||||||
|
).rejects.toSatisfy(isScreenShareAudioCaptureError);
|
||||||
|
expect(armNativeAudioForNextCapture).toHaveBeenCalledWith('window:42:0');
|
||||||
|
expect(setScreenShareEnabled).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('switching the display source', () => {
|
describe('switching the display source', () => {
|
||||||
test('preserves the running share state when the switch fails', async () => {
|
test('preserves the running share state when the switch fails', async () => {
|
||||||
replaceActiveDisplayScreenShare.mockResolvedValue(false);
|
replaceActiveDisplayScreenShare.mockResolvedValue(false);
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ import {
|
|||||||
disarmPendingNativeAudio,
|
disarmPendingNativeAudio,
|
||||||
getLastNativeAudioArmFailure,
|
getLastNativeAudioArmFailure,
|
||||||
} from '@app/features/voice/utils/NativeAudioCaptureBridge';
|
} from '@app/features/voice/utils/NativeAudioCaptureBridge';
|
||||||
import type {ScreenShareAudioCaptureDebugInfo} from '@app/features/voice/utils/ScreenShareAudioCaptureError';
|
import {
|
||||||
|
type ScreenShareAudioCaptureDebugInfo,
|
||||||
|
ScreenShareAudioCaptureError,
|
||||||
|
} from '@app/features/voice/utils/ScreenShareAudioCaptureError';
|
||||||
import {
|
import {
|
||||||
type DisplayShareEnvironment,
|
type DisplayShareEnvironment,
|
||||||
getDisplayShareEnvironment,
|
getDisplayShareEnvironment,
|
||||||
@@ -250,6 +253,11 @@ function degradeAudioToVideoOnly(
|
|||||||
removeAudioFromCaptureOptions(captureOptions);
|
removeAudioFromCaptureOptions(captureOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function failRequestedAudioCapture(debugInfo: ScreenShareAudioCaptureDebugInfo): never {
|
||||||
|
logger.warn('Screen share audio capture was requested but could not start', debugInfo);
|
||||||
|
throw new ScreenShareAudioCaptureError(debugInfo);
|
||||||
|
}
|
||||||
|
|
||||||
function cleanupNativeAudioAfterCaptureDidNotStart(mode: 'start' | 'switch'): void {
|
function cleanupNativeAudioAfterCaptureDidNotStart(mode: 'start' | 'switch'): void {
|
||||||
if (mode === 'switch') {
|
if (mode === 'switch') {
|
||||||
disarmPendingNativeAudio();
|
disarmPendingNativeAudio();
|
||||||
@@ -399,8 +407,7 @@ async function runConfiguredDisplayScreenShare(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!nativeAudioArmed) {
|
if (!nativeAudioArmed) {
|
||||||
degradeAudioToVideoOnly(
|
failRequestedAudioCapture(
|
||||||
captureOptions,
|
|
||||||
buildAudioCaptureFailureDebug({
|
buildAudioCaptureFailureDebug({
|
||||||
sourceId,
|
sourceId,
|
||||||
reason: getLastNativeAudioArmFailure()?.reason ?? 'linux-window-audio-route-unavailable',
|
reason: getLastNativeAudioArmFailure()?.reason ?? 'linux-window-audio-route-unavailable',
|
||||||
@@ -425,7 +432,7 @@ async function runConfiguredDisplayScreenShare(
|
|||||||
reason: getLastNativeAudioArmFailure()?.reason ?? 'system-audio-route-unavailable',
|
reason: getLastNativeAudioArmFailure()?.reason ?? 'system-audio-route-unavailable',
|
||||||
});
|
});
|
||||||
logger.warn('Desktop audio unavailable; aborting screen share because audio was requested', debugInfo);
|
logger.warn('Desktop audio unavailable; aborting screen share because audio was requested', debugInfo);
|
||||||
degradeAudioToVideoOnly(captureOptions, debugInfo);
|
failRequestedAudioCapture(debugInfo);
|
||||||
}
|
}
|
||||||
} else if (linuxDesktopAudioSourceMode === 'none') {
|
} else if (linuxDesktopAudioSourceMode === 'none') {
|
||||||
removeAudioFromCaptureOptions(captureOptions);
|
removeAudioFromCaptureOptions(captureOptions);
|
||||||
@@ -444,8 +451,7 @@ async function runConfiguredDisplayScreenShare(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!nativeAudioArmed) {
|
if (!nativeAudioArmed) {
|
||||||
degradeAudioToVideoOnly(
|
failRequestedAudioCapture(
|
||||||
captureOptions,
|
|
||||||
buildAudioCaptureFailureDebug({
|
buildAudioCaptureFailureDebug({
|
||||||
sourceMode,
|
sourceMode,
|
||||||
reason: getLastNativeAudioArmFailure()?.reason ?? 'linux-system-audio-route-unavailable',
|
reason: getLastNativeAudioArmFailure()?.reason ?? 'linux-system-audio-route-unavailable',
|
||||||
@@ -477,7 +483,7 @@ async function runConfiguredDisplayScreenShare(
|
|||||||
platform: electronApi.platform,
|
platform: electronApi.platform,
|
||||||
reason: debugInfo.reason,
|
reason: debugInfo.reason,
|
||||||
});
|
});
|
||||||
degradeAudioToVideoOnly(captureOptions, debugInfo);
|
failRequestedAudioCapture(debugInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -489,8 +495,7 @@ async function runConfiguredDisplayScreenShare(
|
|||||||
electronApi.platform !== 'win32' &&
|
electronApi.platform !== 'win32' &&
|
||||||
electronApi.platform !== 'linux'
|
electronApi.platform !== 'linux'
|
||||||
) {
|
) {
|
||||||
degradeAudioToVideoOnly(
|
failRequestedAudioCapture(
|
||||||
captureOptions,
|
|
||||||
buildAudioCaptureFailureDebug({
|
buildAudioCaptureFailureDebug({
|
||||||
sourceId,
|
sourceId,
|
||||||
platform: electronApi.platform,
|
platform: electronApi.platform,
|
||||||
|
|||||||
Reference in New Issue
Block a user