kitowall 2.5.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 +12 -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 {
|
|
@@ -199,6 +130,7 @@ function getCoexistServices() {
|
|
|
199
130
|
const cfg = readWeConfig();
|
|
200
131
|
const defaults = [
|
|
201
132
|
'swww-daemon.service',
|
|
133
|
+
'swww-daemon@kitowall.service',
|
|
202
134
|
'hyprwall-watch.service',
|
|
203
135
|
'hyprwall-next.timer',
|
|
204
136
|
'kitowall-next.timer'
|
|
@@ -601,41 +533,13 @@ function workshopWallpaperEngineStatus() {
|
|
|
601
533
|
if (node_fs_1.default.existsSync(manifest))
|
|
602
534
|
manifests.push(manifest);
|
|
603
535
|
}
|
|
604
|
-
const engine = workshopSceneEngineStatus();
|
|
605
536
|
return {
|
|
606
537
|
ok: true,
|
|
607
538
|
installed: manifests.length > 0,
|
|
608
539
|
manifests,
|
|
609
|
-
steamapps
|
|
610
|
-
engine
|
|
540
|
+
steamapps
|
|
611
541
|
};
|
|
612
542
|
}
|
|
613
|
-
function workshopSceneEngineStatus() {
|
|
614
|
-
const configured = clean(process.env.KITOWALL_SCENE_ENGINE_CMD);
|
|
615
|
-
const candidates = configured
|
|
616
|
-
? [configured]
|
|
617
|
-
: ['linux-wallpaperengine', 'linux-wallpaperengine-cli', 'wallpaper-engine'];
|
|
618
|
-
for (const cmd of candidates) {
|
|
619
|
-
const resolved = resolveOnPath(cmd);
|
|
620
|
-
if (!resolved)
|
|
621
|
-
continue;
|
|
622
|
-
const verOut = (0, node_child_process_1.spawnSync)(resolved, ['--version'], {
|
|
623
|
-
encoding: 'utf8',
|
|
624
|
-
timeout: 2500,
|
|
625
|
-
env: buildSceneEngineEnv(resolved)
|
|
626
|
-
});
|
|
627
|
-
const stdout = clean(verOut.stdout) ?? '';
|
|
628
|
-
const stderr = clean(verOut.stderr) ?? '';
|
|
629
|
-
const version = (stdout.split('\n')[0] || stderr.split('\n')[0] || '').trim();
|
|
630
|
-
return {
|
|
631
|
-
installed: true,
|
|
632
|
-
path: resolved,
|
|
633
|
-
version: version || undefined,
|
|
634
|
-
command: cmd
|
|
635
|
-
};
|
|
636
|
-
}
|
|
637
|
-
return { installed: false, command: configured ?? 'linux-wallpaperengine' };
|
|
638
|
-
}
|
|
639
543
|
function findPreviewCandidate(dir) {
|
|
640
544
|
if (!node_fs_1.default.existsSync(dir))
|
|
641
545
|
return undefined;
|
|
@@ -1334,34 +1238,6 @@ function spawnMpvpaper(monitor, entry) {
|
|
|
1334
1238
|
}, 180);
|
|
1335
1239
|
});
|
|
1336
1240
|
}
|
|
1337
|
-
function spawnSceneEngine(monitor, wallpaperDir) {
|
|
1338
|
-
const engine = workshopSceneEngineStatus();
|
|
1339
|
-
if (!engine.installed || !engine.path) {
|
|
1340
|
-
throw new Error('Scene engine not installed. Install linux-wallpaperengine first.');
|
|
1341
|
-
}
|
|
1342
|
-
const enginePath = engine.path;
|
|
1343
|
-
return new Promise((resolve, reject) => {
|
|
1344
|
-
const child = (0, node_child_process_1.spawn)(enginePath, ['--screen-root', monitor, '--bg', wallpaperDir], {
|
|
1345
|
-
detached: true,
|
|
1346
|
-
stdio: 'ignore',
|
|
1347
|
-
env: buildSceneEngineEnv(enginePath)
|
|
1348
|
-
});
|
|
1349
|
-
let settled = false;
|
|
1350
|
-
const done = (fn) => {
|
|
1351
|
-
if (settled)
|
|
1352
|
-
return;
|
|
1353
|
-
settled = true;
|
|
1354
|
-
fn();
|
|
1355
|
-
};
|
|
1356
|
-
child.once('error', (err) => done(() => reject(err)));
|
|
1357
|
-
setTimeout(() => {
|
|
1358
|
-
done(() => {
|
|
1359
|
-
child.unref();
|
|
1360
|
-
resolve(child.pid ?? 0);
|
|
1361
|
-
});
|
|
1362
|
-
}, 220);
|
|
1363
|
-
});
|
|
1364
|
-
}
|
|
1365
1241
|
async function workshopApply(input) {
|
|
1366
1242
|
const id = clean(input.id);
|
|
1367
1243
|
const monitor = clean(input.monitor);
|
|
@@ -1381,8 +1257,8 @@ async function workshopApply(input) {
|
|
|
1381
1257
|
const type = project.type !== 'unknown'
|
|
1382
1258
|
? project.type
|
|
1383
1259
|
: detectTypeFromEntry(inferredEntry ?? node_path_1.default.join(dir, 'scene.json'));
|
|
1384
|
-
if (type
|
|
1385
|
-
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).`);
|
|
1386
1262
|
}
|
|
1387
1263
|
let state = readActiveState();
|
|
1388
1264
|
if (!state) {
|
|
@@ -1400,30 +1276,16 @@ async function workshopApply(input) {
|
|
|
1400
1276
|
}
|
|
1401
1277
|
let backend;
|
|
1402
1278
|
let pid = 0;
|
|
1403
|
-
if (
|
|
1404
|
-
|
|
1405
|
-
throw new Error(`Invalid backend for video wallpaper: ${requestedBackend}`);
|
|
1406
|
-
}
|
|
1407
|
-
if (!inferredEntry || !node_fs_1.default.existsSync(inferredEntry)) {
|
|
1408
|
-
throw new Error(`Video entry not found for wallpaper: ${id}`);
|
|
1409
|
-
}
|
|
1410
|
-
backend = 'mpvpaper';
|
|
1411
|
-
pid = await spawnMpvpaper(monitor, inferredEntry).catch((err) => {
|
|
1412
|
-
throw new Error(`Failed to launch mpvpaper: ${err instanceof Error ? err.message : String(err)}`);
|
|
1413
|
-
});
|
|
1279
|
+
if (!(requestedBackend === 'auto' || requestedBackend === 'mpvpaper')) {
|
|
1280
|
+
throw new Error(`Invalid backend for video wallpaper: ${requestedBackend}`);
|
|
1414
1281
|
}
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
throw new Error(`Invalid backend for scene wallpaper: ${requestedBackend}`);
|
|
1418
|
-
}
|
|
1419
|
-
backend = 'linux-wallpaperengine';
|
|
1420
|
-
pid = await spawnSceneEngine(monitor, dir).catch((err) => {
|
|
1421
|
-
throw new Error(`Failed to launch scene engine: ${err instanceof Error ? err.message : String(err)}`);
|
|
1422
|
-
});
|
|
1423
|
-
}
|
|
1424
|
-
else {
|
|
1425
|
-
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}`);
|
|
1426
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
|
+
});
|
|
1427
1289
|
if (!pid) {
|
|
1428
1290
|
throw new Error(`${backend} started without pid`);
|
|
1429
1291
|
}
|