From 15de6776a959c0b267b6f601417caf1f973b3b38 Mon Sep 17 00:00:00 2001 From: Florrie Date: Fri, 22 Mar 2019 17:51:06 -0300 Subject: Initial commit --- .gitignore | 2 + README.md | 11 ++++ extension/background.js | 42 +++++++++++++++ extension/borderify.js | 3 ++ extension/icons/beasts-32.png | Bin 0 -> 1093 bytes extension/manifest.json | 36 +++++++++++++ extension/popup/index.html | 1 + index.js | 113 ++++++++++++++++++++++++++++++++++++++ native-app/index.js | 122 ++++++++++++++++++++++++++++++++++++++++++ native-app/manifest.json | 7 +++ package-lock.json | 21 ++++++++ package.json | 14 +++++ track1.wav | Bin 0 -> 29635016 bytes track2.wav | Bin 0 -> 29635016 bytes track3.wav | Bin 0 -> 29635016 bytes 15 files changed, 372 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 extension/background.js create mode 100644 extension/borderify.js create mode 100644 extension/icons/beasts-32.png create mode 100644 extension/manifest.json create mode 100644 extension/popup/index.html create mode 100644 index.js create mode 100755 native-app/index.js create mode 100644 native-app/manifest.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100755 track1.wav create mode 100755 track2.wav create mode 100755 track3.wav diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cf5c15b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/node_modules +/native-app/log diff --git a/README.md b/README.md new file mode 100644 index 0000000..f8e1753 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Interactive BGM + +Adds background music to your browsing. + +## Installation + +Modfy `native-app/index.js` to have the proper paths and filenames. + +Copy (or link) `native-app/interactive_bgm.json` into `~/.mozilla/native-messaging-hosts/`. Open `about:debugging`, click "Load Temporary Add-on...", and pick `extension/manifest.json`. + +(The music files included here, while WIP, are ripped from Hollow Knight.) diff --git a/extension/background.js b/extension/background.js new file mode 100644 index 0000000..b23c38b --- /dev/null +++ b/extension/background.js @@ -0,0 +1,42 @@ +console.log('Start'); + +const port = browser.runtime.connectNative('interactive_bgm'); + +browser.browserAction.onClicked.addListener(() => { + console.log('Hello??'); + // port.postMessage('[{"track": "mantis", "volume": 100}]\n'); +}); + +console.log('Hi', port); + +port.postMessage('[{"track": "mantis", "volume": 100}]\n'); + +port.onMessage.addListener(msg => { + console.log('Nyoom', msg); +}); + +/* +setTimeout(() => { + port.disconnect(); +}, 4000); +*/ + +port.onDisconnect.addListener(() => { + console.log('Disconnected'); +}); + +browser.runtime.onMessage.addListener(({hostname}) => { + const map = { + 'scratch.mit.edu': ['mantis'], + 'stackoverflow.com': ['bass', 'main'] + }; + + const mode = map[hostname]; + + if (mode) { + console.log('BGM:', mode); + port.postMessage(mode.map(track => ({track, volume: 100}))); + } else { + console.log('No BGM found for ' + location.hostname); + } +}); diff --git a/extension/borderify.js b/extension/borderify.js new file mode 100644 index 0000000..032dc19 --- /dev/null +++ b/extension/borderify.js @@ -0,0 +1,3 @@ +window.addEventListener('focus', () => { + browser.runtime.sendMessage({hostname: location.hostname}); +}); diff --git a/extension/icons/beasts-32.png b/extension/icons/beasts-32.png new file mode 100644 index 0000000..89863cc Binary files /dev/null and b/extension/icons/beasts-32.png differ diff --git a/extension/manifest.json b/extension/manifest.json new file mode 100644 index 0000000..27cafda --- /dev/null +++ b/extension/manifest.json @@ -0,0 +1,36 @@ +{ + "manifest_version": 2, + "name": "Interactive BGM", + "version": "1.0", + + "description": "Adds a red border to all webpages matching mozilla.org.", + + "permissions": [ + "activeTab", + "nativeMessaging" + ], + + "applications": { + "gecko": { + "id": "interactive_bgm@florrie.ed1.club", + "strict_min_version": "50.0" + } + }, + + "browser_action": { + "default_icon": "icons/beasts-32.png", + "default_title": "Interactive BGM", + "default_popup": "popup/index.html" + }, + + "content_scripts": [ + { + "matches": [""], + "js": ["borderify.js"] + } + ], + + "background": { + "scripts": ["background.js"] + } +} diff --git a/extension/popup/index.html b/extension/popup/index.html new file mode 100644 index 0000000..e6cf5e5 --- /dev/null +++ b/extension/popup/index.html @@ -0,0 +1 @@ +

Nice.

diff --git a/index.js b/index.js new file mode 100644 index 0000000..72beebf --- /dev/null +++ b/index.js @@ -0,0 +1,113 @@ +const { spawn } = require('child_process'); +const FIFO = require('fifo-js'); +const http = require('http'); + +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, + ]); + + this.process.stderr.pipe(process.stderr); + } + + 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('track1.wav'), + bass: new TrackPlayer('track2.wav'), + main: new TrackPlayer('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)) { + console.log('targetMode is not an array.'); + 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); + + const server = http.createServer((request, response) => { + response.setHeader('Access-Control-Allow-Origin', '*'); + response.setHeader('Access-Control-Allow-Headers', 'Authorization, Cache-Control, Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers'); + console.log('Got request.'); + + if (request.method === 'GET') { + response.write('Please use POST.'); + response.end(); + } else if (request.method === 'POST') { + let allData = ''; + request.on('data', data => { + allData += data; + }); + request.on('end', () => { + try { + targetMode = JSON.parse(allData); + response.write('Set.'); + } catch (error) { + response.write('Invalid JSON.'); + } + response.end(); + }); + } else { + response.end(); + } + }); + + server.listen(8000); +}, 250); diff --git a/native-app/index.js b/native-app/index.js new file mode 100755 index 0000000..2f174ea --- /dev/null +++ b/native-app/index.js @@ -0,0 +1,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'); +}); diff --git a/native-app/manifest.json b/native-app/manifest.json new file mode 100644 index 0000000..73f90dd --- /dev/null +++ b/native-app/manifest.json @@ -0,0 +1,7 @@ +{ + "name": "interactive_bgm", + "description": "Adds background music to your browsing.", + "path": "/home/florrie/Documents/interactive-bgm/native-app/index.js", + "type": "stdio", + "allowed_extensions": ["interactive_bgm@florrie.ed1.club"] +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0a342b5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,21 @@ +{ + "name": "interactive-bgm", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "es6-error": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-3.2.0.tgz", + "integrity": "sha1-5WfP3LMk1OeuWSKjcAraXeh5oMo=" + }, + "fifo-js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fifo-js/-/fifo-js-2.1.0.tgz", + "integrity": "sha1-iEBfId6gZzYlWBieegdlXcD+FL4=", + "requires": { + "es6-error": "^3.0.1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6fcae8f --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "interactive-bgm", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "GPL-3.0", + "dependencies": { + "fifo-js": "^2.1.0" + } +} diff --git a/track1.wav b/track1.wav new file mode 100755 index 0000000..bdbba6e Binary files /dev/null and b/track1.wav differ diff --git a/track2.wav b/track2.wav new file mode 100755 index 0000000..76452bd Binary files /dev/null and b/track2.wav differ diff --git a/track3.wav b/track3.wav new file mode 100755 index 0000000..09fcef7 Binary files /dev/null and b/track3.wav differ -- cgit 1.3.0-6-gf8a5