showing brightness value in slider, remember bridge ip when picking from multiple bridges, fix light strobe, remove error handling on bridge finding ( TRIAL )
This commit is contained in:
parent
7db49d310c
commit
d12e599814
20 changed files with 521 additions and 528 deletions
|
|
@ -28,12 +28,11 @@ export default Component.extend({
|
||||||
manualBridgeIp: null,
|
manualBridgeIp: null,
|
||||||
manualBridgeIpNotFound: false,
|
manualBridgeIpNotFound: false,
|
||||||
multipleBridgeIps: [],
|
multipleBridgeIps: [],
|
||||||
error: false,
|
|
||||||
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('init', observer('bridgeIp', function () {
|
||||||
if(!this.get('trial') && !this.get('isAuthenticating')) {
|
if (!this.get('trial') && !this.get('isAuthenticating')) {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
bridgePingIntervalHandle: setInterval(this.pingBridgeUser.bind(this), this.get('bridgeUsernamePingIntervalTime')),
|
bridgePingIntervalHandle: setInterval(this.pingBridgeUser.bind(this), this.get('bridgeUsernamePingIntervalTime')),
|
||||||
bridgeUserNamePingIntervalProgress: 0
|
bridgeUserNamePingIntervalProgress: 0
|
||||||
|
|
@ -42,14 +41,14 @@ export default Component.extend({
|
||||||
})),
|
})),
|
||||||
|
|
||||||
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');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('resume', () => {
|
document.addEventListener('resume', () => {
|
||||||
if(this.get('error') || this.get('trial') || this.get('bridgeFindFail')) {
|
if (this.get('trial') || this.get('bridgeFindFail')) {
|
||||||
this.send('tryAgain');
|
this.send('tryAgain');
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
@ -59,11 +58,11 @@ export default Component.extend({
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
if(this.get('bridgeIp') === null) {
|
if (this.get('bridgeIp') === null) {
|
||||||
$.ajax('https://www.meethue.com/api/nupnp', {
|
$.ajax('https://www.meethue.com/api/nupnp', {
|
||||||
timeout: 30000
|
timeout: 30000
|
||||||
})
|
})
|
||||||
.done((result, status)=> {
|
.done((result, status) => {
|
||||||
let bridgeFindStatus = 'fail';
|
let bridgeFindStatus = 'fail';
|
||||||
|
|
||||||
if (status === 'success' && result.length === 1) {
|
if (status === 'success' && result.length === 1) {
|
||||||
|
|
@ -84,9 +83,9 @@ export default Component.extend({
|
||||||
|
|
||||||
this.set('bridgeFindStatus', bridgeFindStatus);
|
this.set('bridgeFindStatus', bridgeFindStatus);
|
||||||
})
|
})
|
||||||
.fail(()=>{
|
.fail(() => {
|
||||||
this.set('bridgeFindStatus', 'fail');
|
this.set('bridgeFindStatus', 'fail');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -97,11 +96,11 @@ 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)=>{
|
}).done((result, status) => {
|
||||||
if(!this.isDestroyed){
|
if (!this.isDestroyed) {
|
||||||
this.set('bridgeAuthenticateReachedStatus', status);
|
this.set('bridgeAuthenticateReachedStatus', status);
|
||||||
|
|
||||||
if (status === 'success' && !result[0].error) {
|
if (status === 'success' && !result[0].error) {
|
||||||
|
|
@ -110,18 +109,15 @@ export default Component.extend({
|
||||||
this.set('bridgeUsername', result[0].success.username);
|
this.set('bridgeUsername', result[0].success.username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).fail(()=>{
|
|
||||||
this.clearBridgePingIntervalHandle();
|
|
||||||
this.set('error', true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.incrementProperty('bridgeUserNamePingIntervalProgress', this.get('bridgeUsernamePingIntervalTime')/bridgeUsernamePingMaxTime*100);
|
this.incrementProperty('bridgeUserNamePingIntervalProgress', this.get('bridgeUsernamePingIntervalTime') / bridgeUsernamePingMaxTime * 100);
|
||||||
} else {
|
} else {
|
||||||
this.clearBridgePingIntervalHandle();
|
this.clearBridgePingIntervalHandle();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
clearBridgePingIntervalHandle(){
|
clearBridgePingIntervalHandle() {
|
||||||
clearInterval(this.get('bridgePingIntervalHandle'));
|
clearInterval(this.get('bridgePingIntervalHandle'));
|
||||||
this.set('bridgePingIntervalHandle', null);
|
this.set('bridgePingIntervalHandle', null);
|
||||||
},
|
},
|
||||||
|
|
@ -131,11 +127,12 @@ export default Component.extend({
|
||||||
this.get('storage').clear();
|
this.get('storage').clear();
|
||||||
location.reload();
|
location.reload();
|
||||||
},
|
},
|
||||||
retry(){
|
retry() {
|
||||||
this.onBridgeIpChange();
|
this.onBridgeIpChange();
|
||||||
},
|
},
|
||||||
chooseBridge(bridge){
|
chooseBridge(bridge) {
|
||||||
this.set('bridgeIp', bridge);
|
this.set('bridgeIp', bridge);
|
||||||
|
this.get('storage').set('huegasm.bridgeIp', bridge);
|
||||||
},
|
},
|
||||||
findBridgeByIp() {
|
findBridgeByIp() {
|
||||||
let manualBridgeIp = this.get('manualBridgeIp');
|
let manualBridgeIp = this.get('manualBridgeIp');
|
||||||
|
|
@ -148,12 +145,12 @@ 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(() => {
|
}).fail(() => {
|
||||||
this.set('manualBridgeIpNotFound', true);
|
this.set('manualBridgeIpNotFound', true);
|
||||||
later(this, function() {
|
later(this, function () {
|
||||||
this.set('manualBridgeIpNotFound', false);
|
this.set('manualBridgeIpNotFound', false);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,15 @@
|
||||||
<div class="title"><img src="assets/images/logo.png" alt="Huegasm"></div>
|
<div class="title"><img src="assets/images/logo.png" alt="Huegasm"></div>
|
||||||
{{#unless bridgeUsername}}
|
{{#unless bridgeUsername}}
|
||||||
{{#if bridgeIp}}
|
{{#if bridgeIp}}
|
||||||
{{#if error}}
|
<img src="assets/images/pressButtonBridge.png" id="press-bridge-button-img"> {{paper-progress-linear warn=true value=bridgeUserNamePingIntervalProgress}}
|
||||||
<p>Huegasm encountered a critical error while trying to connect to your bridge.<br><br>
|
<p class="bridge-finder-bottom">
|
||||||
<a href="#" {{action "tryAgain"}}>TRY AGAIN</a>
|
{{#if isAuthenticating}}
|
||||||
</p>
|
Your bridge IP is <b>{{bridgeIp}}</b>
|
||||||
{{else}}
|
<br> Press the button on your bridge to authenticate this application.
|
||||||
<img src="assets/images/pressButtonBridge.png" id="press-bridge-button-img">
|
{{else}}
|
||||||
{{paper-progress-linear warn=true value=bridgeUserNamePingIntervalProgress}}
|
You failed to press the button in time. <a class="no-text-decoration" href="#" {{action 'retry'}}>RETRY</a>
|
||||||
<p class="bridge-finder-bottom">
|
{{/if}}
|
||||||
{{#if isAuthenticating}}
|
</p>
|
||||||
Your bridge IP is <b>{{bridgeIp}}</b>
|
|
||||||
<br>
|
|
||||||
Press the button on your bridge to authenticate this application.
|
|
||||||
{{else}}
|
|
||||||
You failed to press the button in time. <a class="no-text-decoration" href="#" {{action 'retry'}}>RETRY</a>
|
|
||||||
{{/if}}
|
|
||||||
</p>
|
|
||||||
{{/if}}
|
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#unless bridgeFindStatus}}
|
{{#unless bridgeFindStatus}}
|
||||||
{{paper-progress-circular diameter=100}}
|
{{paper-progress-circular diameter=100}}
|
||||||
|
|
@ -25,8 +17,7 @@
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
{{#if bridgeFindMultiple}}
|
{{#if bridgeFindMultiple}}
|
||||||
<p>Found multiple hue bridges. <br>
|
<p>Huegasm found multiple hue bridges. <br> Please select the one you want to use for this application.</p>
|
||||||
Please select the one you want to use for this application.</p>
|
|
||||||
|
|
||||||
<div id="bridge-button-group">
|
<div id="bridge-button-group">
|
||||||
{{#each multipleBridgeIps as |bridge|}}
|
{{#each multipleBridgeIps as |bridge|}}
|
||||||
|
|
@ -35,9 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#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> ( or type <b>offline</b> to look around )
|
||||||
Enter one manually? <br><br>
|
|
||||||
( or type <b>offline</b> to look around )
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<span id="bridge-input">
|
<span id="bridge-input">
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,10 @@ export default Component.extend({
|
||||||
trial: false,
|
trial: false,
|
||||||
storage: null,
|
storage: null,
|
||||||
|
|
||||||
init(){
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
let storage = new window.Locally.Store({compress: true});
|
let storage = new window.Locally.Store({ compress: true });
|
||||||
this.set('storage', storage);
|
this.set('storage', storage);
|
||||||
|
|
||||||
if (!isEmpty(storage.get('huegasm.bridgeIp')) && !isEmpty(storage.get('huegasm.bridgeUsername'))) {
|
if (!isEmpty(storage.get('huegasm.bridgeIp')) && !isEmpty(storage.get('huegasm.bridgeUsername'))) {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ const {
|
||||||
observer,
|
observer,
|
||||||
computed,
|
computed,
|
||||||
on,
|
on,
|
||||||
run: { later },
|
run: { later, once },
|
||||||
$
|
$
|
||||||
} = Ember;
|
} = Ember;
|
||||||
|
|
||||||
|
|
@ -20,45 +20,45 @@ export default Component.extend({
|
||||||
|
|
||||||
colorLoopOn: false,
|
colorLoopOn: false,
|
||||||
|
|
||||||
lightsOnTxt: computed('lightsOn', function(){
|
lightsOnTxt: computed('lightsOn', function () {
|
||||||
return this.get('lightsOn') ? 'On' : 'Off';
|
return this.get('lightsOn') ? 'On' : 'Off';
|
||||||
}),
|
}),
|
||||||
|
|
||||||
colorloopOnTxt: computed('colorLoopOn', function(){
|
colorloopOnTxt: computed('colorLoopOn', function () {
|
||||||
return this.get('colorLoopOn') ? 'On' : 'Off';
|
return this.get('colorLoopOn') ? 'On' : 'Off';
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// determines the average brightness of the hue system for the brightness slider
|
// determines the average brightness of the hue system for the brightness slider
|
||||||
lightsBrightness: computed('lightsData', function(){
|
lightsBrightness: computed('lightsData', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
activeLights = this.get('activeLights'),
|
activeLights = this.get('activeLights'),
|
||||||
lightsBrightness = 0;
|
lightsBrightness = 0;
|
||||||
|
|
||||||
activeLights.forEach(function(light){
|
activeLights.forEach(function (light) {
|
||||||
lightsBrightness += lightsData[light].state.bri;
|
lightsBrightness += lightsData[light].state.bri;
|
||||||
});
|
});
|
||||||
|
|
||||||
return lightsBrightness/activeLights.length;
|
return lightsBrightness / activeLights.length;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
brightnessControlDisabled: computed.not('lightsOn'),
|
brightnessControlDisabled: computed.not('lightsOn'),
|
||||||
|
|
||||||
onColorLoopOnChange: observer('colorLoopOn', function(){
|
onColorLoopOnChange: observer('colorLoopOn', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
activeLights = this.get('activeLights'),
|
activeLights = this.get('activeLights'),
|
||||||
colorLoopsOn = this.get('colorLoopOn'),
|
colorLoopsOn = this.get('colorLoopOn'),
|
||||||
effect = colorLoopsOn ? 'colorloop' : 'none';
|
effect = colorLoopsOn ? 'colorloop' : 'none';
|
||||||
|
|
||||||
let colorLoopsOnSystem = activeLights.some(function(light) {
|
let colorLoopsOnSystem = activeLights.some(function (light) {
|
||||||
return lightsData[light].state.effect === 'colorloop';
|
return lightsData[light].state.effect === 'colorloop';
|
||||||
});
|
});
|
||||||
|
|
||||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||||
if(colorLoopsOn !== colorLoopsOnSystem){
|
if (colorLoopsOn !== colorLoopsOnSystem) {
|
||||||
activeLights.forEach((light)=>{
|
activeLights.forEach((light) => {
|
||||||
if(this.get('lightsData')[light].state.effect !== effect) {
|
if (this.get('lightsData')[light].state.effect !== effect) {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||||
data: JSON.stringify({'effect': effect }),
|
data: JSON.stringify({ 'effect': effect }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
|
|
@ -67,7 +67,7 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
rgbPreview: observer('rgb', function() {
|
rgbPreview: observer('rgb', function () {
|
||||||
let rgb = this.get('rgb'),
|
let rgb = this.get('rgb'),
|
||||||
xy = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
xy = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
||||||
|
|
||||||
|
|
@ -75,7 +75,7 @@ export default Component.extend({
|
||||||
|
|
||||||
this.get('activeLights').forEach((light) => {
|
this.get('activeLights').forEach((light) => {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||||
data: JSON.stringify({"xy": xy}),
|
data: JSON.stringify({ "xy": xy }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
|
|
@ -86,9 +86,9 @@ export default Component.extend({
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// determines whether the lights are on/off for the lights switch
|
// determines whether the lights are on/off for the lights switch
|
||||||
lightsOnChange: on('init', observer('lightsData.@each.state.on', 'activeLights.[]', function(){
|
lightsOnChange: on('init', observer('lightsData.@each.state.on', 'activeLights.[]', function () {
|
||||||
if(!this.get('strobeOn')){
|
if (!this.get('strobeOn')) {
|
||||||
let lightsData = this.get('lightsData'), lightsOn = this.get('activeLights').some(function(light) {
|
let lightsData = this.get('lightsData'), lightsOn = this.get('activeLights').some(function (light) {
|
||||||
return lightsData[light].state.on === true;
|
return lightsData[light].state.on === true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -96,20 +96,20 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
|
|
||||||
onLightsOnChange: observer('lightsOn', function(){
|
onLightsOnChange: observer('lightsOn', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
activeLights = this.get('activeLights'),
|
activeLights = this.get('activeLights'),
|
||||||
lightsOn = this.get('lightsOn');
|
lightsOn = this.get('lightsOn');
|
||||||
|
|
||||||
let lightsOnSystem = activeLights.some(function(light) {
|
let lightsOnSystem = activeLights.some(function (light) {
|
||||||
return lightsData[light].state.on === true;
|
return lightsData[light].state.on === true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||||
if(lightsOn !== lightsOnSystem){
|
if (lightsOn !== lightsOnSystem) {
|
||||||
activeLights.forEach((light)=>{
|
activeLights.forEach((light) => {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||||
data: JSON.stringify({"on": lightsOn}),
|
data: JSON.stringify({ "on": lightsOn }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
|
|
@ -117,32 +117,34 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
onBrightnessChanged: observer('lightsBrightness', function(){
|
onBrightnessChanged: observer('lightsBrightness', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
once(this, function () {
|
||||||
lightsBrightnessSystem = false,
|
let lightsData = this.get('lightsData'),
|
||||||
lightsBrightness = this.get('lightsBrightness'),
|
lightsBrightnessSystem = false,
|
||||||
activeLights = this.get('activeLights');
|
lightsBrightness = this.get('lightsBrightness'),
|
||||||
|
activeLights = this.get('activeLights');
|
||||||
|
|
||||||
activeLights.forEach(function(light){
|
activeLights.forEach(function (light) {
|
||||||
lightsBrightnessSystem += lightsData[light].state.bri;
|
lightsBrightnessSystem += lightsData[light].state.bri;
|
||||||
});
|
|
||||||
|
|
||||||
lightsBrightnessSystem /= activeLights.length;
|
|
||||||
|
|
||||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
|
||||||
if(lightsBrightness !== lightsBrightnessSystem){
|
|
||||||
activeLights.forEach((light)=>{
|
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
|
||||||
data: JSON.stringify({"bri": lightsBrightness}),
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'PUT'
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
lightsBrightnessSystem /= activeLights.length;
|
||||||
|
|
||||||
|
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||||
|
if (lightsBrightness !== lightsBrightnessSystem) {
|
||||||
|
activeLights.forEach((light) => {
|
||||||
|
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||||
|
data: JSON.stringify({ "bri": lightsBrightness }),
|
||||||
|
contentType: 'application/json',
|
||||||
|
type: 'PUT'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// sync the current light settings to the newly added light
|
// sync the current light settings to the newly added light
|
||||||
onaActiveLightsChange: observer('syncLight', function(){
|
onaActiveLightsChange: observer('syncLight', function () {
|
||||||
let options = {
|
let options = {
|
||||||
on: this.get('lightsOn'),
|
on: this.get('lightsOn'),
|
||||||
bri: this.get('lightsBrightness'),
|
bri: this.get('lightsBrightness'),
|
||||||
|
|
@ -150,7 +152,7 @@ export default Component.extend({
|
||||||
}, rgb = this.get('rgb'),
|
}, rgb = this.get('rgb'),
|
||||||
syncLight = this.get('syncLight');
|
syncLight = this.get('syncLight');
|
||||||
|
|
||||||
if(rgb[0] !== 255 && rgb[1] !== 255 && rgb[2] !== 255) {
|
if (rgb[0] !== 255 && rgb[1] !== 255 && rgb[2] !== 255) {
|
||||||
options['xy'] = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
options['xy'] = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,9 +169,8 @@ export default Component.extend({
|
||||||
strobeOn: false,
|
strobeOn: false,
|
||||||
|
|
||||||
strobeOnInervalHandle: null,
|
strobeOnInervalHandle: null,
|
||||||
strobeSat: 0,
|
|
||||||
preStrobeOnLightsDataCache: null,
|
preStrobeOnLightsDataCache: null,
|
||||||
lastStrobeLight: 0,
|
nextLightIdx: 0,
|
||||||
|
|
||||||
onStrobeOnChange: observer('strobeOn', function () {
|
onStrobeOnChange: observer('strobeOn', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
|
|
@ -177,7 +178,7 @@ export default Component.extend({
|
||||||
|
|
||||||
if (strobeOn) {
|
if (strobeOn) {
|
||||||
this.set('preStrobeOnLightsDataCache', lightsData);
|
this.set('preStrobeOnLightsDataCache', lightsData);
|
||||||
let stobeInitRequestData = {'sat': this.get('strobeSat'), 'transitiontime': 0};
|
let stobeInitRequestData = { 'transitiontime': 0 };
|
||||||
|
|
||||||
for (let key in lightsData) {
|
for (let key in lightsData) {
|
||||||
if (lightsData.hasOwnProperty(key)) {
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
|
@ -195,7 +196,7 @@ export default Component.extend({
|
||||||
|
|
||||||
this.set('strobeOnInervalHandle', setInterval(this.strobeStep.bind(this), 500));
|
this.set('strobeOnInervalHandle', setInterval(this.strobeStep.bind(this), 500));
|
||||||
} else { // revert the light system to pre-strobe
|
} else { // revert the light system to pre-strobe
|
||||||
let preStrobeOnLightsDataCache = this.get('preStrobeOnLightsDataCache'), updateLight = (lightIndex)=> {
|
let preStrobeOnLightsDataCache = this.get('preStrobeOnLightsDataCache'), updateLight = (lightIndex) => {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + lightIndex + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + lightIndex + '/state', {
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
'on': preStrobeOnLightsDataCache[lightIndex].state.on,
|
'on': preStrobeOnLightsDataCache[lightIndex].state.on,
|
||||||
|
|
@ -220,45 +221,46 @@ export default Component.extend({
|
||||||
}),
|
}),
|
||||||
|
|
||||||
strobeStep() {
|
strobeStep() {
|
||||||
let lastStrobeLight = (this.get('lastStrobeLight') + 1) % (this.get('activeLights').length + 1),
|
let nextLightIdx = this.get('nextLightIdx') % this.get('activeLights').length,
|
||||||
turnOnOptions = {'on': true, 'transitiontime': 0, 'alert': 'select'};
|
nextStrobeLight = this.get('activeLights')[nextLightIdx],
|
||||||
|
turnOnOptions = { on: true, transitiontime: 0, alert: 'select' };
|
||||||
|
|
||||||
// random light if in cololoop mode
|
// random light if in cololoop mode
|
||||||
if(this.get('colorLoopOn')) {
|
if (this.get('colorLoopOn')) {
|
||||||
turnOnOptions.hue = Math.floor(Math.random() * 65535);
|
turnOnOptions.hue = Math.floor(Math.random() * 65535);
|
||||||
}
|
}
|
||||||
|
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + lastStrobeLight + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + nextStrobeLight + '/state', {
|
||||||
data: JSON.stringify(turnOnOptions),
|
data: JSON.stringify(turnOnOptions),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + lastStrobeLight + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + nextStrobeLight + '/state', {
|
||||||
data: JSON.stringify({'on': false, 'transitiontime': 0}),
|
data: JSON.stringify({ 'on': false, 'transitiontime': 0 }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('lastStrobeLight', lastStrobeLight);
|
this.set('nextLightIdx', ++nextLightIdx);
|
||||||
},
|
},
|
||||||
|
|
||||||
strobeOnTxt: computed('strobeOn', function () {
|
strobeOnTxt: computed('strobeOn', function () {
|
||||||
return this.get('strobeOn') ? 'On' : 'Off';
|
return this.get('strobeOn') ? 'On' : 'Off';
|
||||||
}),
|
}),
|
||||||
|
|
||||||
dimmerOnClass: computed('dimmerOn', function(){
|
dimmerOnClass: computed('dimmerOn', function () {
|
||||||
return this.get('dimmerOn') ? 'dimmerOn' : null;
|
return this.get('dimmerOn') ? 'dimmerOn' : null;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// **************** STROBE LIGHT FINISH ****************
|
// **************** STROBE LIGHT FINISH ****************
|
||||||
// http://www.developers.meethue.com/documentation/color-conversions-rgb-xy
|
// http://www.developers.meethue.com/documentation/color-conversions-rgb-xy
|
||||||
rgbToXy(red, green, blue){
|
rgbToXy(red, green, blue) {
|
||||||
let X, Y, Z, x, y;
|
let X, Y, Z, x, y;
|
||||||
|
|
||||||
// normalize
|
// normalize
|
||||||
red = Number((red/255));
|
red = Number((red / 255));
|
||||||
green = Number((green/255));
|
green = Number((green / 255));
|
||||||
blue = Number((blue/255));
|
blue = Number((blue / 255));
|
||||||
|
|
||||||
// gamma correction
|
// gamma correction
|
||||||
red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
|
red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
|
||||||
|
|
@ -273,10 +275,10 @@ export default Component.extend({
|
||||||
x = X / (X + Y + Z);
|
x = X / (X + Y + Z);
|
||||||
y = Y / (X + Y + Z);
|
y = Y / (X + Y + Z);
|
||||||
|
|
||||||
return [x,y];
|
return [x, y];
|
||||||
},
|
},
|
||||||
|
|
||||||
xyToRgb(x, y){
|
xyToRgb(x, y) {
|
||||||
let r, g, b, X, Y = 1.0, Z;
|
let r, g, b, X, Y = 1.0, Z;
|
||||||
|
|
||||||
X = (Y / y) * x;
|
X = (Y / y) * x;
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@
|
||||||
|
|
||||||
{{#paper-item}}
|
{{#paper-item}}
|
||||||
{{paper-icon "brightness-4" class=dimmerOnClass}}
|
{{paper-icon "brightness-4" class=dimmerOnClass}}
|
||||||
<p>Brightness</p>
|
<p class="layout flex-60">Brightness</p>
|
||||||
{{paper-slider flex=true min=1 max=254 value=lightsBrightness disabled=brightnessControlDisabled}}
|
{{paper-slider class="flex" discrete=true step="10" min="1" max="254" value=lightsBrightness disabled=brightnessControlDisabled}}
|
||||||
{{/paper-item}}
|
{{/paper-item}}
|
||||||
|
|
||||||
{{#paper-item class="color-row"}}
|
{{#paper-item class="color-row" }}
|
||||||
{{paper-icon "color-lens" class=dimmerOnClass}}
|
{{paper-icon "color-lens" class=dimmerOnClass}}
|
||||||
<p>Color</p>
|
<p>Color</p>
|
||||||
{{#paper-menu offset="0 -100" as |menu|}}
|
{{#paper-menu offset="0 -100" as |menu|}}
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,17 @@ const {
|
||||||
} = Ember;
|
} = 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');
|
||||||
|
|
||||||
if(playQueuePointer !== -1){
|
if (playQueuePointer !== -1) {
|
||||||
let song = playQueue[playQueuePointer];
|
let song = playQueue[playQueuePointer];
|
||||||
if(song.title){
|
if (song.title) {
|
||||||
title = song.title;
|
title = song.title;
|
||||||
|
|
||||||
if(song.artist){
|
if (song.artist) {
|
||||||
title += (' - ' + song.artist);
|
title += (' - ' + song.artist);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -35,14 +35,14 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
document.title = title;
|
document.title = title;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
changePlayerControl(name, value, saveBeatPrefs){
|
changePlayerControl(name, value, saveBeatPrefs) {
|
||||||
this.set(name, value);
|
this.set(name, value);
|
||||||
|
|
||||||
if(name === 'threshold'){
|
if (name === 'threshold') {
|
||||||
this.get('kick').set({threshold: value});
|
this.get('kick').set({ threshold: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
if(saveBeatPrefs && this.get('playQueuePointer') !== -1){
|
if (saveBeatPrefs && this.get('playQueuePointer') !== -1) {
|
||||||
this.saveSongBeatPreferences();
|
this.saveSongBeatPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,11 +51,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
|
|
||||||
saveSongBeatPreferences() {
|
saveSongBeatPreferences() {
|
||||||
let song = this.get('playQueue')[this.get('playQueuePointer')];
|
let song = this.get('playQueue')[this.get('playQueuePointer')];
|
||||||
if(song) {
|
if (song) {
|
||||||
let title = isEmpty(song.artist) ? song.fileName : song.artist + '-' + song.title,
|
let title = isEmpty(song.artist) ? song.fileName : song.artist + '-' + song.title,
|
||||||
songBeatPreferences = this.get('songBeatPreferences');
|
songBeatPreferences = this.get('songBeatPreferences');
|
||||||
|
|
||||||
songBeatPreferences[title] = {threshold: this.get('threshold')};
|
songBeatPreferences[title] = { threshold: this.get('threshold') };
|
||||||
|
|
||||||
this.set('usingBeatPreferences', true);
|
this.set('usingBeatPreferences', true);
|
||||||
this.get('storage').set('huegasm.songBeatPreferences', songBeatPreferences);
|
this.get('storage').set('huegasm.songBeatPreferences', songBeatPreferences);
|
||||||
|
|
@ -70,12 +70,12 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
@ -86,11 +86,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
clearCurrentAudio(resetPointer) {
|
clearCurrentAudio(resetPointer) {
|
||||||
let dancer = this.get('dancer');
|
let dancer = this.get('dancer');
|
||||||
|
|
||||||
if(dancer.audio.pause) {
|
if (dancer.audio.pause) {
|
||||||
dancer.pause();
|
dancer.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(resetPointer){
|
if (resetPointer) {
|
||||||
this.set('playQueuePointer', -1);
|
this.set('playQueuePointer', -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,19 +108,19 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
transitiontime = this.get('flashingTransitions'),
|
transitiontime = this.get('flashingTransitions'),
|
||||||
brightnessRange = this.get('brightnessRange'),
|
brightnessRange = this.get('brightnessRange'),
|
||||||
stimulateLight = (light, brightness, hue) => {
|
stimulateLight = (light, brightness, hue) => {
|
||||||
let options = {'bri': brightness};
|
let options = { 'bri': brightness };
|
||||||
|
|
||||||
if(transitiontime) {
|
if (transitiontime) {
|
||||||
options['transitiontime'] = 0;
|
options['transitiontime'] = 0;
|
||||||
} else {
|
} else {
|
||||||
options['transitiontime'] = 1;
|
options['transitiontime'] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isNone(hue)) {
|
if (!isNone(hue)) {
|
||||||
options.hue = hue;
|
options.hue = hue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lightsData[light].state.on === false){
|
if (lightsData[light].state.on === false) {
|
||||||
options.on = true;
|
options.on = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,7 +132,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
},
|
},
|
||||||
timeToBriOff = 100;
|
timeToBriOff = 100;
|
||||||
|
|
||||||
if(activeLights.length > 0){
|
if (activeLights.length > 0) {
|
||||||
let lastLightBopIndex = this.get('lastLightBopIndex'),
|
let lastLightBopIndex = this.get('lastLightBopIndex'),
|
||||||
lightBopIndex,
|
lightBopIndex,
|
||||||
light;
|
light;
|
||||||
|
|
@ -140,8 +140,8 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
lightBopIndex = Math.floor(Math.random() * activeLights.length);
|
lightBopIndex = 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) {
|
||||||
while(lightBopIndex === lastLightBopIndex) {
|
while (lightBopIndex === lastLightBopIndex) {
|
||||||
lightBopIndex = Math.floor(Math.random() * activeLights.length);
|
lightBopIndex = Math.floor(Math.random() * activeLights.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -149,13 +149,13 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
light = activeLights[lightBopIndex];
|
light = activeLights[lightBopIndex];
|
||||||
this.set('lastLightBopIndex', lightBopIndex);
|
this.set('lastLightBopIndex', lightBopIndex);
|
||||||
|
|
||||||
if(!this.get('colorloopMode')) {
|
if (!this.get('colorloopMode')) {
|
||||||
let hueRange = this.get('hueRange');
|
let hueRange = this.get('hueRange');
|
||||||
|
|
||||||
color = Math.floor(Math.random()*(hueRange[1] - hueRange[0] + 1)+hueRange[0]);
|
color = Math.floor(Math.random() * (hueRange[1] - hueRange[0] + 1) + hueRange[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(transitiontime){
|
if (transitiontime) {
|
||||||
timeToBriOff = 80;
|
timeToBriOff = 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,13 +164,15 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set('paused', true);
|
this.set('paused', true);
|
||||||
later(this, function(){{
|
later(this, function () {
|
||||||
this.set('paused', false);
|
{
|
||||||
}}, 150);
|
this.set('paused', false);
|
||||||
|
}
|
||||||
|
}, 150);
|
||||||
|
|
||||||
//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').velocity({ blur: 3 }, 100).velocity({ blur: 0 }, 100);
|
||||||
$('#beat-speaker-center-inner').velocity({scale: 1.05}, 100).velocity({scale: 1}, 100);
|
$('#beat-speaker-center-inner').velocity({ scale: 1.05 }, 100).velocity({ scale: 1 }, 100);
|
||||||
},
|
},
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
|
@ -198,11 +200,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
kick: kick
|
kick: kick
|
||||||
});
|
});
|
||||||
|
|
||||||
['shuffle', 'repeat', 'threshold', 'playerBottomDisplayed', 'audioMode', 'songBeatPreferences', 'firstVisit', 'currentVisName', 'playQueue', 'playQueuePointer', 'flashingTransitions', 'colorloopMode', 'hueRange', 'brightnessRange'].forEach((item)=>{
|
['shuffle', 'repeat', 'threshold', 'playerBottomDisplayed', 'audioMode', 'songBeatPreferences', 'firstVisit', 'currentVisName', 'playQueue', 'playQueuePointer', 'flashingTransitions', 'colorloopMode', 'hueRange', 'brightnessRange'].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);
|
||||||
|
|
||||||
if(isNone(this.actions[item+'Changed'])){
|
if (isNone(this.actions[item + 'Changed'])) {
|
||||||
this.set(item, itemVal);
|
this.set(item, itemVal);
|
||||||
} else {
|
} else {
|
||||||
this.send(item + 'Changed', itemVal);
|
this.send(item + 'Changed', itemVal);
|
||||||
|
|
@ -217,7 +219,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
this.set('oldPlayQueueLength', this.get('playQueue.length'));
|
this.set('oldPlayQueueLength', this.get('playQueue.length'));
|
||||||
|
|
||||||
document.addEventListener('stop', () => {
|
document.addEventListener('stop', () => {
|
||||||
if(this.get('playing')){
|
if (this.get('playing')) {
|
||||||
this.send('play');
|
this.send('play');
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
|
@ -234,29 +236,29 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// demo tracks
|
// demo tracks
|
||||||
if(this.get('firstVisit')){
|
if (this.get('firstVisit')) {
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/candyland-speechless-feat-rkcb');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/candyland-speechless-feat-rkcb');
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/dillistone/dillistone-lili-n-rude');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/dillistone/dillistone-lili-n-rude');
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/vallis-alps-young-feki-remix');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/vallis-alps-young-feki-remix');
|
||||||
|
|
@ -268,86 +270,87 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/90-pounds-of-pete-waited-too-long-feat-devon-baldwin');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/90-pounds-of-pete-waited-too-long-feat-devon-baldwin');
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/draper-eyes-open');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/draper-eyes-open');
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/itspapaya/sunny');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/itspapaya/sunny');
|
||||||
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/stonesthrow/nxworries-anderson-paak-knxwledge-suede');
|
||||||
|
|
||||||
this.get('storage').set('huegasm.firstVisit', false);
|
this.get('storage').set('huegasm.firstVisit', false);
|
||||||
|
|
||||||
this.sendAction();
|
this.sendAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.get('playerBottomDisplayed')) {
|
if (!this.get('playerBottomDisplayed')) {
|
||||||
$('#player-bottom').hide();
|
$('#player-bottom').hide();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
setVisName(name){
|
setVisName(name) {
|
||||||
this.set('currentVisName', name);
|
this.set('currentVisName', name);
|
||||||
},
|
},
|
||||||
gotoSCURL(URL){
|
gotoSCURL(URL) {
|
||||||
// need to pause the music since soundcloud is going to start playing this song anyways
|
// need to pause the music since soundcloud is going to start playing this song anyways
|
||||||
if(this.get('playing')){
|
if (this.get('playing')) {
|
||||||
this.send('play');
|
this.send('play');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.send('gotoURL', URL);
|
this.send('gotoURL', URL);
|
||||||
},
|
},
|
||||||
gotoURL(URL){
|
gotoURL(URL) {
|
||||||
window.open(URL, '_blank');
|
window.open(URL, '_blank');
|
||||||
},
|
},
|
||||||
handleNewSoundCloudURL(URL){
|
handleNewSoundCloudURL(URL) {
|
||||||
if(URL) {
|
if (URL) {
|
||||||
SC.resolve(URL).then((resultObj)=>{
|
SC.resolve(URL).then((resultObj) => {
|
||||||
let processResult = (result)=>{
|
let processResult = (result) => {
|
||||||
if(result.kind === 'user'){
|
if (result.kind === 'user') {
|
||||||
this.get('notify').alert({html: this.get('scUserNotSupportedHtml')});
|
this.get('notify').alert({ html: this.get('scUserNotSupportedHtml') });
|
||||||
} else if(result.kind === 'track') {
|
} else if (result.kind === 'track') {
|
||||||
if(result.streamable === true){
|
if (result.streamable === true) {
|
||||||
let picture = null;
|
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)
|
$.get(picture)
|
||||||
.done(()=>{
|
.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 });
|
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
|
}).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 });
|
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 {
|
} else {
|
||||||
failedSongs.push(result.title);
|
failedSongs.push(result.title);
|
||||||
}
|
|
||||||
} else if(result.kind === 'playlist'){
|
|
||||||
if(result.streamable === true){
|
|
||||||
result.tracks.forEach(processResult);
|
|
||||||
} else {
|
|
||||||
failedSongs.push(result.title);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
} else if (result.kind === 'playlist') {
|
||||||
|
if (result.streamable === true) {
|
||||||
|
result.tracks.forEach(processResult);
|
||||||
|
} else {
|
||||||
|
failedSongs.push(result.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
failedSongs = [];
|
failedSongs = [];
|
||||||
|
|
||||||
if(resultObj instanceof Array){
|
if (resultObj instanceof Array) {
|
||||||
resultObj.forEach(processResult);
|
resultObj.forEach(processResult);
|
||||||
} else {
|
} else {
|
||||||
processResult(resultObj);
|
processResult(resultObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(failedSongs.length > 0) {
|
if (failedSongs.length > 0) {
|
||||||
this.get('notify').alert({html: this.get('notStreamableHtml')(failedSongs)});
|
this.get('notify').alert({ html: this.get('notStreamableHtml')(failedSongs) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.get('playQueuePointer') === -1){
|
if (this.get('playQueuePointer') === -1) {
|
||||||
if(this.get('firstVisit')){
|
if (this.get('firstVisit')) {
|
||||||
this.send('goToSong', 0);
|
this.send('goToSong', 0);
|
||||||
} else {
|
} else {
|
||||||
this.send('next');
|
this.send('next');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, () => {
|
}, () => {
|
||||||
this.get('notify').alert({html: this.get('urlNotFoundHtml')(URL)});
|
this.get('notify').alert({ html: this.get('urlNotFoundHtml')(URL) });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -356,57 +359,57 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
toggleIsShowingAddSoundCloudModal() {
|
toggleIsShowingAddSoundCloudModal() {
|
||||||
this.toggleProperty('isShowingAddSoundCloudModal');
|
this.toggleProperty('isShowingAddSoundCloudModal');
|
||||||
},
|
},
|
||||||
slideTogglePlayerBottom(){
|
slideTogglePlayerBottom() {
|
||||||
let elem = this.$('#player-bottom');
|
let elem = this.$('#player-bottom');
|
||||||
|
|
||||||
elem.velocity(elem.is(':visible') ? 'slideUp' : 'slideDown', { duration: 300 });
|
elem.velocity(elem.is(':visible') ? 'slideUp' : 'slideDown', { duration: 300 });
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isNone(playQueue[index])) {
|
if (!isNone(playQueue[index])) {
|
||||||
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];
|
||||||
|
|
||||||
if(this.get('soundCloudFuckUps') >= this.get('maxSoundCloudFuckUps')) {
|
if (this.get('soundCloudFuckUps') >= this.get('maxSoundCloudFuckUps')) {
|
||||||
this.get('notify').alert({html: this.get('tooManySoundCloudFuckUps')});
|
this.get('notify').alert({ html: this.get('tooManySoundCloudFuckUps') });
|
||||||
this.send('play');
|
this.send('play');
|
||||||
this.set('soundCloudFuckUps', 0);
|
this.set('soundCloudFuckUps', 0);
|
||||||
} else {
|
} else {
|
||||||
if(song.local){
|
if (song.local) {
|
||||||
this.send('removeAudio', playQueuePointer);
|
this.send('removeAudio', playQueuePointer);
|
||||||
} else {
|
} else {
|
||||||
this.send('next', true);
|
this.send('next', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(event.target.error.code === 2){
|
if (event.target.error.code === 2) {
|
||||||
this.get('notify').alert({html: this.get('failedToDecodeFileHtml')(song.fileName)});
|
this.get('notify').alert({ html: this.get('failedToDecodeFileHtml')(song.fileName) });
|
||||||
} else {
|
} else {
|
||||||
this.get('notify').alert({html: this.get('failedToPlayFileHtml')(song.fileName)});
|
this.get('notify').alert({ html: this.get('failedToPlayFileHtml')(song.fileName) });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set('usingBeatPreferences', false);
|
this.set('usingBeatPreferences', false);
|
||||||
this.incrementProperty('soundCloudFuckUps');
|
this.incrementProperty('soundCloudFuckUps');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
audio.ontimeupdate = ()=>{
|
audio.ontimeupdate = () => {
|
||||||
this.set('timeElapsed', Math.floor(audio.currentTime));
|
this.set('timeElapsed', Math.floor(audio.currentTime));
|
||||||
};
|
};
|
||||||
audio.onended = ()=> {
|
audio.onended = () => {
|
||||||
this.send('next');
|
this.send('next');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -416,29 +419,29 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
|
|
||||||
this.loadSongBeatPreferences();
|
this.loadSongBeatPreferences();
|
||||||
|
|
||||||
if(playSong){
|
if (playSong) {
|
||||||
this.send('play');
|
this.send('play');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(scrollToSong){
|
if (scrollToSong) {
|
||||||
next(this, ()=>{
|
next(this, () => {
|
||||||
$('.track'+index).velocity('scroll', { container: $('#play-list-area'), duration: 200 });
|
$('.track' + index).velocity('scroll', { container: $('#play-list-area'), duration: 200 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeAudio(index){
|
removeAudio(index) {
|
||||||
this.get('playQueue').removeAt(index);
|
this.get('playQueue').removeAt(index);
|
||||||
|
|
||||||
if(index === this.get('playQueuePointer')) {
|
if (index === this.get('playQueuePointer')) {
|
||||||
this.send('goToSong', index, true, true);
|
this.send('goToSong', index, true, true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
playerAreaPlay(){
|
playerAreaPlay() {
|
||||||
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: 1, scale: 1}, 0).velocity({opacity: 0, scale: 3}, 500);
|
$('#play-notification').velocity({ opacity: 1, scale: 1 }, 0).velocity({ opacity: 0, scale: 3 }, 500);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
play(replayPause) {
|
play(replayPause) {
|
||||||
|
|
@ -447,22 +450,22 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
playing = this.get('playing'),
|
playing = this.get('playing'),
|
||||||
lightsData = this.get('lightsData');
|
lightsData = this.get('lightsData');
|
||||||
|
|
||||||
if(playQueuePointer !== -1 ) {
|
if (playQueuePointer !== -1) {
|
||||||
if (playing) {
|
if (playing) {
|
||||||
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'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let key in lightsData) {
|
for (let key in lightsData) {
|
||||||
if (lightsData.hasOwnProperty(key)) {
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
|
@ -470,14 +473,14 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!replayPause){
|
if (!replayPause) {
|
||||||
this.set('timeElapsed', Math.floor(dancer.getTime()));
|
this.set('timeElapsed', Math.floor(dancer.getTime()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let timeTotal = this.get('timeTotal');
|
let timeTotal = this.get('timeTotal');
|
||||||
|
|
||||||
// replay song
|
// replay song
|
||||||
if(this.get('timeElapsed') === timeTotal && timeTotal !== 0){
|
if (this.get('timeElapsed') === timeTotal && timeTotal !== 0) {
|
||||||
this.send('next', true);
|
this.send('next', true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -500,17 +503,17 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
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
|
||||||
if(shufflePlayed.length === playQueue.length){
|
if (shufflePlayed.length === playQueue.length) {
|
||||||
shufflePlayed.clear();
|
shufflePlayed.clear();
|
||||||
this.send('play', true);
|
this.send('play', true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -519,11 +522,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
// we're going to assume that the song URL is the id
|
// we're going to assume that the song URL is the id
|
||||||
do {
|
do {
|
||||||
nextSong = Math.floor(Math.random() * playQueue.length);
|
nextSong = Math.floor(Math.random() * playQueue.length);
|
||||||
} while(shufflePlayed.includes(playQueue[nextSong].url));
|
} while (shufflePlayed.includes(playQueue[nextSong].url));
|
||||||
|
|
||||||
shufflePlayed.pushObject(playQueue[nextSong].url);
|
shufflePlayed.pushObject(playQueue[nextSong].url);
|
||||||
} else if(nextSong > playQueue.length-1){
|
} else if (nextSong > playQueue.length - 1) {
|
||||||
if(repeat === 1 || repeatAll){
|
if (repeat === 1 || repeatAll) {
|
||||||
nextSong = nextSong % playQueue.length;
|
nextSong = nextSong % playQueue.length;
|
||||||
} else {
|
} else {
|
||||||
this.send('play', true);
|
this.send('play', true);
|
||||||
|
|
@ -534,26 +537,26 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
this.send('goToSong', nextSong, true, true);
|
this.send('goToSong', nextSong, true, true);
|
||||||
},
|
},
|
||||||
previous() {
|
previous() {
|
||||||
if(this.get('timeElapsed') > 5) {
|
if (this.get('timeElapsed') > 5) {
|
||||||
this.send('seekChanged', 0);
|
this.send('seekChanged', 0);
|
||||||
} else {
|
} else {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
@ -565,7 +568,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
} else {
|
} else {
|
||||||
nextSong--;
|
nextSong--;
|
||||||
|
|
||||||
if(nextSong < 0) {
|
if (nextSong < 0) {
|
||||||
nextSong = playQueue.length - 1;
|
nextSong = playQueue.length - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -576,7 +579,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
seekChanged(position) {
|
seekChanged(position) {
|
||||||
let dancer = this.get('dancer');
|
let dancer = this.get('dancer');
|
||||||
|
|
||||||
if(dancer.audio){
|
if (dancer.audio) {
|
||||||
dancer.audio.currentTime = Math.floor(this.get('timeTotal') * position / 100);
|
dancer.audio.currentTime = Math.floor(this.get('timeTotal') * position / 100);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -601,20 +604,20 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
hueRangeChanged(value) {
|
hueRangeChanged(value) {
|
||||||
this.changePlayerControl('hueRange', value);
|
this.changePlayerControl('hueRange', value);
|
||||||
},
|
},
|
||||||
playQueuePointerChanged(value){
|
playQueuePointerChanged(value) {
|
||||||
this.send('goToSong', value, false, true);
|
this.send('goToSong', value, false, true);
|
||||||
},
|
},
|
||||||
clickSpeaker(){
|
clickSpeaker() {
|
||||||
this.simulateKick(1);
|
this.simulateKick(1);
|
||||||
},
|
},
|
||||||
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]);
|
||||||
|
|
@ -634,7 +637,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
|
|
||||||
ID3.clearAll();
|
ID3.clearAll();
|
||||||
|
|
||||||
if(self.get('playQueuePointer') === -1){
|
if (self.get('playQueuePointer') === -1) {
|
||||||
self.send('next');
|
self.send('next');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -643,8 +646,8 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
if (files.hasOwnProperty(key)) {
|
if (files.hasOwnProperty(key)) {
|
||||||
let file = files[key];
|
let file = files[key];
|
||||||
|
|
||||||
if(file.type.startsWith('audio')) {
|
if (file.type.startsWith('audio')) {
|
||||||
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']
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,6 @@
|
||||||
.paper-icon {
|
.paper-icon {
|
||||||
line-height: 0.8 !important;
|
line-height: 0.8 !important;
|
||||||
}
|
}
|
||||||
md-slider {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#hue-controls {
|
#hue-controls {
|
||||||
|
|
|
||||||
|
|
@ -244,10 +244,10 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
.option-description {
|
.option-description {
|
||||||
font-size: 18px;
|
display: inline-flex;
|
||||||
white-space: nowrap;
|
font-size: 20px;
|
||||||
overflow: hidden;
|
justify-content: center;
|
||||||
text-overflow: ellipsis;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
|
@ -359,4 +359,7 @@
|
||||||
#sensitivity-settings .noUi-value-vertical {
|
#sensitivity-settings .noUi-value-vertical {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
.option-description {
|
||||||
|
height: 55px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -48,3 +48,7 @@ md-switch.md-default-theme.md-checked .md-thumb {
|
||||||
md-list-item {
|
md-list-item {
|
||||||
margin-bottom: 2vh;
|
margin-bottom: 2vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.md-thumb-text {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,8 @@ 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('init', observer('bridgeIp', function () {
|
||||||
if(!this.get('trial') && !this.get('isAuthenticating')) {
|
if (!this.get('trial') && !this.get('isAuthenticating')) {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
bridgePingIntervalHandle: setInterval(this.pingBridgeUser.bind(this), this.get('bridgeUsernamePingIntervalTime')),
|
bridgePingIntervalHandle: setInterval(this.pingBridgeUser.bind(this), this.get('bridgeUsernamePingIntervalTime')),
|
||||||
bridgeUserNamePingIntervalProgress: 0
|
bridgeUserNamePingIntervalProgress: 0
|
||||||
|
|
@ -41,8 +41,8 @@ export default Component.extend({
|
||||||
})),
|
})),
|
||||||
|
|
||||||
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');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -52,11 +52,11 @@ export default Component.extend({
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
if(this.get('bridgeIp') === null) {
|
if (this.get('bridgeIp') === null) {
|
||||||
$.ajax('https://www.meethue.com/api/nupnp', {
|
$.ajax('https://www.meethue.com/api/nupnp', {
|
||||||
timeout: 30000
|
timeout: 30000
|
||||||
})
|
})
|
||||||
.done((result, status)=> {
|
.done((result, status) => {
|
||||||
let bridgeFindStatus = 'fail';
|
let bridgeFindStatus = 'fail';
|
||||||
|
|
||||||
if (status === 'success' && result.length === 1) {
|
if (status === 'success' && result.length === 1) {
|
||||||
|
|
@ -77,9 +77,9 @@ export default Component.extend({
|
||||||
|
|
||||||
this.set('bridgeFindStatus', bridgeFindStatus);
|
this.set('bridgeFindStatus', bridgeFindStatus);
|
||||||
})
|
})
|
||||||
.fail(()=>{
|
.fail(() => {
|
||||||
this.set('bridgeFindStatus', 'fail');
|
this.set('bridgeFindStatus', 'fail');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -90,11 +90,11 @@ 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)=>{
|
}).done((result, status) => {
|
||||||
if(!this.isDestroyed){
|
if (!this.isDestroyed) {
|
||||||
this.set('bridgeAuthenticateReachedStatus', status);
|
this.set('bridgeAuthenticateReachedStatus', status);
|
||||||
|
|
||||||
if (status === 'success' && !result[0].error) {
|
if (status === 'success' && !result[0].error) {
|
||||||
|
|
@ -105,23 +105,24 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.incrementProperty('bridgeUserNamePingIntervalProgress', this.get('bridgeUsernamePingIntervalTime')/bridgeUsernamePingMaxTime*100);
|
this.incrementProperty('bridgeUserNamePingIntervalProgress', this.get('bridgeUsernamePingIntervalTime') / bridgeUsernamePingMaxTime * 100);
|
||||||
} else {
|
} else {
|
||||||
this.clearBridgePingIntervalHandle();
|
this.clearBridgePingIntervalHandle();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
clearBridgePingIntervalHandle(){
|
clearBridgePingIntervalHandle() {
|
||||||
clearInterval(this.get('bridgePingIntervalHandle'));
|
clearInterval(this.get('bridgePingIntervalHandle'));
|
||||||
this.set('bridgePingIntervalHandle', null);
|
this.set('bridgePingIntervalHandle', null);
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
retry(){
|
retry() {
|
||||||
this.onBridgeIpChange();
|
this.onBridgeIpChange();
|
||||||
},
|
},
|
||||||
chooseBridge(bridge){
|
chooseBridge(bridge) {
|
||||||
this.set('bridgeIp', bridge);
|
this.set('bridgeIp', bridge);
|
||||||
|
this.get('storage').set('huegasm.bridgeIp', bridge);
|
||||||
},
|
},
|
||||||
findBridgeByIp() {
|
findBridgeByIp() {
|
||||||
let manualBridgeIp = this.get('manualBridgeIp');
|
let manualBridgeIp = this.get('manualBridgeIp');
|
||||||
|
|
@ -134,12 +135,12 @@ 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(() => {
|
}).fail(() => {
|
||||||
this.set('manualBridgeIpNotFound', true);
|
this.set('manualBridgeIpNotFound', true);
|
||||||
later(this, function(){
|
later(this, function () {
|
||||||
this.set('manualBridgeIpNotFound', false);
|
this.set('manualBridgeIpNotFound', false);
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
<div class="title"><img src="assets/images/logo.png" alt="Huegasm"></div>
|
<div class="title"><img src="assets/images/logo.png" alt="Huegasm"></div>
|
||||||
{{#unless bridgeUsername}}
|
{{#unless bridgeUsername}}
|
||||||
{{#if bridgeIp}}
|
{{#if bridgeIp}}
|
||||||
<img src="assets/images/pressButtonBridge.png" id="press-bridge-button-img">
|
<img src="assets/images/pressButtonBridge.png" id="press-bridge-button-img"> {{paper-progress-linear warn=true value=bridgeUserNamePingIntervalProgress}}
|
||||||
{{paper-progress-linear warn=true value=bridgeUserNamePingIntervalProgress}}
|
|
||||||
|
|
||||||
{{#if isAuthenticating}}
|
{{#if isAuthenticating}}
|
||||||
<p>
|
<p>
|
||||||
Your bridge IP is <b>{{bridgeIp}}</b>
|
Your bridge IP is <b>{{bridgeIp}}</b>
|
||||||
<br>
|
<br> Press the button on your bridge to authenticate this application.
|
||||||
Press the button on your bridge to authenticate this application.
|
|
||||||
</p>
|
</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
<p>You failed to press the button in time. <a class="no-text-decoration" href="#" {{action 'retry'}}>RETRY</a></p>
|
<p>You failed to press the button in time. <a class="no-text-decoration" href="#" {{action 'retry'}}>RETRY</a></p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#unless bridgeFindStatus}}
|
{{#unless bridgeFindStatus}}
|
||||||
|
|
@ -20,8 +18,7 @@
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
|
|
||||||
{{#if bridgeFindMultiple}}
|
{{#if bridgeFindMultiple}}
|
||||||
<p>Found multiple hue bridges. <br>
|
<p>Huegasm found multiple hue bridges. <br> Please select the one you want to use for this application.</p>
|
||||||
Please select the one you want to use for this application.</p>
|
|
||||||
|
|
||||||
<div id="bridge-button-group">
|
<div id="bridge-button-group">
|
||||||
{{#each multipleBridgeIps as |bridge|}}
|
{{#each multipleBridgeIps as |bridge|}}
|
||||||
|
|
@ -30,9 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#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> ( or type <b>offline</b> to look around )
|
||||||
Enter one manually? <br><br>
|
|
||||||
( or type <b>offline</b> to look around )
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<span id="bridge-input">
|
<span id="bridge-input">
|
||||||
|
|
@ -41,7 +36,7 @@
|
||||||
<div>
|
<div>
|
||||||
{{paper-button onClick=(action "findBridgeByIp") raised=true primary=true label="Find"}}
|
{{paper-button onClick=(action "findBridgeByIp") raised=true primary=true label="Find"}}
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{{#if manualBridgeIpNotFound}}
|
{{#if manualBridgeIpNotFound}}
|
||||||
<p class="bg-danger">
|
<p class="bg-danger">
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ export default Component.extend({
|
||||||
ready: false,
|
ready: false,
|
||||||
elementId: 'huegasm',
|
elementId: 'huegasm',
|
||||||
|
|
||||||
init(){
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
let storage = this.get('storage');
|
let storage = this.get('storage');
|
||||||
|
|
@ -27,15 +27,15 @@ export default Component.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
toggleDimmer(){
|
toggleDimmer() {
|
||||||
this.sendAction('toggleDimmer');
|
this.sendAction('toggleDimmer');
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleLightsIcons(){
|
toggleLightsIcons() {
|
||||||
this.sendAction('toggleLightsIcons');
|
this.sendAction('toggleLightsIcons');
|
||||||
},
|
},
|
||||||
|
|
||||||
isReady(){
|
isReady() {
|
||||||
this.set('ready', true);
|
this.set('ready', true);
|
||||||
$('html, body').velocity('scroll');
|
$('html, body').velocity('scroll');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
{{#if bridgeUsername}}
|
{{#if bridgeUsername}}
|
||||||
{{hue-controls bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial dimmerOn=dimmerOn lightsIconsOn=lightsIconsOn storage=storage toggleDimmer="toggleDimmer" toggleLightsIcons="toggleLightsIcons"}}
|
{{hue-controls bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial dimmerOn=dimmerOn lightsIconsOn=lightsIconsOn
|
||||||
|
storage=storage toggleDimmer="toggleDimmer" toggleLightsIcons="toggleLightsIcons"}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if ready}}
|
{{#if ready}}
|
||||||
{{bridge-finder bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial storage=storage}}
|
{{bridge-finder bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial storage=storage}}
|
||||||
|
|
@ -13,7 +14,7 @@
|
||||||
Your lights meet your music.
|
Your lights meet your music.
|
||||||
</p>
|
</p>
|
||||||
<p id="intro-paragraph">
|
<p id="intro-paragraph">
|
||||||
Huegasm is a free web application for managing and synchronizing your <a target="_blank" href="http://www2.meethue.com">Philips Hue lights</a> with the beat of your music.
|
Huegasm is a free web application for managing and synchronizing your <a target="_blank" href="http://www2.meethue.com">Philips Hue lights</a> with the beat of your music.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="embed-container-wrapper">
|
<div class="embed-container-wrapper">
|
||||||
|
|
@ -21,7 +22,7 @@
|
||||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/zi9J6Qg-MPw" frameborder="0" allowfullscreen></iframe>
|
<iframe width="560" height="315" src="https://www.youtube.com/embed/zi9J6Qg-MPw" frameborder="0" allowfullscreen></iframe>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{paper-button raised=true primary=true onClick=(action "isReady") class="go-button center-block" label="Go!"}}
|
{{paper-button raised=true primary=true warn=true onClick=(action "isReady") class="go-button center-block" label="START"}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
@ -5,7 +5,7 @@ const {
|
||||||
observer,
|
observer,
|
||||||
computed,
|
computed,
|
||||||
on,
|
on,
|
||||||
run: { later },
|
run: { later, once },
|
||||||
$
|
$
|
||||||
} = Ember;
|
} = Ember;
|
||||||
|
|
||||||
|
|
@ -21,45 +21,45 @@ export default Component.extend({
|
||||||
// COLOR LOOP related stuff
|
// COLOR LOOP related stuff
|
||||||
colorLoopOn: false,
|
colorLoopOn: false,
|
||||||
|
|
||||||
lightsOnTxt: computed('lightsOn', function(){
|
lightsOnTxt: computed('lightsOn', function () {
|
||||||
return this.get('lightsOn') ? 'On' : 'Off';
|
return this.get('lightsOn') ? 'On' : 'Off';
|
||||||
}),
|
}),
|
||||||
|
|
||||||
colorloopOnTxt: computed('colorLoopOn', function(){
|
colorloopOnTxt: computed('colorLoopOn', function () {
|
||||||
return this.get('colorLoopOn') ? 'On' : 'Off';
|
return this.get('colorLoopOn') ? 'On' : 'Off';
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// determines the average brightness of the hue system for the brightness slider
|
// determines the average brightness of the hue system for the brightness slider
|
||||||
lightsBrightness: computed('lightsData', function(){
|
lightsBrightness: computed('lightsData', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
activeLights = this.get('activeLights'),
|
activeLights = this.get('activeLights'),
|
||||||
lightsBrightness = 0;
|
lightsBrightness = 0;
|
||||||
|
|
||||||
activeLights.forEach(function(light){
|
activeLights.forEach(function (light) {
|
||||||
lightsBrightness += lightsData[light].state.bri;
|
lightsBrightness += lightsData[light].state.bri;
|
||||||
});
|
});
|
||||||
|
|
||||||
return lightsBrightness/activeLights.length;
|
return lightsBrightness / activeLights.length;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
brightnessControlDisabled: computed.not('lightsOn'),
|
brightnessControlDisabled: computed.not('lightsOn'),
|
||||||
|
|
||||||
onColorLoopOnChange: observer('colorLoopOn', function(){
|
onColorLoopOnChange: observer('colorLoopOn', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
activeLights = this.get('activeLights'),
|
activeLights = this.get('activeLights'),
|
||||||
colorLoopsOn = this.get('colorLoopOn'),
|
colorLoopsOn = this.get('colorLoopOn'),
|
||||||
effect = colorLoopsOn ? 'colorloop' : 'none';
|
effect = colorLoopsOn ? 'colorloop' : 'none';
|
||||||
|
|
||||||
let colorLoopsOnSystem = activeLights.some(function(light) {
|
let colorLoopsOnSystem = activeLights.some(function (light) {
|
||||||
return lightsData[light].state.effect === 'colorloop';
|
return lightsData[light].state.effect === 'colorloop';
|
||||||
});
|
});
|
||||||
|
|
||||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||||
if(colorLoopsOn !== colorLoopsOnSystem){
|
if (colorLoopsOn !== colorLoopsOnSystem) {
|
||||||
activeLights.forEach((light)=>{
|
activeLights.forEach((light) => {
|
||||||
if(this.get('lightsData')[light].state.effect !== effect) {
|
if (this.get('lightsData')[light].state.effect !== effect) {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||||
data: JSON.stringify({'effect': effect }),
|
data: JSON.stringify({ 'effect': effect }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
|
|
@ -68,7 +68,7 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
rgbPreview: observer('rgb', function() {
|
rgbPreview: observer('rgb', function () {
|
||||||
let rgb = this.get('rgb'),
|
let rgb = this.get('rgb'),
|
||||||
xy = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
xy = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ export default Component.extend({
|
||||||
|
|
||||||
this.get('activeLights').forEach((light) => {
|
this.get('activeLights').forEach((light) => {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||||
data: JSON.stringify({"xy": xy}),
|
data: JSON.stringify({ "xy": xy }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
|
|
@ -87,9 +87,9 @@ export default Component.extend({
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// determines whether the lights are on/off for the lights switch
|
// determines whether the lights are on/off for the lights switch
|
||||||
lightsOnChange: on('init', observer('lightsData.@each.state.on', 'activeLights.[]', function(){
|
lightsOnChange: on('init', observer('lightsData.@each.state.on', 'activeLights.[]', function () {
|
||||||
if(!this.get('strobeOn')){
|
if (!this.get('strobeOn')) {
|
||||||
let lightsData = this.get('lightsData'), lightsOn = this.get('activeLights').some(function(light) {
|
let lightsData = this.get('lightsData'), lightsOn = this.get('activeLights').some(function (light) {
|
||||||
return lightsData[light].state.on === true;
|
return lightsData[light].state.on === true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -97,20 +97,20 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
})),
|
})),
|
||||||
|
|
||||||
onLightsOnChange: observer('lightsOn', function(){
|
onLightsOnChange: observer('lightsOn', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
activeLights = this.get('activeLights'),
|
activeLights = this.get('activeLights'),
|
||||||
lightsOn = this.get('lightsOn');
|
lightsOn = this.get('lightsOn');
|
||||||
|
|
||||||
let lightsOnSystem = activeLights.some(function(light) {
|
let lightsOnSystem = activeLights.some(function (light) {
|
||||||
return lightsData[light].state.on === true;
|
return lightsData[light].state.on === true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||||
if(lightsOn !== lightsOnSystem){
|
if (lightsOn !== lightsOnSystem) {
|
||||||
activeLights.forEach((light)=>{
|
activeLights.forEach((light) => {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||||
data: JSON.stringify({"on": lightsOn}),
|
data: JSON.stringify({ "on": lightsOn }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
|
|
@ -118,32 +118,34 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
||||||
onBrightnessChanged: observer('lightsBrightness', function(){
|
onBrightnessChanged: observer('lightsBrightness', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
once(this, function () {
|
||||||
lightsBrightnessSystem = false,
|
let lightsData = this.get('lightsData'),
|
||||||
lightsBrightness = this.get('lightsBrightness'),
|
lightsBrightnessSystem = false,
|
||||||
activeLights = this.get('activeLights');
|
lightsBrightness = this.get('lightsBrightness'),
|
||||||
|
activeLights = this.get('activeLights');
|
||||||
|
|
||||||
activeLights.forEach(function(light){
|
activeLights.forEach(function (light) {
|
||||||
lightsBrightnessSystem += lightsData[light].state.bri;
|
lightsBrightnessSystem += lightsData[light].state.bri;
|
||||||
});
|
|
||||||
|
|
||||||
lightsBrightnessSystem /= activeLights.length;
|
|
||||||
|
|
||||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
|
||||||
if(lightsBrightness !== lightsBrightnessSystem){
|
|
||||||
activeLights.forEach((light)=>{
|
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
|
||||||
data: JSON.stringify({"bri": lightsBrightness}),
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'PUT'
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
lightsBrightnessSystem /= activeLights.length;
|
||||||
|
|
||||||
|
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||||
|
if (lightsBrightness !== lightsBrightnessSystem) {
|
||||||
|
activeLights.forEach((light) => {
|
||||||
|
$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||||
|
data: JSON.stringify({ "bri": lightsBrightness }),
|
||||||
|
contentType: 'application/json',
|
||||||
|
type: 'PUT'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// sync the current light settings to the newly added light
|
// sync the current light settings to the newly added light
|
||||||
onaActiveLightsChange: observer('syncLight', function(){
|
onaActiveLightsChange: observer('syncLight', function () {
|
||||||
let options = {
|
let options = {
|
||||||
on: this.get('lightsOn'),
|
on: this.get('lightsOn'),
|
||||||
bri: this.get('lightsBrightness'),
|
bri: this.get('lightsBrightness'),
|
||||||
|
|
@ -151,7 +153,7 @@ export default Component.extend({
|
||||||
}, rgb = this.get('rgb'),
|
}, rgb = this.get('rgb'),
|
||||||
syncLight = this.get('syncLight');
|
syncLight = this.get('syncLight');
|
||||||
|
|
||||||
if(rgb[0] !== 255 && rgb[1] !== 255 && rgb[2] !== 255) {
|
if (rgb[0] !== 255 && rgb[1] !== 255 && rgb[2] !== 255) {
|
||||||
options['xy'] = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
options['xy'] = this.rgbToXy(rgb[0], rgb[1], rgb[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,9 +170,8 @@ export default Component.extend({
|
||||||
strobeOn: false,
|
strobeOn: false,
|
||||||
|
|
||||||
strobeOnInervalHandle: null,
|
strobeOnInervalHandle: null,
|
||||||
strobeSat: 0,
|
|
||||||
preStrobeOnLightsDataCache: null,
|
preStrobeOnLightsDataCache: null,
|
||||||
lastStrobeLight: 0,
|
nextLightIdx: 0,
|
||||||
|
|
||||||
onStrobeOnChange: observer('strobeOn', function () {
|
onStrobeOnChange: observer('strobeOn', function () {
|
||||||
let lightsData = this.get('lightsData'),
|
let lightsData = this.get('lightsData'),
|
||||||
|
|
@ -178,7 +179,7 @@ export default Component.extend({
|
||||||
|
|
||||||
if (strobeOn) {
|
if (strobeOn) {
|
||||||
this.set('preStrobeOnLightsDataCache', lightsData);
|
this.set('preStrobeOnLightsDataCache', lightsData);
|
||||||
let stobeInitRequestData = {'sat': this.get('strobeSat'), 'transitiontime': 0};
|
let stobeInitRequestData = { transitiontime: 0 };
|
||||||
|
|
||||||
for (let key in lightsData) {
|
for (let key in lightsData) {
|
||||||
if (lightsData.hasOwnProperty(key)) {
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
|
@ -196,11 +197,11 @@ export default Component.extend({
|
||||||
|
|
||||||
this.set('strobeOnInervalHandle', setInterval(this.strobeStep.bind(this), 500));
|
this.set('strobeOnInervalHandle', setInterval(this.strobeStep.bind(this), 500));
|
||||||
} else { // revert the light system to pre-strobe
|
} else { // revert the light system to pre-strobe
|
||||||
let preStrobeOnLightsDataCache = this.get('preStrobeOnLightsDataCache'), updateLight = (lightIndex)=> {
|
let preStrobeOnLightsDataCache = this.get('preStrobeOnLightsDataCache'), updateLight = (lightIndex) => {
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + lightIndex + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + lightIndex + '/state', {
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
'on': preStrobeOnLightsDataCache[lightIndex].state.on,
|
on: preStrobeOnLightsDataCache[lightIndex].state.on,
|
||||||
'sat': preStrobeOnLightsDataCache[lightIndex].state.sat
|
sat: preStrobeOnLightsDataCache[lightIndex].state.sat
|
||||||
}),
|
}),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
|
|
@ -221,51 +222,52 @@ export default Component.extend({
|
||||||
}),
|
}),
|
||||||
|
|
||||||
strobeStep() {
|
strobeStep() {
|
||||||
let lastStrobeLight = (this.get('lastStrobeLight') + 1) % (this.get('activeLights').length + 1),
|
let nextLightIdx = this.get('nextLightIdx') % this.get('activeLights').length,
|
||||||
turnOnOptions = {'on': true, 'transitiontime': 0, 'alert': 'select'};
|
nextStrobeLight = this.get('activeLights')[nextLightIdx],
|
||||||
|
turnOnOptions = { on: true, transitiontime: 0, alert: 'select' };
|
||||||
|
|
||||||
// random light if in cololoop mode
|
// random light if in cololoop mode
|
||||||
if(this.get('colorLoopOn')) {
|
if (this.get('colorLoopOn')) {
|
||||||
turnOnOptions.hue = Math.floor(Math.random() * 65535);
|
turnOnOptions.hue = Math.floor(Math.random() * 65535);
|
||||||
}
|
}
|
||||||
|
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + lastStrobeLight + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + nextStrobeLight + '/state', {
|
||||||
data: JSON.stringify(turnOnOptions),
|
data: JSON.stringify(turnOnOptions),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
$.ajax(this.get('apiURL') + '/lights/' + lastStrobeLight + '/state', {
|
$.ajax(this.get('apiURL') + '/lights/' + nextStrobeLight + '/state', {
|
||||||
data: JSON.stringify({'on': false, 'transitiontime': 0}),
|
data: JSON.stringify({ 'on': false, 'transitiontime': 0 }),
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('lastStrobeLight', lastStrobeLight);
|
this.set('nextLightIdx', ++nextLightIdx);
|
||||||
},
|
},
|
||||||
|
|
||||||
strobeOnTxt: computed('strobeOn', function () {
|
strobeOnTxt: computed('strobeOn', function () {
|
||||||
return this.get('strobeOn') ? 'On' : 'Off';
|
return this.get('strobeOn') ? 'On' : 'Off';
|
||||||
}),
|
}),
|
||||||
|
|
||||||
dimmerOnClass: computed('dimmerOn', function(){
|
dimmerOnClass: computed('dimmerOn', function () {
|
||||||
return this.get('dimmerOn') ? 'dimmerOn' : null;
|
return this.get('dimmerOn') ? 'dimmerOn' : null;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
toggleDimmer(){
|
toggleDimmer() {
|
||||||
this.sendAction('toggleDimmer');
|
this.sendAction('toggleDimmer');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// **************** STROBE LIGHT FINISH ****************
|
// **************** STROBE LIGHT FINISH ****************
|
||||||
// http://www.developers.meethue.com/documentation/color-conversions-rgb-xy
|
// http://www.developers.meethue.com/documentation/color-conversions-rgb-xy
|
||||||
rgbToXy(red, green, blue){
|
rgbToXy(red, green, blue) {
|
||||||
let X, Y, Z, x, y;
|
let X, Y, Z, x, y;
|
||||||
|
|
||||||
// normalize
|
// normalize
|
||||||
red = Number((red/255));
|
red = Number((red / 255));
|
||||||
green = Number((green/255));
|
green = Number((green / 255));
|
||||||
blue = Number((blue/255));
|
blue = Number((blue / 255));
|
||||||
|
|
||||||
// gamma correction
|
// gamma correction
|
||||||
red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
|
red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
|
||||||
|
|
@ -280,10 +282,10 @@ export default Component.extend({
|
||||||
x = X / (X + Y + Z);
|
x = X / (X + Y + Z);
|
||||||
y = Y / (X + Y + Z);
|
y = Y / (X + Y + Z);
|
||||||
|
|
||||||
return [x,y];
|
return [x, y];
|
||||||
},
|
},
|
||||||
|
|
||||||
xyToRgb(x, y){
|
xyToRgb(x, y) {
|
||||||
let r, g, b, X, Y = 1.0, Z;
|
let r, g, b, X, Y = 1.0, Z;
|
||||||
|
|
||||||
X = (Y / y) * x;
|
X = (Y / y) * x;
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@
|
||||||
|
|
||||||
{{#paper-item}}
|
{{#paper-item}}
|
||||||
{{paper-icon "brightness-4" class=dimmerOnClass}}
|
{{paper-icon "brightness-4" class=dimmerOnClass}}
|
||||||
<p data-toggle="tooltip" data-placement="top auto" class="bootstrap-tooltip lights-control-tooltip" data-title="The brightness level of the selected lights">Brightness</p>
|
<p data-toggle="tooltip" data-placement="top auto" class="layout flex-60 bootstrap-tooltip lights-control-tooltip" data-title="The brightness level of the selected lights">Brightness</p>
|
||||||
{{paper-slider flex=true min=1 max=254 value=lightsBrightness disabled=brightnessControlDisabled}}
|
{{paper-slider class="flex" discrete=true step="10" min="1" max="254" value=lightsBrightness disabled=brightnessControlDisabled}}
|
||||||
{{/paper-item}}
|
{{/paper-item}}
|
||||||
|
|
||||||
{{#paper-item elementId="color-row"}}
|
{{#paper-item elementId="color-row" }}
|
||||||
{{paper-icon "color-lens" class=dimmerOnClass}}
|
{{paper-icon "color-lens" class=dimmerOnClass}}
|
||||||
<p data-toggle="tooltip" data-placement="top auto" class="bootstrap-tooltip lights-control-tooltip" data-title="The color of the selected lights">Color</p>
|
<p data-toggle="tooltip" data-placement="top auto" class="bootstrap-tooltip lights-control-tooltip" data-title="The color of the selected lights">Color</p>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,17 @@ const {
|
||||||
} = Ember;
|
} = 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');
|
||||||
|
|
||||||
if(playQueuePointer !== -1){
|
if (playQueuePointer !== -1) {
|
||||||
let song = playQueue[playQueuePointer];
|
let song = playQueue[playQueuePointer];
|
||||||
if(song.title){
|
if (song.title) {
|
||||||
title = song.title;
|
title = song.title;
|
||||||
|
|
||||||
if(song.artist){
|
if (song.artist) {
|
||||||
title += (' - ' + song.artist);
|
title += (' - ' + song.artist);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -35,14 +35,14 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
document.title = title;
|
document.title = title;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
changePlayerControl(name, value, saveBeatPrefs){
|
changePlayerControl(name, value, saveBeatPrefs) {
|
||||||
this.set(name, value);
|
this.set(name, value);
|
||||||
|
|
||||||
if(name === 'threshold'){
|
if (name === 'threshold') {
|
||||||
this.get('kick').set({threshold: value});
|
this.get('kick').set({ threshold: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
if(saveBeatPrefs && this.get('playQueuePointer') !== -1){
|
if (saveBeatPrefs && this.get('playQueuePointer') !== -1) {
|
||||||
this.saveSongBeatPreferences();
|
this.saveSongBeatPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,11 +51,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
|
|
||||||
saveSongBeatPreferences() {
|
saveSongBeatPreferences() {
|
||||||
let song = this.get('playQueue')[this.get('playQueuePointer')];
|
let song = this.get('playQueue')[this.get('playQueuePointer')];
|
||||||
if(song) {
|
if (song) {
|
||||||
let title = isEmpty(song.artist) ? song.fileName : song.artist + '-' + song.title,
|
let title = isEmpty(song.artist) ? song.fileName : song.artist + '-' + song.title,
|
||||||
songBeatPreferences = this.get('songBeatPreferences');
|
songBeatPreferences = this.get('songBeatPreferences');
|
||||||
|
|
||||||
songBeatPreferences[title] = {threshold: this.get('threshold')};
|
songBeatPreferences[title] = { threshold: this.get('threshold') };
|
||||||
|
|
||||||
this.set('usingBeatPreferences', true);
|
this.set('usingBeatPreferences', true);
|
||||||
this.get('storage').set('huegasm.songBeatPreferences', songBeatPreferences);
|
this.get('storage').set('huegasm.songBeatPreferences', songBeatPreferences);
|
||||||
|
|
@ -70,12 +70,12 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
@ -86,11 +86,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
clearCurrentAudio(resetPointer) {
|
clearCurrentAudio(resetPointer) {
|
||||||
let dancer = this.get('dancer');
|
let dancer = this.get('dancer');
|
||||||
|
|
||||||
if(dancer.audio.pause) {
|
if (dancer.audio.pause) {
|
||||||
dancer.pause();
|
dancer.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(resetPointer){
|
if (resetPointer) {
|
||||||
this.set('playQueuePointer', -1);
|
this.set('playQueuePointer', -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,9 +110,9 @@ 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(/*mag, ratioKickMag*/) {
|
simulateKick(/*mag, ratioKickMag*/) {
|
||||||
|
|
@ -122,19 +122,19 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
|
|
||||||
transitiontime = this.get('flashingTransitions'),
|
transitiontime = this.get('flashingTransitions'),
|
||||||
stimulateLight = (light, brightness, hue) => {
|
stimulateLight = (light, brightness, hue) => {
|
||||||
let options = {'bri': brightness};
|
let options = { 'bri': brightness };
|
||||||
|
|
||||||
if(transitiontime) {
|
if (transitiontime) {
|
||||||
options['transitiontime'] = 0;
|
options['transitiontime'] = 0;
|
||||||
} else {
|
} else {
|
||||||
options['transitiontime'] = 1;
|
options['transitiontime'] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isNone(hue)) {
|
if (!isNone(hue)) {
|
||||||
options.hue = hue;
|
options.hue = hue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lightsData[light].state.on === false){
|
if (lightsData[light].state.on === false) {
|
||||||
options.on = true;
|
options.on = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,7 +146,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
},
|
},
|
||||||
timeToBriOff = 100;
|
timeToBriOff = 100;
|
||||||
|
|
||||||
if(activeLights.length > 0){
|
if (activeLights.length > 0) {
|
||||||
let lastLightBopIndex = this.get('lastLightBopIndex'),
|
let lastLightBopIndex = this.get('lastLightBopIndex'),
|
||||||
lightBopIndex,
|
lightBopIndex,
|
||||||
brightnessRange = this.get('brightnessRange'),
|
brightnessRange = this.get('brightnessRange'),
|
||||||
|
|
@ -155,8 +155,8 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
lightBopIndex = Math.floor(Math.random() * activeLights.length);
|
lightBopIndex = 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) {
|
||||||
while(lightBopIndex === lastLightBopIndex) {
|
while (lightBopIndex === lastLightBopIndex) {
|
||||||
lightBopIndex = Math.floor(Math.random() * activeLights.length);
|
lightBopIndex = Math.floor(Math.random() * activeLights.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -164,13 +164,13 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
light = activeLights[lightBopIndex];
|
light = activeLights[lightBopIndex];
|
||||||
this.set('lastLightBopIndex', lightBopIndex);
|
this.set('lastLightBopIndex', lightBopIndex);
|
||||||
|
|
||||||
if(!this.get('colorloopMode')) {
|
if (!this.get('colorloopMode')) {
|
||||||
let hueRange = this.get('hueRange');
|
let hueRange = this.get('hueRange');
|
||||||
|
|
||||||
color = Math.floor(Math.random()*(hueRange[1] - hueRange[0] + 1)+hueRange[0]);
|
color = Math.floor(Math.random() * (hueRange[1] - hueRange[0] + 1) + hueRange[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(transitiontime){
|
if (transitiontime) {
|
||||||
timeToBriOff = 80;
|
timeToBriOff = 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,13 +179,13 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set('paused', true);
|
this.set('paused', true);
|
||||||
later(this, function(){
|
later(this, function () {
|
||||||
this.set('paused', false);
|
this.set('paused', false);
|
||||||
}, 150);
|
}, 150);
|
||||||
|
|
||||||
//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').velocity({ blur: 3 }, 100).velocity({ blur: 0 }, 100);
|
||||||
$('#beat-speaker-center-inner').velocity({scale: 1.05}, 100).velocity({scale: 1}, 100);
|
$('#beat-speaker-center-inner').velocity({ scale: 1.05 }, 100).velocity({ scale: 1 }, 100);
|
||||||
},
|
},
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
|
@ -213,11 +213,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
kick: kick
|
kick: kick
|
||||||
});
|
});
|
||||||
|
|
||||||
['volume', 'shuffle', 'repeat', 'volumeMuted', 'threshold', 'playerBottomDisplayed', 'songBeatPreferences', 'firstVisit', 'currentVisName', 'playQueue', 'playQueuePointer', 'flashingTransitions', 'colorloopMode', 'hueRange', 'brightnessRange'].forEach((item)=>{
|
['volume', 'shuffle', 'repeat', 'volumeMuted', 'threshold', 'playerBottomDisplayed', 'songBeatPreferences', 'firstVisit', 'currentVisName', 'playQueue', 'playQueuePointer', 'flashingTransitions', 'colorloopMode', 'hueRange', 'brightnessRange'].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);
|
||||||
|
|
||||||
if(isNone(this.actions[item+'Changed'])){
|
if (isNone(this.actions[item + 'Changed'])) {
|
||||||
this.set(item, itemVal);
|
this.set(item, itemVal);
|
||||||
} else {
|
} else {
|
||||||
this.send(item + 'Changed', itemVal);
|
this.send(item + 'Changed', itemVal);
|
||||||
|
|
@ -238,37 +238,37 @@ 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;
|
||||||
|
|
||||||
if(event.deltaY < 0) {
|
if (event.deltaY < 0) {
|
||||||
scrollSize *= -1;
|
scrollSize *= -1;
|
||||||
}
|
}
|
||||||
let newVolume = this.get('volume') + scrollSize;
|
let newVolume = this.get('volume') + scrollSize;
|
||||||
|
|
@ -278,8 +278,8 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// demo tracks
|
// demo tracks
|
||||||
if(this.get('firstVisit')){
|
if (this.get('firstVisit')) {
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/candyland-speechless-feat-rkcb');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/candyland-speechless-feat-rkcb');
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/dillistone/dillistone-lili-n-rude');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/dillistone/dillistone-lili-n-rude');
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/vallis-alps-young-feki-remix');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/vallis-alps-young-feki-remix');
|
||||||
|
|
@ -291,93 +291,94 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/90-pounds-of-pete-waited-too-long-feat-devon-baldwin');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/90-pounds-of-pete-waited-too-long-feat-devon-baldwin');
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/draper-eyes-open');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/mrsuicidesheep/draper-eyes-open');
|
||||||
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/itspapaya/sunny');
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/itspapaya/sunny');
|
||||||
|
this.send('handleNewSoundCloudURL', 'https://soundcloud.com/stonesthrow/nxworries-anderson-paak-knxwledge-suede');
|
||||||
|
|
||||||
this.get('storage').set('huegasm.firstVisit', false);
|
this.get('storage').set('huegasm.firstVisit', false);
|
||||||
|
|
||||||
this.sendAction();
|
this.sendAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this.get('playerBottomDisplayed')) {
|
if (!this.get('playerBottomDisplayed')) {
|
||||||
$('#player-bottom').hide();
|
$('#player-bottom').hide();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
clearPlaylist(){
|
clearPlaylist() {
|
||||||
this.get('playQueue').clear();
|
this.get('playQueue').clear();
|
||||||
},
|
},
|
||||||
setVisName(name){
|
setVisName(name) {
|
||||||
this.set('currentVisName', name);
|
this.set('currentVisName', name);
|
||||||
},
|
},
|
||||||
hideTooltip(){
|
hideTooltip() {
|
||||||
$('.bootstrap-tooltip').tooltip('hide');
|
$('.bootstrap-tooltip').tooltip('hide');
|
||||||
},
|
},
|
||||||
gotoSCURL(URL){
|
gotoSCURL(URL) {
|
||||||
// need to pause the music since soundcloud is going to start playing this song anyways
|
// need to pause the music since soundcloud is going to start playing this song anyways
|
||||||
if(this.get('playing')){
|
if (this.get('playing')) {
|
||||||
this.send('play');
|
this.send('play');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.send('gotoURL', URL);
|
this.send('gotoURL', URL);
|
||||||
},
|
},
|
||||||
gotoURL(URL){
|
gotoURL(URL) {
|
||||||
$('.tooltip').remove();
|
$('.tooltip').remove();
|
||||||
window.open(URL, '_blank');
|
window.open(URL, '_blank');
|
||||||
},
|
},
|
||||||
handleNewSoundCloudURL(URL){
|
handleNewSoundCloudURL(URL) {
|
||||||
if(URL) {
|
if (URL) {
|
||||||
SC.resolve(URL).then((resultObj)=>{
|
SC.resolve(URL).then((resultObj) => {
|
||||||
let processResult = (result)=>{
|
let processResult = (result) => {
|
||||||
if(result.kind === 'user'){
|
if (result.kind === 'user') {
|
||||||
this.get('notify').alert({html: this.get('scUserNotSupportedHtml')});
|
this.get('notify').alert({ html: this.get('scUserNotSupportedHtml') });
|
||||||
} else if(result.kind === 'track') {
|
} else if (result.kind === 'track') {
|
||||||
if(result.streamable === true){
|
if (result.streamable === true) {
|
||||||
let picture = null;
|
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)
|
$.get(picture)
|
||||||
.done(()=>{
|
.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 });
|
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
|
}).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 });
|
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 {
|
} else {
|
||||||
failedSongs.push(result.title);
|
failedSongs.push(result.title);
|
||||||
}
|
|
||||||
} else if(result.kind === 'playlist'){
|
|
||||||
if(result.streamable === true){
|
|
||||||
result.tracks.forEach(processResult);
|
|
||||||
} else {
|
|
||||||
failedSongs.push(result.title);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
} else if (result.kind === 'playlist') {
|
||||||
|
if (result.streamable === true) {
|
||||||
|
result.tracks.forEach(processResult);
|
||||||
|
} else {
|
||||||
|
failedSongs.push(result.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
failedSongs = [];
|
failedSongs = [];
|
||||||
|
|
||||||
if(resultObj instanceof Array){
|
if (resultObj instanceof Array) {
|
||||||
resultObj.forEach(processResult);
|
resultObj.forEach(processResult);
|
||||||
} else {
|
} else {
|
||||||
processResult(resultObj);
|
processResult(resultObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(failedSongs.length > 0) {
|
if (failedSongs.length > 0) {
|
||||||
this.get('notify').alert({html: this.get('notStreamableHtml')(failedSongs)});
|
this.get('notify').alert({ html: this.get('notStreamableHtml')(failedSongs) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.get('playQueuePointer') === -1){
|
if (this.get('playQueuePointer') === -1) {
|
||||||
if(this.get('firstVisit')){
|
if (this.get('firstVisit')) {
|
||||||
this.send('goToSong', 0);
|
this.send('goToSong', 0);
|
||||||
} else {
|
} else {
|
||||||
this.send('next');
|
this.send('next');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, () => {
|
}, () => {
|
||||||
this.get('notify').alert({html: this.get('urlNotFoundHtml')(URL)});
|
this.get('notify').alert({ html: this.get('urlNotFoundHtml')(URL) });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,57 +387,57 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
toggleIsShowingAddSoundCloudModal() {
|
toggleIsShowingAddSoundCloudModal() {
|
||||||
this.toggleProperty('isShowingAddSoundCloudModal');
|
this.toggleProperty('isShowingAddSoundCloudModal');
|
||||||
},
|
},
|
||||||
slideTogglePlayerBottom(){
|
slideTogglePlayerBottom() {
|
||||||
let elem = this.$('#player-bottom');
|
let elem = this.$('#player-bottom');
|
||||||
|
|
||||||
elem.velocity(elem.is(':visible') ? 'slideUp' : 'slideDown', { duration: 300 });
|
elem.velocity(elem.is(':visible') ? 'slideUp' : 'slideDown', { duration: 300 });
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isNone(playQueue[index])) {
|
if (!isNone(playQueue[index])) {
|
||||||
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];
|
||||||
|
|
||||||
if(this.get('soundCloudFuckUps') >= this.get('maxSoundCloudFuckUps')) {
|
if (this.get('soundCloudFuckUps') >= this.get('maxSoundCloudFuckUps')) {
|
||||||
this.get('notify').alert({html: this.get('tooManySoundCloudFuckUps')});
|
this.get('notify').alert({ html: this.get('tooManySoundCloudFuckUps') });
|
||||||
this.send('play');
|
this.send('play');
|
||||||
this.set('soundCloudFuckUps', 0);
|
this.set('soundCloudFuckUps', 0);
|
||||||
} else {
|
} else {
|
||||||
if(song.local){
|
if (song.local) {
|
||||||
this.send('removeAudio', playQueuePointer);
|
this.send('removeAudio', playQueuePointer);
|
||||||
} else {
|
} else {
|
||||||
this.send('next', true);
|
this.send('next', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(event.target.error.code === 2){
|
if (event.target.error.code === 2) {
|
||||||
this.get('notify').alert({html: this.get('failedToDecodeFileHtml')(song.fileName)});
|
this.get('notify').alert({ html: this.get('failedToDecodeFileHtml')(song.fileName) });
|
||||||
} else {
|
} else {
|
||||||
this.get('notify').alert({html: this.get('failedToPlayFileHtml')(song.fileName)});
|
this.get('notify').alert({ html: this.get('failedToPlayFileHtml')(song.fileName) });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set('usingBeatPreferences', false);
|
this.set('usingBeatPreferences', false);
|
||||||
this.incrementProperty('soundCloudFuckUps');
|
this.incrementProperty('soundCloudFuckUps');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
audio.ontimeupdate = ()=>{
|
audio.ontimeupdate = () => {
|
||||||
this.set('timeElapsed', Math.floor(audio.currentTime));
|
this.set('timeElapsed', Math.floor(audio.currentTime));
|
||||||
};
|
};
|
||||||
audio.onended = ()=> {
|
audio.onended = () => {
|
||||||
this.send('next');
|
this.send('next');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -446,33 +447,33 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
|
|
||||||
this.loadSongBeatPreferences();
|
this.loadSongBeatPreferences();
|
||||||
|
|
||||||
if(playSong){
|
if (playSong) {
|
||||||
this.send('play');
|
this.send('play');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(scrollToSong){
|
if (scrollToSong) {
|
||||||
// this is just a bad workaround to make sure that the track has been rendered to the playlist
|
// this is just a bad workaround to make sure that the track has been rendered to the playlist
|
||||||
next(this, ()=>{
|
next(this, () => {
|
||||||
$('.track'+index).velocity('scroll', { container: $('#play-list-area'), duration: 200 });
|
$('.track' + index).velocity('scroll', { container: $('#play-list-area'), duration: 200 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeAudio(index){
|
removeAudio(index) {
|
||||||
this.get('playQueue').removeAt(index);
|
this.get('playQueue').removeAt(index);
|
||||||
|
|
||||||
// need to manually remove the tooltip
|
// need to manually remove the tooltip
|
||||||
$('body .tooltip').remove();
|
$('body .tooltip').remove();
|
||||||
|
|
||||||
if(index === this.get('playQueuePointer')) {
|
if (index === this.get('playQueuePointer')) {
|
||||||
this.send('goToSong', index, true, true);
|
this.send('goToSong', index, true, true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
playerAreaPlay(){
|
playerAreaPlay() {
|
||||||
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) {
|
||||||
|
|
@ -481,22 +482,22 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
playing = this.get('playing'),
|
playing = this.get('playing'),
|
||||||
lightsData = this.get('lightsData');
|
lightsData = this.get('lightsData');
|
||||||
|
|
||||||
if(playQueuePointer !== -1 ) {
|
if (playQueuePointer !== -1) {
|
||||||
if (playing) {
|
if (playing) {
|
||||||
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'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let key in lightsData) {
|
for (let key in lightsData) {
|
||||||
if (lightsData.hasOwnProperty(key)) {
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
|
@ -504,20 +505,20 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!replayPause){
|
if (!replayPause) {
|
||||||
this.set('timeElapsed', Math.floor(dancer.getTime()));
|
this.set('timeElapsed', Math.floor(dancer.getTime()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let timeTotal = this.get('timeTotal');
|
let timeTotal = this.get('timeTotal');
|
||||||
|
|
||||||
if(this.get('volumeMuted')) {
|
if (this.get('volumeMuted')) {
|
||||||
dancer.setVolume(0);
|
dancer.setVolume(0);
|
||||||
} else {
|
} else {
|
||||||
dancer.setVolume(this.get('volume')/100);
|
dancer.setVolume(this.get('volume') / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
// replay song
|
// replay song
|
||||||
if(this.get('timeElapsed') === timeTotal && timeTotal !== 0){
|
if (this.get('timeElapsed') === timeTotal && timeTotal !== 0) {
|
||||||
this.send('next', true);
|
this.send('next', true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -535,11 +536,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
},
|
},
|
||||||
volumeChanged(value) {
|
volumeChanged(value) {
|
||||||
this.changePlayerControl('volume', value);
|
this.changePlayerControl('volume', value);
|
||||||
if(this.get('playing')) {
|
if (this.get('playing')) {
|
||||||
this.get('dancer').setVolume(value/100);
|
this.get('dancer').setVolume(value / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.get('volume') > 0 && this.get('volumeMuted')){
|
if (this.get('volume') > 0 && this.get('volumeMuted')) {
|
||||||
this.changePlayerControl('volumeMuted', false);
|
this.changePlayerControl('volumeMuted', false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -550,17 +551,17 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
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
|
||||||
if(shufflePlayed.length === playQueue.length){
|
if (shufflePlayed.length === playQueue.length) {
|
||||||
shufflePlayed.clear();
|
shufflePlayed.clear();
|
||||||
this.send('play', true);
|
this.send('play', true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -569,11 +570,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
// we're going to assume that the song URL is the id
|
// we're going to assume that the song URL is the id
|
||||||
do {
|
do {
|
||||||
nextSong = Math.floor(Math.random() * playQueue.length);
|
nextSong = Math.floor(Math.random() * playQueue.length);
|
||||||
} while(shufflePlayed.includes(playQueue[nextSong].url));
|
} while (shufflePlayed.includes(playQueue[nextSong].url));
|
||||||
|
|
||||||
shufflePlayed.pushObject(playQueue[nextSong].url);
|
shufflePlayed.pushObject(playQueue[nextSong].url);
|
||||||
} else if(nextSong > playQueue.length-1){
|
} else if (nextSong > playQueue.length - 1) {
|
||||||
if(repeat === 1 || repeatAll){
|
if (repeat === 1 || repeatAll) {
|
||||||
nextSong = nextSong % playQueue.length;
|
nextSong = nextSong % playQueue.length;
|
||||||
} else {
|
} else {
|
||||||
this.send('play', true);
|
this.send('play', true);
|
||||||
|
|
@ -584,26 +585,26 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
this.send('goToSong', nextSong, true, true);
|
this.send('goToSong', nextSong, true, true);
|
||||||
},
|
},
|
||||||
previous() {
|
previous() {
|
||||||
if(this.get('timeElapsed') > 5) {
|
if (this.get('timeElapsed') > 5) {
|
||||||
this.send('seekChanged', 0);
|
this.send('seekChanged', 0);
|
||||||
} else {
|
} else {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
@ -615,7 +616,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
} else {
|
} else {
|
||||||
nextSong--;
|
nextSong--;
|
||||||
|
|
||||||
if(nextSong < 0) {
|
if (nextSong < 0) {
|
||||||
nextSong = playQueue.length - 1;
|
nextSong = playQueue.length - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -626,7 +627,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
seekChanged(position) {
|
seekChanged(position) {
|
||||||
let dancer = this.get('dancer');
|
let dancer = this.get('dancer');
|
||||||
|
|
||||||
if(dancer.audio){
|
if (dancer.audio) {
|
||||||
dancer.audio.currentTime = Math.floor(this.get('timeTotal') * position / 100);
|
dancer.audio.currentTime = Math.floor(this.get('timeTotal') * position / 100);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -636,11 +637,11 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
|
|
||||||
this.changePlayerControl('volumeMuted', volumeMuted);
|
this.changePlayerControl('volumeMuted', volumeMuted);
|
||||||
|
|
||||||
if(this.get('playing')){
|
if (this.get('playing')) {
|
||||||
if(volumeMuted){
|
if (volumeMuted) {
|
||||||
dancer.setVolume(0);
|
dancer.setVolume(0);
|
||||||
} else {
|
} else {
|
||||||
dancer.setVolume(this.get('volume')/100);
|
dancer.setVolume(this.get('volume') / 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -665,33 +666,33 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
hueRangeChanged(value) {
|
hueRangeChanged(value) {
|
||||||
this.changePlayerControl('hueRange', value);
|
this.changePlayerControl('hueRange', value);
|
||||||
},
|
},
|
||||||
playQueuePointerChanged(value){
|
playQueuePointerChanged(value) {
|
||||||
this.send('goToSong', value, false, true);
|
this.send('goToSong', value, false, true);
|
||||||
},
|
},
|
||||||
clickSpeaker(){
|
clickSpeaker() {
|
||||||
this.simulateKick(1);
|
this.simulateKick(1);
|
||||||
},
|
},
|
||||||
dropFiles(files){
|
dropFiles(files) {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
dragging: false,
|
dragging: false,
|
||||||
draggingOverPlayListArea: false
|
draggingOverPlayListArea: false
|
||||||
});
|
});
|
||||||
this.send('handleNewFiles', files);
|
this.send('handleNewFiles', files);
|
||||||
},
|
},
|
||||||
playerListAreaDragOver(){
|
playerListAreaDragOver() {
|
||||||
this.set('draggingOverPlayListArea', true);
|
this.set('draggingOverPlayListArea', true);
|
||||||
},
|
},
|
||||||
playerListAreaDragLeave(){
|
playerListAreaDragLeave() {
|
||||||
this.set('draggingOverPlayListArea', false);
|
this.set('draggingOverPlayListArea', false);
|
||||||
},
|
},
|
||||||
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]);
|
||||||
|
|
@ -711,7 +712,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
|
|
||||||
ID3.clearAll();
|
ID3.clearAll();
|
||||||
|
|
||||||
if(self.get('playQueuePointer') === -1){
|
if (self.get('playQueuePointer') === -1) {
|
||||||
self.send('next');
|
self.send('next');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -720,8 +721,8 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
if (files.hasOwnProperty(key)) {
|
if (files.hasOwnProperty(key)) {
|
||||||
let file = files[key];
|
let file = files[key];
|
||||||
|
|
||||||
if(file.type.startsWith('audio')) {
|
if (file.type.startsWith('audio')) {
|
||||||
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']
|
||||||
});
|
});
|
||||||
|
|
@ -729,7 +730,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleDimmer(){
|
toggleDimmer() {
|
||||||
this.sendAction('toggleDimmer');
|
this.sendAction('toggleDimmer');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,4 @@
|
||||||
width: 100px;
|
width: 100px;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
&:hover {
|
|
||||||
background: darken(#3f51b5, 10%) !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,6 @@
|
||||||
.paper-icon {
|
.paper-icon {
|
||||||
line-height: 0.8 !important;
|
line-height: 0.8 !important;
|
||||||
}
|
}
|
||||||
md-slider {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.lights-control-tooltip + .tooltip {
|
.lights-control-tooltip + .tooltip {
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,10 @@ md-slider {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.md-thumb-text {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
md-slider.md-default-theme .md-thumb:after {
|
md-slider.md-default-theme .md-thumb:after {
|
||||||
border-color: $secondaryThemeColor;
|
border-color: $secondaryThemeColor;
|
||||||
background-color: $secondaryThemeColor;
|
background-color: $secondaryThemeColor;
|
||||||
|
|
|
||||||
Reference in a new issue