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
125 lines
2.8 KiB
JavaScript
6 years ago
|
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();
|