fix(electron): clear embedded mpv transient errors

This commit is contained in:
4gray committed 2026-06-09 08:12:14 +02:00
1 parent b5b495f0f5
commit 5a2d43976d
8 files changed
+115 -27

No files matched your search

+35 -23
View File
@@ -117,33 +117,45 @@ jobs:
const crypto = require('crypto');
const fs = require('fs');
const deploymentTarget = process.env.MACOSX_DEPLOYMENT_TARGET || '11.0';
const safeDeploymentTarget = deploymentTarget.replace(/[^A-Za-z0-9_.-]/g, '-');
let xcodeVersion = 'none';
try {
xcodeVersion = childProcess
.execSync('xcodebuild -version', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })
.replace(/\s+$/g, '')
.replace(/\n/g, ' ');
} catch {
xcodeVersion = 'none';
}
const hash = (value) => crypto.createHash('sha256').update(value).digest('hex');
const sourceHash = hash([
'tools/embedded-mpv/build-macos-runtime.mjs',
'tools/embedded-mpv/stage-macos-runtime.mjs',
const targetPlatform = '${{ matrix.embedded_mpv_platform }}';
const targetArch = '${{ matrix.embedded_mpv_arch }}';
const sourceHashFiles = [
'tools/embedded-mpv/stage-runtime.mjs',
].map((filePath) => fs.readFileSync(filePath)).join('\n'));
const xcodeHash = hash(xcodeVersion);
const cacheKey = [
];
const cacheKeyParts = [
'embedded-mpv-runtime-v2',
'${{ matrix.embedded_mpv_platform }}',
'${{ matrix.embedded_mpv_arch }}',
targetPlatform,
targetArch,
process.env.RUNNER_OS,
`macos${safeDeploymentTarget}`,
`xcode${xcodeHash}`,
sourceHash,
].join('-');
];
let deploymentTarget = '';
let xcodeVersion = 'none';
if (targetPlatform === 'darwin') {
deploymentTarget = process.env.MACOSX_DEPLOYMENT_TARGET || '11.0';
const safeDeploymentTarget = deploymentTarget.replace(/[^A-Za-z0-9_.-]/g, '-');
sourceHashFiles.push(
'tools/embedded-mpv/build-macos-runtime.mjs',
'tools/embedded-mpv/stage-macos-runtime.mjs'
);
try {
xcodeVersion = childProcess
.execSync('xcodebuild -version', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })
.replace(/\s+$/g, '')
.replace(/\n/g, ' ');
} catch {
xcodeVersion = 'none';
}
cacheKeyParts.push(
`macos${safeDeploymentTarget}`,
`xcode${hash(xcodeVersion)}`
);
}
const sourceHash = hash(
sourceHashFiles.map((filePath) => fs.readFileSync(filePath)).join('\n')
);
cacheKeyParts.push(sourceHash);
const cacheKey = cacheKeyParts.join('-');
fs.appendFileSync(process.env.GITHUB_OUTPUT, `deployment-target=${deploymentTarget}\n`);
fs.appendFileSync(process.env.GITHUB_OUTPUT, `xcode-version=${xcodeVersion}\n`);
+1 -1
View File
@@ -6,7 +6,7 @@ const {
findLibMpv,
patchAddonForBundledRuntime,
validateNoForbiddenRuntimeLinks,
} = require('../../tools/packaging/embedded-mpv-macos.cjs');
} = require('../../tools/packaging/embedded-mpv-packaging.cjs');
const workspaceRoot = process.cwd();
const addonRoot = path.join(workspaceRoot, 'apps', 'electron-backend', 'native');
@@ -508,6 +508,7 @@ void runEventLoop(std::shared_ptr<Session> session)
session->snapshot.status == SessionStatus::Paused
? SessionStatus::Paused
: SessionStatus::Playing;
session->snapshot.error.clear();
break;
case MPV_EVENT_END_FILE: {
const auto* endFile =
@@ -538,6 +539,7 @@ void runEventLoop(std::shared_ptr<Session> session)
session->snapshot.status = paused
? SessionStatus::Paused
: SessionStatus::Playing;
session->snapshot.error.clear();
} else if (name == "volume" && property->format == MPV_FORMAT_DOUBLE) {
session->snapshot.volumePercent =
*static_cast<double*>(property->data);
@@ -25,6 +25,10 @@ describe('Embedded MPV native source recording invariants', () => {
path.resolve(__dirname, '../../../build-embedded-mpv.js'),
'utf8'
);
const buildAndMakeWorkflowSource = readFileSync(
path.resolve(__dirname, '../../../../../.github/workflows/build-and-make.yaml'),
'utf8'
);
function functionBody(name: string): string {
const start = nativeSource.indexOf(`Napi::Value ${name}(`);
@@ -99,6 +103,42 @@ describe('Embedded MPV native source recording invariants', () => {
);
});
it('clears transient Windows/Linux MPV operation errors after healthy playback states', () => {
const fileLoadedCaseStart = widCommonSource.indexOf(
'case MPV_EVENT_FILE_LOADED:'
);
expect(fileLoadedCaseStart).toBeGreaterThanOrEqual(0);
const endFileCaseStart = widCommonSource.indexOf(
'case MPV_EVENT_END_FILE:',
fileLoadedCaseStart
);
expect(endFileCaseStart).toBeGreaterThan(fileLoadedCaseStart);
const fileLoadedCase = widCommonSource.slice(
fileLoadedCaseStart,
endFileCaseStart
);
expect(fileLoadedCase).toContain('session->snapshot.error.clear();');
const pausePropertyStart = widCommonSource.indexOf(
'const bool paused = *static_cast<int*>(property->data) != 0;'
);
expect(pausePropertyStart).toBeGreaterThanOrEqual(0);
const volumePropertyStart = widCommonSource.indexOf(
'} else if (name == "volume"',
pausePropertyStart
);
expect(volumePropertyStart).toBeGreaterThan(pausePropertyStart);
const pausePropertyBranch = widCommonSource.slice(
pausePropertyStart,
volumePropertyStart
);
expect(pausePropertyBranch).toContain(
'session->snapshot.error.clear();'
);
});
it('copies Windows runtime DLLs next to the addon for Windows loader lookup', () => {
expect(buildScriptSource).toContain(
"for (const windowsDllName of ['mpv-2.dll', 'mpv.dll'])"
@@ -124,6 +164,25 @@ describe('Embedded MPV native source recording invariants', () => {
expect(linuxSource).toContain('XNextEvent(display_, &event)');
expect(linuxSource).toContain('drainEvents();');
});
it('uses platform-specific embedded MPV runtime cache key inputs in CI', () => {
expect(buildAndMakeWorkflowSource).toContain(
"const targetPlatform = '${{ matrix.embedded_mpv_platform }}';"
);
expect(buildAndMakeWorkflowSource).toContain(
"if (targetPlatform === 'darwin')"
);
expect(buildAndMakeWorkflowSource).toContain(
"'tools/embedded-mpv/build-macos-runtime.mjs'"
);
expect(buildAndMakeWorkflowSource).toContain(
"'tools/embedded-mpv/stage-runtime.mjs'"
);
expect(buildAndMakeWorkflowSource).not.toContain(
'`macos${safeDeploymentTarget}`,\n' +
' `xcode${xcodeHash}`,'
);
});
});
describe('Embedded MPV native build configuration', () => {
+1 -1
View File
@@ -1,7 +1,7 @@
const linuxAfterPack = require('./linux-after-pack.cjs');
const {
validatePackagedEmbeddedMpv,
} = require('./embedded-mpv-macos.cjs');
} = require('./embedded-mpv-packaging.cjs');
const fs = require('fs');
const path = require('path');
@@ -45,9 +45,13 @@ const packageLayoutVerifier = fs.readFileSync(
join(currentDir, 'verify-electron-package-layout.mjs'),
'utf8'
);
const electronAfterPackSource = fs.readFileSync(
join(currentDir, 'electron-after-pack.cjs'),
'utf8'
);
const {
validatePackagedEmbeddedMpv,
} = require('./embedded-mpv-macos.cjs');
} = require('./embedded-mpv-packaging.cjs');
test('Linux package identity does not expose the internal Electron backend project name', () => {
assert.equal(electronBuilderConfig.productName, 'IPTVnator');
@@ -222,6 +226,17 @@ test('embedded MPV package validation accepts Windows and Linux runtime files',
}
});
test('embedded MPV packaging helpers use a cross-platform module name', () => {
assert.match(
electronAfterPackSource,
/require\(['"]\.\/embedded-mpv-packaging\.cjs['"]\)/
);
assert.match(
packageLayoutVerifier,
/require\(['"]\.\/embedded-mpv-packaging\.cjs['"]\)/
);
});
test('embedded MPV package validation rejects missing required Windows runtime', () => {
const tempDir = fs.mkdtempSync(join(os.tmpdir(), 'iptvnator-mpv-package-'));
@@ -6,7 +6,7 @@ import { buildElectronBuilderMetadata } from './generate-electron-builder-metada
const require = createRequire(import.meta.url);
const { extractFile } = require('@electron/asar');
const { validatePackagedEmbeddedMpv } = require('./embedded-mpv-macos.cjs');
const { validatePackagedEmbeddedMpv } = require('./embedded-mpv-packaging.cjs');
const args = process.argv.slice(2);
const normalizedArgs = args[0] === '--' ? args.slice(1) : args;
const [platform, arch = ''] = normalizedArgs;