--- a/.hgignore Mon Jan 12 17:23:05 2015 +0100
+++ b/.hgignore Tue Jan 13 10:46:05 2015 +0100
@@ -21,8 +21,10 @@
\.orig$
^client/pianoroll/dist
^client/pianoroll/.tmp
-^client/pianoroll/.sass-cache
^client/pianoroll/app/lib
+^client/annotviz/dist
+^client/annotviz/.tmp
+^client/annotviz/app/lib
node_modules
.DS_Store
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/.bowerrc Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,3 @@
+{
+ "directory": "app/lib"
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/.editorconfig Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,13 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/.gitattributes Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,1 @@
+* text=auto
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/.jshintrc Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,21 @@
+{
+ "node": true,
+ "esnext": true,
+ "bitwise": true,
+ "camelcase": true,
+ "curly": true,
+ "eqeqeq": true,
+ "immed": true,
+ "indent": 4,
+ "latedef": true,
+ "newcap": true,
+ "noarg": true,
+ "quotmark": "single",
+ "regexp": true,
+ "undef": true,
+ "unused": true,
+ "strict": true,
+ "trailing": true,
+ "smarttabs": true,
+ "white": false
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/README.md Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,1 @@
+# Mons Pianoroll
Binary file client/annotviz/app/img/favicon.ico has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/app/index.html Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1">
+ <meta name="description" content="">
+ <meta name="author" content="I.R.I">
+ <link rel="shortcut icon" href="/img/favicon.ico">
+
+ <title>Piano Roll</title>
+
+ <!-- Custom styles for this template -->
+ <link href="/css/pianoroll.css" rel="stylesheet">
+</head>
+
+<body>
+ <h1>Piano Roll</h1>
+ <noscript>You must enable JavaScript</noscript>
+ <div id="canvasContainer"></div>
+ <p>
+ <a href="#" onclick="clearInterval(moveInterval); clearInterval(verticalLinesInterval); return false;">stop intervals</a>
+ - temps écoulé : <span id="myspan"></span>
+ </p>
+ <pre id="log"></pre>
+ <script src="/js/libs-pianoroll.js"></script>
+ <script>
+ var eventCode = "test_1";
+ </script>
+ <script src="/js/pianoroll.js"></script>
+ <script>
+ var moveInterval = pianoroll.moveInterval;
+ var verticalLinesInterval = pianoroll.verticalLinesInterval;
+ </script>
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/app/js/main.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,198 @@
+/**
+ * scripts/main.js
+ *
+ * This is the starting point for your application.
+ * Take a look at http://browserify.org/ for more info
+ */
+
+'use strict';
+
+
+var PIXI = require('pixi');
+
+// Config vars
+var logger = false;
+var sceneWidth = 1920;
+var prHeight1 = 435;
+var prHeight2 = 645;
+var sceneHeight = prHeight1 + prHeight2;
+var sceneBgColor = 0xFFFFFF;
+var lineColor = 0x444444;
+var pixelsPerSecond1 = Math.floor(sceneWidth / 10); // nb of pixels per second
+var manualFramerate = pixelsPerSecond1 / 4;
+var pixelsPerSecond2 = Math.floor(sceneWidth / 60); // nb of pixels per second
+var lineInterval = 5000; // means line every 5 seconds
+var nbLines = -1;
+var noteHeight = 110;
+var noteColors = [0xB90000, 0x4BDD71, 0xAF931E, 0x1C28BA, 0x536991];
+var colorsReg = {};
+// Vars
+var noteDict = [];
+// Timecode method
+var timePageLoaded = Date.now();
+var offsetMusic = false;
+
+
+//create an new instance of a pixi stage
+var stage = new PIXI.Stage(sceneBgColor);
+
+//create a renderer instance.
+var renderer = PIXI.autoDetectRenderer(sceneWidth, sceneHeight);
+
+//add the renderer view element to the DOM
+document.getElementById('canvasContainer').appendChild(renderer.view);
+
+var uberContainer = new PIXI.DisplayObjectContainer();
+uberContainer.position.x = Math.floor(sceneWidth*9/10);
+uberContainer.position.y = 0;
+stage.addChild(uberContainer);
+
+var PianoRoll = require('./pianoroll.js')
+
+// Init containers
+var containerList = [];
+containerList.push(new PianoRoll(uberContainer, 0, 0, prHeight1, true, pixelsPerSecond1, sceneWidth, noteColors, colorsReg, lineColor, lineInterval, offsetMusic, prHeight1 / 128));
+containerList.push(new PianoRoll(uberContainer, 0, prHeight1, prHeight2, false, pixelsPerSecond2, sceneWidth, noteColors, colorsReg, lineColor, lineInterval, offsetMusic, prHeight2 / 128));
+
+// Line between two containers
+var graphics = new PIXI.Graphics();
+graphics.beginFill(0xFFFF00);
+graphics.lineStyle(1, lineColor);
+graphics.moveTo(0, prHeight1);
+graphics.lineTo(sceneWidth, prHeight1);
+graphics.endFill();
+stage.addChild(graphics);
+
+
+function replaceContainers(){
+ var diff = (Date.now() - timePageLoaded)/1000;// nb of seconds since page loaded
+ //console.log("replace ! diff1 = ", container1.x - Math.floor(-diff*pixelsPerSecond1), ", diff 2 = ", container2.x - Math.floor(-diff*pixelsPerSecond2));
+ for(var i=0;i<containerList.length;i++){
+ containerList[i].moveTo(-diff);
+ }
+ renderer.render(stage);
+}
+
+function addNotes(data){
+ if(!offsetMusic){
+ // get difference between the current note timecode and my zero to set the difference between the canvas's zero and the music's zero
+ // in order to place in real time
+ var now = Date.now();
+ var timeBetweenNowAndStart = now - timePageLoaded;
+ offsetMusic = timeBetweenNowAndStart - data.content[1];
+ //console.log("start: ", timePageLoaded, ", now: ", now, ", timeBetweenNowAndStart = ", timeBetweenNowAndStart, ", offsetMusic = ", offsetMusic);
+ }
+ var note = data.content[3];
+ var velocity = data.content[4];
+ if(velocity===0){
+ if(typeof noteDict[data.content[2]][note]!=='undefined'){
+ // We close the note in container one
+ //console.log("coucou 2", data);
+ var duration = data.content[1] - noteDict[data.content[2]][note].ts;
+ for(var i=0;i<containerList.length;i++){
+ // addNote(note, startTime, duration, velocity, canal)
+ containerList[i].addNote(note, noteDict[data.content[2]][note].ts, duration, noteDict[data.content[2]][note].velocity, data.content[2]);
+ }
+ // delete entry
+ delete noteDict[data.content[2]][note];
+ }
+ }
+ else{
+ if(typeof noteDict[data.content[2]]==='undefined'){
+ noteDict[data.content[2]] = {};
+ }
+ noteDict[data.content[2]][note] = {ts: data.content[1], velocity:velocity};
+ }
+}
+
+function addLine(){
+ ts = new Date();
+ for(var i=0;i<containerList.length;i++){
+ containerList[i].addLine(ts);
+ }
+}
+
+
+
+// Socket management
+var sock = null;
+var ellog = null;
+function log(m) {
+ if(logger){
+ ellog.innerHTML += m + '\n';
+ ellog.scrollTop = ellog.scrollHeight;
+ }
+}
+window.onload = function(){
+
+ if(logger){
+ ellog = document.getElementById('log');
+ }
+ else{
+ document.body.removeChild(document.getElementById('log'));
+ }
+
+ var wsuri;
+ if (window.location.protocol === 'file:') {
+ wsuri = 'ws://127.0.0.1:8090/broadcast';
+ } else {
+ wsuri = 'ws://' + window.location.hostname + ':8090/broadcast';
+ }
+ wsuri = wsuri + '?channel=PIANOROLL&event_code='+eventCode;
+
+ if ('WebSocket' in window) {
+ sock = new WebSocket(wsuri);
+ } else if ('MozWebSocket' in window) {
+ sock = new MozWebSocket(wsuri);
+ } else {
+ log('Browser does not support WebSocket!');
+ window.location = 'http://autobahn.ws/unsupportedbrowser';
+ }
+
+ if (sock) {
+ sock.onopen = function(){
+ if(logger){
+ log('Connected to ' + wsuri);
+ }
+ };
+
+ sock.onclose = function(e) {
+ if(logger){
+ log('Connection closed (wasClean = ' + e.wasClean + ', code = ' + e.code + ', reason = \'' + e.reason + '\')');
+ }
+ sock = null;
+ };
+
+ sock.onmessage = function(e) {
+ if(logger){
+ log('Got message: ' + e.data);
+ }
+ addNotes(JSON.parse(e.data));
+ };
+ }
+};
+
+
+// Init page and intervals
+addLine();
+var moveInterval = window.setInterval(replaceContainers, 1000/manualFramerate);
+var verticalLinesInterval = window.setInterval(addLine, lineInterval);
+
+// Little inteval to show time
+var nbSec = 0;
+var mySpan = document.getElementById('myspan');
+function updateTime(){
+ nbSec++;
+ var hours = parseInt( nbSec / 3600 ) % 24;
+ var minutes = parseInt( nbSec / 60 ) % 60;
+ var seconds = nbSec % 60;
+ var timeStr = (hours < 10 ? '0' + hours : hours) + ':' + (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds);
+ mySpan.innerHTML = timeStr;
+}
+var secondInterval = window.setInterval(updateTime, 1000);
+
+module.exports = {
+ moveInterval: moveInterval,
+ verticalLinesInterval: verticalLinesInterval,
+ secondInterval: secondInterval
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/app/js/pianoroll.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,118 @@
+/**
+* js/pianoroll.js
+*
+* pianoroll basic component
+*
+*/
+
+'use strict';
+
+var PIXI = require('pixi');
+var randomColor = require('randomColor');
+
+function PianoRoll(parentContainer, xInit, yInit, height, linesDown, pixelsPerSecond, width, noteColors, colorsReg, lineColor, lineInterval, offsetMusic, noteHeight){
+ var _this = this;
+ this.container = new PIXI.DisplayObjectContainer();
+ this.container.position.x = xInit;
+ this.container.position.y = yInit;
+ 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.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);
+ var color = this.colorsReg[canal];
+ if(typeof(color) === 'undefined') {
+ var colorsRegSize = Object.keys(this.colorsReg).length;
+ if(colorsRegSize < this.noteColors.length) {
+ color = this.colorsReg[canal] = this.noteColors[colorsRegSize];
+ }
+ else {
+ 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);
+ graphics.endFill();
+ graphics.x = beginX;
+ this.container.addChild(graphics);
+ };
+
+ this.addLine = function(ts){
+ var graphics = new PIXI.Graphics();
+ var x = -this.container.x;
+ graphics.beginFill(0xFFFF00);
+ graphics.lineStyle(1, this.lineColor);
+ var y = this.linesDown ? this.height - 20 : 0;
+ graphics.moveTo(x, y);
+ graphics.lineTo(x, y + 20);
+ graphics.endFill();
+ this.container.addChild(graphics);
+ // Add text
+ //var totalSec = lineNb * this.lineInterval / 1000;
+ var hours = ts.getHours();
+ var minutes =ts.getMinutes();
+ var seconds = ts.getSeconds();
+ var timeStr = (hours < 10 ? '0' + hours : hours) + ':' + (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds);
+
+ var fontObj = { font: '10pt Arial', fill: '#444444' };
+ var t = new PIXI.Text(timeStr, fontObj);
+ t.x = x + 2;
+ t.y = this.linesDown ? this.height - 15 : 2;
+ this.container.addChild(t);
+ };
+
+ this.moveTo = function(diffTime){
+ this.container.x = Math.floor(diffTime*this.pixelsPerSecond);
+ };
+
+ this.removePassedObjets = function(){
+ var nbChilds = _this.container.children.length;
+ var i = 0, childIsNowDisplayed = false, childrenToRemove = [];
+ 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') {
+ continue;
+ }
+ if((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)){
+ childrenToRemove.push(child);
+ //console.log(" remove !!!");
+ }
+ else {
+ childIsNowDisplayed = true;
+ //console.log(" childIsNowDisplayed");
+ }
+ }
+ childrenToRemove.forEach(function(child) {
+ _this.container.removeChild(child);
+ });
+ //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 );
+
+}
+
+module.exports = PianoRoll;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/app/less/app.less Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,13 @@
+/* ==========================================================================
+ App Stylesheet
+ app.less
+ ========================================================================== */
+
+
+/* Mixins (User defined mixins)
+ ======================================================================== */
+
+
+/* Components
+ ======================================================================== */
+@import "components/base.less";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/app/less/components/base.less Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,15 @@
+/* ==========================================================================
+ Base Stylesheet
+ base.less
+ ========================================================================== */
+body {
+ margin: 0;
+ padding: 0;
+ background-color: #FFF;
+}
+#log {
+ height: 20em;
+ overflow-y: scroll;
+ background-color: #faa;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/app/less/variables.less Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,5 @@
+/* ==========================================================================
+ You can copy the variables file here or simply add new overrides here
+ and import the bootstrap variables file.
+ variables.less
+ ========================================================================== */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/bower.json Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,8 @@
+{
+ "name": "annotviz",
+ "version": "0.0.0",
+ "dependencies": {
+ "randomColor": "davidmerfield/randomColor#~0.1.1",
+ "pixi": "~2.2.3"
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/config.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,12 @@
+var path = require('path');
+var production = (process.env.NODE_ENV === 'production');
+
+module.exports = {
+ bower: 'app/lib',
+ dist: production ? 'dist' : '.tmp',
+ livereloadPort: 35729,
+ port: 8888,
+ root: path.resolve('./'),
+ browser: "FirefoxDeveloperEdition",
+ serverStatic: path.resolve('../../annot-server/static')
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/index.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,7 @@
+var fs = require('fs');
+var onlyScripts = require('./util/scriptFilter');
+var tasks = fs.readdirSync('./gulp/tasks/').filter(onlyScripts);
+
+tasks.forEach(function(task) {
+ require('./tasks/' + task);
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/browserify.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,41 @@
+'use strict';
+
+var browserify = require('browserify');
+var config = require('../config');
+var partialify = require('partialify');
+var gulp = require('gulp');
+var debug = require('gulp-debug');
+var rename = require('gulp-rename');
+var source = require('vinyl-source-stream');
+var p = require('../../package.json')
+var uglify = require('gulp-uglify');
+
+// Vendor
+gulp.task('vendor', function() {
+ return browserify({debug: true})
+ .require('./app/lib/pixi/bin/pixi.js', { expose: 'pixi' })
+ .require('./app/lib/randomColor/randomColor.js', {expose: 'randomColor'})
+ .bundle()
+ .pipe(source('libs-pianoroll.js'))
+ .pipe(gulp.dest(config.dist + '/js/'));
+});
+
+// Browserify
+gulp.task('browserify', function() {
+ return browserify({debug: true, standalone: 'pianoroll'})
+ .add('./app/js/main.js')
+ .external('pixi')
+ .external('randomColor')
+ .transform(partialify) // Transform to allow requireing of templates
+ .bundle()
+ .pipe(source(p.name+'.js'))
+ .pipe(gulp.dest(config.dist + '/js/'));
+});
+
+// Script Dist
+gulp.task('scripts:dist', function() {
+ return gulp.src([config.dist + '/js/*.js', '!'+config.dist + '/js/*.min.js'], {base: config.dist})
+ .pipe(uglify())
+ .pipe(rename({extname: '.min.js'}))
+ .pipe(gulp.dest(config.dist));
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/build.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,8 @@
+'use strict';
+
+var gulp = require('gulp');
+
+// Build
+gulp.task('build', ['html', 'styles', 'vendor', 'browserify', 'images'], function() {
+
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/clean.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,9 @@
+'use strict';
+
+var gulp = require('gulp');
+var rimraf = require('gulp-rimraf');
+
+// Clean
+gulp.task('clean', function () {
+ return gulp.src(['.tmp', 'dist/css', 'dist/js', 'dist/img'], {read: false}).pipe(rimraf());
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/default.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,8 @@
+'use strict';
+
+var gulp = require('gulp');
+
+// Default task
+gulp.task('default', ['clean'], function () {
+ gulp.start('dev');
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/dev.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,6 @@
+'use strict';
+
+var gulp = require('gulp');
+
+// Dev Server
+gulp.task('dev', ['html', 'styles', 'vendor', 'browserify', 'images', 'watch']);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/dist.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,21 @@
+'use strict';
+
+var gulp = require('gulp');
+var runSequence = require('run-sequence');
+var config = require('../config');
+
+// Build
+gulp.task('dist', function() {
+ runSequence(['html', 'images:dist','styles', 'styles:dist', 'vendor', 'browserify'], 'scripts:dist', function() {
+ return gulp.src(['.tmp/css/*.css', '.tmp/js/*.js', '.tmp/img/*'], {base: '.tmp'})
+ .pipe(gulp.dest('dist'));
+ });
+});
+
+gulp.task('server', function() {
+ runSequence(['html', 'images:dist','styles', 'styles:dist', 'vendor', 'browserify'], 'scripts:dist', function() {
+ return gulp.src(['.tmp/css/*.css', '.tmp/js/*.js', '.tmp/img/*'], {base: '.tmp'})
+ .pipe(gulp.dest('dist'))
+ .pipe(gulp.dest(config.serverStatic));
+ });
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/html.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,11 @@
+'use strict';
+
+var config = require('../config');
+var gulp = require('gulp');
+var size = require('gulp-size');
+
+gulp.task('html', function () {
+ return gulp.src('app/*.html')
+ .pipe(gulp.dest(config.dist))
+ .pipe(size());
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/images.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,37 @@
+'use strict';
+
+var config = require('../config');
+var path = require('path');
+var gulp = require('gulp');
+var cache = require('gulp-cache');
+var changed = require('gulp-changed');
+var imagemin = require('gulp-imagemin');
+var size = require('gulp-size');
+
+// Images
+gulp.task('images', function() {
+ var dest = config.dist + '/img';
+
+ return gulp.src('app/img/**/*')
+ .pipe(changed(dest)) // Ignore unchanged files
+ .pipe(imagemin()) // Optimize
+ .pipe(gulp.dest(dest));
+});
+
+
+// Images Dist
+gulp.task('images:dist', ['images'], function () {
+ var dest = config.dist + '/img';
+ return gulp.src(['app/img/**/*'], {base: path.resolve('app')+"/img"})
+ // Commenting out the cache section for now.
+ // .pipe(gulp.dest('dist'))
+ // .pipe(rev())
+ // .pipe(cache(imagemin({
+ // optimizationLevel: 3,
+ // progressive: true,
+ // interlaced: false
+ // })))
+ .pipe(imagemin()) // Optimize
+ .pipe(size())
+ .pipe(gulp.dest(dest));
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/jshint.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,11 @@
+'use strict';
+
+var gulp = require('gulp');
+var jshint = require('gulp-jshint');
+
+// JSHint
+gulp.task('jshint', function () {
+ return gulp.src('app/js/**/*.js')
+ .pipe(jshint('.jshintrc'))
+ .pipe(jshint.reporter(require('jshint-stylish')));
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/less.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,43 @@
+'use strict';
+
+var config = require('../config');
+var p = require('../../package.json')
+var gulp = require('gulp');
+// var prefix = require('gulp-autoprefixer');
+var csso = require('gulp-csso');
+var less = require('gulp-less');
+var rename = require('gulp-rename');
+var size = require('gulp-size');
+var fs = require('fs')
+
+// Styles
+gulp.task('styles', function () {
+ return gulp.src('app/less/app.less')
+ // Leaving out recess support due to string interpolation missing in less v1.3 (which recess is dependent on)
+ // .pipe(recess())
+ .pipe(less({
+ style: 'expanded',
+ loadPath: [config.bower]
+ }))
+ .pipe(rename(p.name+'.css'))
+ .pipe(gulp.dest(config.dist + '/css'))
+ .pipe(size());
+});
+
+
+// Styles Dist
+gulp.task('styles:dist', function () {
+
+ return gulp.src('app/less/app.less')
+ // Leaving out recess support due to string interpolation missing in less v1.3 (which recess is dependent on)
+ // .pipe(recess())
+ .pipe(less({
+ style: 'expanded',
+ loadPath: [config.bower]
+ }))
+ // .pipe(prefix('last 1 version')) // add vendor prefixes if necessary
+ .pipe(rename(p.name+'.min.css'))
+ .pipe(csso()) // minify css
+ .pipe(gulp.dest(config.dist + '/css'))
+ .pipe(size());
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/serve.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,27 @@
+'use strict';
+
+var config = require('../config');
+var gulp = require('gulp');
+
+// Connect
+gulp.task('connect', function () {
+ var connect = require('connect');
+ var app = connect()
+ .use(require('connect-livereload')({ port: config.livereloadPort }))
+ .use('/', connect.static('.tmp'))
+ .use('/', connect.static('app'))
+ // paths to bower_components should be relative to the current file
+ // e.g. in app/index.html you should use ../bower_components
+ .use('/lib', connect.static('lib'))
+ .use(connect.directory('app'));
+
+ require('http').createServer(app)
+ .listen(config.port)
+ .on('listening', function () {
+ console.log('Started connect web server on http://localhost:' + config.port);
+ });
+});
+
+gulp.task('serve', ['connect', 'styles'], function () {
+ require('opn')('http://localhost:' + config.port, config.browser);
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/tasks/watch.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,33 @@
+'use strict';
+
+// var config = require('../config.js');
+var gulp = require('gulp');
+var livereload = require('gulp-livereload');
+
+// Watch
+gulp.task('watch', ['connect', 'serve'], function () {
+ var server = livereload();
+ // Watch for changes in `app` folder
+ gulp.watch([
+ // 'app/jade/**/*.jade',
+ // 'app/*.html',
+ // 'app/scss/**/*.scss',
+ // 'app/scripts/**/*.js',
+ // 'app/images/**/*',
+ '.tmp/**/*'
+ ]).on('change', function(file) {
+ server.changed(file.path);
+ });
+
+ // Watch .less files
+ gulp.watch('app/less/**/*.less', ['styles']);
+
+ // Watch .js files
+ gulp.watch('app/js/**/*.js', ['browserify']);
+
+ // Watch image files
+ gulp.watch('app/img/**/*', ['images']);
+
+ // Watch .html files
+ gulp.watch('app/**/*.html', ['html']);
+});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulp/util/scriptFilter.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,7 @@
+var path = require('path');
+
+// Filters out non .js files. Prevents
+// accidental inclusion of possible hidden files
+module.exports = function(name) {
+ return /(\.(js)$)/i.test(path.extname(name));
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/gulpfile.js Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,15 @@
+'use strict';
+// Generated on 2015-01-11 using generator-browserify 0.4.1
+
+/**
+ * gulpfile.js
+ * ===========
+ * Rather than manage one giant configuration file responsible
+ * for creating multiple tasks, each task has been broken out into
+ * its own file in gulp/tasks. Any file in that folder gets automatically
+ * required by the loop in ./gulp/index.js (required below).
+
+ * To add a new task, simply add a new task file to gulp/tasks.
+ */
+
+require('./gulp');
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/client/annotviz/package.json Tue Jan 13 10:46:05 2015 +0100
@@ -0,0 +1,45 @@
+{
+ "name": "annotviz",
+ "description": "Mons annotviz",
+ "repository": "https://www.iri.centrepompidou.fr/dev/hg/mons",
+ "version": "0.0.0",
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "scripts": {
+ "dist": "NODE_ENV=production gulp dist"
+ },
+ "devDependencies": {
+ "bower": "^1.3.12",
+ "browserify": "^5.12.1",
+ "browserify-shim": "^3.7.0",
+ "connect": "^2.25.9",
+ "connect-livereload": "^0.4.0",
+ "debowerify": "^0.8.1",
+ "gulp": "3.8.7",
+ "gulp-autoprefixer": "^0.0.10",
+ "gulp-cache": "^0.2.2",
+ "gulp-changed": "^1.0.0",
+ "gulp-concat": "^2.3.5",
+ "gulp-csso": "^0.2.9",
+ "gulp-debug": "^1.0.1",
+ "gulp-imagemin": "^1.0.1",
+ "gulp-jshint": "^1.8.4",
+ "gulp-less": "^1.3.5",
+ "gulp-livereload": "^2.1.1",
+ "gulp-load-plugins": "^0.6.0",
+ "gulp-rename": "^1.2.0",
+ "gulp-rimraf": "^0.1.0",
+ "gulp-size": "^1.1.0",
+ "gulp-uglify": "^1.0.1",
+ "gulp-util": "^3.0.1",
+ "jshint-stylish": "^0.4.0",
+ "mocha": "^1.21.4",
+ "opn": "^1.0.0",
+ "partialify": "^3.1.1",
+ "run-sequence": "^1.0.2",
+ "should": "^4.0.4",
+ "vinyl-source-stream": "^0.1.1"
+ },
+ "dependencies": {}
+}
--- a/client/pianoroll/app/index.html Mon Jan 12 17:23:05 2015 +0100
+++ b/client/pianoroll/app/index.html Tue Jan 13 10:46:05 2015 +0100
@@ -24,7 +24,7 @@
<pre id="log"></pre>
<script src="/js/libs-pianoroll.js"></script>
<script>
- var eventCode = "mons_samedi25";
+ var eventCode = "test_1";
</script>
<script src="/js/pianoroll.js"></script>
<script>
--- a/client/pianoroll/app/js/app.js Mon Jan 12 17:23:05 2015 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-/**
- * js/app.js
- *
- * This is a sample CommonJS module.
- * Take a look at http://browserify.org/ for more info
- */
-
-'use strict';
-
-function App() {
- console.log('app initialized');
-}
-
-module.exports = App;
-
-App.prototype.beep = function () {
- console.log('boop');
-};
--- a/client/pianoroll/app/js/main.js Mon Jan 12 17:23:05 2015 +0100
+++ b/client/pianoroll/app/js/main.js Tue Jan 13 10:46:05 2015 +0100
@@ -51,8 +51,8 @@
// Init containers
var containerList = [];
-containerList.push(new PianoRoll(uberContainer, 0, 0, prHeight1, true, pixelsPerSecond1, sceneWidth, noteColors, colorsReg, lineColor, lineInterval));
-containerList.push(new PianoRoll(uberContainer, 0, prHeight1, prHeight2, false, pixelsPerSecond2, sceneWidth, noteColors, colorsReg, lineColor, lineInterval));
+containerList.push(new PianoRoll(uberContainer, 0, 0, prHeight1, true, pixelsPerSecond1, sceneWidth, noteColors, colorsReg, lineColor, lineInterval, offsetMusic, prHeight1 / 128));
+containerList.push(new PianoRoll(uberContainer, 0, prHeight1, prHeight2, false, pixelsPerSecond2, sceneWidth, noteColors, colorsReg, lineColor, lineInterval, offsetMusic, prHeight2 / 128));
// Line between two containers
var graphics = new PIXI.Graphics();
--- a/client/pianoroll/app/js/pianoroll.js Mon Jan 12 17:23:05 2015 +0100
+++ b/client/pianoroll/app/js/pianoroll.js Tue Jan 13 10:46:05 2015 +0100
@@ -10,7 +10,7 @@
var PIXI = require('pixi');
var randomColor = require('randomColor');
-function PianoRoll(parentContainer, xInit, yInit, height, linesDown, pixelsPerSecond, width, noteColors, colorsReg, lineColor, lineInterval){
+function PianoRoll(parentContainer, xInit, yInit, height, linesDown, pixelsPerSecond, width, noteColors, colorsReg, lineColor, lineInterval, offsetMusic, noteHeight){
var _this = this;
this.container = new PIXI.DisplayObjectContainer();
this.container.position.x = xInit;
@@ -25,11 +25,17 @@
this.colorsReg = colorsReg || {};
this.lineColor = lineColor;
this.lineInterval = lineInterval;
+ this.offsetMusic = offsetMusic || 0;
+ this.noteHeight = noteHeight;
this.addNote = function(note, startTime, duration, velocity, canal){
//console.log("coucou 1", note, timeFromZero, ts, velocity, pixelsPerSecond, container, prHeight);
- var beginX = (offsetMusic + startTime) * this.pixelsPerSecond / 1000;
+ 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);
@@ -80,20 +86,25 @@
this.removePassedObjets = function(){
var nbChilds = _this.container.children.length;
- var i = 0, childIsNowDisplayed = false;
+ var i = 0, childIsNowDisplayed = false, childrenToRemove = [];
while(i<nbChilds && !childIsNowDisplayed){
- var child = _this.container.children[0];
+ 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') {
+ continue;
+ }
if((child.x + child.width) < (Math.abs(_this.container.x) - _this.width)){
- _this.container.removeChild(child);
+ childrenToRemove.push(child);
//console.log(" remove !!!");
}
- else{
+ else {
childIsNowDisplayed = true;
//console.log(" childIsNowDisplayed");
}
- i++;
}
+ childrenToRemove.forEach(function(child) {
+ _this.container.removeChild(child);
+ });
//console.log("before : ", nbChilds, ", after : ", _this.container.children.length);
};
--- a/utils/pianoroll-client.py Mon Jan 12 17:23:05 2015 +0100
+++ b/utils/pianoroll-client.py Tue Jan 13 10:46:05 2015 +0100
@@ -7,12 +7,11 @@
import argparse
import csv
-import sys
import time
+import ntplib
from twisted.internet import reactor
from txosc import osc
-from txosc import dispatch
from txosc import async
@@ -20,13 +19,14 @@
"""
Example that sends UDP messages.
"""
- def __init__(self, port, host, address, rows):
+ def __init__(self, port, host, address, rows, shift):
self.port = port
self.host = host
self.client = async.DatagramClientProtocol()
self._client_port = reactor.listenUDP(0, self.client)
self.rows = rows
self.address = address
+ self.shift = shift
reactor.callLater(0, self.send_messages)
def _send(self, element):
@@ -35,8 +35,10 @@
print("Sent %s to %s:%d" % (element, self.host, self.port))
def send_messages(self):
- tc = 0
+ t0 = time.time()
for row in self.rows:
+ if self.shift:
+ row[0] = ntplib.system_to_ntp_time(t0 + float(row[1])/10**3)
row_conv = [ osc.TimeTagArgument(float(row[0]))] + [osc.IntArgument(int(a)) for a in row[1:]]
#time.sleep((row_conv[1].value-tc)/10**3)
time.sleep(0.1)
@@ -50,11 +52,12 @@
parser = argparse.ArgumentParser(description='Simulate an (osc) pianoroll client.')
parser.add_argument('datafile', metavar='DATAFILE', help='The file containing the pianoroll data (CSV).')
parser.add_argument('-e', '--event', dest='event', metavar='EVENT', required=True, help='the event code.')
+ parser.add_argument('-s', '--shift', dest='shift', action='store_true', required=False, help='Shift the data.', default=False)
args = parser.parse_args()
with open(args.datafile, 'rU') as datafile:
reader = csv.reader(datafile, delimiter=' ')
- app = UDPSenderApplication(9090, "127.0.0.1", "/pianoroll/%s/" % args.event, list(reader))
+ app = UDPSenderApplication(9090, "127.0.0.1", "/pianoroll/%s/" % args.event, list(reader), args.shift)
reactor.run()