client/annotviz/app/js/doubleroll.js
changeset 94 e0e514c5470f
child 95 806739a26858
equal deleted inserted replaced
93:79ae42ad97d4 94:e0e514c5470f
       
     1 /**
       
     2 * scripts/doubleroll.js
       
     3 *
       
     4 * This is the starting point for your application.
       
     5 * Take a look at http://browserify.org/ for more info
       
     6 */
       
     7 
       
     8 /* global window: false */
       
     9 /* global document: false */
       
    10 /* global WebSocket: false */
       
    11 /* global MozWebSocket: false */
       
    12 
       
    13 'use strict';
       
    14 
       
    15 
       
    16 var PIXI = require('pixi');
       
    17 var _ = require('lodash');
       
    18 var PianoRoll = require('./pianoroll.js');
       
    19 
       
    20 var NTP_EPOCH_DELTA = 2208988800; //c.f. RFC 868
       
    21 
       
    22 var defaultConfig = {
       
    23     logger: false,
       
    24     sceneWidth: 1920,
       
    25     pianorolls : [
       
    26       {
       
    27         height: 435,
       
    28         timeWidth: 10,
       
    29         lineInterval: 5000,
       
    30         noteHeight: undefined
       
    31       },
       
    32       {
       
    33         height: 645,
       
    34         timeWidth: 60,
       
    35         lineInterval: 5000,
       
    36         noteHeight: undefined
       
    37       },
       
    38     ],
       
    39     framerate: 25,
       
    40     offsetMusic: false,
       
    41     sceneBgColor: 0xFFFFFF,
       
    42     lineColor: 0x444444,
       
    43     lineFillColor: 0xFFFF00,
       
    44     noteColors: [0xB90000, 0x4BDD71, 0xAF931E, 0x1C28BA, 0x536991],
       
    45     canvasContainer: 'canvasContainer',
       
    46     logContainer: 'log',
       
    47     timeContainer: 'timeStarted',
       
    48     noteHeight: undefined,
       
    49     zeroShift: 0.9,
       
    50     timeWidth: 60,
       
    51     lineInterval: 5000,
       
    52     annotationChannel: 'PIANOROLL'
       
    53 //    wsUri: undefined,
       
    54 //    eventCode: undefined
       
    55 
       
    56 };
       
    57 
       
    58 function DoubleRoll(options) {
       
    59 
       
    60     var _this = this;
       
    61     var opts = _(options).defaults(defaultConfig).value();
       
    62 
       
    63     this.logger = opts.logger;
       
    64     this.lineColor = opts.lineColor;
       
    65     this.lineFillColor = opts.lineFillColor;
       
    66     this.framerate = opts.framerate;
       
    67     this.offsetMusic = opts.offsetMusic;
       
    68     this.noteColors = opts.noteColors;
       
    69 
       
    70     var noteHeight = opts.noteHeight;
       
    71     var sceneBgColor = opts.sceneBgColor;
       
    72     var sceneHeight = opts.sceneHeight || _(opts.pianorolls).reduce(function(s,p) { return s + p.height; }, 0);
       
    73     var timeWidth = opts.timeWidth;
       
    74     var lineInterval = opts.lineInterval;
       
    75     var offsetMusic = opts.offsetMusic;
       
    76 
       
    77     var sceneWidth = opts.sceneWidth;
       
    78     var canvasContainer = opts.canvasContainer;
       
    79     var logContainer = opts.logContainer;
       
    80     var timeContainer = opts.timeContainer;
       
    81 
       
    82     var zeroShift = opts.zeroShift;
       
    83 
       
    84     var eventCode = opts.eventCode;
       
    85     var annotationChannel = opts.annotationChannel;
       
    86     var wsUri = opts.wsUri;
       
    87     if(!wsUri) {
       
    88         if (window.location.protocol === 'file:') {
       
    89             wsUri = 'ws://127.0.0.1:8090/broadcast';
       
    90         }
       
    91         else {
       
    92             wsUri = 'ws://' + window.location.hostname + ':8090/broadcast';
       
    93         }
       
    94         wsUri += '?channel='+annotationChannel+'&event_code='+eventCode;
       
    95     }
       
    96 
       
    97 
       
    98     var colorsReg = {};
       
    99 
       
   100     //create an new instance of a pixi stage
       
   101     var stage = new PIXI.Stage(sceneBgColor);
       
   102     //create a renderer instance.
       
   103     var renderer = PIXI.autoDetectRenderer(sceneWidth, sceneHeight);
       
   104 
       
   105     var uberContainer = new PIXI.DisplayObjectContainer();
       
   106     uberContainer.x = Math.floor(sceneWidth*zeroShift);
       
   107     uberContainer.y = 0;
       
   108     stage.addChild(uberContainer);
       
   109 
       
   110     var pianorollList = [];
       
   111 
       
   112     var pianorollOptions = {
       
   113         parentContainer: uberContainer,
       
   114         xInit: 0,
       
   115         width: sceneWidth,
       
   116         noteColors: this.noteColors,
       
   117         colorsReg: colorsReg,
       
   118         lineColor: this.lineColor,
       
   119         lineInterval: lineInterval,
       
   120         offsetMusic: offsetMusic,
       
   121     };
       
   122 
       
   123     var yInit = 0;
       
   124     var linesDown = true;
       
   125     _(opts.pianorolls).forEach(function(prDef, i) {
       
   126         var prNoteHeight = noteHeight || prDef.noteHeight || prDef.height / 128;
       
   127         var prTimeWidth = prDef.timeWidth || timeWidth;
       
   128         pianorollList.push(new PianoRoll(_({
       
   129             yInit: yInit,
       
   130             height: prDef.height,
       
   131             linesDown: linesDown,
       
   132             pixelsPerSecond: Math.floor(sceneWidth / prTimeWidth),
       
   133             noteHeight: prNoteHeight,
       
   134             lineInterval: prDef.lineInterval
       
   135         }).defaults(pianorollOptions).value()));
       
   136         yInit += prDef.height;
       
   137         linesDown = !linesDown;
       
   138 
       
   139         if(i<(opts.pianorolls.length-1)) {
       
   140             var lineGraphics = new PIXI.Graphics()
       
   141                 .beginFill(_this.lineFillColor)
       
   142                 .lineStyle(1, _this.lineColor)
       
   143                 .moveTo(0, yInit)
       
   144                 .lineTo(sceneWidth, yInit)
       
   145                 .endFill();
       
   146             stage.addChild(lineGraphics);
       
   147         }
       
   148     });
       
   149 
       
   150     this.init = function() {
       
   151 
       
   152         if(typeof(canvasContainer) === 'string') {
       
   153             canvasContainer = document.getElementById(canvasContainer);
       
   154         }
       
   155         if(typeof(logContainer) === 'string') {
       
   156             logContainer = document.getElementById(logContainer);
       
   157         }
       
   158         if(typeof(timeContainer) === 'string') {
       
   159             timeContainer = document.getElementById(timeContainer);
       
   160         }
       
   161 
       
   162 
       
   163         if(!this.logger){
       
   164             document.body.removeChild(logContainer);
       
   165             logContainer = undefined;
       
   166         }
       
   167         var sock;
       
   168 
       
   169         canvasContainer.appendChild(renderer.view);
       
   170 
       
   171         if ('WebSocket' in window) {
       
   172             sock = new WebSocket(wsUri);
       
   173         } else if ('MozWebSocket' in window) {
       
   174             sock = new MozWebSocket(wsUri);
       
   175         } else {
       
   176             this.log('Browser does not support WebSocket!');
       
   177             window.location = 'http://autobahn.ws/unsupportedbrowser';
       
   178         }
       
   179 
       
   180         if (!sock) {
       
   181             return;
       
   182         }
       
   183         sock.onopen = function(){
       
   184             if(_this.logger){
       
   185                 _this.log('Connected to ' + _this.wsUri);
       
   186             }
       
   187         };
       
   188 
       
   189         sock.onclose = function(e) {
       
   190             if(_this.logger){
       
   191                 _this.log('Connection closed (wasClean = ' + e.wasClean + ', code = ' + e.code + ', reason = \'' + e.reason + '\')');
       
   192             }
       
   193             sock = null;
       
   194         };
       
   195 
       
   196         sock.onmessage = function(e) {
       
   197             var dataJson = JSON.parse(e.data);
       
   198             if(_this.logger){
       
   199                 var dataDate = new Date((dataJson.content[0]-NTP_EPOCH_DELTA)*1000);
       
   200                 _this.log('Got message: ' + e.data + ' - ' + dataDate.toISOString());
       
   201             }
       
   202             _this.addNotes(dataJson);
       
   203         };
       
   204 
       
   205     };
       
   206 
       
   207 
       
   208     this.addNotes = function(data) {
       
   209         var note = data.content[3];
       
   210         var velocity = data.content[4];
       
   211         var ts = (data.content[0] - NTP_EPOCH_DELTA)*1000;
       
   212         var channel = data.content[2];
       
   213         var sessionTs = data.content[1];
       
   214 
       
   215         pianorollList.forEach(function(c) {
       
   216             c.addNote(note, ts, sessionTs, velocity, channel, 0);
       
   217         });
       
   218     };
       
   219 
       
   220     this.refreshStage = function() {
       
   221         pianorollList.forEach(function(c) {
       
   222             c.move();
       
   223         });
       
   224         renderer.render(stage);
       
   225     };
       
   226 
       
   227     // Init page and intervals
       
   228     var refreshInterval;
       
   229     var refreshTimeInterval;
       
   230     var startTs;
       
   231 
       
   232     this.updateTime = function(){
       
   233         var nbSec = (Date.now() - startTs) / 1000;
       
   234         var hours = Math.floor( nbSec / 3600 ) % 24;
       
   235         var minutes = Math.floor( nbSec / 60 ) % 60;
       
   236         var seconds = Math.floor(nbSec % 60);
       
   237         var timeStr = (hours < 10 ? '0' + hours : hours) + ':' + (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds  < 10 ? '0' + seconds : seconds);
       
   238         timeContainer.innerHTML = timeStr;
       
   239     };
       
   240 
       
   241     this.start = function() {
       
   242 
       
   243         startTs = Date.now();
       
   244         refreshInterval = window.setInterval(function() {_this.refreshStage();}, 1000/this.framerate);
       
   245         refreshTimeInterval = window.setInterval(function() {_this.updateTime();}, 1000);
       
   246         pianorollList.forEach(function(c) {
       
   247             c.start();
       
   248         });
       
   249     };
       
   250 
       
   251     this.stop = function() {
       
   252         window.clearInterval(refreshInterval);
       
   253         window.clearInterval(refreshTimeInterval);
       
   254         pianorollList.forEach(function(c) {
       
   255             c.stop();
       
   256         });
       
   257     };
       
   258 
       
   259 
       
   260     this.log = function(m) {
       
   261         if(this.logger){
       
   262             this.logContainer.innerHTML += m + '\n';
       
   263             this.logContainer.scrollTop = logContainer.scrollHeight;
       
   264         }
       
   265     };
       
   266 
       
   267 
       
   268     window.onload = function() {
       
   269         _this.init();
       
   270         _this.start();
       
   271     };
       
   272 
       
   273     return this;
       
   274 }
       
   275 
       
   276 module.exports = {
       
   277     DoubleRoll: DoubleRoll
       
   278 };