You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
2.8 KiB
JavaScript

const fs = require("fs");
const WiiDevice = require("./wii-device.js");
const EventEmitter = require("events");
const { spawn } = require("child_process");
class WiiDevices extends EventEmitter {
constructor() {
super();
this.wii_devices = [];
this.refresh_wii_devices();
this.inotify = spawn("inotifywait", [
"-m",
"-r",
"-e",
"CREATE",
"-e",
"DELETE",
"/dev/input",
]).stdout;
this.inotify.on("data", () => this.refresh_wii_devices());
}
static parseDevice(string) {
const obj = {};
string
.split("\n")
.map(line => line.split(": "))
.filter(line_elements => ["N", "H"].includes(line_elements[0]))
.map(line_elements => line_elements[1])
.map(prop_desc => prop_desc.split("="))
.forEach(
prop_desc_elements =>
(obj[prop_desc_elements[0].toLowerCase()] =
prop_desc_elements[1])
);
if (obj.handlers) {
obj.handlers = obj.handlers.trim().split(" ");
}
return obj;
}
is_wii_device_new(description) {
return !description.handlers
.filter(h => h != "kbd")
.some(handler =>
this.wii_devices.some(wii_device =>
wii_device.has_handler(handler)
)
);
}
add_wii_device_if_new(description) {
if (this.is_wii_device_new(description)) {
const wii_device = WiiDevice.fromDesc(description);
this.wii_devices.push(wii_device);
this.emit("change");
}
}
remove_wii_device_if_not_in_list(devices_list, wii_device) {
if (
!devices_list
.map(e => e.handlers)
.reduce((a, b) => a.concat(b), [])
.filter(handler => handler != "kbd")
.filter(handler => wii_device.has_handler(handler)).length
) {
wii_device.close();
this.wii_devices.splice(
this.wii_devices
.map(wii_device => wii_device.id)
.indexOf(wii_device.id),
1
);
this.emit("change");
}
}
refresh_wii_devices() {
try {
const devices = fs
.readFileSync("/proc/bus/input/devices", "utf-8")
.trim();
const entries = devices
.split("\n\n")
.map(WiiDevices.parseDevice)
.filter(d => WiiDevice.getPossibleTypes().includes(d.name));
entries.forEach(wii_device_description =>
this.add_wii_device_if_new(wii_device_description)
);
this.wii_devices.forEach(wii_device =>
this.remove_wii_device_if_not_in_list(entries, wii_device)
);
return this.wii_devices;
} catch (e) {
console.error(e);
return this.refresh_wii_devices();
}
}
get_wii_devices() {
return this.wii_devices;
}
quit() {
this.wii_devices.forEach(wii_device => wii_device.close());
}
async wait_for_event() {
return new Promise((resolve, reject) => {
const listener = event => {
this.wii_devices.forEach(wii_device =>
wii_device.removeListener("input", listener)
);
resolve(event);
};
this.wii_devices.forEach(wii_device =>
wii_device.once("input", listener)
);
});
}
}
module.exports = new WiiDevices();