-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmpv.js
155 lines (135 loc) · 4.21 KB
/
mpv.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
const net = require("net");
const { log } = require("./utils");
class Mpv {
MPV_SERVER;
IS_MPV_SERVER_CONNECTED = false;
CALLBACKS = {};
REQUEST_ID = 1;
EVENT_CALLBACKS = {};
PROPERTY_AFFECTED = {};
constructor(socketPath) {
this.MPV_SERVER = net.createConnection(socketPath);
this.MPV_SERVER.on("connect", async () => {
log("Connected");
this.IS_MPV_SERVER_CONNECTED = true;
});
this.MPV_SERVER.on("data", (data) => {
const events = data
.toString()
.trim()
.split("\n")
.map((event) => JSON.parse(event));
events.forEach((event) => {
log(`onData(${JSON.stringify(event)})`);
if (this.CALLBACKS[event.request_id]) {
this.CALLBACKS[event.request_id](event);
}
if (this.EVENT_CALLBACKS[event.event]) {
this.EVENT_CALLBACKS[event.event](event);
}
if (this.CALLBACKS[event.id]) {
this.CALLBACKS[event.id](event);
}
});
});
}
// TODO(isamert): Handle mpv errors
sendCommand = async (command, args, options) => {
if (!this.IS_MPV_SERVER_CONNECTED) {
log("sendMpvCommand() :: Waiting connection to MPV server");
await new Promise((resolve, reject) => {
this.MPV_SERVER.once("connect", () => {
log("sendMpvCommand() :: Connected");
this.IS_MPV_SERVER_CONNECTED = true;
resolve();
});
});
}
if (options?.affectsProperty) {
this.PROPERTY_AFFECTED[options.affectsProperty] = true;
}
this.REQUEST_ID = this.REQUEST_ID + 1;
this.CALLBACKS[this.REQUEST_ID] = options?.callback;
let commandObject;
if (command === "observe_property") {
commandObject = { command: [command, this.REQUEST_ID, ...args] };
} else {
commandObject = {
command: [command, ...args],
request_id: this.REQUEST_ID,
};
}
const mpvCommand = JSON.stringify(commandObject) + "\n";
log(`sendMpvCommand(${command},${args}) => ${mpvCommand.trim()}`);
return new Promise((resolve, reject) => {
this.MPV_SERVER.write(mpvCommand, () => {
resolve();
});
});
};
sendCommandAsync = (command, args) => {
return new Promise((resolve, reject) => {
this.sendCommand(command, args, {
callback: (data) => {
resolve(data);
},
});
});
};
observeProperty = (property, callback) => {
return this.sendCommand("observe_property", [property], {
callback: (data) => {
// Check if we need to skip this event, and if so, make sure
// event contains some data to ensure it is really the event
// that we want to skip. mpv sometimes sends duplicate
// property-change events without any data. Not sure if this
// solution fits all cases but seems to work fine.
if (this.PROPERTY_AFFECTED[property] && data.data) {
this.PROPERTY_AFFECTED[property] = false;
return;
}
callback(data);
},
});
};
observeEvent = (event, callback) => {
this.EVENT_CALLBACKS[event] = callback;
};
getCurrentSubtitlePath = async () => {
const subTitleId = (await this.sendCommandAsync("get_property", ["sid"]))
.data;
const subTitles = [];
const trackListCount = (
await this.sendCommandAsync("get_property", ["track-list/count"])
).data;
for (let i = 0; i < trackListCount; i++) {
const trackType = await this.sendCommandAsync("get_property", [
`track-list/${i}/type`,
]);
if (trackType.data === "sub") {
const subTitlePath = (
await this.sendCommandAsync("get_property", [
`track-list/${i}/external-filename`,
])
).data;
subTitles.push(subTitlePath);
}
}
return subTitles[subTitleId - 1];
};
/*
* Add a new key binding. Each time given key is pressed call the callback.
*/
bindKey = async (key, callback) => {
const keyEventName = `pressed${key}`;
await this.sendCommand("keybind", [key, `script-message ${keyEventName}`]);
this.observeEvent("client-message", async (data) => {
if (data.args[0] === keyEventName) {
callback();
}
});
};
}
module.exports = {
Mpv,
};