prettier formatting

This commit is contained in:
Egor 2017-12-09 19:32:12 -08:00
parent ea6eb4f968
commit b64e19c3fe
13 changed files with 279 additions and 214 deletions

4
.prettierrc Normal file
View file

@ -0,0 +1,4 @@
{
"singleQuote": true,
"printWidth": 140
}

View file

@ -9,6 +9,7 @@ module.exports = {
browser: true browser: true
}, },
rules: { rules: {
'no-debugger': 'off'
}, },
globals: { globals: {
chrome: false, chrome: false,

View file

@ -1,15 +1,6 @@
import Ember from 'ember'; import Ember from 'ember';
const { const { Component, observer, computed, on, isNone, run: { later }, $, String: { htmlSafe } } = Ember;
Component,
observer,
computed,
on,
isNone,
run: { later },
$,
String: { htmlSafe }
} = Ember;
export default Component.extend({ export default Component.extend({
elementId: 'bridge-finder', elementId: 'bridge-finder',
@ -31,17 +22,20 @@ export default Component.extend({
isAuthenticating: computed.notEmpty('bridgePingIntervalHandle'), isAuthenticating: computed.notEmpty('bridgePingIntervalHandle'),
// try to authenticate against the bridge here // try to authenticate against the bridge here
onBridgeIpChange: on('init', observer('bridgeIp', function () { onBridgeIpChange: on(
if (!this.get('trial') && !this.get('isAuthenticating')) { 'init',
this.setProperties({ observer('bridgeIp', function() {
bridgePingIntervalHandle: setInterval(this.pingBridgeUser.bind(this), this.get('bridgeUsernamePingIntervalTime')), if (!this.get('trial') && !this.get('isAuthenticating')) {
bridgeUserNamePingIntervalProgress: 0 this.setProperties({
}); bridgePingIntervalHandle: setInterval(this.pingBridgeUser.bind(this), this.get('bridgeUsernamePingIntervalTime')),
} bridgeUserNamePingIntervalProgress: 0
})), });
}
})
),
didInsertElement() { didInsertElement() {
$(document).keypress((event) => { $(document).keypress(event => {
if (!isNone(this.get('manualBridgeIp')) && event.which === 13) { if (!isNone(this.get('manualBridgeIp')) && event.which === 13) {
this.send('findBridgeByIp'); this.send('findBridgeByIp');
} }
@ -66,7 +60,7 @@ export default Component.extend({
} else if (result.length > 1) { } else if (result.length > 1) {
let multipleBridgeIps = this.get('multipleBridgeIps'); let multipleBridgeIps = this.get('multipleBridgeIps');
result.forEach(function (item) { result.forEach(function(item) {
multipleBridgeIps.pushObject(item.internalipaddress); multipleBridgeIps.pushObject(item.internalipaddress);
}); });
@ -90,27 +84,34 @@ export default Component.extend({
if (bridgeIp !== null && bridgeUserNamePingIntervalProgress < 100) { if (bridgeIp !== null && bridgeUserNamePingIntervalProgress < 100) {
$.ajax('http://' + bridgeIp + '/api', { $.ajax('http://' + bridgeIp + '/api', {
data: JSON.stringify({ "devicetype": "huegasm" }), data: JSON.stringify({ devicetype: 'huegasm' }),
contentType: 'application/json', contentType: 'application/json',
type: 'POST' type: 'POST'
}).done((result, status) => { })
if (!this.isDestroyed) { .done((result, status) => {
if (status === 'success' && !result[0].error) { if (!this.isDestroyed) {
this.clearBridgePingIntervalHandle(); if (status === 'success' && !result[0].error) {
this.get('storage').set('huegasm.bridgeUsername', result[0].success.username); this.clearBridgePingIntervalHandle();
this.set('bridgeUsername', result[0].success.username); this.get('storage').set('huegasm.bridgeUsername', result[0].success.username);
this.set('bridgeUsername', result[0].success.username);
}
} }
}
}).fail(() => {
this.clearBridgePingIntervalHandle();
this.setProperties({
bridgeConnectError: true,
bridgeConnectMessage: htmlSafe('Your network and/or computer security settings are preventing Huegasm from connecting to your Hue bridge.' +
'<br><span>Feel free to contact us at <a href="mailto:huegasm.app@gmail.com">huegasm.app@gmail.com</a> if this is unexpected and you need help debugging the problem.</span>')
}) })
}); .fail(() => {
this.clearBridgePingIntervalHandle();
this.setProperties({
bridgeConnectError: true,
bridgeConnectMessage: htmlSafe(
'Your network and/or computer security settings are preventing Huegasm from connecting to your Hue bridge.' +
'<br><span>Feel free to contact us at <a href="mailto:huegasm.app@gmail.com">huegasm.app@gmail.com</a> if this is unexpected and you need help debugging the problem.</span>'
)
});
});
this.incrementProperty('bridgeUserNamePingIntervalProgress', this.get('bridgeUsernamePingIntervalTime') / bridgeUsernamePingMaxTime * 100); this.incrementProperty(
'bridgeUserNamePingIntervalProgress',
this.get('bridgeUsernamePingIntervalTime') / bridgeUsernamePingMaxTime * 100
);
} else { } else {
this.clearBridgePingIntervalHandle(); this.clearBridgePingIntervalHandle();
} }
@ -140,18 +141,24 @@ export default Component.extend({
}); });
} else { } else {
$.ajax('http://' + manualBridgeIp + '/api', { $.ajax('http://' + manualBridgeIp + '/api', {
data: JSON.stringify({ "devicetype": "huegasm" }), data: JSON.stringify({ devicetype: 'huegasm' }),
contentType: 'application/json', contentType: 'application/json',
type: 'POST' type: 'POST'
}).fail(() => { })
this.set('manualBridgeIpNotFound', true); .fail(() => {
later(this, function () { this.set('manualBridgeIpNotFound', true);
this.set('manualBridgeIpNotFound', false); later(
}, 5000); this,
}).then(() => { function() {
this.send('chooseBridge', manualBridgeIp); this.set('manualBridgeIpNotFound', false);
}); },
5000
);
})
.then(() => {
this.send('chooseBridge', manualBridgeIp);
});
} }
} }
}, }
}); });

View file

@ -50,7 +50,7 @@
{{/unless}} {{/unless}}
{{#if bridgeFindMultiple}} {{#if bridgeFindMultiple}}
<p>Huegasm found multiple hue bridges. <br> Please select the one you want to use for Huegasm.</p> <p>Multiple Hue bridge were found on your network. <br> Please select the one you want to use for Huegasm.</p>
<div id="bridge-button-group"> <div id="bridge-button-group">
{{#each multipleBridgeIps as |bridge|}} {{#each multipleBridgeIps as |bridge|}}

View file

@ -51,7 +51,9 @@ export default Component.extend({
// here's a weird way to automatically initialize bootstrap tooltips // here's a weird way to automatically initialize bootstrap tooltips
let observer = new MutationObserver(function(mutations) { let observer = new MutationObserver(function(mutations) {
let haveTooltip = !mutations.every(function(mutation) { let haveTooltip = !mutations.every(function(mutation) {
return isEmpty(mutation.addedNodes) || isNone(mutation.addedNodes[0].classList) || mutation.addedNodes[0].classList.contains('tooltip'); return (
isEmpty(mutation.addedNodes) || isNone(mutation.addedNodes[0].classList) || mutation.addedNodes[0].classList.contains('tooltip')
);
}); });
if (haveTooltip) { if (haveTooltip) {
@ -92,7 +94,9 @@ export default Component.extend({
if (isNone(this.get('lightsData'))) { if (isNone(this.get('lightsData'))) {
this.send('clearBridge'); this.send('clearBridge');
} else if (this.get('displayNextFailure')) { } else if (this.get('displayNextFailure')) {
this.get('notify').warning({ html: '<div class="alert alert-warning" role="alert">Error retrieving data from your lights. Yikes.</div>' }); this.get('notify').warning({
html: '<div class="alert alert-warning" role="alert">Error retrieving data from your lights. Yikes.</div>'
});
this.set('displayNextFailure', false); this.set('displayNextFailure', false);
later( later(
@ -174,7 +178,8 @@ export default Component.extend({
}, },
{ {
element: $('#playlist md-menu')[0], element: $('#playlist md-menu')[0],
intro: '<img src="/assets/images/soundcloudUrl.png" id="soundcloud-tutorial">You can add songs from SoundCloud by copy and pasting the URL shown here' intro:
'<img src="/assets/images/soundcloudUrl.png" id="soundcloud-tutorial">You can add songs from SoundCloud by copy and pasting the URL shown here'
}, },
{ {
element: '#player-area', element: '#player-area',
@ -196,7 +201,9 @@ export default Component.extend({
}, },
{ {
element: '#beat-container', element: '#beat-container',
intro: 'An interactive speaker that will bump when a beat is registered. <br><br>' + '<i><b>TIP</b>: Click on the center of the speaker to simulate a beat.</i>', intro:
'An interactive speaker that will bump when a beat is registered. <br><br>' +
'<i><b>TIP</b>: Click on the center of the speaker to simulate a beat.</i>',
position: 'top' position: 'top'
}, },
{ {

View file

@ -1,10 +1,6 @@
import Ember from 'ember'; import Ember from 'ember';
const { const { Component, isEmpty, $ } = Ember;
Component,
isEmpty,
$
} = Ember;
export default Component.extend({ export default Component.extend({
bridgeIp: null, bridgeIp: null,

View file

@ -1,15 +1,12 @@
import Ember from 'ember'; import Ember from 'ember';
const { const { Component, computed } = Ember;
Component,
computed
} = Ember;
export default Component.extend({ export default Component.extend({
tagName: 'footer', tagName: 'footer',
elementId: 'footer', elementId: 'footer',
year: computed(function () { year: computed(function() {
return new Date().getFullYear(); return new Date().getFullYear();
}) })
}); });

View file

@ -1,14 +1,6 @@
import Ember from 'ember'; import Ember from 'ember';
const { const { A, Component, computed, isEmpty, isNone, observer, $ } = Ember;
A,
Component,
computed,
isEmpty,
isNone,
observer,
$
} = Ember;
export default Component.extend({ export default Component.extend({
elementId: 'active-lights', elementId: 'active-lights',
@ -17,7 +9,7 @@ export default Component.extend({
activeLights: A(), activeLights: A(),
// list of all the lights in the hue system // list of all the lights in the hue system
lightsList: computed('lightsData', 'activeLights.[]', 'dimmerOn', function () { lightsList: computed('lightsData', 'activeLights.[]', 'dimmerOn', function() {
let lightsData = this.get('lightsData'), let lightsData = this.get('lightsData'),
activeLights = this.get('activeLights'), activeLights = this.get('activeLights'),
dimmerOn = this.get('dimmerOn'), dimmerOn = this.get('dimmerOn'),
@ -172,7 +164,7 @@ export default Component.extend({
return lightsList; return lightsList;
}), }),
onActiveLightsChange: observer('activeLights.[]', function () { onActiveLightsChange: observer('activeLights.[]', function() {
this.get('storage').set('huegasm.activeLights', this.get('activeLights')); this.get('storage').set('huegasm.activeLights', this.get('activeLights'));
}), }),
@ -184,7 +176,7 @@ export default Component.extend({
activeLightsCache = this.get('storage').get('huegasm.activeLights'); activeLightsCache = this.get('storage').get('huegasm.activeLights');
if (!isNone(activeLightsCache)) { if (!isNone(activeLightsCache)) {
activeLightsCache.forEach(function (i) { activeLightsCache.forEach(function(i) {
if (!isNone(lightsData) && lightsData.hasOwnProperty(i) && lightsData[i].state.reachable) { if (!isNone(lightsData) && lightsData.hasOwnProperty(i) && lightsData[i].state.reachable) {
activeLights.pushObject(i); activeLights.pushObject(i);
} }
@ -211,15 +203,15 @@ export default Component.extend({
} }
}, },
lightStartHover(id) { lightStartHover(id) {
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) { if (!window.matchMedia || window.matchMedia('(min-width: 768px)').matches) {
let activeLights = this.get('activeLights'), let activeLights = this.get('activeLights'),
hoveredLight = this.get('lightsList').filter(function (light) { hoveredLight = this.get('lightsList').filter(function(light) {
return light.activeClass !== 'unreachable' && light.id === id[0] && activeLights.indexOf(id) !== -1; return light.activeClass !== 'unreachable' && light.id === id[0] && activeLights.indexOf(id) !== -1;
}); });
if (!isEmpty(hoveredLight) && this.get('noHover') !== true) { if (!isEmpty(hoveredLight) && this.get('noHover') !== true) {
$.ajax(this.get('apiURL') + '/lights/' + id + '/state', { $.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
data: JSON.stringify({ "alert": "lselect" }), data: JSON.stringify({ alert: 'lselect' }),
contentType: 'application/json', contentType: 'application/json',
type: 'PUT' type: 'PUT'
}); });
@ -232,14 +224,14 @@ export default Component.extend({
} }
}, },
lightStopHover(id) { lightStopHover(id) {
if (!window.matchMedia || (window.matchMedia("(min-width: 768px)").matches)) { if (!window.matchMedia || window.matchMedia('(min-width: 768px)').matches) {
let hoveredLight = this.get('lightsList').filter(function (light) { let hoveredLight = this.get('lightsList').filter(function(light) {
return light.activeClass !== 'unreachable' && light.id === id[0]; return light.activeClass !== 'unreachable' && light.id === id[0];
}); });
if (!isEmpty(hoveredLight) && this.get('noHover') !== true) { if (!isEmpty(hoveredLight) && this.get('noHover') !== true) {
$.ajax(this.get('apiURL') + '/lights/' + id + '/state', { $.ajax(this.get('apiURL') + '/lights/' + id + '/state', {
data: JSON.stringify({ "alert": "none" }), data: JSON.stringify({ alert: 'none' }),
contentType: 'application/json', contentType: 'application/json',
type: 'PUT' type: 'PUT'
}); });

View file

@ -1,9 +1,6 @@
import Ember from 'ember'; import Ember from 'ember';
const { const { Component, $ } = Ember;
Component,
$
} = Ember;
export default Component.extend({ export default Component.extend({
elementId: 'color-picker', elementId: 'color-picker',
@ -12,17 +9,17 @@ export default Component.extend({
canvasContext: null, canvasContext: null,
pressingDown: false, pressingDown: false,
mouseUp(){ mouseUp() {
this.set('pressingDown', false); this.set('pressingDown', false);
}, },
mouseMove(event){ mouseMove(event) {
if (this.get('pressingDown')) { if (this.get('pressingDown')) {
this.mouseDown(event); this.mouseDown(event);
} }
}, },
mouseDown(event){ mouseDown(event) {
let canvasOffset = $(this.get('canvas')).offset(), let canvasOffset = $(this.get('canvas')).offset(),
canvasX = Math.floor(event.pageX - canvasOffset.left), canvasX = Math.floor(event.pageX - canvasOffset.left),
canvasY = Math.floor(event.pageY - canvasOffset.top); canvasY = Math.floor(event.pageY - canvasOffset.top);
@ -39,14 +36,14 @@ export default Component.extend({
}, },
// https://dzone.com/articles/creating-your-own-html5 // https://dzone.com/articles/creating-your-own-html5
didInsertElement(){ didInsertElement() {
// handle color changes // handle color changes
let canvas = $('#picker')[0], let canvas = $('#picker')[0],
canvasContext = canvas.getContext('2d'), canvasContext = canvas.getContext('2d'),
image = new Image(); image = new Image();
image.src = 'assets/images/colormap.png'; image.src = 'assets/images/colormap.png';
image.onload = function () { image.onload = function() {
canvasContext.drawImage(image, 0, 0, image.width, image.height); // draw the image on the canvas canvasContext.drawImage(image, 0, 0, image.width, image.height); // draw the image on the canvas
}; };

View file

@ -1,33 +1,25 @@
import Ember from 'ember'; import Ember from 'ember';
const { const { Component, observer, computed, isEmpty, isNone, run: { later }, $ } = Ember;
Component,
observer,
computed,
isEmpty,
isNone,
run: { later },
$
} = Ember;
export default Component.extend({ export default Component.extend({
url: null, url: null,
onIsShowingModalChange: observer('isShowingModal', function () { onIsShowingModalChange: observer('isShowingModal', function() {
if (this.get('isShowingModal')) { if (this.get('isShowingModal')) {
this.set('url', null); this.set('url', null);
later(function () { later(function() {
$('md-input-container input').focus(); $('md-input-container input').focus();
}, 500); }, 500);
} }
}), }),
saveDisabled: computed('url', function () { saveDisabled: computed('url', function() {
return isNone(this.get('url')) || isEmpty(this.get('url').trim()); return isNone(this.get('url')) || isEmpty(this.get('url').trim());
}), }),
didInsertElement: function () { didInsertElement: function() {
$(document).keypress((event) => { $(document).keypress(event => {
if (!this.get('saveDisabled') && event.which === 13) { if (!this.get('saveDisabled') && event.which === 13) {
this.send('add'); this.send('add');
} }

View file

@ -6,7 +6,7 @@ import visualizerMixin from './mixins/visualizer';
const { Component, observer, isEmpty, isNone, $, run: { later, next } } = Ember; const { Component, observer, isEmpty, isNone, $, run: { later, next } } = Ember;
export default Component.extend(helperMixin, visualizerMixin, { export default Component.extend(helperMixin, visualizerMixin, {
updatePageTitle: observer('playQueuePointer', function () { updatePageTitle: observer('playQueuePointer', function() {
let title = 'Huegasm', let title = 'Huegasm',
playQueuePointer = this.get('playQueuePointer'), playQueuePointer = this.get('playQueuePointer'),
playQueue = this.get('playQueue'); playQueue = this.get('playQueue');
@ -17,7 +17,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
title = song.title; title = song.title;
if (song.artist) { if (song.artist) {
title += (' - ' + song.artist); title += ' - ' + song.artist;
} }
} else { } else {
title = song.fileName; title = song.fileName;
@ -64,12 +64,14 @@ export default Component.extend(helperMixin, visualizerMixin, {
oldBeatPrefCache = this.get('oldBeatPrefCache'), oldBeatPrefCache = this.get('oldBeatPrefCache'),
newOldBeatPrefCache = null; newOldBeatPrefCache = null;
if (!isNone(preference)) { // load existing beat prefs if (!isNone(preference)) {
// load existing beat prefs
newOldBeatPrefCache = { threshold: this.get('threshold') }; newOldBeatPrefCache = { threshold: this.get('threshold') };
this.changePlayerControl('threshold', preference.threshold); this.changePlayerControl('threshold', preference.threshold);
this.set('usingBeatPreferences', true); this.set('usingBeatPreferences', true);
} else if (!isNone(oldBeatPrefCache)) { // revert to using beat prefs before the remembered song } else if (!isNone(oldBeatPrefCache)) {
// revert to using beat prefs before the remembered song
this.changePlayerControl('threshold', oldBeatPrefCache.threshold); this.changePlayerControl('threshold', oldBeatPrefCache.threshold);
this.set('usingBeatPreferences', false); this.set('usingBeatPreferences', false);
} }
@ -106,7 +108,12 @@ export default Component.extend(helperMixin, visualizerMixin, {
dragLeave() { dragLeave() {
// need to delay the dragLeave notification to avoid flickering (hovering over some page elements causes this event to be sent) // need to delay the dragLeave notification to avoid flickering (hovering over some page elements causes this event to be sent)
this.set('dragLeaveTimeoutHandle', setTimeout(() => { this.set('dragging', false); }, 500)); this.set(
'dragLeaveTimeoutHandle',
setTimeout(() => {
this.set('dragging', false);
}, 500)
);
}, },
simulateKick() { simulateKick() {
@ -118,7 +125,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
let options = { bri, transitiontime: 0 }; let options = { bri, transitiontime: 0 };
if (!transitiontime) { if (!transitiontime) {
options.transitiontime = 1; options.transitiontime = 1;
} }
if (!isNone(hue)) { if (!isNone(hue)) {
@ -168,20 +175,32 @@ export default Component.extend(helperMixin, visualizerMixin, {
timeToBriOff = 80; timeToBriOff = 80;
} }
later(this, () => { later(
stimulateLight(light, brightnessRange[1], true); this,
later(this, stimulateLight, light, brightnessRange[0], false, color, timeToBriOff); () => {
}, this.get('beatDelay')); stimulateLight(light, brightnessRange[1], true);
later(this, stimulateLight, light, brightnessRange[0], false, color, timeToBriOff);
},
this.get('beatDelay')
);
} }
this.set('paused', true); this.set('paused', true);
later(this, function () { later(
this.set('paused', false); this,
}, 200); function() {
this.set('paused', false);
},
200
);
//work the music beat area - simulate the speaker vibration by running a CSS animation on it //work the music beat area - simulate the speaker vibration by running a CSS animation on it
$('#beat-speaker-center-outer').velocity({ blur: 3 }, 100).velocity({ blur: 0 }, 100); $('#beat-speaker-center-outer')
$('#beat-speaker-center-inner').velocity({ scale: 1.05 }, 100).velocity({ scale: 1 }, 100); .velocity({ blur: 3 }, 100)
.velocity({ blur: 0 }, 100);
$('#beat-speaker-center-inner')
.velocity({ scale: 1.05 }, 100)
.velocity({ scale: 1 }, 100);
}, },
doAmbience(mag) { doAmbience(mag) {
@ -189,12 +208,13 @@ export default Component.extend(helperMixin, visualizerMixin, {
if (mag > 0.01 && !this.pauseAmbience && activeLights.length > 0) { if (mag > 0.01 && !this.pauseAmbience && activeLights.length > 0) {
let _stimulateLight = (lightIndex, options) => { let _stimulateLight = (lightIndex, options) => {
$.ajax(this.get('apiURL') + '/lights/' + lightIndex + '/state', { $.ajax(this.get('apiURL') + '/lights/' + lightIndex + '/state', {
data: JSON.stringify(options), data: JSON.stringify(options),
contentType: 'application/json', contentType: 'application/json',
type: 'PUT' type: 'PUT'
}); });
}, lightIndex = Math.floor(Math.random() * activeLights.length); },
lightIndex = Math.floor(Math.random() * activeLights.length);
// let's try not to select the same light twice in a row // let's try not to select the same light twice in a row
if (activeLights.length > 1) { if (activeLights.length > 1) {
@ -210,14 +230,14 @@ export default Component.extend(helperMixin, visualizerMixin, {
this.lastAmbienceLightIndex = lightIndex; this.lastAmbienceLightIndex = lightIndex;
_stimulateLight(light, { bri: Math.floor(brightnessRange[1] / 1.4), hue, transitiontime: Math.floor(Math.random() * 4) + 4 }); _stimulateLight(light, { bri: Math.floor(brightnessRange[1] / 1.4), hue, transitiontime: Math.floor(Math.random() * 4) + 4 });
setTimeout(function () { setTimeout(function() {
hue = Math.floor(Math.random() * (hueRange[1] - hueRange[0] + 1) + hueRange[0]); hue = Math.floor(Math.random() * (hueRange[1] - hueRange[0] + 1) + hueRange[0]);
_stimulateLight(light, { bri: brightnessRange[0], hue, transitiontime: Math.floor(Math.random() * 4) + 4 }); _stimulateLight(light, { bri: brightnessRange[0], hue, transitiontime: Math.floor(Math.random() * 4) + 4 });
}, 1000); }, 1000);
this.pauseAmbience = true; this.pauseAmbience = true;
let pauseTime = Math.floor(1000 + (2000 / activeLights.length)); let pauseTime = Math.floor(1000 + 2000 / activeLights.length);
setTimeout(() => { setTimeout(() => {
this.pauseAmbience = false; this.pauseAmbience = false;
@ -228,9 +248,15 @@ export default Component.extend(helperMixin, visualizerMixin, {
init() { init() {
this._super(...arguments); this._super(...arguments);
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame; window.requestAnimationFrame =
window.cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame; window.requestAnimationFrame ||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; 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;
let dancer = new Dancer(), let dancer = new Dancer(),
storage = this.get('storage'), storage = this.get('storage'),
@ -241,7 +267,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
this.simulateKick(mag, ratioKickMag); this.simulateKick(mag, ratioKickMag);
} }
}, },
offKick: (mag) => { offKick: mag => {
if (this.get('ambienceMode')) { if (this.get('ambienceMode')) {
this.doAmbience(mag); this.doAmbience(mag);
} }
@ -255,7 +281,25 @@ export default Component.extend(helperMixin, visualizerMixin, {
kick: kick kick: kick
}); });
['volume', 'shuffle', 'repeat', 'volumeMuted', 'threshold', 'ambienceMode', 'blackoutMode', 'playerBottomDisplayed', 'songBeatPreferences', 'firstVisit', 'currentVisName', 'playQueue', 'playQueuePointer', 'flashingTransitions', 'hueRange', 'brightnessRange', 'beatDelay'].forEach((item) => { [
'volume',
'shuffle',
'repeat',
'volumeMuted',
'threshold',
'ambienceMode',
'blackoutMode',
'playerBottomDisplayed',
'songBeatPreferences',
'firstVisit',
'currentVisName',
'playQueue',
'playQueuePointer',
'flashingTransitions',
'hueRange',
'brightnessRange',
'beatDelay'
].forEach(item => {
if (!isNone(storage.get('huegasm.' + item))) { if (!isNone(storage.get('huegasm.' + item))) {
let itemVal = storage.get('huegasm.' + item); let itemVal = storage.get('huegasm.' + item);
@ -280,33 +324,33 @@ export default Component.extend(helperMixin, visualizerMixin, {
let self = this; let self = this;
// file input code // file input code
$('#file-input').on('change', function () { $('#file-input').on('change', function() {
let files = this.files; let files = this.files;
self.send('handleNewFiles', files); self.send('handleNewFiles', files);
this.value = null; // reset in case upload the second file again this.value = null; // reset in case upload the second file again
}); });
$(document).on('click', '.alert', (event) => { $(document).on('click', '.alert', event => {
$(event.target).addClass('removed'); $(event.target).addClass('removed');
}); });
// prevent space/text selection when the user repeatedly clicks on the center // prevent space/text selection when the user repeatedly clicks on the center
$('#beat-container').on('mousedown', '#beat-speaker-center-inner', function (event) { $('#beat-container').on('mousedown', '#beat-speaker-center-inner', function(event) {
event.preventDefault(); event.preventDefault();
}); });
$(document).keypress((event) => { $(document).keypress(event => {
if (event.which === 32 && event.target.type !== 'text') { if (event.which === 32 && event.target.type !== 'text') {
this.send('play'); this.send('play');
} }
}); });
this.$().on('drop', '#play-list-area', (event) => { this.$().on('drop', '#play-list-area', event => {
this.send('dropFiles', event.dataTransfer.files); this.send('dropFiles', event.dataTransfer.files);
}); });
// control the volume by scrolling up/down // control the volume by scrolling up/down
$('#player-area').on('mousewheel', (event) => { $('#player-area').on('mousewheel', event => {
if (this.get('playQueueNotEmpty')) { if (this.get('playQueueNotEmpty')) {
let scrollSize = 5; let scrollSize = 5;
@ -368,59 +412,77 @@ export default Component.extend(helperMixin, visualizerMixin, {
}, },
handleNewSoundCloudURL(URL) { handleNewSoundCloudURL(URL) {
if (URL) { if (URL) {
SC.resolve(URL).then((resultObj) => { SC.resolve(URL).then(
let processResult = (result) => { resultObj => {
if (result.kind === 'user') { let processResult = result => {
this.get('notify').alert({ html: this.get('scUserNotSupportedHtml') }); if (result.kind === 'user') {
} else if (result.kind === 'track') { this.get('notify').alert({ html: this.get('scUserNotSupportedHtml') });
if (result.streamable === true) { } else if (result.kind === 'track') {
let picture = null; if (result.streamable === true) {
let picture = null;
if (result.artwork_url) { if (result.artwork_url) {
picture = result.artwork_url.replace('large', 't67x67'); picture = result.artwork_url.replace('large', 't67x67');
} else if (result.user.avatar_url) { } else if (result.user.avatar_url) {
picture = result.user.avatar_url; picture = result.user.avatar_url;
}
$.get(picture)
.done(() => {
this.get('playQueue').pushObject({
url: result.stream_url + '?client_id=' + this.get('SC_CLIENT_ID'),
fileName: result.title + ' - ' + result.user.username,
artist: result.user.username,
scUrl: result.permalink_url,
title: result.title,
picture: picture
});
})
.fail(() => {
// no picture
this.get('playQueue').pushObject({
url: result.stream_url + '?client_id=' + this.get('SC_CLIENT_ID'),
fileName: result.title + ' - ' + result.user.username,
artist: result.user.username,
scUrl: result.permalink_url,
title: result.title
});
});
} else {
failedSongs.push(result.title);
}
} else if (result.kind === 'playlist') {
if (result.streamable === true) {
result.tracks.forEach(processResult);
} else {
failedSongs.push(result.title);
}
} }
},
failedSongs = [];
$.get(picture) if (resultObj instanceof Array) {
.done(() => { resultObj.forEach(processResult);
this.get('playQueue').pushObject({ url: result.stream_url + '?client_id=' + this.get('SC_CLIENT_ID'), fileName: result.title + ' - ' + result.user.username, artist: result.user.username, scUrl: result.permalink_url, title: result.title, picture: picture }); } else {
}).fail(() => { // no picture processResult(resultObj);
this.get('playQueue').pushObject({ url: result.stream_url + '?client_id=' + this.get('SC_CLIENT_ID'), fileName: result.title + ' - ' + result.user.username, artist: result.user.username, scUrl: result.permalink_url, title: result.title }); }
});
if (failedSongs.length > 0) {
this.get('notify').alert({ html: this.get('notStreamableHtml')(failedSongs) });
}
if (this.get('playQueuePointer') === -1) {
if (this.get('firstVisit')) {
this.send('goToSong', 0);
} else { } else {
failedSongs.push(result.title); this.send('next');
}
} else if (result.kind === 'playlist') {
if (result.streamable === true) {
result.tracks.forEach(processResult);
} else {
failedSongs.push(result.title);
} }
} }
}, },
failedSongs = []; () => {
this.get('notify').alert({ html: this.get('urlNotFoundHtml')(URL) });
if (resultObj instanceof Array) {
resultObj.forEach(processResult);
} else {
processResult(resultObj);
} }
);
if (failedSongs.length > 0) {
this.get('notify').alert({ html: this.get('notStreamableHtml')(failedSongs) });
}
if (this.get('playQueuePointer') === -1) {
if (this.get('firstVisit')) {
this.send('goToSong', 0);
} else {
this.send('next');
}
}
}, () => {
this.get('notify').alert({ html: this.get('urlNotFoundHtml')(URL) });
});
} }
this.set('isShowingAddSoundCloudModal', false); this.set('isShowingAddSoundCloudModal', false);
@ -435,7 +497,8 @@ export default Component.extend(helperMixin, visualizerMixin, {
this.changePlayerControl('playerBottomDisplayed', !this.get('playerBottomDisplayed')); this.changePlayerControl('playerBottomDisplayed', !this.get('playerBottomDisplayed'));
}, },
goToSong(index, playSong, scrollToSong) { goToSong(index, playSong, scrollToSong) {
let dancer = this.get('dancer'), playQueue = this.get('playQueue'); let dancer = this.get('dancer'),
playQueue = this.get('playQueue');
if (dancer.audio) { if (dancer.audio) {
this.clearCurrentAudio(true); this.clearCurrentAudio(true);
@ -445,12 +508,12 @@ export default Component.extend(helperMixin, visualizerMixin, {
let audio = new Audio(); let audio = new Audio();
audio.src = this.get('playQueue')[index].url; audio.src = this.get('playQueue')[index].url;
audio.crossOrigin = "anonymous"; audio.crossOrigin = 'anonymous';
audio.oncanplay = () => { audio.oncanplay = () => {
this.set('timeTotal', Math.floor(audio.duration)); this.set('timeTotal', Math.floor(audio.duration));
this.set('soundCloudFuckUps', 0); this.set('soundCloudFuckUps', 0);
}; };
audio.onerror = (event) => { audio.onerror = event => {
let playQueuePointer = this.get('playQueuePointer'), let playQueuePointer = this.get('playQueuePointer'),
song = this.get('playQueue')[playQueuePointer]; song = this.get('playQueue')[playQueuePointer];
@ -514,7 +577,9 @@ export default Component.extend(helperMixin, visualizerMixin, {
if (isEmpty($('#player-controls:hover')) && this.get('playQueuePointer') !== -1) { if (isEmpty($('#player-controls:hover')) && this.get('playQueuePointer') !== -1) {
this.send('play'); this.send('play');
$('#play-notification').velocity({ opacity: 0.8, scale: 1 }, 0).velocity({ opacity: 0, scale: 3 }, 500); $('#play-notification')
.velocity({ opacity: 0.8, scale: 1 }, 0)
.velocity({ opacity: 0, scale: 3 }, 500);
} }
}, },
play(replayPause) { play(replayPause) {
@ -528,12 +593,12 @@ export default Component.extend(helperMixin, visualizerMixin, {
dancer.pause(); dancer.pause();
let preMusicLightsDataCache = this.get('preMusicLightsDataCache'), let preMusicLightsDataCache = this.get('preMusicLightsDataCache'),
updateLight = (lightIndex) => { updateLight = lightIndex => {
$.ajax(this.get('apiURL') + '/lights/' + lightIndex + '/state', { $.ajax(this.get('apiURL') + '/lights/' + lightIndex + '/state', {
data: JSON.stringify({ data: JSON.stringify({
'on': preMusicLightsDataCache[lightIndex].state.on, on: preMusicLightsDataCache[lightIndex].state.on,
'hue': preMusicLightsDataCache[lightIndex].state.hue, hue: preMusicLightsDataCache[lightIndex].state.hue,
'bri': preMusicLightsDataCache[lightIndex].state.bri bri: preMusicLightsDataCache[lightIndex].state.bri
}), }),
contentType: 'application/json', contentType: 'application/json',
type: 'PUT' type: 'PUT'
@ -587,17 +652,19 @@ export default Component.extend(helperMixin, visualizerMixin, {
next(repeatAll) { next(repeatAll) {
let playQueuePointer = this.get('playQueuePointer'), let playQueuePointer = this.get('playQueuePointer'),
playQueue = this.get('playQueue'), playQueue = this.get('playQueue'),
nextSong = (playQueuePointer + 1), nextSong = playQueuePointer + 1,
repeat = this.get('repeat'), repeat = this.get('repeat'),
shuffle = this.get('shuffle'); shuffle = this.get('shuffle');
if (repeat === 2) { // repeating one song takes precedence over shuffling if (repeat === 2) {
// repeating one song takes precedence over shuffling
if (playQueuePointer === -1 && playQueue.length > 0) { if (playQueuePointer === -1 && playQueue.length > 0) {
nextSong = 0; nextSong = 0;
} else { } else {
nextSong = playQueuePointer; nextSong = playQueuePointer;
} }
} else if (shuffle) { // next shuffle song } else if (shuffle) {
// next shuffle song
let shufflePlayed = this.get('shufflePlayed'); let shufflePlayed = this.get('shufflePlayed');
// played all the song in shuffle mode // played all the song in shuffle mode
@ -631,19 +698,22 @@ export default Component.extend(helperMixin, visualizerMixin, {
let nextSong = this.get('playQueuePointer'), let nextSong = this.get('playQueuePointer'),
playQueue = this.get('playQueue'); playQueue = this.get('playQueue');
if (this.get('shuffle') && !isNone(playQueue[nextSong])) { // go to the previously shuffled song if (this.get('shuffle') && !isNone(playQueue[nextSong])) {
// go to the previously shuffled song
let shufflePlayed = this.get('shufflePlayed'), let shufflePlayed = this.get('shufflePlayed'),
shuffledSongIndx = this.get('shufflePlayed').indexOf(playQueue[nextSong].url), shuffledSongIndx = this.get('shufflePlayed').indexOf(playQueue[nextSong].url),
i = 0; i = 0;
if (shufflePlayed.length > 0 && shuffledSongIndx !== -1) { // only if there was one if (shufflePlayed.length > 0 && shuffledSongIndx !== -1) {
// only if there was one
nextSong = shuffledSongIndx - 1; nextSong = shuffledSongIndx - 1;
if (nextSong < 0) { if (nextSong < 0) {
nextSong = shufflePlayed.length - 1; nextSong = shufflePlayed.length - 1;
} }
playQueue.some(function (item) { // try to find the previous song id playQueue.some(function(item) {
// try to find the previous song id
if (item.url === shufflePlayed[nextSong]) { if (item.url === shufflePlayed[nextSong]) {
nextSong = i; nextSong = i;
return true; return true;
@ -685,7 +755,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
} }
} }
}, },
addLocalAudio: function () { addLocalAudio: function() {
$('#file-input').click(); $('#file-input').click();
}, },
shuffleChanged(value) { shuffleChanged(value) {
@ -728,21 +798,21 @@ export default Component.extend(helperMixin, visualizerMixin, {
handleNewFiles(files) { handleNewFiles(files) {
let self = this, let self = this,
playQueue = this.get('playQueue'), playQueue = this.get('playQueue'),
updatePlayQueue = function () { updatePlayQueue = function() {
let tags = ID3.getAllTags("local"), let tags = ID3.getAllTags('local'),
picture = null; picture = null;
if (tags.picture) { if (tags.picture) {
let base64String = ""; let base64String = '';
for (let i = 0; i < tags.picture.data.length; i++) { for (let i = 0; i < tags.picture.data.length; i++) {
base64String += String.fromCharCode(tags.picture.data[i]); base64String += String.fromCharCode(tags.picture.data[i]);
} }
picture = "data:" + tags.picture.format + ";base64," + window.btoa(base64String); picture = 'data:' + tags.picture.format + ';base64,' + window.btoa(base64String);
} }
playQueue.pushObject({ playQueue.pushObject({
fileName: this.name.replace(/\.[^/.]+$/, ""), fileName: this.name.replace(/\.[^/.]+$/, ''),
url: URL.createObjectURL(this), url: URL.createObjectURL(this),
artist: tags.artist, artist: tags.artist,
title: tags.title, title: tags.title,
@ -762,7 +832,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
let file = files[key]; let file = files[key];
if (file.type.startsWith('audio') || file.type.startsWith('video')) { if (file.type.startsWith('audio') || file.type.startsWith('video')) {
ID3.loadTags("local", updatePlayQueue.bind(file), { ID3.loadTags('local', updatePlayQueue.bind(file), {
dataReader: new FileAPIReader(file), dataReader: new FileAPIReader(file),
tags: ['title', 'artist', 'album', 'track', 'picture'] tags: ['title', 'artist', 'album', 'track', 'picture']
}); });

View file

@ -147,7 +147,9 @@ export default Mixin.create({
'<div class="alert alert-danger" role="alert">The SoundCloud API is not seving the audio properly. More details <a href="https://www.soundcloudcommunity.com/soundcloud/topics/some-soundcloud-cdn-hosted-tracks-dont-have-access-control-allow-origin-header" target="_blank" rel="noopener noreferrer">HERE</a>.</div>', '<div class="alert alert-danger" role="alert">The SoundCloud API is not seving the audio properly. More details <a href="https://www.soundcloudcommunity.com/soundcloud/topics/some-soundcloud-cdn-hosted-tracks-dont-have-access-control-allow-origin-header" target="_blank" rel="noopener noreferrer">HERE</a>.</div>',
notStreamableHtml(fileNames) { notStreamableHtml(fileNames) {
let html = let html =
'<div class="alert alert-danger" role="alert">The following file(s) could not be added because they are not allowed to be streamed:<br>' + fileNames.toString().replace(/,/g, '<br>') + '</div>'; '<div class="alert alert-danger" role="alert">The following file(s) could not be added because they are not allowed to be streamed:<br>' +
fileNames.toString().replace(/,/g, '<br>') +
'</div>';
return html; return html;
}, },
@ -319,7 +321,10 @@ export default Mixin.create({
} }
}), }),
onOptionChange: observer('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'ambienceMode', 'blackoutMode', function(self, option) { onOptionChange: observer('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'ambienceMode', 'blackoutMode', function(
self,
option
) {
option = option.replace('.[]', ''); option = option.replace('.[]', '');
let value = this.get(option); let value = this.get(option);
@ -350,7 +355,7 @@ export default Mixin.create({
} }
if (!isNone(value)) { if (!isNone(value)) {
this.get('storage').set('huegasm.' + option, value); this.get('storage').set('huegasm.' + option, value);
} }
}), }),

View file

@ -1,20 +1,16 @@
import Ember from 'ember'; import Ember from 'ember';
const { const { Mixin, observer, $ } = Ember;
Mixin,
observer,
$
} = Ember;
export default Mixin.create({ export default Mixin.create({
currentVisName: 'None', currentVisName: 'None',
visNames: ['None', 'Bars', 'Wave'], visNames: ['None', 'Bars', 'Wave'],
onCurrentVisNameChange: observer('currentVisName', function () { onCurrentVisNameChange: observer('currentVisName', function() {
let currentVisName = this.get('currentVisName'); let currentVisName = this.get('currentVisName');
if(currentVisName === 'None'){ if (currentVisName === 'None') {
let canvasEl = $('#visualization')[0], let canvasEl = $('#visualization')[0],
ctx = canvasEl.getContext('2d'); ctx = canvasEl.getContext('2d');
@ -24,19 +20,20 @@ export default Mixin.create({
this.get('storage').set('huegasm.currentVisName', currentVisName); this.get('storage').set('huegasm.currentVisName', currentVisName);
}), }),
didInsertElement(){ didInsertElement() {
let dancer = this.get('dancer'), let dancer = this.get('dancer'),
canvas = $('#visualization')[0], canvas = $('#visualization')[0],
playerArea = $('#player-area'), playerArea = $('#player-area'),
ctx = canvas.getContext('2d'), ctx = canvas.getContext('2d'),
spacing = 2, spacing = 2,
h = playerArea.height(), w; h = playerArea.height(),
w;
canvas.height = h; canvas.height = h;
// must be done to preserver resolution so that things don't appear blurry // must be done to preserver resolution so that things don't appear blurry
// note that the height is set to 400px via css so it doesn't need to be recalculated // note that the height is set to 400px via css so it doesn't need to be recalculated
let syncCanvasHeight = ()=>{ let syncCanvasHeight = () => {
w = playerArea.width(); w = playerArea.width();
canvas.width = w; canvas.width = w;
}; };
@ -51,7 +48,7 @@ export default Mixin.create({
pageHidden = document.hidden || document.msHidden || document.webkitHidden || document.mozHidden; pageHidden = document.hidden || document.msHidden || document.webkitHidden || document.mozHidden;
// dont do anything if the page is hidden or no visualization // dont do anything if the page is hidden or no visualization
if(currentVisName === 'None' || pageHidden || !this.get('active')){ if (currentVisName === 'None' || pageHidden || !this.get('active')) {
return; return;
} }
@ -71,7 +68,7 @@ export default Mixin.create({
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(0, h / 2); ctx.moveTo(0, h / 2);
for (let i = 0, l = waveform.length; i < l && i < count; i++) { for (let i = 0, l = waveform.length; i < l && i < count; i++) {
ctx.lineTo(i * ( spacing + width ), ( h / 2 ) + waveform[i] * ( h / 2 )); ctx.lineTo(i * (spacing + width), h / 2 + waveform[i] * (h / 2));
} }
ctx.stroke(); ctx.stroke();
ctx.closePath(); ctx.closePath();
@ -86,7 +83,7 @@ export default Mixin.create({
ctx.fillStyle = gradient; ctx.fillStyle = gradient;
let spectrum = dancer.getSpectrum(); let spectrum = dancer.getSpectrum();
for (let i = 0, l = spectrum.length; i < l && i < count; i++) { for (let i = 0, l = spectrum.length; i < l && i < count; i++) {
ctx.fillRect(i * ( spacing + width ), h, width, -spectrum[i] * h - 60); ctx.fillRect(i * (spacing + width), h, width, -spectrum[i] * h - 60);
} }
} }
}); });