'use strict' // "Open with PLWL" (file manager -> Open With -> PLWL): a file handed in via // `--open ` (or the Exec %f plumbing) is parked here until the renderer // picks it up, then launched ad hoc with the wine version + prefix chosen in // the picker popup. Nothing is imported into the library. const fs = require('fs') const path = require('path') let pending = null // file path waiting for the picker (service not ready yet) function setPending(p) { pending = p } function getPending() { return pending } function hasPending() { return !!pending } function clearPending() { pending = null } // The launcher's own translations may not cover openwith texts in older // installs - fall back to English keys so the UI never shows raw key names. function textsFor(code) { let texts = {} try { texts = require('./i18n').getLang(code).texts || {} } catch {} const fallback = { 'openwith.title': 'Open with Wine', 'openwith.file': 'File', 'openwith.fileMissing': 'This file no longer exists.', 'openwith.wine': 'Wine / Proton version', 'openwith.wineDefault': 'Default ({0})', 'openwith.prefix': 'Wine prefix', 'openwith.prefixDefault': 'Default prefix ({0})', 'openwith.run': 'Run', 'openwith.startFailed': 'Could not start {0}: {1}', 'openwith.notWindows': 'This is not a Windows executable (exe/msi/bat/cmd/lnk).' } return { ...fallback, ...texts } } function resolveWine(id) { return require('./wines').resolveWine(id) } function resolvePrefix(name) { const defs = require('./prefixes').listPrefixes() const known = name && defs.prefixes.some(p => p.name === name) ? name : '' return known || defs.default || 'Main' } // Ad-hoc run target: shaped exactly like a library game (runner.buildEnv and // the playtime/log paths expect those fields) but nothing is persisted. function makeTarget(openPath, wineId, prefixName) { const dir = path.dirname(openPath) return { id: 'openwith', name: path.basename(openPath), mode: 'open', path: dir, exePath: openPath, workdir: dir, wine: wineId || 'default', prefix: prefixName || '', args: '', dllOverrides: [], env: {}, iconSource: '', playSeconds: 0, created: 0, lastPlayed: 0 } } // Launch without importing: resolves the chosen wine/prefix, builds the ad // hoc target and runs it exactly like a library app (same env, same logging, // same detached process group). async function run({ openPath, wine: wineId, prefix: prefixName0, lang, onStarted }) { if (!openPath || !fs.existsSync(openPath)) return { ok: false, error: 'file-missing' } if (!/\.(exe|msi|bat|cmd|lnk)$/i.test(openPath)) return { ok: false, error: 'not-windows' } const wine = resolveWine(wineId) const prefixName = resolvePrefix(prefixName0) const runner = require('./runner') try { // runAdHoc builds the synthetic target internally (shared `openwith` id, // so logs/playtime never collide with a library app id); the resolved // prefix is passed through so buildEnv uses the chosen one const res = await runner.runAdHoc({ openPath, wine, systemWine: wine.type === 'system', prefix: prefixName }) if (onStarted) onStarted({ name: path.basename(openPath), pid: res.pid }) return { ok: true, pid: res.pid || null, logFile: res.logFile || null } } catch (err) { return { ok: false, error: String((err && err.message) || err) } } } module.exports = { setPending, getPending, hasPending, clearPending, run, makeTarget, resolveWine, resolvePrefix, textsFor }