@@ -0,0 +1,82 @@ | |||
var syscheck = require("./js/syscheck"); | |||
var modules = { | |||
display: require("./modules/display"), | |||
input: require("./modules/input"), | |||
wallpaper: require("./modules/wallpaper") | |||
}; | |||
var config = { | |||
display: [ | |||
{ | |||
name: "*", | |||
resolution: "max", | |||
rate: "max", | |||
where: { left_of: "primary" }, | |||
}, | |||
], | |||
input: [ | |||
{ | |||
type: "pointer", | |||
name: "*", | |||
options: [, | |||
[ "libinput Tapping Enabled", 1 ], | |||
], | |||
}, | |||
{ | |||
type: "keyboard", | |||
name: "*", | |||
commands: [ | |||
"xset r rate 200 60", | |||
"setxkbmap dvorak -option ctrl:swapcaps -option altwin:swap_alt_win", | |||
] | |||
} | |||
], | |||
wallpaper: { | |||
path: "/home/martin/background.jpg", | |||
}, | |||
} | |||
function createLogger(name) { | |||
function log(pre, msg) { | |||
console.error(pre+msg.join(" ")); | |||
} | |||
return { | |||
info: (...msg) => log(name+": INFO: ", msg), | |||
warn: (...msg) => log(name+": WARNING: ", msg), | |||
error: (...msg) => log(name+": ERROR: ", msg), | |||
} | |||
} | |||
function startAll() { | |||
Object.keys(modules).forEach(i => { | |||
var mod = modules[i]; | |||
var conf = config[i] || {}; | |||
mod.start(conf, createLogger(i), modules); | |||
}); | |||
} | |||
function stopAll(cb) { | |||
var keys = Object.keys(modules); | |||
var cbs = keys.length; | |||
function next() { | |||
cbs -= 1; | |||
if (cbs === 0) | |||
cb(); | |||
} | |||
keys.forEach(i => modules.stop(next)); | |||
} | |||
syscheck(ok => { | |||
if (ok) | |||
startAll(); | |||
else | |||
console.error("Missing binaries, exiting."); | |||
}); |
@@ -0,0 +1,14 @@ | |||
module.exports = debounce; | |||
function debounce(fn, ms) { | |||
if (ms == null) | |||
ms = 100; | |||
var timeout = null; | |||
return function() { | |||
if (timeout != null) | |||
clearTimeout(timeout); | |||
timeout = setTimeout(fn, ms); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
var spawn = require("child_process").spawn; | |||
module.exports = check; | |||
var needed = [ | |||
"feh", | |||
]; | |||
function need(str, cb) { | |||
var child = spawn("which", [ str ]); | |||
child.on("close", code => { | |||
if (code === 0) { | |||
cb(true); | |||
} else { | |||
console.error("Missing system binary:", str); | |||
cb(false); | |||
} | |||
}); | |||
} | |||
function check(cb) { | |||
var ok = true; | |||
var cbs = needed.length; | |||
function next(res) { | |||
if (!res) | |||
ok = false; | |||
cbs -= 1; | |||
if (cbs === 0) | |||
cb(ok); | |||
} | |||
needed.forEach(s => need(s, next)); | |||
} |
@@ -0,0 +1,21 @@ | |||
exports.start = start; | |||
exports.stop = stop; | |||
exports.event = event; | |||
var conf; | |||
var logger; | |||
var modules; | |||
function start(conf_, logger_, modules_) { | |||
conf = conf_ || conf; | |||
logger = logger_ || logger; | |||
modules = modules_ || modules; | |||
} | |||
function stop(cb) { | |||
cb(); | |||
} | |||
function event(name, ...params) { | |||
logger.info("Event", name, params.toString()); | |||
} |
@@ -0,0 +1,21 @@ | |||
exports.start = start; | |||
exports.stop = stop; | |||
exports.event = event; | |||
var conf; | |||
var logger; | |||
var modules; | |||
function start(conf_, logger_, modules_) { | |||
conf = conf_ || conf; | |||
logger = logger_ || logger; | |||
modules = modules_ || modules; | |||
} | |||
function stop(cb) { | |||
cb(); | |||
} | |||
function event(name, ...params) { | |||
logger.info("Event", name, params.toString()); | |||
} |
@@ -0,0 +1,88 @@ | |||
var spawn = require("child_process").spawn; | |||
var fs = require("fs"); | |||
var pathlib = require("path"); | |||
var debounce = require("../../js/debounce"); | |||
exports.start = start; | |||
exports.stop = stop; | |||
exports.event = event; | |||
var conf; | |||
var logger; | |||
var modules; | |||
function runFeh() { | |||
var mode; | |||
logger.info("Setting background to", conf.path); | |||
switch (conf.mode) { | |||
case "scale": | |||
case undefined: | |||
mode = "--bg-scale"; | |||
break; | |||
case "center": | |||
mode = "--bg-center"; | |||
break; | |||
case "fill": | |||
mode = "--bg-fill"; | |||
break; | |||
case "max": | |||
mode = "--bg-max"; | |||
break; | |||
case "tile": | |||
mode = "--bg-tile"; | |||
break; | |||
default: | |||
return logger.error("Invalid mode: "+conf.mode); | |||
} | |||
var child = spawn("feh", [ mode, conf.path ]); | |||
child.stdout.on("data", d => | |||
logger.info("feh stdout:", d.toString().trim())); | |||
child.stderr.on("data", d => | |||
logger.info("feh stderr:", d.toString().trim())); | |||
} | |||
function start(conf_, logger_, modules_) { | |||
conf = conf_ || conf; | |||
logger = logger_ || logger; | |||
modules = modules_ || modules; | |||
if (!conf.path) | |||
return logger.error("Expected conf.path"); | |||
runFeh(); | |||
var dirname = pathlib.dirname(conf.path); | |||
var basename = pathlib.basename(conf.path); | |||
var run = debounce(runFeh); | |||
fs.watch(dirname, (type, name) => { | |||
if (name !== basename) | |||
return; | |||
run(); | |||
}); | |||
} | |||
function stop(cb) { | |||
cb(); | |||
} | |||
function event(name, ...params) { | |||
logger.info("Event", name, params.toString()); | |||
switch (name) { | |||
case "reload": | |||
runFeh(); | |||
break; | |||
} | |||
} |