client/annotviz/app/js/pianoroll.js
changeset 93 79ae42ad97d4
parent 85 eff9460bd4f2
child 94 e0e514c5470f
--- a/client/annotviz/app/js/pianoroll.js	Tue Jan 13 15:27:20 2015 +0100
+++ b/client/annotviz/app/js/pianoroll.js	Fri Jan 16 03:16:19 2015 +0100
@@ -5,40 +5,38 @@
 *
 */
 
+/* global window: false */
 'use strict';
 
+
 var PIXI = require('pixi');
 var randomColor = require('randomColor');
+var _ = require('lodash');
 
-function PianoRoll(parentContainer, xInit, yInit, height, linesDown, pixelsPerSecond, width, noteColors, colorsReg, lineColor, lineInterval, offsetMusic, noteHeight){
+
+function PianoRoll(options) {
     var _this = this;
     this.container = new PIXI.DisplayObjectContainer();
-    this.container.position.x = xInit;
-    this.container.position.y = yInit;
-    parentContainer.addChild(this.container);
+    this.container.position.x = options.xInit;
+    this.container.position.y = options.yInit;
+    options.parentContainer.addChild(this.container);
 
-    this.linesDown = linesDown;
-    this.height = height;
-    this.pixelsPerSecond = pixelsPerSecond;
-    this.width = width;
-    this.noteColors = noteColors;
-    this.colorsReg = colorsReg || {};
-    this.lineColor = lineColor;
-    this.lineInterval = lineInterval;
-    this.offsetMusic = offsetMusic || 0;
-    this.noteHeight = noteHeight;
+    this.linesDown = options.linesDown;
+    this.height = options.height;
+    this.pixelsPerSecond = options.pixelsPerSecond;
+    this.width = options.width;
+    this.noteColors = options.noteColors;
+    this.colorsReg = options.colorsReg || {};
+    this.lineColor = options.lineColor;
+    this.lineInterval = options.lineInterval;
+    this.offsetMusic = options.offsetMusic || false;
+    this.noteHeight = options.noteHeight;
+    this.noteDict = {};
+    this.startTs = options.startTs || Date.now();
 
-    this.addNote = function(note, startTime, duration, velocity, canal){
-        //console.log("coucou 1", note, timeFromZero, ts, velocity, pixelsPerSecond, container, prHeight);
-        var beginX = (this.offsetMusic + startTime) * this.pixelsPerSecond / 1000;
-        var width = duration * this.pixelsPerSecond / 1000;
-        if((beginX+width) <  (Math.abs(this.container.x) - this.width)) {
-            // not visible. do nothing
-            return;
-        }
-        // We draw the rectangle
-        var graphics = new PIXI.Graphics();
-        //console.log("beginX = ", beginX, "canal = ", canal, "color = ", noteColor[canal], "width = ", width, "note = ", note, "velocity = ", velocity);
+
+    //TODO: I do not like the "regColor" object. This should not be global, but local
+    this.getColor = function(canal) {
         var color = this.colorsReg[canal];
         if(typeof(color) === 'undefined') {
             var colorsRegSize = Object.keys(this.colorsReg).length;
@@ -49,15 +47,85 @@
                 color = this.colorsReg[canal] = parseInt(randomColor({ luminosity: 'light', hue: 'random', format:'hex'}).replace(/^#/, ''), 16);
             }
         }
-        graphics.beginFill(color, (velocity / 128));
-        var y = (128-note) * this.height / 128; // (128-note) because y = 0 is for note = 128 and y = 128 for note = 0
-        graphics.drawRect(0, Math.floor(y - (noteHeight/2) + ((this.height / 128)/2)), width, noteHeight);
+        return color;
+    };
+
+    this.getNoteRect = function(x, y, color, alpha, width, height) {
+        var graphics = new PIXI.Graphics();
+        //console.log("beginX = ", beginX, "canal = ", canal, "color = ", noteColor[canal], "width = ", width, "note = ", note, "velocity = ", velocity);
+        graphics.beginFill(color, alpha);
+        graphics.drawRect(0, 0, width, height);
         graphics.endFill();
-        graphics.x = beginX;
-        this.container.addChild(graphics);
+        graphics.x = x;
+        graphics.y = y;
+        graphics.width = width;
+        graphics.height = height;
+        return graphics;
+    };
+
+    this.addNote = function(note, startTime, sessionTs, velocity, channel, duration) {
+
+        var ts = startTime;
+        if(this.offsetMusic) {
+            ts = this.startTs + sessionTs;
+        }
+
+        var noteDuration = duration;
+        var noteVelocity = velocity;
+        var graphics;
+        if(!duration) {
+            if(typeof this.noteDict[channel]==='undefined'){
+                this.noteDict[channel] = {};
+            }
+            if(velocity===0) {
+                if(typeof this.noteDict[channel][note] !== 'undefined') {
+                    var noteDef = this.noteDict[channel][note];
+                    delete this.noteDict[channel][note];
+                    noteDuration = sessionTs - noteDef.sessionTs;
+                    graphics = noteDef.graphics;
+                    noteVelocity = noteDef.velocity;
+                    ts = noteDef.ts;
+                }
+            }
+            else {
+                noteDuration = Date.now() - ts;
+                this.noteDict[channel][note] = { ts: ts, velocity: velocity, sessionTs: sessionTs};
+            }
+        }
+
+
+        if(!this.offsetMusic || velocity===0) {
+
+            var width = noteDuration * this.pixelsPerSecond / 1000;
+            if(!graphics) {
+                var x = (ts-this.startTs) * this.pixelsPerSecond / 1000;
+                if((x+width) <  (Math.abs(this.container.x) - this.width)) {
+                    // not visible. do nothing
+                    return;
+                }
+                var y = Math.floor((128-note+0.5) * this.height / 128 - (this.noteHeight/2));
+                var color = this.getColor(channel);
+                var alpha = (noteVelocity / 128);
+
+                graphics = this.getNoteRect(x, y, color, alpha, width, this.noteHeight);
+                this.container.addChild(graphics);
+                //console.log(color, alpha, graphics.lineColor, graphics.fillAlpha);
+            }
+            else {
+                graphics.width = width;
+            }
+
+            if(!duration && velocity) {
+                this.noteDict[channel][note].graphics = graphics;
+            }
+        }
     };
 
     this.addLine = function(ts){
+
+        if(typeof(ts) === 'undefined') {
+            ts = new Date();
+        }
         var graphics = new PIXI.Graphics();
         var x = -this.container.x;
         graphics.beginFill(0xFFFF00);
@@ -82,7 +150,21 @@
     };
 
     this.moveTo = function(diffTime){
+        var oldX = this.container.x;
         this.container.x = Math.floor(diffTime*this.pixelsPerSecond);
+        var deltaX = Math.abs(oldX-this.container.x);
+        _.forOwn(this.noteDict, function(channelDict) {
+            _.forOwn(channelDict, function(noteDef) {
+                if(noteDef.graphics) {
+                    noteDef.graphics.width = noteDef.graphics.width + deltaX;
+                }
+            });
+        });
+    };
+
+    this.move = function() {
+        var diff = (this.startTs - Date.now())/1000;
+        this.moveTo(diff);
     };
 
     this.removePassedObjets = function(){
@@ -91,7 +173,7 @@
         while(i<nbChilds && !childIsNowDisplayed){
             var child = _this.container.children[i++];
             //console.log("remove ? ", child.x, child.width, ((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)));
-            if(typeof(child) == 'undefined') {
+            if(typeof(child) === 'undefined') {
                 continue;
             }
             if((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)){
@@ -109,9 +191,23 @@
         //console.log("before : ", nbChilds, ", after : ", _this.container.children.length);
     };
 
-    // remove notes each scene width
-    //var removeInterval = window.setInterval(this.removePassedObjets, 1000 * sceneWidth / this.pixelsPerSecond );
-    window.setInterval(this.removePassedObjets, 1000 * this.width / this.pixelsPerSecond );
+    this.start = function() {
+        if(typeof(this.startTs) === 'undefined') {
+            console.log('Container Started');
+            this.startTs = Date.now();
+            this.addLine();
+        }
+        var _this = this;
+        this.verticalLinesInterval = window.setInterval(function() { _this.addLine(); }, this.lineInterval);
+        this.cleanInterval = window.setInterval(function () { _this.removePassedObjets(); }, 1000 * this.width / this.pixelsPerSecond );
+    };
+
+    this.stop = function() {
+        //window.clearInterval(this.moveInterval);
+        window.clearInterval(this.verticalLinesInterval);
+        window.clearInterval(this.cleanInterval);
+    };
+
 
 }