kitowall 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +5 -5
- package/dist/core/workshop.js +11 -150
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -131,11 +131,11 @@ Commands:
|
|
|
131
131
|
we library List downloaded workshop items
|
|
132
132
|
we scan-steam Detect Steam workshop folders and list downloaded ids
|
|
133
133
|
we sync-steam Sync local Steam Workshop 431960 items into Kitsune downloads
|
|
134
|
-
we app-status Detect if Wallpaper Engine
|
|
134
|
+
we app-status Detect if Wallpaper Engine is installed in Steam
|
|
135
135
|
we active Show current livewallpaper authority/lock state
|
|
136
|
-
we apply <id> --monitor <name> [--backend auto|mpvpaper
|
|
137
|
-
Apply live wallpaper on one monitor
|
|
138
|
-
we apply --map DP-1:<id1>,HDMI-A-1:<id2> [--backend auto|mpvpaper
|
|
136
|
+
we apply <id> --monitor <name> [--backend auto|mpvpaper]
|
|
137
|
+
Apply video live wallpaper on one monitor
|
|
138
|
+
we apply --map DP-1:<id1>,HDMI-A-1:<id2> [--backend auto|mpvpaper]
|
|
139
139
|
Apply wallpapers in batch by monitor map
|
|
140
140
|
we stop [--monitor <name> | --all] Stop livewallpaper instances and restore previous services
|
|
141
141
|
we coexist enter|exit|status Temporarily stop/restore wallpaper rotation services
|
|
@@ -440,7 +440,7 @@ async function main() {
|
|
|
440
440
|
const id = cleanOpt(args[2] ?? null);
|
|
441
441
|
const monitor = cleanOpt(getOptionValue(args, '--monitor'));
|
|
442
442
|
if (!id || !monitor) {
|
|
443
|
-
throw new Error('Usage: we apply <id> --monitor <name> [--backend auto|mpvpaper
|
|
443
|
+
throw new Error('Usage: we apply <id> --monitor <name> [--backend auto|mpvpaper] OR we apply --map DP-1:<id1>,HDMI-A-1:<id2>');
|
|
444
444
|
}
|
|
445
445
|
const out = await (0, workshop_1.workshopApply)({ id, monitor, backend });
|
|
446
446
|
console.log(JSON.stringify(out, null, 2));
|
package/dist/core/workshop.js
CHANGED
|
@@ -7,7 +7,6 @@ exports.setWorkshopApiKey = setWorkshopApiKey;
|
|
|
7
7
|
exports.workshopGetSteamRoots = workshopGetSteamRoots;
|
|
8
8
|
exports.workshopSetSteamRoots = workshopSetSteamRoots;
|
|
9
9
|
exports.workshopWallpaperEngineStatus = workshopWallpaperEngineStatus;
|
|
10
|
-
exports.workshopSceneEngineStatus = workshopSceneEngineStatus;
|
|
11
10
|
exports.workshopScanSteamDownloads = workshopScanSteamDownloads;
|
|
12
11
|
exports.workshopSyncSteamDownloads = workshopSyncSteamDownloads;
|
|
13
12
|
exports.workshopSearch = workshopSearch;
|
|
@@ -46,74 +45,6 @@ function clean(input) {
|
|
|
46
45
|
const v = input.trim();
|
|
47
46
|
return v.length > 0 ? v : undefined;
|
|
48
47
|
}
|
|
49
|
-
function isExecutable(filePath) {
|
|
50
|
-
try {
|
|
51
|
-
node_fs_1.default.accessSync(filePath, node_fs_1.default.constants.X_OK);
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
function resolveOnPath(binary) {
|
|
59
|
-
const bin = clean(binary);
|
|
60
|
-
if (!bin)
|
|
61
|
-
return undefined;
|
|
62
|
-
if (bin.includes('/')) {
|
|
63
|
-
const resolved = node_path_1.default.resolve(bin);
|
|
64
|
-
return node_fs_1.default.existsSync(resolved) && isExecutable(resolved) ? resolved : undefined;
|
|
65
|
-
}
|
|
66
|
-
const pathEnv = clean(process.env.PATH) ?? '';
|
|
67
|
-
const parts = pathEnv.split(':').filter(Boolean);
|
|
68
|
-
for (const p of parts) {
|
|
69
|
-
const candidate = node_path_1.default.join(p, bin);
|
|
70
|
-
if (node_fs_1.default.existsSync(candidate) && isExecutable(candidate))
|
|
71
|
-
return candidate;
|
|
72
|
-
}
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
function buildSceneEngineEnv(enginePath) {
|
|
76
|
-
const env = { ...process.env };
|
|
77
|
-
const libPaths = [];
|
|
78
|
-
const seen = new Set();
|
|
79
|
-
const pushLibPath = (candidate) => {
|
|
80
|
-
const value = clean(candidate);
|
|
81
|
-
if (!value || seen.has(value))
|
|
82
|
-
return;
|
|
83
|
-
seen.add(value);
|
|
84
|
-
libPaths.push(value);
|
|
85
|
-
};
|
|
86
|
-
const current = clean(process.env.LD_LIBRARY_PATH);
|
|
87
|
-
if (current) {
|
|
88
|
-
for (const segment of current.split(':')) {
|
|
89
|
-
const v = clean(segment);
|
|
90
|
-
if (v)
|
|
91
|
-
pushLibPath(v);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
const resolvedEngine = clean(enginePath);
|
|
95
|
-
if (resolvedEngine) {
|
|
96
|
-
const engineDir = node_path_1.default.dirname(resolvedEngine);
|
|
97
|
-
if (node_fs_1.default.existsSync(node_path_1.default.join(engineDir, 'libcef.so'))) {
|
|
98
|
-
pushLibPath(engineDir);
|
|
99
|
-
}
|
|
100
|
-
const siblingLib = node_path_1.default.join(engineDir, 'lib');
|
|
101
|
-
if (node_fs_1.default.existsSync(siblingLib) && node_fs_1.default.statSync(siblingLib).isDirectory()) {
|
|
102
|
-
pushLibPath(siblingLib);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
// Arch linux-wallpaperengine installs runtime libs here when bypassing the wrapper.
|
|
106
|
-
if (node_fs_1.default.existsSync('/opt/linux-wallpaperengine/libcef.so')) {
|
|
107
|
-
pushLibPath('/opt/linux-wallpaperengine');
|
|
108
|
-
}
|
|
109
|
-
if (node_fs_1.default.existsSync('/opt/linux-wallpaperengine/lib') && node_fs_1.default.statSync('/opt/linux-wallpaperengine/lib').isDirectory()) {
|
|
110
|
-
pushLibPath('/opt/linux-wallpaperengine/lib');
|
|
111
|
-
}
|
|
112
|
-
if (libPaths.length > 0) {
|
|
113
|
-
env.LD_LIBRARY_PATH = libPaths.join(':');
|
|
114
|
-
}
|
|
115
|
-
return env;
|
|
116
|
-
}
|
|
117
48
|
function getWePaths() {
|
|
118
49
|
const root = node_path_1.default.join(node_os_1.default.homedir(), '.local', 'share', 'kitsune', 'we');
|
|
119
50
|
return {
|
|
@@ -602,41 +533,13 @@ function workshopWallpaperEngineStatus() {
|
|
|
602
533
|
if (node_fs_1.default.existsSync(manifest))
|
|
603
534
|
manifests.push(manifest);
|
|
604
535
|
}
|
|
605
|
-
const engine = workshopSceneEngineStatus();
|
|
606
536
|
return {
|
|
607
537
|
ok: true,
|
|
608
538
|
installed: manifests.length > 0,
|
|
609
539
|
manifests,
|
|
610
|
-
steamapps
|
|
611
|
-
engine
|
|
540
|
+
steamapps
|
|
612
541
|
};
|
|
613
542
|
}
|
|
614
|
-
function workshopSceneEngineStatus() {
|
|
615
|
-
const configured = clean(process.env.KITOWALL_SCENE_ENGINE_CMD);
|
|
616
|
-
const candidates = configured
|
|
617
|
-
? [configured]
|
|
618
|
-
: ['linux-wallpaperengine', 'linux-wallpaperengine-cli', 'wallpaper-engine'];
|
|
619
|
-
for (const cmd of candidates) {
|
|
620
|
-
const resolved = resolveOnPath(cmd);
|
|
621
|
-
if (!resolved)
|
|
622
|
-
continue;
|
|
623
|
-
const verOut = (0, node_child_process_1.spawnSync)(resolved, ['--version'], {
|
|
624
|
-
encoding: 'utf8',
|
|
625
|
-
timeout: 2500,
|
|
626
|
-
env: buildSceneEngineEnv(resolved)
|
|
627
|
-
});
|
|
628
|
-
const stdout = clean(verOut.stdout) ?? '';
|
|
629
|
-
const stderr = clean(verOut.stderr) ?? '';
|
|
630
|
-
const version = (stdout.split('\n')[0] || stderr.split('\n')[0] || '').trim();
|
|
631
|
-
return {
|
|
632
|
-
installed: true,
|
|
633
|
-
path: resolved,
|
|
634
|
-
version: version || undefined,
|
|
635
|
-
command: cmd
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
return { installed: false, command: configured ?? 'linux-wallpaperengine' };
|
|
639
|
-
}
|
|
640
543
|
function findPreviewCandidate(dir) {
|
|
641
544
|
if (!node_fs_1.default.existsSync(dir))
|
|
642
545
|
return undefined;
|
|
@@ -1335,34 +1238,6 @@ function spawnMpvpaper(monitor, entry) {
|
|
|
1335
1238
|
}, 180);
|
|
1336
1239
|
});
|
|
1337
1240
|
}
|
|
1338
|
-
function spawnSceneEngine(monitor, wallpaperDir) {
|
|
1339
|
-
const engine = workshopSceneEngineStatus();
|
|
1340
|
-
if (!engine.installed || !engine.path) {
|
|
1341
|
-
throw new Error('Scene engine not installed. Install linux-wallpaperengine first.');
|
|
1342
|
-
}
|
|
1343
|
-
const enginePath = engine.path;
|
|
1344
|
-
return new Promise((resolve, reject) => {
|
|
1345
|
-
const child = (0, node_child_process_1.spawn)(enginePath, ['--screen-root', monitor, '--bg', wallpaperDir], {
|
|
1346
|
-
detached: true,
|
|
1347
|
-
stdio: 'ignore',
|
|
1348
|
-
env: buildSceneEngineEnv(enginePath)
|
|
1349
|
-
});
|
|
1350
|
-
let settled = false;
|
|
1351
|
-
const done = (fn) => {
|
|
1352
|
-
if (settled)
|
|
1353
|
-
return;
|
|
1354
|
-
settled = true;
|
|
1355
|
-
fn();
|
|
1356
|
-
};
|
|
1357
|
-
child.once('error', (err) => done(() => reject(err)));
|
|
1358
|
-
setTimeout(() => {
|
|
1359
|
-
done(() => {
|
|
1360
|
-
child.unref();
|
|
1361
|
-
resolve(child.pid ?? 0);
|
|
1362
|
-
});
|
|
1363
|
-
}, 220);
|
|
1364
|
-
});
|
|
1365
|
-
}
|
|
1366
1241
|
async function workshopApply(input) {
|
|
1367
1242
|
const id = clean(input.id);
|
|
1368
1243
|
const monitor = clean(input.monitor);
|
|
@@ -1382,8 +1257,8 @@ async function workshopApply(input) {
|
|
|
1382
1257
|
const type = project.type !== 'unknown'
|
|
1383
1258
|
? project.type
|
|
1384
1259
|
: detectTypeFromEntry(inferredEntry ?? node_path_1.default.join(dir, 'scene.json'));
|
|
1385
|
-
if (type
|
|
1386
|
-
throw new Error(`Unsupported wallpaper type for apply: ${type}. Supported: video
|
|
1260
|
+
if (type !== 'video') {
|
|
1261
|
+
throw new Error(`Unsupported wallpaper type for apply: ${type}. Supported: video (mpvpaper).`);
|
|
1387
1262
|
}
|
|
1388
1263
|
let state = readActiveState();
|
|
1389
1264
|
if (!state) {
|
|
@@ -1401,30 +1276,16 @@ async function workshopApply(input) {
|
|
|
1401
1276
|
}
|
|
1402
1277
|
let backend;
|
|
1403
1278
|
let pid = 0;
|
|
1404
|
-
if (
|
|
1405
|
-
|
|
1406
|
-
throw new Error(`Invalid backend for video wallpaper: ${requestedBackend}`);
|
|
1407
|
-
}
|
|
1408
|
-
if (!inferredEntry || !node_fs_1.default.existsSync(inferredEntry)) {
|
|
1409
|
-
throw new Error(`Video entry not found for wallpaper: ${id}`);
|
|
1410
|
-
}
|
|
1411
|
-
backend = 'mpvpaper';
|
|
1412
|
-
pid = await spawnMpvpaper(monitor, inferredEntry).catch((err) => {
|
|
1413
|
-
throw new Error(`Failed to launch mpvpaper: ${err instanceof Error ? err.message : String(err)}`);
|
|
1414
|
-
});
|
|
1279
|
+
if (!(requestedBackend === 'auto' || requestedBackend === 'mpvpaper')) {
|
|
1280
|
+
throw new Error(`Invalid backend for video wallpaper: ${requestedBackend}`);
|
|
1415
1281
|
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
throw new Error(`Invalid backend for scene wallpaper: ${requestedBackend}`);
|
|
1419
|
-
}
|
|
1420
|
-
backend = 'linux-wallpaperengine';
|
|
1421
|
-
pid = await spawnSceneEngine(monitor, dir).catch((err) => {
|
|
1422
|
-
throw new Error(`Failed to launch scene engine: ${err instanceof Error ? err.message : String(err)}`);
|
|
1423
|
-
});
|
|
1424
|
-
}
|
|
1425
|
-
else {
|
|
1426
|
-
throw new Error(`Unsupported wallpaper type for apply: ${type}`);
|
|
1282
|
+
if (!inferredEntry || !node_fs_1.default.existsSync(inferredEntry)) {
|
|
1283
|
+
throw new Error(`Video entry not found for wallpaper: ${id}`);
|
|
1427
1284
|
}
|
|
1285
|
+
backend = 'mpvpaper';
|
|
1286
|
+
pid = await spawnMpvpaper(monitor, inferredEntry).catch((err) => {
|
|
1287
|
+
throw new Error(`Failed to launch mpvpaper: ${err instanceof Error ? err.message : String(err)}`);
|
|
1288
|
+
});
|
|
1428
1289
|
if (!pid) {
|
|
1429
1290
|
throw new Error(`${backend} started without pid`);
|
|
1430
1291
|
}
|