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