UNPKG

xpl-sound

Version:
323 lines (258 loc) 7.62 kB
/*jslint node: true, vars: true, nomen: true, esversion: 6 */ 'use strict'; var Xpl = require("xpl-api"); var commander = require('commander'); var SoundPlayer = require('soundplayer'); var os = require('os'); var loudness = require('loudness'); var debug = require('debug')('xpl-sound'); var Semaphore = require('semaphore'); commander.version(require("./package.json").version); commander.option("--heapDump", "Enable heap dump (require heapdump)"); commander.option("--minimumDelayBetweenProgress", "Minimum delay between two progress events (seconds)", parseFloat); commander.option("--volumeStateDelay", "Volume and mute state interval", parseInt); Xpl.fillCommander(commander); commander.command('*').description("Start waiting sound commands").action(() => { console.log("Start"); if (!commander.xplSource) { var hostName = os.hostname(); if (hostName.indexOf('.') > 0) { hostName = hostName.substring(0, hostName.indexOf('.')); } commander.xplSource = "soundplayer." + hostName; } var xpl = new Xpl(commander); xpl.on("error", (error) => { console.error("XPL error", error); }); xpl.bind((error) => { if (error) { console.log("Can not open xpl bridge ", error); process.exit(2); return; } console.log("Xpl bind succeed "); // xpl.sendXplTrig(body, callback); var timer = 5; if (commander.volumeStateDelay !== undefined) { timer = commander.volumeStateDelay; } if (timer > 0) { setInterval(updateLoudnessChanges.bind(this, xpl), 1000 * timer); } var soundPlayer = new SoundPlayer(commander); xpl.on("xpl:xpl-cmnd", (message) => { debug("XplMessage", message); if (message.bodyName !== "audio.basic") { return; } var body = message.body; switch (body.command) { case "play": var url = body.url; if (!url) { console.error("No specified url", body); return; } playSound(soundPlayer, xpl, url, body.uuid, body.inTrackList==="enable"); return; case "stop": soundPlayer.stop(); return; case "volume+": changeVolume(xpl, 1); return; case "volume-": changeVolume(xpl, -1); return; case "mute": changeMute(xpl, true); return; case "unmute": changeMute(xpl, false); return; } }); }); }); var updateLock = Semaphore(1); function changeMute(xpl, mute) { debug("Change mute to ", mute); updateLock.take(function() { loudness.setMuted(mute, function(error) { updateLock.leave(); if (error) { console.error(error); return; } updateLoudnessChanges(xpl); }); }); } function changeVolume(xpl, increment) { debug("Change volume to ", increment); updateLock.take(() => { loudness.getVolume((error, volume) => { if (error) { updateLock.leave(); console.error(error); return; } loudness.setVolume(volume + increment, function(error) { updateLock.leave(); if (error) { console.error(error); return; } updateLoudnessChanges(xpl); }); }); }); } var lastVolume; var lastMuted; function updateLoudnessChanges(xpl) { debug("Update loundness changes"); function updateMute() { loudness.getMuted((error, mute) => { debug("getMuted() returns", mute, error); if (error) { console.error(error); updateLock.leave(); return; } if (mute === lastMuted) { updateLock.leave(); return; } lastMuted = mute; xpl.sendXplTrig({ command : 'muted', current : !!mute }, "audio.basic", function(error) { if (error) { console.error(error); } updateLock.leave(); }); }); } updateLock.take(() => { loudness.getVolume((error, volume) => { debug("getVolume() returns", volume, error); if (error) { console.error(error); return updateMute(); } if (volume === lastVolume) { return updateMute(); } lastVolume = volume; xpl.sendXplTrig({ command : 'volume', current : volume }, "audio.basic", function(error) { if (error) { console.error(error); } updateMute(); }); }); }); } var trackList=[]; function playSound(soundPlayer, xpl, url, uuid, trackList) { debug("Play sound url=", url); var sound = soundPlayer.newSound(url, uuid); if (trackList) { sound._inTrackList=true; trackList.push(sound); debug("Track list=", trackList); if (trackList.length>1) { return; } } playSound1(soundPlayer, xpl, sound); } function playSound1(soundPlayer, xpl, sound) { function onPlaying() { xpl.sendXplTrig({ url : sound.url, command : 'playing', uuid : sound.uuid }, "audio.basic"); } function onProgress(progress) { var d = { url : sound.url, command : 'progress', uuid : sound.uuid }; for ( var i in progress) { d[i] = progress[i]; } xpl.sendXplTrig(d, "audio.basic"); } function onStopped() { sound.removeListener('playing', onPlaying); sound.removeListener('progress', onProgress); sound.removeListener('error', onError); xpl.removeListener('xpl:xpl-cmnd', onXplStop); xpl.sendXplTrig({ uuid : sound.uuid, url : sound.url, command : 'stop' }, "audio.basic"); if (sound._inTrackList) { trackList.shift(); if (trackList[0]) { playSound1(soundPlayer, xpl, trackList[0]); } } } function onError() { sound.removeListener('playing', onPlaying); sound.removeListener('progress', onProgress); sound.removeListener('stopped', onStopped); xpl.removeListener('xpl:xpl-cmnd', onXplStop); xpl.sendXplTrig({ url : sound.url, command : 'error', uuid : sound.uuid }, "audio.basic"); if (sound._inTrackList) { trackList.shift(); if (trackList[0]) { playSound1(soundPlayer, xpl, trackList[0]); } } } function onXplStop(message) { if (message.bodyName !== "audio.basic" || message.body.command !== 'stop') { return; } if (message.body.uuid && message.body.uuid !== sound.uuid) { return; } if (message.body.url && message.body.url !== sound.url) { return; } if (sound._inTrackList) { trackList=[]; } sound.stop(); } sound.once('playing', onPlaying); sound.on('progress', onProgress); sound.once('stopped', onStopped); sound.once('error', onError); xpl.on("xpl:xpl-cmnd", onXplStop); sound.play(); } commander.parse(process.argv); if (commander.headDump) { var heapdump = require("heapdump"); console.log("***** HEAPDUMP enabled **************"); }