« get me outta code hell

index.js « native-app - interactive-bgm - Browser extension that adds background music based on the site you're browsing
about summary refs log tree commit diff
path: root/native-app/index.js
blob: 2f174ea2f162a69475b723f2aef4e3aaa4e1eb84 (plain)
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
#!/usr/bin/env node

const basePath = '/home/florrie/Documents/interactive-bgm';

const logFile = basePath + '/native-app/log';

const log = msg => {
    require('fs').appendFileSync(logFile, msg + '\n');
};


log('Started ' + Date());

const { spawn } = require('child_process');
const EventEmitter = require('events');
const FIFO = require('fifo-js');
const http = require('http');

log('Loaded modules');

class TrackPlayer {
    constructor(file) {
        this.file = file;
        this.volume = 0;
        this.storedVolume = this.volume;
    }

    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 = () => {};
        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');
});