diff options
Diffstat (limited to 'public/js')
| -rw-r--r-- | public/js/chat.js | 93 | ||||
| -rw-r--r-- | public/js/sample.js | 94 |
2 files changed, 187 insertions, 0 deletions
diff --git a/public/js/chat.js b/public/js/chat.js new file mode 100644 index 0000000..27b0c8e --- /dev/null +++ b/public/js/chat.js @@ -0,0 +1,93 @@ +/* -*- mode:javascript; coding:utf-8; -*- */ + +'use strict'; + +(function (window) { + function on_ended(context) { + if (this.link && this.link.buffer) { + console.log('playing next sound'); + queue.link = this.link; + this.link.onended = _.partial(on_ended, context); + this.link.play(context); + } + else { + console.log('playing again'); + this.play(context); + } + }; + + function Queue() { + this.last = this; + } + + Queue.prototype.append = function (x) { + if (!this.seen || x.gt(this.seen)) { + this.last.link = x; + this.last = x; + this.seen = { + seq: x.seq, + timestamp: x.timestamp + }; + return x; + } + else { + return null; + } + }; + + var queue = new Queue(); + + window.AudioContext = window.AudioContext || window.webkitAudioContext; + + window.onload = function () { + var context = new AudioContext(); + var field = document.getElementById("field"); + var history = document.getElementById("history"); + var send = document.getElementById('send'); + + var messages = []; + var socket = io.connect('/'); + + socket.on('message', function (data) { + if (data.message) { + messages.push(data.message); + + var html = ''; + + for (var i = 0; i < messages.length; i++) { + html += messages[i] + '<br />'; + } + history.innerHTML = html; + + if (data.queue) { + _.each(data.queue, function (s) { + try { + var sample = new Sample(s); + + if (queue.append(sample)) { + if (queue.link === sample) { + sample.onended = _.partial(on_ended, context); + sample.onload = function () { + this.play(context); + }; + } + sample.load(context); + } + } + catch (e) { + console.error((e.message || 'error') + ' in "' + s + '"'); + } + }); + } + } + else { + console.error('error: ', data); + } + }); + + send.onclick = function () { + var text = field.value; + socket.emit('send', { message: text }); + }; + }; +})(window); diff --git a/public/js/sample.js b/public/js/sample.js new file mode 100644 index 0000000..d54be71 --- /dev/null +++ b/public/js/sample.js @@ -0,0 +1,94 @@ +/* -*- mode:javascript; coding:utf-8; -*- */ + +'use strict'; + +(function (window) { + var LOOP_COUNT = 4; + + function sample(json) { + var x = JSON.parse(json); + + this.seq = x.seq || 0; + this.timestamp = x.timestamp || 0; + this.url = x.url; + } + + sample.prototype.gt = function (x) { + return this.timestamp > x.timestamp || this.timestamp === x.timestamp && this.seq > x.seq; + }; + + sample.prototype.load = function (context) { + var self = this; + + if (self.url) { + var request = new XMLHttpRequest(); + + request.open('GET', self.url, true); + request.responseType = 'arraybuffer'; + + request.onload = function (v) { + if (v && v.target && v.target.status == 200) { + context.decodeAudioData(request.response, function (buffer) { + if (buffer) { + self.buffer = buffer; + + if (self.onload) { + self.onload(); + } + console.log('sample.load: finished ', self.url); + } + else { + console.error('sample.load: no decoded data', self); + } + }, function (e) { + console.error('sample.load: decodeAudioData error', e, self); + }); + } + }; + + request.onerror = function (e) { + var s = (e && e.target && e.target.status && e.target.statusText + ? (e.target.status + ' ' + e.target.statusText) + : 'error'); + console.error('sample.load: ' + s + ' while loading', self); + }; + + request.send(); + } + else { + console.error('sample.load: no URL'); + } + }; + + sample.prototype.play = function (context) { + var self = this; + + if (self.buffer) { + var delay = self.buffer.duration * LOOP_COUNT + var source = context.createBufferSource(); + + source.buffer = self.buffer; + source.loop = true; + + source.connect(context.destination); + source.start(context.currentTime); + source.stop(context.currentTime + delay); + + window.setTimeout(function () { + if (self.onended) { + self.onended(); + } + }, delay * 1000); + + // does not work + //source.onended = function (e) { + // console.log(e); + //}; + } + else { + console.error('sample.play: no buffer', self); + } + }; + + window['Sample'] = sample; +})(window); |
