diff --git a/apps/electron-backend/native/src/embedded_mpv_wid_common.h b/apps/electron-backend/native/src/embedded_mpv_wid_common.h index 99bee138c..7b2b82dd7 100644 --- a/apps/electron-backend/native/src/embedded_mpv_wid_common.h +++ b/apps/electron-backend/native/src/embedded_mpv_wid_common.h @@ -865,7 +865,8 @@ void refreshLinuxMpvSnapshot(const std::shared_ptr& session) session->snapshot.durationSeconds = std::max(0.0, *duration); } if (volume) { - session->snapshot.volumePercent = clampVolumePercent(*volume); + session->snapshot.volumePercent = + std::max(0.0, std::min(100.0, *volume)); } if (paused) { session->snapshot.status = diff --git a/apps/electron-backend/src/app/services/embedded-mpv-native-source.spec.ts b/apps/electron-backend/src/app/services/embedded-mpv-native-source.spec.ts index c6015c61c..8e966b66d 100644 --- a/apps/electron-backend/src/app/services/embedded-mpv-native-source.spec.ts +++ b/apps/electron-backend/src/app/services/embedded-mpv-native-source.spec.ts @@ -354,6 +354,22 @@ describe('Embedded MPV native source recording invariants', () => { ); }); + it('keeps Linux MPV IPC volume readback in mpv percent units', () => { + const refreshBody = sourceFunctionBody( + widCommonSource, + 'void refreshLinuxMpvSnapshot(', + 'refreshLinuxMpvSnapshot' + ); + expect(refreshBody).toContain( + 'queryLinuxMpvNumber(socketPath, "volume")' + ); + expect(refreshBody).toContain( + 'session->snapshot.volumePercent =\n' + + ' std::max(0.0, std::min(100.0, *volume));' + ); + expect(refreshBody).not.toContain('clampVolumePercent(*volume)'); + }); + it('keeps Linux MPV snapshot IPC off the NAPI snapshot read path', () => { const getSnapshotBody = sourceFunctionBody( widCommonSource, diff --git a/apps/electron-backend/src/app/services/embedded-mpv-native.service.spec.ts b/apps/electron-backend/src/app/services/embedded-mpv-native.service.spec.ts index d16d2318a..8044d9401 100644 --- a/apps/electron-backend/src/app/services/embedded-mpv-native.service.spec.ts +++ b/apps/electron-backend/src/app/services/embedded-mpv-native.service.spec.ts @@ -477,10 +477,6 @@ describe('EmbeddedMpvNativeService power blocker', () => { platform: 'win32' as NodeJS.Platform, runtimeFile: path.join('lib', 'mpv-2.dll'), }, - { - platform: 'linux' as NodeJS.Platform, - runtimeFile: path.join('lib', 'libmpv.so.2'), - }, ])( 'loads the addon after validating the $platform runtime file exists', ({ platform, runtimeFile }) => { @@ -513,6 +509,36 @@ describe('EmbeddedMpvNativeService power blocker', () => { } ); + it('loads the Linux addon without bundled libmpv runtime files', () => { + delete process.env.WAYLAND_DISPLAY; + Object.defineProperty(process, 'platform', { + value: 'linux', + }); + const nativeDir = createTempDir(); + const addonPath = path.join(nativeDir, 'embedded_mpv.node'); + writeFileSync(addonPath, ''); + const loadAddonModule = jest.fn().mockReturnValue(addon); + + Object.assign(service as unknown as Record, { + addon: null, + addonLoadError: null, + loadAddonModule, + getAddonCandidatePaths: () => [addonPath], + }); + + expect(service.getSupport()).toEqual( + expect.objectContaining({ + supported: true, + platform: 'linux', + }) + ); + expect(loadAddonModule).toHaveBeenCalledWith(addonPath); + expect(mockSpawnSync).toHaveBeenCalledWith('mpv', ['--version'], { + stdio: 'ignore', + timeout: 3000, + }); + }); + it('loads the addon before reporting support capabilities', () => { const loadAddonModule = jest.fn().mockReturnValue(addon); Object.assign(service as unknown as Record, { diff --git a/apps/electron-backend/src/app/services/embedded-mpv-native.service.ts b/apps/electron-backend/src/app/services/embedded-mpv-native.service.ts index 716b54d2a..94a4e5fff 100644 --- a/apps/electron-backend/src/app/services/embedded-mpv-native.service.ts +++ b/apps/electron-backend/src/app/services/embedded-mpv-native.service.ts @@ -944,6 +944,10 @@ export class EmbeddedMpvNativeService { const nativeDir = path.dirname(addonPath); const runtimeCandidates = this.getRuntimeLibraryCandidates(nativeDir); + if (runtimeCandidates.length === 0) { + return null; + } + if (!runtimeCandidates.some((candidate) => existsSync(candidate))) { return [ 'Embedded MPV runtime is incomplete. Missing one of:', @@ -969,11 +973,7 @@ export class EmbeddedMpvNativeService { path.join(nativeDir, 'mpv.dll'), ]; case 'linux': - return [ - path.join(nativeDir, 'lib', 'libmpv.so.2'), - path.join(nativeDir, 'lib', 'libmpv.so.1'), - path.join(nativeDir, 'lib', 'libmpv.so'), - ]; + return []; default: return []; }