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
|
#!/usr/bin/env node
const { spawn } = require('child_process');
const EventEmitter = require('events');
const FIFO = require('fifo-js');
const http = require('http');
const path = require('path');
const fs = require('fs');
const basePath = path.resolve(__dirname, '..');
const logFile = basePath + '/native-app/log';
const log = msg => fs.appendFileSync(logFile, msg + '\n');
log('Started ' + Date());
class TrackPlayer {
constructor(file) {
this.file = file;
this.volume = 0;
this.storedVolume = this.volume;
log('Created track: ' + file);
}
loadProcess() {
this.fifo = new FIFO();
this.process = spawn('mpv', [
'--no-video',
'--loop',
'--volume=' + this.volume,
'--input-file=' + this.fifo.path,
this.file,
]);
const stream = new EventEmitter();
stream.write = () => {};
stream.end = () => {};
this.process.stderr.pipe(stream);
}
sendCommand(command) {
if (this.fifo) {
this.fifo.write(command);
}
}
seekToStart() {
this.sendCommand('seek 0 absolute');
}
pause() {
this.sendCommand('set pause yes');
}
play() {
this.sendCommand('set pause no');
}
setVolume(volume) {
if (Math.floor(volume) !== this.storedVolume) {
this.storedVolume = Math.floor(volume);
this.sendCommand(`set volume ${volume}`);
}
this.volume = volume;
}
}
const tracks = {
mantis: new TrackPlayer(basePath + '/track1.wav'),
bass: new TrackPlayer(basePath + '/track2.wav'),
main: new TrackPlayer(basePath + '/track3.wav')
};
for (const track of Object.values(tracks)) {
track.loadProcess();
track.pause();
}
setTimeout(() => {
for (const track of Object.values(tracks)) {
track.seekToStart();
track.play();
}
let targetMode = [
{track: 'main', volume: 100}
];
setInterval(() => {
if (!Array.isArray(targetMode)) {
targetMode = [];
}
for (const [key, track] of Object.entries(tracks)) {
const mode = targetMode.find(m => m.track === key) || {volume: 0};
track.setVolume(track.volume + 0.1 * (mode.volume - track.volume));
}
}, 100);
process.stdin.on('data', data => {
log('STDIN: ' + data);
const probablyJSON = data.toString().slice(data.indexOf('[')).trim();
try {
targetMode = JSON.parse(probablyJSON);
} catch (error) {
}
});
}, 250);
log('Go!');
process.on('SIGTERM', () => {
log('Exiting [sigterm]');
for (const track of Object.values(tracks)) {
track.process.kill();
}
log('Cleaned up');
});
|