visualizations

This commit is contained in:
Egor 2015-10-25 22:55:09 -07:00
parent 1ed8f535ea
commit f92c9896e4
13 changed files with 256 additions and 388 deletions

View file

@ -5,7 +5,6 @@ Music awesomeness for hue lights.
# TODO # TODO
## FEATURES ## FEATURES
- app intro with intro.js - app intro with intro.js
- music visualizations with three.js
- microphone mode - microphone mode
- about, help page, youtube video - about, help page, youtube video

View file

@ -14,6 +14,7 @@ export default Em.Component.extend({
type: 'POST' type: 'POST'
}); });
// crappy code to redraw the lights
newGroupsData['9999'] = newGroupData; newGroupsData['9999'] = newGroupData;
this.setProperties({ this.setProperties({

View file

@ -2,7 +2,7 @@
{{#modal-dialog close="close" alignment="center" translucentOverlay=true attachment="center" targetAttachment="center"}} {{#modal-dialog close="close" alignment="center" translucentOverlay=true attachment="center" targetAttachment="center"}}
<p>Enter a <a href="https://soundcloud.com">SoundCloud</a> track or playlist/set URL</p> <p>Enter a <a href="https://soundcloud.com">SoundCloud</a> track or playlist/set URL</p>
<p>( ex. https://soundcloud.com/mrsuicidesheep/danrell-x-smaland-hostage )</p> <p>( ex. https://soundcloud.com/mrsuicidesheep/tracks )</p>
{{paper-input label="SoundCloud URL" icon="search" value=url}} {{paper-input label="SoundCloud URL" icon="search" value=url}}

View file

@ -32,7 +32,7 @@ export default Em.Component.extend({
findBridgeByIp() { findBridgeByIp() {
var manualBridgeIp = this.get('manualBridgeIp'), self = this; var manualBridgeIp = this.get('manualBridgeIp'), self = this;
if (manualBridgeIp.toLowerCase() === 'trial') { if (manualBridgeIp.toLowerCase() === 'trial' || manualBridgeIp.toLowerCase() === 'offline') {
this.setProperties({ this.setProperties({
trial: true, trial: true,
bridgeIp: 'trial', bridgeIp: 'trial',

View file

@ -28,7 +28,7 @@
{{#if bridgeFindFail}} {{#if bridgeFindFail}}
<p>A hue bridge could not be automatically found on your network. <br> <p>A hue bridge could not be automatically found on your network. <br>
Enter one manually? <br><br> Enter one manually? <br><br>
( or enter <b>trial</b> to look around ) ( or type <b>offline</b> to look around )
</p> </p>
<span id="bridgeInput"> <span id="bridgeInput">

View file

@ -16,11 +16,22 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
}.observes('active'), }.observes('active'),
actions: { actions: {
clearPlaylist(){
this.get('playQueue').clear();
},
setVisName(name){ setVisName(name){
this.set('currentVisName', name); this.set('currentVisName', name);
}, },
hideTooltip(){ hideTooltip(){
Em.$(event.target).parent().parent().find('.tooltip').remove() Em.$(event.target).parent().parent().find('.tooltip').remove();
},
gotoSCURL(URL){
// need to pause the music since soundcloud is going to start playing this song anyways
if(this.get('playing')){
this.send('play');
}
this.send('gotoURL', URL);
}, },
gotoURL(URL){ gotoURL(URL){
Em.$('.tooltip').remove(); Em.$('.tooltip').remove();
@ -66,8 +77,12 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
processResult(resultObj); processResult(resultObj);
} }
if(this.get('playQueuePointer') === -1 && !this.get('firstVisit')){ if(this.get('playQueuePointer') === -1){
this.send('next'); if(this.get('firstVisit')){
this.send('goToSong', 0);
} else {
this.send('next');
}
} }
}, () => { }, () => {
this.get('notify').alert({html: this.get('urlNotFoundHtml')(URL)}); this.get('notify').alert({html: this.get('urlNotFoundHtml')(URL)});
@ -125,13 +140,17 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
audio.oncanplay = ()=>{ audio.oncanplay = ()=>{
this.set('timeTotal', Math.floor(audio.duration)); this.set('timeTotal', Math.floor(audio.duration));
}; };
audio.onerror = ()=>{ audio.onerror = (event)=>{
var playQueuePointer =this.get('playQueuePointer'), var playQueuePointer =this.get('playQueuePointer'),
song = this.get('playQueue')[playQueuePointer]; song = this.get('playQueue')[playQueuePointer];
this.send('removeAudio', playQueuePointer); this.send('removeAudio', playQueuePointer);
this.get('notify').alert({html: this.get('failedToPlayFileHtml')(song.fileName)}); if(event.target.error.code){
this.get('notify').alert({html: this.get('failedToDecodeFileHtml')(song.fileName)});
} else {
this.get('notify').alert({html: this.get('failedToPlayFileHtml')(song.fileName)});
}
}; };
audio.ontimeupdate = ()=>{ audio.ontimeupdate = ()=>{
this.set('timeElapsed', Math.floor(audio.currentTime)); this.set('timeElapsed', Math.floor(audio.currentTime));
@ -157,7 +176,7 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
Em.run.later(()=>{ Em.run.later(()=>{
var track = Em.$('.track'+index); var track = Em.$('.track'+index);
if(!Em.isNone(track)) { if(!Em.isNone(track) && !Em.isNone(track.offset)) {
playListArea.animate({ playListArea.animate({
scrollTop: track.offset().top - playListArea.offset().top + playListArea.scrollTop() scrollTop: track.offset().top - playListArea.offset().top + playListArea.scrollTop()
}); });
@ -212,7 +231,8 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
// replay song // replay song
if(this.get('timeElapsed') === timeTotal && timeTotal !== 0){ if(this.get('timeElapsed') === timeTotal && timeTotal !== 0){
this.send('seekChanged', 0); this.send('next', true);
return;
} }
dancer.play(); dancer.play();
@ -626,6 +646,10 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
init() { init() {
this._super(); this._super();
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame;
window.cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
var dancer = new Dancer(), var dancer = new Dancer(),
self = this, self = this,
storage = this.get('storage'), storage = this.get('storage'),
@ -642,31 +666,16 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
kick.on(); kick.on();
//dancer.bind('update', function(){
// var waveform = this.getWaveform(), spectrum = this.getSpectrum(), sumS = 0, sumW = 0;
// for (let i = 0, l = spectrum.length; i < l && i < 512; i++ ) {
// sumS += spectrum[i];
// }
//
// for (let i = 0, l = waveform.length; i < l && i < 512; i++ ) {
// sumW += waveform[i];
// }
//
// //console.log('sumW: ' + sumW + ', sumS: ' + sumS);
//});
this.setProperties({ this.setProperties({
dancer: dancer, dancer: dancer,
kick: kick kick: kick
}); });
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if(navigator.getUserMedia === undefined){ if(navigator.getUserMedia === undefined){
this.set('usingMicSupported', false); this.set('usingMicSupported', false);
} }
['volume', 'shuffle', 'repeat', 'volumeMuted', 'threshold', 'interval', 'frequency', 'speakerViewed', 'transitionTime', 'randomTransition', 'playerBottomDisplayed', 'onBeatBriAndColor', 'audioMode', 'songBeatPreferences', 'debugFiltered', 'firstVisit', 'currentVisName'].forEach(function (item) { ['volume', 'shuffle', 'repeat', 'volumeMuted', 'threshold', 'interval', 'frequency', 'speakerViewed', 'transitionTime', 'randomTransition', 'playerBottomDisplayed', 'onBeatBriAndColor', 'audioMode', 'songBeatPreferences', 'debugFiltered', 'firstVisit', 'currentVisName', 'playQueue', 'playQueuePointer'].forEach(function (item) {
if (!Em.isNone(storage.get('huegasm.' + item))) { if (!Em.isNone(storage.get('huegasm.' + item))) {
var itemVal = storage.get('huegasm.' + item); var itemVal = storage.get('huegasm.' + item);
@ -684,6 +693,8 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
}, },
didInsertElement() { didInsertElement() {
this._super();
var self = this; var self = this;
Em.$('#fileInput').on('change', function () { Em.$('#fileInput').on('change', function () {
@ -712,13 +723,11 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
} }
}); });
// demo tracks // demo tracks
if(this.get('firstVisit')){ if(this.get('firstVisit')){
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/jacobanthony43/jacobychillcatalystbarstommisch'); this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/tracks');
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/odesza/light-feat-little-dragon');
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/sinusic-prod/lisboa'); this.get('storage').set('huegasm.firstVisit', false);
// TODO: uncomment and test
//this.get('storage').set('huegasm.firstVisit', false);
} }
if(!this.get('playerBottomDisplayed')) { if(!this.get('playerBottomDisplayed')) {

View file

@ -77,7 +77,7 @@ export default Em.Mixin.create({
timeTotal: 0, timeTotal: 0,
lastLightBopIndex: 0, lastLightBopIndex: 0,
usingMicSupported: false, usingMicSupported: true,
// 0 - local, 1 - mic, possibly more to come // 0 - local, 1 - mic, possibly more to come
audioMode: 0, audioMode: 0,
usingLocalAudio: Em.computed.equal('audioMode', 0), usingLocalAudio: Em.computed.equal('audioMode', 0),
@ -105,6 +105,9 @@ export default Em.Mixin.create({
failedToPlayFileHtml: function(fileName){ failedToPlayFileHtml: function(fileName){
return '<div class="alert alert-danger" role="alert">Failed to play file ( ' + fileName + ' ).</div>'; return '<div class="alert alert-danger" role="alert">Failed to play file ( ' + fileName + ' ).</div>';
}, },
failedToDecodeFileHtml: function(fileName){
return '<div class="alert alert-danger" role="alert">Failed to decode file ( ' + fileName + ' ).</div>';
},
scUrl: function(){ scUrl: function(){
var rtn = null, var rtn = null,
@ -214,10 +217,10 @@ export default Em.Mixin.create({
}.property('repeat'), }.property('repeat'),
playingIcon: function () { playingIcon: function () {
if(this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0){ if(this.get('playing')){
return 'replay';
} else if (this.get('playing')) {
return 'pause'; return 'pause';
} else if(this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0){
return 'replay';
} else { } else {
return 'play-arrow'; return 'play-arrow';
} }
@ -286,8 +289,9 @@ export default Em.Mixin.create({
}.property('volumeMuted', 'volume'), }.property('volumeMuted', 'volume'),
onOptionChange: function(self, option){ onOptionChange: function(self, option){
this.get('storage').set('huegasm.' + option, this.get(option)); option = option.replace('.[]', '');
}.observes('randomTransition', 'onBeatBriAndColor'), this.get('storage').set('huegasm.' + option, this.get(option), { compress: true });
}.observes('randomTransition', 'onBeatBriAndColor', 'playQueue.[]', 'playQueuePointer'),
onRepeatChange: function () { onRepeatChange: function () {
var tooltipTxt = 'Repeat all', type = 'repeat'; var tooltipTxt = 'Repeat all', type = 'repeat';

View file

@ -1,219 +1,74 @@
import Em from 'ember'; import Em from 'ember';
export default Em.Mixin.create({ export default Em.Mixin.create({
currentVisName: 'None', currentVisName: 'Wave',
currentVisSettings: function () { visNames: ['None', 'Bars', 'Wave'],
var name = this.get('currentVisName');
this.get('storage').set('huegasm.currentVisName', name); onCurrentVisNameChange: function () {
var currentVisName = this.get('currentVisName');
if (Em.isNone(name)) { if(currentVisName === 'None'){
return null; var canvasEl = Em.$('#visualization')[0],
} else { ctx = canvasEl.getContext('2d');
return this.get('visSettings').filter(function (vis) {
return vis.name === name ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);
});
} }
}.property('currentVisName'),
visNames: function () { this.get('storage').set('huegasm.currentVisName', currentVisName);
return this.get('visSettings').map(function (vis) { }.observes('currentVisName'),
return vis.name;
didInsertElement(){
var dancer = this.get('dancer'),
canvasEl = Em.$('#visualization')[0],
ctx = canvasEl.getContext('2d'),
spacing = 0,
h = canvasEl.height,
w = canvasEl.width;
dancer.bind('update', () => {
var currentVisName = this.get('currentVisName');
if(currentVisName === 'None'){
return;
}
ctx.clearRect(0, 0, w, h);
if (currentVisName === 'Wave') {
let width = 2,
count = 1024,
gradient = ctx.createLinearGradient(0, 0, 0, 300);
gradient.addColorStop(0, '#0036FA');
gradient.addColorStop(0.3, 'white');
ctx.lineWidth = 1;
ctx.strokeStyle = gradient;
var waveform = dancer.getWaveform();
ctx.beginPath();
ctx.moveTo(0, h / 2);
for (let i = 0, l = waveform.length; i < l && i < count; i++) {
ctx.lineTo(i * ( spacing + width ), ( h / 2 ) + waveform[i] * ( h / 2 ));
}
ctx.stroke();
ctx.closePath();
} else if (currentVisName === 'Bars') {
let width = 4,
count = 128,
gradient = ctx.createLinearGradient(0, 0, 0, 300);
gradient.addColorStop(0.5, '#0f0');
gradient.addColorStop(0.4, '#ff0');
gradient.addColorStop(0, '#F12B24');
ctx.fillStyle = gradient;
var spectrum = dancer.getSpectrum();
for (let i = 0, l = spectrum.length; i < l && i < count; i++) {
ctx.fillRect(i * ( spacing + width ), h, width, -spectrum[i] * h - 23);
}
}
}); });
}.property('visSettings'), }
})
visSettings: [{ ;
name: "None",
set: null
}, {
name: "Borealis",
set: {
controls: {
seuilAudible: 0.002942,
radiusAmplitude: 0,
radius: 116,
radiusVar: 0.16,
amplitudeOnMag: -1.02,
colors: {r: 0.91, g: 0.6, b: 0.75},
burningColors: {r: 8.7, g: 4.64, b: 3.29},
burningColorsMax: {r: 0.898, g: 0.665, b: 0.258},
spectralColors: {r: -1.24, g: -0.98, b: -1.6},
bgColors: {r: 0, g: 0, b: 4},
speed: -0.13,
picture: "assets/images/flares/flare4.png",
colorsDecr: {r: 0.04787, g: -0.00097, b: -0.00281},
dots: 288,
maxSize: 758,
rotation: {x: 0, y: 0, z: 0},
position: {x: 0, y: 0, z: 0},
radiusIncr: -1.24,
speedIncr: 4,
opacityBase: 0.471,
opacityAmp: 1.5,
opacityDecr: 0.0048,
centerAmp: 0,
sizeAmp: 0.73,
sizeDecr: -0.00289,
freqSpeedIncr: 7.6313,
magSpeedIncr: 0,
baseRotate: -910.3086207435979,
autoRotate: 0,
rotateAmp: -0.029517,
textureRotateDecr: 0.128881,
textureRotateAmp: -0.7313,
equalizer: 263,
gravity: {x: -0.00558, y: 0.0068, z: 0.0121},
showAmp: 0,
blending: 2,
autoTraveler: 1,
camera: {
positionIncr: {x: 0, y: 0, z: 0},
traveler: {
freq: {x: 0, y: 0.01, z: 0.01, x2: 0, y2: 0, z2: 0},
phase: {x: 0, y: 0.01, z: 0.01, x2: 0, y2: 0, z2: 0},
width: {x: 0, y: 0.1, z: 0.1, x2: 0, y2: 0, z2: 0},
center: {x: 0, y: 0, z: 0, x2: 0, y2: 0, z2: 0}
}
}
},
camera: {
position: {x: 40, y: 13.218400900933863, z: -9.516315737622158},
rotation: {x: -2.194772871513226, y: 1.184106819993227, z: 2.2315573880289308}
},
particles: {
position: {x: -198.4052190636108, y: -37.40200000000022, z: 15.228000000000227},
rotation: {x: 4.733931634852215, y: 1.9666500000000078, z: -0.16421999999999976}
}
}
},
{
name: "Lightwave",
set: [{
controls: {
seuilAudible: 0.002088,
radiusAmplitude: -7.852,
radius: 120,
radiusVar: 0.012,
radiusVarAmp: 0,
amplitudeOnMag: 0,
colors: {r: 0.81, g: 0.81, b: 0.94},
burningColors: {r: 7.24, g: 4.02, b: 9.42},
burningColorsMax: {r: 0.206, g: 0.299, b: 0.9},
spectralColors: {r: -0.28, g: 0, b: 0.19},
bgColors: {r: 0, g: 0, b: -1},
speed: -0.48,
picture: "assets/images/flares/vor8.2.png",
colorsDecr: {r: 0.00057, g: 0.00364, b: 0.02},
dots: 482,
maxSize: 464,
rotation: {x: 0, y: 0, z: 0},
position: {x: 0, y: 0, z: 0},
radiusIncr: -1.89,
radiusIncrAmp: 4.8,
speedIncr: -37,
opacityBase: 0.986,
opacityAmp: 6.7,
opacityDecr: 0.0086,
centerAmp: 0,
sizeAmp: 2.63,
sizeDecr: 0,
freqSpeedIncr: 0,
magSpeedIncr: 0,
baseRotate: -910.8242890837017,
autoRotate: 0.0011,
rotateAmp: -0.179517,
textureRotateDecr: 0.02761,
textureRotateAmp: 0,
equalizer: -145,
gravity: {x: -0.00011, y: -0.0116, z: 0.0154},
gravityAmp: {x: 0, y: 0, z: 1.97},
showAmp: 0,
blending: 2,
autoTraveler: 1,
camera: {
positionIncr: {x: 0, y: 0, z: 0},
traveler: {
freq: {x: 0.0191, y: 0.01, z: 0.01, x2: 0, y2: 0.008925, z2: 0.00265},
phase: {x: 0.0154, y: 0.01, z: 0.01, x2: 0, y2: 0.0125, z2: 0.003525},
width: {x: 0.84, y: -0.02, z: -0.02, x2: 0, y2: 0.005, z2: 0},
center: {x: 0, y: 0, z: 0, x2: 0, y2: 0, z2: 0}
}
}
},
camera: {
position: {x: 28.290507810306817, y: -79.05312595414983, z: 148.26913157117622},
rotation: {x: 0.4898326329313103, y: 0.16680418921697668, z: -0.08829352787105102}
},
particles: {
position: {x: 31, y: 35.789000000000456, z: 30.221000000000057},
rotation: {x: 1.5, y: 3.813987739867519, z: 10.34557348383392}
}
}]
},
{
name: "Neutrino",
set: {
controls: {
seuilAudible: 0.001,
radiusAmplitude: 0.422,
radius: 207,
radiusVar: 0.008,
radiusVarAmp: -4510,
amplitudeOnMag: 0,
colors: {r: 0.38, g: 0.84, b: 0.87},
burningColors: {r: 9.42, g: 8.17, b: 1.5},
burningColorsMax: {r: 1, g: 0.583, b: 0.183},
spectralColors: {r: -0.3, g: 0.23, b: -0.13},
bgColors: {r: 0, g: 0, b: -1},
speed: 8.49,
picture: "assets/images/flares/colo.png",
colorsDecr: {r: 0, g: 0, b: 0},
dots: 478,
maxSize: 392,
rotation: {x: 0, y: 0, z: 0},
position: {x: 0, y: 0, z: 0},
radiusIncr: -1.13,
radiusIncrAmp: -14.48,
speedIncr: 0,
opacityBase: 0.88,
opacityAmp: 1.3,
opacityDecr: 0.0152,
centerAmp: 0,
sizeAmp: 2.625,
sizeDecr: 0,
freqSpeedIncr: 2.6026,
magSpeedIncr: 0.3834,
baseRotate: -543.1624876256562,
autoRotate: 0,
rotateAmp: 0,
textureRotateDecr: 0.02761,
textureRotateAmp: 0,
equalizer: 83,
gravity: {x: -0.00281, y: 0.0136, z: 0.0196},
gravityAmp: {x: -4.2, y: -0.15, z: 1.02},
showAmp: 0,
blending: 2,
autoTraveler: 0,
camera: {
positionIncr: {x: 0, y: 0, z: 0},
traveler: {
freq: {x: 0, y: 0.01, z: 0.01, x2: 0, y2: 0.008925, z2: 0.00265},
phase: {x: 0, y: 0.01, z: 0.01, x2: 0, y2: 0.0125, z2: 0.003525},
width: {x: 0, y: -0.02, z: -0.02, x2: 0, y2: 0.005, z2: 0},
center: {x: 0, y: 0, z: 0, x2: 0, y2: 0, z2: 0}
}
}
},
camera: {
position: {x: 40, y: -305.0573302931556, z: -176.2810417210021},
rotation: {x: 2.094778817564933, y: 0.11304655916704225, z: -2.9488045979781217}
},
particles: {
position: {x: -20, y: 62.67200000000026, z: 77.36300000000016},
rotation: {x: 1.5, y: 4.53220881574775, z: 12.23706348383359}
}
}
}
]
});

View file

@ -26,7 +26,7 @@
<span class="pull-right"> <span class="pull-right">
{{#if scUrl}} {{#if scUrl}}
<a href="#" data-toggle="tooltip" data-placement="top" class="soundCloudLink bootstrapTooltip" data-title="Listen on SoundCloud" {{action "gotoURL" scUrl}}> <a href="#" data-toggle="tooltip" data-placement="top" class="soundCloudLink bootstrapTooltip" data-title="Listen on SoundCloud" {{action "gotoSCURL" scUrl}}>
<img src="assets/images/sc-white.png" /> <img src="assets/images/sc-white.png" />
</a> </a>
{{/if}} {{/if}}
@ -41,148 +41,147 @@
{{#each visNames as |name|}} {{#each visNames as |name|}}
<li><a href="#" {{action "setVisName" name}}>{{name}} {{#if (eq currentVisName name)}}{{paper-icon icon="check"}}{{/if}}</a></li> <li><a href="#" {{action "setVisName" name}}>{{name}} {{#if (eq currentVisName name)}}{{paper-icon icon="check"}}{{/if}}</a></li>
{{/each}} {{/each}}
<li><a href="" class="credits" {{action "gotoURL" "http://do.adive.in/music/"}}>Music visualizations by Vor</a></li>
</ul> </ul>
</span> </span>
<span data-toggle="tooltip" data-placement="top" class="bootstrapTooltip" data-title="Full screen" {{action "fullscreen"}}>{{paper-icon icon="fullscreen" class="playerControllIcon"}}</span> {{!--<span data-toggle="tooltip" data-placement="top" class="bootstrapTooltip" data-title="Full screen" {{action "fullscreen"}}>{{paper-icon icon="fullscreen" class="playerControllIcon"}}</span>--}}
</span> </span>
</div> </div>
</div> </div>
<div id="playlist" class="col-sm-4 col-xs-12"> <div id="playlist" class="col-sm-4 col-xs-12">
<input id="fileInput" type="file" accept="audio/*" multiple="true"/> <input id="fileInput" type="file" accept="audio/*" multiple="true"/>
<div id="playListControls"> <div id="playListControls">
{{#if usingLocalAudio}} {{#if usingLocalAudio}}
<button class="dropdown-toggle pull-right addNewMusic" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> <button class="dropdown-toggle pull-right addNewMusic" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
Add new music Add new music
<span class="caret"></span> <span class="caret"></span>
</button> </button>
<ul id="addMusicChoices" class="dropdown-menu"> <ul id="addMusicChoices" class="dropdown-menu">
<li><a href="#" {{action "addLocalAudio"}}>Local</a></li> <li><a href="#" {{action "addLocalAudio"}}>Local</a></li>
<li><a href="#" {{action "toggleIsShowingAddSoundCloudModal"}}>SoundCloud</a></li> <li><a href="#" {{action "toggleIsShowingAddSoundCloudModal"}}>SoundCloud</a></li>
</ul> </ul>
<span data-toggle="tooltip" data-placement="bottom auto" class="bootstrapTooltip" id="shuffleTooltip" data-title={{shuffleTooltipTxt}} {{action "shuffleChanged"}}>{{paper-icon icon="shuffle" class=shuffleClass}}</span> <span data-toggle="tooltip" data-placement="bottom auto" class="bootstrapTooltip" id="shuffleTooltip" data-title={{shuffleTooltipTxt}} {{action "shuffleChanged"}}>{{paper-icon icon="shuffle" class=shuffleClass}}</span>
<span data-toggle="tooltip" data-placement="bottom auto" class="bootstrapTooltip" id="repeatTooltip" data-title={{repeatTooltipTxt}} {{action "repeatChanged"}}>{{paper-icon icon=repeatIcon class=repeatClass}}</span> <span data-toggle="tooltip" data-placement="bottom auto" class="bootstrapTooltip" id="repeatTooltip" data-title={{repeatTooltipTxt}} {{action "repeatChanged"}}>{{paper-icon icon=repeatIcon class=repeatClass}}</span>
{{/if}} <span data-toggle="tooltip" data-placement="bottom auto" class="bootstrapTooltip" data-title="Clear playlist" {{action "clearPlaylist"}}>{{paper-icon icon="clear-all" class="playerControllIcon"}}</span>
{{/if}}
{{#if usingMicSupported}} {{#if usingMicSupported}}
<span data-toggle="tooltip" data-placement="bottom auto" class="bootstrapTooltip" data-title="Listen to audio through mic" {{action "useMicAudio"}}>{{paper-icon icon=micIcon class=usingMicAudioClass}}</span> <span data-toggle="tooltip" data-placement="bottom auto" class="bootstrapTooltip" data-title="Listen to audio through mic" {{action "useMicAudio"}}>{{paper-icon icon=micIcon class=usingMicAudioClass}}</span>
{{/if}}
</div>
{{#if usingMicAudio}}
<div id="playAreaMic">
{{paper-icon icon="mic"}}
</div>
{{else}}
{{#if usingLocalAudio}}
<div id="playListArea" class={{playListAreaClass}} {{action "addLocalAudio"}} {{action "playListAreaDragOver" on="dragOver"}} {{action "playListAreaDragLeave" on="dragLeave"}} {{action "dropFiles" on="drop"}}>
{{#if (or playQueueEmpty dragging)}}
<div id="dragHere">
{{#if dragging}}
Drag your music files here
{{else}}
Add your music files here
{{/if}} {{/if}}
</div> </div>
{{paper-icon icon="library-music" class=dimmerOnClass}}
{{/if}}
{{#if usingMicAudio}} {{#each playQueue as |item index|}}
<div id="playAreaMic"> <div class="playlistItem cursorPointer track{{index}} {{if (eq index playQueuePointer) "active"}} {{if dragging "hidden"}}" {{action "goToSong" index true bubbles=false}}>
{{paper-icon icon="mic"}} {{#if item.picture}}
<img class="albumArt" src={{item.picture}}>
{{else}}
<img class="albumArt" src="assets/images/missingArtwork.png">
{{/if}}
<div class="songInfo">
{{#if item.title}}
<div class="songTitle">{{item.title}}</div>
<div class="songArtist">
{{#if item.artistUrl}}
<a href="#" {{action "gotoURL" item.artistUrl bubbles=false}}>{{item.artist}}</a>
{{else}}
{{item.artist}}
{{/if}}
</div>
{{else}}
{{item.filename}}
{{/if}}
</div> </div>
{{else}}
{{#if usingLocalAudio}}
<div id="playListArea" class={{playListAreaClass}} {{action "addLocalAudio"}} {{action "playListAreaDragOver" on="dragOver"}} {{action "playListAreaDragLeave" on="dragLeave"}} {{action "dropFiles" on="drop"}}>
{{#if (or playQueueEmpty dragging)}}
<div id="dragHere">
{{#if dragging}}
Drag your music files here
{{else}}
Add your music files here
{{/if}}
</div>
{{paper-icon icon="library-music" class=dimmerOnClass}}
{{/if}}
{{#each playQueue as |item index|}} <span data-toggle="tooltip" data-placement="bottom auto" data-title="Remove" data-container="body" class="audioRemoveButton cursorPointer bootstrapTooltip" {{action "removeAudio" index bubbles=false}}>{{paper-icon icon="close"}}</span>
<div class="playlistItem cursorPointer track{{index}} {{if (eq index playQueuePointer) "active"}} {{if dragging "hidden"}}" {{action "goToSong" index true bubbles=false}}> </div>
{{#if item.picture}} {{/each}}
<img class="albumArt" src={{item.picture}}> </div>
{{else}} {{/if}}
<img class="albumArt" src="assets/images/missingArtwork.png"> {{/if}}
{{/if}} </div>
<div class="songInfo">
{{#if item.title}}
<div class="songTitle">{{item.title}}</div>
<div class="songArtist">
{{#if item.artistUrl}}
<a href="#" {{action "gotoURL" item.artistUrl bubbles=false}}>{{item.artist}}</a>
{{else}}
{{item.artist}}
{{/if}}
</div>
{{else}}
{{item.filename}}
{{/if}}
</div>
<span data-toggle="tooltip" data-placement="bottom auto" data-title="Remove" data-container="body" class="audioRemoveButton cursorPointer bootstrapTooltip" {{action "removeAudio" index bubbles=false}}>{{paper-icon icon="close"}}</span>
</div>
{{/each}}
</div>
{{/if}}
{{/if}}
</div>
</div> </div>
<div id="slideToggle" class="text-center cursorPointer row" {{action "slideTogglePlayerBottom"}}> <div id="slideToggle" class="text-center cursorPointer row" {{action "slideTogglePlayerBottom"}}>
<div class="col-xs-offset-5 col-xs-2"> <div class="col-xs-offset-5 col-xs-2">
{{paper-icon icon=beatDetectionArrowIcon}} {{paper-icon icon=beatDetectionArrowIcon}}
</div> </div>
</div> </div>
<div id="playerBottom" class="row {{if dimmerOn "dimmerOn"}}"> <div id="playerBottom" class="row {{if dimmerOn "dimmerOn"}}">
<div id="beatArea" class="col-sm-7 col-xs-12"> <div id="beatArea" class="col-sm-7 col-xs-12">
{{#if usingBeatPreferences}} {{#if usingBeatPreferences}}
<span data-toggle="tooltip" data-placement="bottom auto" data-title="Using your saved beat preferences from the last time you listened to this song" class="bootstrapTooltip savedStarTooltip"> <span data-toggle="tooltip" data-placement="bottom auto" data-title="Using your saved beat preferences from the last time you listened to this song" class="bootstrapTooltip savedStarTooltip">
{{paper-icon id="saveBeatPreferencesStar" icon="star"}} {{paper-icon id="saveBeatPreferencesStar" icon="star"}}
</span> </span>
{{/if}} {{/if}}
<div class="row">
<div class="beatOption col-xs-3">
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The minimum sound intensity for the beat to register" class="optionDescription bootstrapTooltip">Beat Threshold</span>
{{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range slide="thresholdChanged" pips=beatOptions.threshold.pips}}
<div class="text-center">{{threshold}}</div>
</div>
<div class="beatOption col-xs-3">
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The minimum amount of time between each registered beat" class="optionDescription bootstrapTooltip">Beat Interval</span>
{{range-slider start=interval orientation="vertical" step=beatOptions.interval.step range=beatOptions.interval.range slide="intervalChanged" pips=beatOptions.interval.pips}}
<div class="text-center">{{interval}} sec</div>
</div>
<div class="row">
<div class="beatOption col-xs-3"> <div class="beatOption col-xs-3">
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The frequency range of the sound to listen on for the beat" class="optionDescription bootstrapTooltip">Frequency Range</span> <span data-toggle="tooltip" data-placement="bottom auto" data-title="The minimum sound intensity for the beat to register" class="optionDescription bootstrapTooltip">Beat Threshold</span>
{{range-slider start=frequency orientation="vertical" step=beatOptions.frequency.step range=beatOptions.frequency.range connect=true slide="frequencyChanged" pips=beatOptions.frequency.pips}} {{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range slide="thresholdChanged" pips=beatOptions.threshold.pips}}
<div class="text-center">[{{#each frequency as |item index|}}{{item}}{{#unless index}} <div class="text-center">{{threshold}}</div>
,{{/unless}}{{/each}}
]
</div>
</div> </div>
<div class="beatOption col-xs-3"> <div class="beatOption col-xs-3">
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The time it takes for a light to change color or brightness" class="optionDescription bootstrapTooltip">Transition Time</span> <span data-toggle="tooltip" data-placement="bottom auto" data-title="The minimum amount of time between each registered beat" class="optionDescription bootstrapTooltip">Beat Interval</span>
{{range-slider start=transitionTime orientation="vertical" step=beatOptions.transitionTime.step range=beatOptions.transitionTime.range slide="transitionTimeChanged" pips=beatOptions.transitionTime.pips}} {{range-slider start=interval orientation="vertical" step=beatOptions.interval.step range=beatOptions.interval.range slide="intervalChanged" pips=beatOptions.interval.pips}}
<div class="text-center">{{transitionTime}} sec</div> <div class="text-center">{{interval}} sec</div>
</div>
<div class="beatOption col-xs-3">
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The frequency range of the sound to listen on for the beat" class="optionDescription bootstrapTooltip">Frequency Range</span>
{{range-slider start=frequency orientation="vertical" step=beatOptions.frequency.step range=beatOptions.frequency.range connect=true slide="frequencyChanged" pips=beatOptions.frequency.pips}}
<div class="text-center">[{{#each frequency as |item index|}}{{item}}{{#unless index}}
,{{/unless}}{{/each}}
]
</div>
</div>
<div class="beatOption col-xs-3">
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The time it takes for a light to change color or brightness" class="optionDescription bootstrapTooltip">Transition Time</span>
{{range-slider start=transitionTime orientation="vertical" step=beatOptions.transitionTime.step range=beatOptions.transitionTime.range slide="transitionTimeChanged" pips=beatOptions.transitionTime.pips}}
<div class="text-center">{{transitionTime}} sec</div>
</div> </div>
</div> </div>
<div id="beatOptionButtonGroup" class="row"> <div id="beatOptionButtonGroup" class="row">
<div class="beatOption col-xs-3"> <div class="beatOption col-xs-3">
{{#paper-button raised=true warn=true action="defaultControls"}}Default{{/paper-button}} {{#paper-button raised=true warn=true action="defaultControls"}}Default{{/paper-button}}
</div> </div>
<div class="beatOption col-xs-4"> <div class="beatOption col-xs-4">
{{#paper-switch checked=randomTransition disabled=trial}}<span data-toggle="tooltip" {{#paper-switch checked=randomTransition disabled=trial}}<span data-toggle="tooltip"
data-placement="bottom auto" data-placement="bottom auto"
data-title="The transition order of lights on beat" data-title="The transition order of lights on beat"
class="optionDescription bootstrapTooltip">{{randomTransitionLabel}}</span>{{/paper-switch}} class="optionDescription bootstrapTooltip">{{randomTransitionLabel}}</span>{{/paper-switch}}
</div> </div>
<div class="beatOption col-xs-5"> <div class="beatOption col-xs-5">
{{#paper-switch checked=onBeatBriAndColor disabled=trial}}<span data-toggle="tooltip" {{#paper-switch checked=onBeatBriAndColor disabled=trial}}<span data-toggle="tooltip"
data-placement="bottom auto" data-placement="bottom auto"
data-title="The properties of the lights to change on beat" data-title="The properties of the lights to change on beat"
class="optionDescription bootstrapTooltip"> {{onBeatBriAndColorLabel}}</span>{{/paper-switch}} class="optionDescription bootstrapTooltip"> {{onBeatBriAndColorLabel}}</span>{{/paper-switch}}
</div> </div>
</div> </div>
</div> </div>
@ -190,27 +189,27 @@
<div id="beatContainer" class="col-sm-5 col-xs-12"> <div id="beatContainer" class="col-sm-5 col-xs-12">
{{#if speakerViewed}} {{#if speakerViewed}}
<div class="bezel"> <div class="bezel">
<div class="rivet1"></div> <div class="rivet1"></div>
<div class="rivet2"></div> <div class="rivet2"></div>
<div class="rivet3"></div> <div class="rivet3"></div>
<div class="rivet4"></div> <div class="rivet4"></div>
<div class="rivet5"></div> <div class="rivet5"></div>
<div class="rivet6"></div> <div class="rivet6"></div>
<div class="rivet7"></div> <div class="rivet7"></div>
<div class="rivet8"></div> <div class="rivet8"></div>
<div id="beatSpeakerCenterOuter"> <div id="beatSpeakerCenterOuter">
<div id="beatSpeakerCenterInner" class="cursorPointer" {{action "clickSpeaker"}}> <div id="beatSpeakerCenterInner" class="cursorPointer" {{action "clickSpeaker"}}>
</div> </div>
</div> </div>
</div> </div>
{{else}} {{else}}
<div id="beatHistory"> <div id="beatHistory">
{{#each beatHistory as |item|}} {{#each beatHistory as |item|}}
<p>{{{item}}}</p> <p>{{{item}}}</p>
{{/each}} {{/each}}
</div> </div>
{{#paper-switch checked=debugFiltered class="debugFilteredSwitch"}} {{debugFilteredText}} {{/paper-switch}} {{#paper-switch checked=debugFiltered class="debugFilteredSwitch"}} {{debugFilteredText}} {{/paper-switch}}
{{/if}} {{/if}}
{{#paper-switch checked=speakerViewed class="speakerSwitch"}} {{speakerLabel}} {{/paper-switch}} {{#paper-switch checked=speakerViewed class="speakerSwitch"}} {{speakerLabel}} {{/paper-switch}}

View file

@ -56,11 +56,11 @@ md-progress-circular[md-mode=indeterminate] .md-spinner-wrapper {
padding-right: 5px; padding-right: 5px;
text-align: right; text-align: right;
z-index: 3; z-index: 3;
font-size:16px font-size: 16px;
} }
.settingsItem { .settingsItem {
margin-left: 15px; margin-left: 10px;
position: relative; position: relative;
display: inline-block; display: inline-block;
transition: 0.1s all ease-in-out; transition: 0.1s all ease-in-out;
@ -477,14 +477,14 @@ md-switch.md-default-theme.md-checked .md-thumb {
width: 100%; width: 100%;
color: white !important; color: white !important;
z-index: 20; z-index: 20;
background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.7)); background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 1));
.tooltip.top { .tooltip.top {
margin-top: -17px; margin-top: -17px;
} }
.tooltip-arrow { .tooltip-arrow {
display: none; display: none;
} }
.play-arrow, .pause { .play-arrow, .pause, .replay {
font-size: 30px; font-size: 30px;
} }
} }
@ -966,6 +966,9 @@ div.ember-modal-dialog {
md-input-container input { md-input-container input {
color: black !important; color: black !important;
} }
md-input-container label {
color: rgba(0, 0, 0, 0.26);
}
} }
.addMusicButton { .addMusicButton {
@ -1005,10 +1008,6 @@ div.ember-modal-dialog {
height: 100%; height: 100%;
} }
.credits {
border-top: 1px solid black;
}
.check { .check {
margin-left: 10px; margin-left: 10px;
position: relative; position: relative;
@ -1016,9 +1015,13 @@ div.ember-modal-dialog {
} }
.visualizersMenu { .visualizersMenu {
left: -165px; left: -135px;
} }
.displayIcon { .displayIcon {
background:url(assets/images/favicons/favicon-194x194.png) center center no-repeat; background:url(images/favicons/favicon-90x90.png) center center no-repeat;
}
.keyboard-arrow-down {
font-size: 20px;
} }

View file

@ -19,8 +19,7 @@
"locallyjs": "~0.3.2", "locallyjs": "~0.3.2",
"matchMedia": "~0.2.0", "matchMedia": "~0.2.0",
"nouislider": "^8.0.1", "nouislider": "^8.0.1",
"qunit": "~1.18.0", "qunit": "~1.18.0"
"three.js": "~0.72.0"
}, },
"resolutions": { "resolutions": {
"ember": "~2.1.0", "ember": "~2.1.0",

View file

@ -13,7 +13,6 @@ module.exports = function(defaults) {
app.import('bower_components/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js'); app.import('bower_components/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js');
app.import('bower_components/JavaScript-ID3-Reader/dist/id3-minimized.js'); app.import('bower_components/JavaScript-ID3-Reader/dist/id3-minimized.js');
app.import('bower_components/jquery-mousewheel/jquery.mousewheel.js'); app.import('bower_components/jquery-mousewheel/jquery.mousewheel.js');
app.import('bower_components/three.js/three.js');
app.import('bower_components/locallyjs/dist/locally.min.js'); app.import('bower_components/locallyjs/dist/locally.min.js');
app.import('bower_components/intro.js/intro.js'); app.import('bower_components/intro.js/intro.js');
app.import('bower_components/intro.js/introjs.css'); app.import('bower_components/intro.js/introjs.css');

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB