changeset 0:156c2fd7c626

First commit.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Wed, 22 Feb 2012 19:57:56 +0100
parents
children 617063bc96f7
files config.js isshouni.js jid.js
diffstat 3 files changed, 261 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/config.js
@@ -0,0 +1,4 @@
+exports.jid = 'you@example.org';
+exports.password = 'pass';
+exports.muc = 'isshouni@muc.linkmauve.fr';
+exports.nick = 'You';
new file mode 100755
--- /dev/null
+++ b/isshouni.js
@@ -0,0 +1,142 @@
+#!/usr/bin/env node
+'use strict';
+
+/**
+  Copyright (c) 2012, Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+
+var config = require('./config');
+var args = ['-slave'].concat(process.argv.slice(2));
+
+var tty = require('tty');
+var xmpp = require('node-xmpp');
+var JID = require('./jid');
+var spawn = require('child_process').spawn;
+
+var cl = new xmpp.Client(config);
+var mplayer = spawn('mplayer', args);
+
+var connect = function() {
+  cl.send(new xmpp.Element('presence', {to: config.muc + '/' + config.nick})
+    .c('x', {xmlns: 'http://jabber.org/protocol/muc'})
+      .c('history', {maxchars: '0'})
+  .up());
+  //TODO: handle join errors.
+};
+cl.on('online', connect);
+
+var disconnect = function() {
+  cl.send(new xmpp.Element('presence', {to: config.muc + '/' + config.nick, type: 'unavailable'}));
+  process.stdin.end();
+  cl.end();
+};
+
+var send_message = function(name, arg) {
+  //console.log('SENT: ' + name + ' ' + arg);
+  var message = new xmpp.Element('message', {to: config.muc, type: 'groupchat'})
+    .c(name, {xmlns: 'urn:linkmauve:player'});
+
+  if (arg)
+    message.t(arg);
+
+  cl.send(message.up());
+};
+
+var send_command = function(text) {
+  //console.log(text);
+  mplayer.stdin.write(text + '\n');
+};
+
+cl.on('stanza', function(stanza) {
+  //console.log(stanza.toString());
+  if (!stanza.is('message') || stanza.attrs['type'] !== 'groupchat')
+    return;
+
+  var from = new JID(stanza.attrs['from']);
+  if (from.bare !== config.muc)
+    return;
+  if (from.resource === config.nick)
+    return;
+
+  var message = stanza.getChild('body');
+  if (message)
+    send_command('osd_show_text "' + from.resource + ': ' + message.getText() + '"');
+
+  var payload = stanza.getChild(null, 'urn:linkmauve:player');
+  if (!payload)
+    return;
+
+  //send_command('osd_show_text "' + from.resource + ' did ' + payload.name + '"');
+
+  if (payload.name === 'pause')
+    send_command('pause');
+  else if (payload.name === 'seek')
+    send_command('seek ' + payload.getText());
+  else if (payload.name === 'synchro')
+    send_command('seek ' + payload.getText() + ' 2');
+});
+
+cl.on('error', function(e) {
+  console.log(e);
+});
+
+var commands = {
+  '+': 'volume 1',
+  '-': 'volume -1',
+  'm': 'mute',
+  ' ': function() {
+    send_message('pause');
+    send_command('get_time_pos');
+    return 'pause';
+  },
+  'q': function() {
+    tty.setRawMode(false);
+    disconnect();
+    return 'quit';
+  },
+};
+
+process.stdin.resume();
+tty.setRawMode(true);
+process.stdin.on('keypress', function(char, key) {
+  if (!char) {
+    if (key.name == 'right')
+      send_command('seek 10');
+    else if (key.name == 'left')
+      send_command('seek -10');
+    else if (key.name == 'up')
+      send_command('seek 60');
+    else if (key.name == 'down')
+      send_command('seek -60');
+  } else if (char in commands) {
+    var command = commands[char];
+    if (typeof command === 'function')
+      command = command();
+    send_command(command);
+  }
+});
+
+mplayer.stdout.on('data', function(data) {
+  //console.log('DATA: '+data);
+  data = /(ANS_TIME_POSITION)=([0-9\.]+)/.exec(data);
+  if (!data)
+    return;
+
+  var cmd = data[1];
+  var arg = data[2];
+  if (cmd === 'ANS_TIME_POSITION')
+    send_message('synchro', arg);
+});
new file mode 100644
--- /dev/null
+++ b/jid.js
@@ -0,0 +1,115 @@
+'use strict';
+
+/**
+  Copyright (c) 2012, Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+
+/**
+ * @constructor Creates a new JID object.
+ * @param {String} [aJID] The host, bare or full JID.
+ */
+var JID = function(aJID) {
+  this.node = null;
+  this.domain = null;
+  this.resource = null;
+
+  if (aJID)
+    this.full = aJID;
+
+  //TODO: use a stringprep library to validate the input.
+};
+
+JID.prototype = {
+  toString: function() {
+    return this.full;
+  },
+
+  equals: function(aJID) {
+    if (!(aJID instanceof JID))
+      aJID = new JID(aJID);
+
+    return (this.node === aJID.node &&
+            this.domain === aJID.domain &&
+            this.resource === aJID.resource)
+  },
+
+  get bare() {
+    if (!this.domain)
+      return null;
+
+    if (this.node)
+      return this.node + '@' + this.domain;
+
+    return this.domain;
+  },
+
+  set bare(aJID) {
+    if (!aJID)
+      return;
+
+    var s = aJID.indexOf('/');
+    if (s != -1)
+      aJID = aJID.substring(0, s);
+
+    s = aJID.indexOf('@');
+    if (s == -1) {
+      this.node = null;
+      this.domain = aJID;
+    } else {
+      this.node = aJID.substring(0, s);
+      this.domain = aJID.substring(s+1);
+    }
+  },
+
+  get full() {
+    if (!this.domain)
+      return null;
+
+    var full = this.domain;
+
+    if (this.node)
+      full = this.node + '@' + full;
+
+    if (this.resource)
+      full = full + '/' + this.resource;
+
+    return full;
+  },
+
+  set full(aJID) {
+    if (!aJID)
+      return;
+
+    var s = aJID.indexOf('/');
+    if (s == -1)
+      this.resource = null;
+    else {
+      this.resource = aJID.substring(s+1);
+      aJID = aJID.substring(0, s);
+    }
+
+    s = aJID.indexOf('@');
+    if (s == -1) {
+      this.node = null;
+      this.domain = aJID;
+    } else {
+      this.node = aJID.substring(0, s);
+      this.domain = aJID.substring(s+1);
+    }
+  }
+};
+
+module.exports = JID;