| 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."); | |||||
| }); |
| 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); | |||||
| } | |||||
| } |
| 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)); | |||||
| } |
| 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()); | |||||
| } |
| 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()); | |||||
| } |
| 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; | |||||
| } | |||||
| } |