Skip to content

Commit

Permalink
Added some basic support for tts and save/restore state
Browse files Browse the repository at this point in the history
  • Loading branch information
Goran58 committed Jun 26, 2014
1 parent 07c6075 commit 3298fe2
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 6 deletions.
123 changes: 120 additions & 3 deletions lib/sonos-http-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

var http = require('http');
var fs = require('fs');
var url = require('url');
var request = require('request');
var paperboy = require('paperboy');

function HttpAPI(discovery, port, presets) {
function HttpAPI(discovery, port, presets, ip, webroot) {

var lockVolumes = {};
var pauseState = {};
var saveState = {};

// This is to handle setTimeout
function pauseAll() {
Expand Down Expand Up @@ -47,14 +51,28 @@ function HttpAPI(discovery, port, presets) {
// This is faulty.
res.end();
return;
} else if (params.length == 2 && ["preset", "pauseall", "resumeall", "reindex"].some(function (i) { return params[0] == i; })) {
} else if (params.length == 2 && ["saveall", "restoreall", "preset", "pauseall", "resumeall", "reindex"].some(function (i) { return params[0] == i; })) {
// Handle presets
var opt = {
action: params[0],
value: params[1]
};
} else if (params.length > 1) {
} else if (params.length > 2 && params[1] == "say") {
// Handle say command
var lang = "en" // Optional
if (params.length > 3) lang = params[3];
var opt = {
room: params[0],
action: params[1],
text: params[2],
lang: lang
};
} else if (params.length == 2 && params[0] == "tts") {
// Handle tts file request from SONOS
streamFile(req, res);
return;

} else if (params.length > 1) {

var opt = {
room: params[0],
Expand Down Expand Up @@ -86,9 +104,108 @@ function HttpAPI(discovery, port, presets) {
player.setVolume(lockVolumes[info.uuid]);
}

function streamFile(req, res) {
// Deliver requested mp3 file to SONOS
var ip = req.connection.remoteAddress;
paperboy
.deliver(webroot, req, res)
.addHeader('Expires', 30000)
.addHeader('Content-type:', 'audio/mpeg')
.addHeader('X-PaperRoute', 'Node')
.before(function() {
console.log('Received Request from Sonos');
})
.after(function(statCode) {
log(statCode, req.url, ip);
})
.error(function(statCode, msg) {
res.writeHead(statCode, {'Content-Type': 'text/plain'});
res.end("Error " + statCode);
log(statCode, req.url, ip, msg);
})
.otherwise(function(err) {
console.log("404 Not Found");
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end("Error 404: File not found");
})
}

function log(statCode, url, ip, err) {
var logStr = statCode + ' - ' + url + ' - ' + ip;
if (err) logStr += ' - ' + err;
console.log(logStr);
}

function handleAction(options, callback) {
console.log(options)

if (options.action == "say") {
// Use Google tts translation service to create a mp3 file
var tts_request = "http://translate.google.com/translate_tts?ie=UTF-8&q=" + options.text + "&tl=" + options.lang;

// Construct a filesystem neutral filename
var filename = decodeURIComponent(options.text);
filename = encodeURIComponent(filename);
filename = filename.replace(/[^a-z0-9_\-]/gi, '_').toLowerCase() + '-' + options.lang + '.mp3';
var filepath = webroot + '/tts/' + filename;

// If not already downloaded request translation
fs.stat(filepath, function(err, stat){
if (err){
console.log("Downloading new tts message file: " + filepath);
request(tts_request, function(error, response, buffer) {
}).pipe(fs.createWriteStream(filepath));
} else{
console.log("Using cached tts message file: " + filepath);
}
})

var player = discovery.getPlayer(options.room);

// Use the preset action to play the tts file
var tts_params = {
"players": [
{"roomName": options.room, "volume": player.getState().volume}
],
"state": "play",
"uri": "http://" + ip + ":" + port + "/tts/" + filename,
"playMode": "NORMAL"
}
discovery.applyPreset(tts_params);

callback();
return;
}

if (options.action === "saveall") {
// Save the current state
saveState = {};
discovery.getZones().forEach(function (zone) {
if (zone.coordinator.state.zoneState == "PLAYING") {
var player = discovery.getPlayerByUUID(zone.uuid);
var state = player.getState();
saveState[zone.uuid] = {
"players": [
{"roomName": player.roomName, "volume": state.volume}
],
"state": "play",
"uri": state.currentTrack.uri,
"playMode": "NORMAL"
}
}
});
callback();
return;
}
if (options.action === "restoreall") {
for (var uuid in saveState) {
// Use the preset action to restore the saved state
discovery.applyPreset(saveState[uuid]);
}
callback();
return;
}

if (options.action === "zones") {
callback(discovery.getZones());
return;
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"url": "https://github.com/jishi/node-sonos-http-api.git"
},
"dependencies": {
"sonos-discovery": "git+https://github.com/jishi/node-sonos-discovery.git#master"
"sonos-discovery": "git+https://github.com/jishi/node-sonos-discovery.git#master",
"paperboy": "*",
"request": "*"
},
"engine": "node 0.8.x",
"main": "lib/sonos-http-api.js"
Expand Down
9 changes: 7 additions & 2 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ var SonosDiscovery = require('sonos-discovery');
var SonosHttpAPI = require('./lib/sonos-http-api.js');
var fs = require('fs');
var discovery = new SonosDiscovery();
var port = 5005;
var path = require('path');

var config = require('./config.json');
var port = config.my_port;
var ip = config.my_ip_address;

var webroot = path.join(path.dirname(__filename), 'sonos');
var presets = {};

fs.exists('./presets.json', function (exists) {
Expand All @@ -14,6 +19,6 @@ fs.exists('./presets.json', function (exists) {
} else {
console.log('no preset file, ignoring...');
}
new SonosHttpAPI(discovery, port, presets);
new SonosHttpAPI(discovery, port, presets, ip, webroot);
});

0 comments on commit 3298fe2

Please sign in to comment.