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 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 and scene engine are installed
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|linux-wallpaperengine]
137
- Apply live wallpaper on one monitor (auto resolves by wallpaper type)
138
- we apply --map DP-1:<id1>,HDMI-A-1:<id2> [--backend auto|mpvpaper|linux-wallpaperengine]
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|linux-wallpaperengine] OR we apply --map DP-1:<id1>,HDMI-A-1:<id2>');
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));
@@ -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 === 'web' || type === 'application' || type === 'unknown') {
1386
- throw new Error(`Unsupported wallpaper type for apply: ${type}. Supported: video, scene.`);
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 (type === 'video') {
1405
- if (!(requestedBackend === 'auto' || requestedBackend === 'mpvpaper')) {
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
- else if (type === 'scene') {
1417
- if (!(requestedBackend === 'auto' || requestedBackend === 'linux-wallpaperengine')) {
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitowall",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "description": "CLI/daemon for Hyprland wallpapers using swww with pack-based rotation.",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "type": "commonjs",