annot-server/static/js/pianoroll.js
changeset 83 9be99c2fb279
parent 82 ae37d35a419c
child 84 d7c5bffdd2d8
equal deleted inserted replaced
82:ae37d35a419c 83:9be99c2fb279
     1 // Config vars
       
     2 var logger = false;
       
     3 var sceneWidth = 1920;
       
     4 var prHeight1 = 435;
       
     5 var prHeight2 = 645;
       
     6 var sceneHeight = prHeight1 + prHeight2;
       
     7 var sceneBgColor = 0xFFFFFF;
       
     8 var lineColor = 0x444444;
       
     9 var pixelsPerSecond1 = Math.floor(sceneWidth / 10); // nb of pixels per second
       
    10 var manualFramerate = pixelsPerSecond1 / 4;
       
    11 var pixelsPerSecond2 = Math.floor(sceneWidth / 60); // nb of pixels per second
       
    12 var lineInterval = 5000; // means line every 5 seconds
       
    13 var nbLines = -1;
       
    14 var noteHeight = 110;
       
    15 var noteColors = [0xB90000, 0x4BDD71, 0xAF931E, 0x1C28BA, 0x536991];
       
    16 var colorsReg = {}
       
    17 // Vars
       
    18 var noteDict = [];
       
    19 // Timecode method
       
    20 var timePageLoaded = Date.now();
       
    21 var offsetMusic = false;
       
    22 
       
    23 
       
    24 //create an new instance of a pixi stage
       
    25 var stage = new PIXI.Stage(sceneBgColor);
       
    26 
       
    27 //create a renderer instance.
       
    28 var renderer = PIXI.autoDetectRenderer(sceneWidth, sceneHeight);
       
    29 
       
    30 //add the renderer view element to the DOM
       
    31 document.getElementById("canvasContainer").appendChild(renderer.view);
       
    32 
       
    33 var uberContainer = new PIXI.DisplayObjectContainer();
       
    34 uberContainer.position.x = Math.floor(sceneWidth*9/10);
       
    35 uberContainer.position.y = 0;
       
    36 stage.addChild(uberContainer);
       
    37 
       
    38 
       
    39 function PianoRoll(parentContainer, xInit, yInit, height, linesDown, pixelsPerSecond, width, noteColors, colorsReg){
       
    40     var _this = this;
       
    41     this.container = new PIXI.DisplayObjectContainer();
       
    42     this.container.position.x = xInit;
       
    43     this.container.position.y = yInit;
       
    44     parentContainer.addChild(this.container);
       
    45 
       
    46     this.linesDown = linesDown;
       
    47     this.height = height;
       
    48     this.pixelsPerSecond = pixelsPerSecond;
       
    49     this.width = width;
       
    50     this.noteColors = noteColors;
       
    51     this.colorsReg = colorsReg || {}
       
    52 
       
    53     this.addNote = function(note, startTime, duration, velocity, canal){
       
    54         //console.log("coucou 1", note, timeFromZero, ts, velocity, pixelsPerSecond, container, prHeight);
       
    55         var beginX = (offsetMusic + startTime) * this.pixelsPerSecond / 1000;
       
    56         var width = duration * this.pixelsPerSecond / 1000;
       
    57         // We draw the rectangle
       
    58         var graphics = new PIXI.Graphics();
       
    59         //console.log("beginX = ", beginX, "canal = ", canal, "color = ", noteColor[canal], "width = ", width, "note = ", note, "velocity = ", velocity);
       
    60         var color = this.colorsReg[canal];
       
    61         if(typeof(color) === 'undefined') {
       
    62             var colorsRegSize = Object.keys(this.colorsReg).length
       
    63             if(colorsRegSize < this.noteColors.length) {
       
    64                 color = this.colorsReg[canal] = this.noteColors[colorsRegSize];
       
    65             }
       
    66             else {
       
    67                 color = this.colorsReg[canal] = parseInt(randomColor({ luminosity: 'light', hue: 'random', format:'hex'}).replace(/^#/, ''), 16);
       
    68             }
       
    69         }
       
    70         graphics.beginFill(color, (velocity / 128));
       
    71         var y = (128-note) * this.height / 128; // (128-note) because y = 0 is for note = 128 and y = 128 for note = 0
       
    72         graphics.drawRect(0, Math.floor(y - (noteHeight/2) + ((this.height / 128)/2)), width, noteHeight);
       
    73         graphics.endFill();
       
    74         graphics.x = beginX;
       
    75         this.container.addChild(graphics);
       
    76     };
       
    77 
       
    78     this.addLine = function(lineNb){
       
    79         var graphics = new PIXI.Graphics();
       
    80         var x = -this.container.x;
       
    81         graphics.beginFill(0xFFFF00);
       
    82         graphics.lineStyle(1, lineColor);
       
    83         var y = this.linesDown ? this.height - 20 : 0;
       
    84         graphics.moveTo(x, y);
       
    85         graphics.lineTo(x, y + 20);
       
    86         graphics.endFill();
       
    87         this.container.addChild(graphics);
       
    88         // Add text
       
    89         var totalSec = lineNb * lineInterval / 1000;
       
    90         var hours = parseInt( totalSec / 3600 ) % 24;
       
    91         var minutes = parseInt( totalSec / 60 ) % 60;
       
    92         var seconds = totalSec % 60;
       
    93         var timeStr = (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes) + ":" + (seconds  < 10 ? "0" + seconds : seconds);
       
    94         var fontObj = { font: "10pt Arial", fill: "#444444" };
       
    95         var t = new PIXI.Text(timeStr, fontObj);
       
    96         t.x = x + 2;
       
    97         t.y = this.linesDown ? this.height - 15 : 2;
       
    98         this.container.addChild(t);
       
    99     };
       
   100 
       
   101     this.moveTo = function(diffTime){
       
   102         this.container.x = Math.floor(diffTime*this.pixelsPerSecond);
       
   103     };
       
   104 
       
   105     this.removePassedObjets = function(){
       
   106         var nbChilds = _this.container.children.length;
       
   107         var i = 0, childIsNowDisplayed = false;
       
   108         while(i<nbChilds && !childIsNowDisplayed){
       
   109             var child = _this.container.children[0];
       
   110             //console.log("remove ? ", child.x, child.width, ((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)));
       
   111             if((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)){
       
   112                 _this.container.removeChild(child);
       
   113                 //console.log("    remove !!!");
       
   114             }
       
   115             else{
       
   116                 childIsNowDisplayed = true;
       
   117                 //console.log("    childIsNowDisplayed");
       
   118             }
       
   119             i++;
       
   120         }
       
   121         //console.log("before : ", nbChilds, ", after : ", _this.container.children.length);
       
   122     };
       
   123 
       
   124     // remove notes each scene width
       
   125     var removeInterval = window.setInterval(this.removePassedObjets, 1000 * sceneWidth / this.pixelsPerSecond );
       
   126 
       
   127 }
       
   128 
       
   129 // Init containers
       
   130 var containerList = [];
       
   131 containerList.push(new PianoRoll(uberContainer, 0, 0, prHeight1, true, pixelsPerSecond1, sceneWidth, noteColors, colorsReg));
       
   132 containerList.push(new PianoRoll(uberContainer, 0, prHeight1, prHeight2, false, pixelsPerSecond2, sceneWidth, noteColors, colorsReg));
       
   133 
       
   134 // Line between two containers
       
   135 var graphics = new PIXI.Graphics();
       
   136 graphics.beginFill(0xFFFF00);
       
   137 graphics.lineStyle(1, lineColor);
       
   138 graphics.moveTo(0, prHeight1);
       
   139 graphics.lineTo(sceneWidth, prHeight1);
       
   140 graphics.endFill();
       
   141 stage.addChild(graphics);
       
   142 
       
   143 
       
   144 function replaceContainers(){
       
   145     var diff = (Date.now() - timePageLoaded)/1000;// nb of seconds since page loaded
       
   146     //console.log("replace ! diff1 = ", container1.x - Math.floor(-diff*pixelsPerSecond1), ", diff 2 = ", container2.x - Math.floor(-diff*pixelsPerSecond2));
       
   147     for(var i=0;i<containerList.length;i++){
       
   148         containerList[i].moveTo(-diff);
       
   149     }
       
   150     renderer.render(stage);
       
   151 }
       
   152 
       
   153 function addNotes(data){
       
   154     if(!offsetMusic){
       
   155         // get difference between the current note timecode and my zero to set the difference between the canvas's zero and the music's zero
       
   156         // in order to place in real time
       
   157         var now = Date.now();
       
   158         var timeBetweenNowAndStart = now - timePageLoaded;
       
   159         offsetMusic = timeBetweenNowAndStart - data.content[1];
       
   160         //console.log("start: ", timePageLoaded, ", now: ", now, ", timeBetweenNowAndStart = ", timeBetweenNowAndStart, ", offsetMusic = ", offsetMusic);
       
   161     }
       
   162     var note = data.content[3];
       
   163     var velocity = data.content[4];
       
   164     if(velocity===0){
       
   165         if(typeof noteDict[data.content[2]][note]!=='undefined'){
       
   166             // We close the note in container one
       
   167             //console.log("coucou 2", data);
       
   168             var duration = data.content[1] - noteDict[data.content[2]][note].ts;
       
   169             for(var i=0;i<containerList.length;i++){
       
   170                 //               addNote(note, startTime,                          duration, velocity,                                 canal)
       
   171                 containerList[i].addNote(note, noteDict[data.content[2]][note].ts, duration, noteDict[data.content[2]][note].velocity, data.content[2]);
       
   172             }
       
   173             // delete entry
       
   174             delete noteDict[data.content[2]][note];
       
   175         }
       
   176     }
       
   177     else{
       
   178         if(typeof noteDict[data.content[2]]==='undefined'){
       
   179             noteDict[data.content[2]] = {};
       
   180         }
       
   181         noteDict[data.content[2]][note] = {ts: data.content[1], velocity:velocity};
       
   182     }
       
   183 }
       
   184 
       
   185 function addLine(){
       
   186     nbLines++;
       
   187     for(var i=0;i<containerList.length;i++){
       
   188         containerList[i].addLine(nbLines);
       
   189     }
       
   190 }
       
   191 
       
   192 
       
   193 
       
   194 // Socket management
       
   195 var sock = null;
       
   196 var ellog = null;
       
   197 function log(m) {
       
   198     if(logger){
       
   199         ellog.innerHTML += m + '\n';
       
   200         ellog.scrollTop = ellog.scrollHeight;
       
   201     }
       
   202 }
       
   203 window.onload = function(){
       
   204 
       
   205     if(logger){
       
   206         ellog = document.getElementById('log');
       
   207     }
       
   208     else{
       
   209         document.body.removeChild(document.getElementById('log'));
       
   210     }
       
   211 
       
   212     var wsuri;
       
   213     if (window.location.protocol === "file:") {
       
   214        wsuri = "ws://127.0.0.1:8090/broadcast";
       
   215     } else {
       
   216        wsuri = "ws://" + window.location.hostname + ":8090/broadcast";
       
   217     }
       
   218     wsuri = wsuri + "?channel=PIANOROLL&event_code="+event_code;
       
   219 
       
   220     if ("WebSocket" in window) {
       
   221        sock = new WebSocket(wsuri);
       
   222     } else if ("MozWebSocket" in window) {
       
   223        sock = new MozWebSocket(wsuri);
       
   224     } else {
       
   225        log("Browser does not support WebSocket!");
       
   226        window.location = "http://autobahn.ws/unsupportedbrowser";
       
   227     }
       
   228 
       
   229     if (sock) {
       
   230         sock.onopen = function(){
       
   231             if(logger){
       
   232                 log("Connected to " + wsuri);
       
   233             }
       
   234         }
       
   235 
       
   236         sock.onclose = function(e) {
       
   237             if(logger){
       
   238                 log("Connection closed (wasClean = " + e.wasClean + ", code = " + e.code + ", reason = '" + e.reason + "')");
       
   239             }
       
   240             sock = null;
       
   241         }
       
   242 
       
   243         sock.onmessage = function(e) {
       
   244             if(logger){
       
   245                 log("Got message: " + e.data);
       
   246             }
       
   247             addNotes(JSON.parse(e.data));
       
   248         }
       
   249     }
       
   250 };
       
   251 
       
   252 
       
   253 // Init page and intervals
       
   254 addLine();
       
   255 var moveInterval = window.setInterval(replaceContainers, 1000/manualFramerate);
       
   256 var verticalLinesInterval = window.setInterval(addLine, lineInterval);
       
   257 
       
   258 // Little inteval to show time
       
   259 var nbSec = 0;
       
   260 var mySpan = document.getElementById("myspan");
       
   261 function updateTime(){
       
   262     nbSec++;
       
   263     var hours = parseInt( nbSec / 3600 ) % 24;
       
   264     var minutes = parseInt( nbSec / 60 ) % 60;
       
   265     var seconds = nbSec % 60;
       
   266     var timeStr = (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes) + ":" + (seconds  < 10 ? "0" + seconds : seconds);
       
   267     mySpan.innerHTML = timeStr;
       
   268 }
       
   269 var secondInterval = window.setInterval(updateTime, 1000);