finishing up soundcloud integration, different filtering for threshold

This commit is contained in:
Egor 2015-10-12 22:57:46 -07:00
parent d829b769b3
commit 0deb6b2345
7 changed files with 247 additions and 136 deletions

View file

@ -2,11 +2,31 @@ import Em from 'ember';
export default Em.Component.extend({
actions: {
close: function () {
close () {
this.sendAction();
},
add (){
this.sendAction('action', this.get('url'));
}
},
url: null,
onIsShowingModalChange: function(){
this.set('url', null);
}.observes('isShowingModal'),
didInsertElement: function() {
var self = this;
Em.$(document).keypress(function(event) {
if(!self.get('saveDisabled') && event.which === 13) {
self.send('add');
}
});
},
saveDisabled: function(){
return Em.isNone(this.get('groupName')) || Em.isEmpty(this.get('selectedLights')) || Em.isEmpty(this.get('groupName').trim());
}.property('groupName', 'selectedLights.[]')
return Em.isEmpty(this.get('url').trim())
}.property('url')
});

View file

@ -1,10 +1,13 @@
{{#if isShowingModal}}
{{#modal-dialog close="close" alignment="center" translucentOverlay=true}}
{{#modal-dialog close="close" alignment="center" translucentOverlay=true attachment="center" targetAttachment="center"}}
<p>Enter a SoundCloud URL for a track or a playlist/set</p>
<p>Enter a <a href="https://soundcloud.com">SoundCloud</a> track or playlist/set URL</p>
<p>( ex. https://soundcloud.com/mrsuicidesheep/danrell-x-smaland-hostage )</p>
{{paper-input label="SoundCloud URL" icon="search" value=url}}
{{#paper-button action="close"}}Close{{/paper-button}}
{{#paper-button class="pull-right" action="delete" primary=true}}Add Music{{/paper-button}}
{{#paper-button class="pull-right" action="add" primary=true}}Add Music{{/paper-button}}
{{/modal-dialog}}
{{/if}}

View file

@ -16,13 +16,46 @@ export default Em.Component.extend(musicControlMixin, visualizerMixin, {
}.observes('active'),
actions: {
toggleIsShowingAddSoundCloudModal: function() {
handleNewSoundCloudURL(URL){
SC.resolve(URL).then((resultObj)=>{
var processResult = (result)=>{
if(result.kind === 'user'){
this.get('notify').alert({html: this.get('scUserNotSupportedHtml')});
} else if(result.kind === 'track') {
if(result.streamable === true){
this.get('playQueue').pushObject({url: result.stream_url + '?client_id=' + this.get('SC_CLIENT_ID'), artist: result.user.username, artistUrl: result.user.permalink_url, title: result.title, artworkUrl: result.artwork_url, fromSoundCloud: true });
// make sure to init the first song
if(this.get('playQueue').length > 0 && this.get('playQueuePointer') === -1){
this.send('goToSong', 0, true);
}
} else {
this.get('notify').alert({html: this.get('notStreamableHtml')(result.title)});
}
} else if(result.kind === 'playlist'){
if(result.streamable === true){
result.tracks.forEach(processResult);
} else {
this.get('notify').alert({html: this.get('notStreamableHtml')(result.title)});
}
}
};
if(resultObj instanceof Array){
resultObj.forEach(processResult);
} else {
processResult(resultObj);
}
});
this.set('isShowingAddSoundCloudModal', false);
},
toggleIsShowingAddSoundCloudModal() {
this.toggleProperty('isShowingAddSoundCloudModal');
},
toggleDimming: function(){
toggleDimming(){
this.changePlayerControl('dimmerEnabled', !this.get('dimmerEnabled'));
},
useLocalAudio: function(){
useLocalAudio(){
var audioStream = this.get('audioStream');
this.changePlayerControl('audioMode', 0);
@ -56,6 +89,7 @@ export default Em.Component.extend(musicControlMixin, visualizerMixin, {
goToSong(index, playSong){
var dancer = this.get('dancer'), audio = new Audio();
audio.src = this.get('playQueue')[index].url;
audio.crossOrigin = "anonymous";
if(dancer.audio) {
this.clearCurrentAudio(true);
@ -290,7 +324,10 @@ export default Em.Component.extend(musicControlMixin, visualizerMixin, {
this.saveSongBeatPreferences();
}
this.get('kick').set(options);
// filter the threshold manually
if(name !== 'threshold'){
this.get('kick').set(options);
}
}
this.get('storage').set('huegasm.' + name, value);
@ -428,70 +465,82 @@ export default Em.Component.extend(musicControlMixin, visualizerMixin, {
},
simulateKick(mag) {
var activeLights = this.get('activeLights'),
transitionTime = this.get('transitionTime') * 10,
onBeatBriAndColor = this.get('onBeatBriAndColor'),
self = this,
color = null,
stimulateLight = function (light, brightness, hue) {
var options = {'bri': brightness, 'transitiontime': transitionTime};
var validBeat = (this.get('threshold') < mag);
if(!Em.isNone(hue)) {
options.hue = hue;
}
if(validBeat){
var activeLights = this.get('activeLights'),
transitionTime = this.get('transitionTime') * 10,
onBeatBriAndColor = this.get('onBeatBriAndColor'),
self = this,
color = null,
stimulateLight = function (light, brightness, hue) {
var options = {'bri': brightness, 'transitiontime': transitionTime};
Em.$.ajax(self.get('apiURL') + '/lights/' + light + '/state', {
data: JSON.stringify(options),
contentType: 'application/json',
type: 'PUT'
});
};
if(activeLights.length > 0){
var lastLightBopIndex = this.get('lastLightBopIndex'),
randomTransition = this.get('randomTransition'),
lightBopIndex,
light;
if(randomTransition) {
lightBopIndex = Math.floor(Math.random() * activeLights.length);
// let's try not to select the same light twice in a row
if(activeLights.length > 1) {
while(lightBopIndex === lastLightBopIndex) {
lightBopIndex = Math.floor(Math.random() * activeLights.length);
if(!Em.isNone(hue)) {
options.hue = hue;
}
Em.$.ajax(self.get('apiURL') + '/lights/' + light + '/state', {
data: JSON.stringify(options),
contentType: 'application/json',
type: 'PUT'
});
};
if(activeLights.length > 0){
var lastLightBopIndex = this.get('lastLightBopIndex'),
randomTransition = this.get('randomTransition'),
lightBopIndex,
light;
if(randomTransition) {
lightBopIndex = Math.floor(Math.random() * activeLights.length);
// let's try not to select the same light twice in a row
if(activeLights.length > 1) {
while(lightBopIndex === lastLightBopIndex) {
lightBopIndex = Math.floor(Math.random() * activeLights.length);
}
}
} else {
lightBopIndex = (lastLightBopIndex + 1) % activeLights.length;
}
} else {
lightBopIndex = (lastLightBopIndex + 1) % activeLights.length;
light = activeLights[lightBopIndex];
this.set('lastLightBopIndex', lightBopIndex);
if(onBeatBriAndColor) {
color = Math.floor(Math.random() * 65535);
}
stimulateLight(light, 254, color);
setTimeout(stimulateLight, transitionTime + 50, light, 1);
this.set('paused', true);
setTimeout(function () {
self.set('paused', false);
}, 150);
}
light = activeLights[lightBopIndex];
this.set('lastLightBopIndex', lightBopIndex);
if(onBeatBriAndColor) {
color = Math.floor(Math.random() * 65535);
}
stimulateLight(light, 254, color);
setTimeout(stimulateLight, transitionTime + 50, light, 1);
this.set('paused', true);
setTimeout(function () {
self.set('paused', false);
}, 150);
}
//work the music beat area
if(this.get('speakerViewed')){
// simulate the speaker vibration by running a CSS animation on it
Em.$('#beatSpeakerCenterOuter').removeClass('vibrateOuter').prop('offsetWidth', Em.$('#beatSpeakerCenterOuter').prop('offsetWidth')).addClass('vibrateOuter');
Em.$('#beatSpeakerCenterInner').removeClass('vibrateInner').prop('offsetWidth', Em.$('#beatSpeakerCenterInner').prop('offsetWidth')).addClass('vibrateInner');
if(validBeat){
// simulate the speaker vibration by running a CSS animation on it
Em.$('#beatSpeakerCenterOuter').removeClass('vibrateOuter').prop('offsetWidth', Em.$('#beatSpeakerCenterOuter').prop('offsetWidth')).addClass('vibrateOuter');
Em.$('#beatSpeakerCenterInner').removeClass('vibrateInner').prop('offsetWidth', Em.$('#beatSpeakerCenterInner').prop('offsetWidth')).addClass('vibrateInner');
}
} else {
var beatHistory = self.get('beatHistory'),
maxSize = self.get('maxBeatHistorySize');
beatHistory.unshiftObjects('Beat intesity of <b>' + mag.toFixed(3) + '</b> at <b>' + self.get('timeElapsedTxt') + '</b>');
var beatHistory = this.get('beatHistory'),
debugFiltered = this.get('debugFiltered'),
maxSize = this.get('maxBeatHistorySize'),
html = 'Beat intesity of <b>' + mag.toFixed(3) + '</b> at <b>' + this.get('timeElapsedTxt') + '</b>';
if(!validBeat && debugFiltered){
html = '<span class="filterBeat">' + html + ' ( filtered ) </span>';
}
beatHistory.unshiftObjects(html);
if(beatHistory.length > maxSize){
beatHistory.popObject();
@ -505,11 +554,10 @@ export default Em.Component.extend(musicControlMixin, visualizerMixin, {
var dancer = new Dancer(),
storage = new window.Locally.Store(),
self = this,
threshold = this.get('threshold'),
decay = this.get('decay'),
frequency = this.get('frequency'),
kick = dancer.createKick({
threshold: threshold,
threshold: this.beatOptions.threshold.range.min,
decay: decay,
frequency: frequency,
onKick: function (mag) {
@ -566,7 +614,7 @@ export default Em.Component.extend(musicControlMixin, visualizerMixin, {
});
SC.initialize({
client_id: 'aeec0034f58ecd85c2bd1deaecc41594'
client_id: this.get('SC_CLIENT_ID')
});
},

View file

@ -7,7 +7,7 @@ export default Em.Mixin.create({
beatOptions: {
threshold: {
range: {min: 0.1, max: 0.9},
range: {min: 0.1, max: 1.0},
step: 0.01,
defaultValue: 0.3,
pips: {
@ -72,7 +72,7 @@ export default Em.Mixin.create({
playQueuePointer: -1,
playQueue: Em.A(),
beatHistory: Em.A(),
maxBeatHistorySize: 30,
maxBeatHistorySize: 100,
timeElapsed: 0,
timeTotal: 0,
lastLightBopIndex: 0,
@ -93,7 +93,12 @@ export default Em.Mixin.create({
dimmerEnabled: false,
isShowingAddSoundCloudModal: false,
SC_CLIENT_ID: 'aeec0034f58ecd85c2bd1deaecc41594',
notFoundHtml: '<div class="alert alert-danger" role="alert">A microphone was not found.</div>',
scUserNotSupportedHtml: '<div class="alert alert-danger" role="alert">SoundCloud user URLs are not supported.</div>',
notStreamableHtml: function(fileName){
return '<div class="alert alert-danger" role="alert">The owner of the file ( ' + fileName +' ) has not allowed for the the file to be streamed.</div>';
},
playQueueEmpty: Em.computed.empty('playQueue'),
playQueueNotEmpty: Em.computed.notEmpty('playQueue'),
@ -131,6 +136,7 @@ export default Em.Mixin.create({
}.property('playing'),
speakerViewed: true,
debugFiltered: true,
speakerLabel: function() {
if(this.get('speakerViewed')){
return 'Speaker View';
@ -138,6 +144,13 @@ export default Em.Mixin.create({
return 'Debug View';
}
}.property('speakerViewed'),
debugFilteredText: function(){
if(this.get('debugFiltered')){
return 'View Filtered';
} else {
return 'Hide Filtered';
}
}.property('debugFiltered'),
randomTransition: true,
randomTransitionLabel: function() {

View file

@ -102,83 +102,87 @@
{{/if}}
<div class="row">
<div class="beatOption col-xs-3">
<div class="beatOption col-xs-4">
<div class="text-center">{{threshold}}</div>
{{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range slide="thresholdChanged" pips=beatOptions.threshold.pips}}
<span data-toggle="tooltip" data-placement="bottom auto" data-title="Maximum intensity of the sound that may be registered as a beat" class="optionDescription bootstrapTooltip">Max. Intensity</span>
<span data-toggle="tooltip" data-placement="bottom auto" data-title="Threshold of the sound intensity for the beat" class="optionDescription bootstrapTooltip">Treshold</span>
</div>
<div class="beatOption col-xs-3">
{{!--
<div class="beatOption col-xs-3">
<div class="text-center">{{decay}}</div>
{{range-slider start=decay orientation="vertical" step=beatOptions.decay.step range=beatOptions.decay.range slide="decayChanged" pips=beatOptions.decay.pips}}
{{range-slider start=decay orientation="vertical" step=beatOptions.decay.step range=beatOptions.decay.range slide="decayChanged" pips=beatOptions.decay.pips}}
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The rate at which the previously registered beat's intensity is reduced to find the next beat" class="optionDescription bootstrapTooltip">Decay Rate</span>
</div>
<div class="beatOption col-xs-3">
<div class="text-center">[{{#each frequency as |item index|}}{{item}}{{#unless index}}
,{{/unless}}{{/each}}
]
</div>
{{range-slider start=frequency orientation="vertical" step=beatOptions.frequency.step range=beatOptions.frequency.range connect=true slide="frequencyChanged" pips=beatOptions.frequency.pips}}
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The frequency range of sound to listen on for the beat" class="optionDescription bootstrapTooltip">Frequency Range</span>
</div>
<div class="beatOption col-xs-3">
<div class="text-center">{{transitionTime}} sec</div>
{{range-slider start=transitionTime orientation="vertical" step=beatOptions.transitionTime.step range=beatOptions.transitionTime.range slide="transitionTimeChanged" pips=beatOptions.transitionTime.pips}}
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The time it takes for a light to change color or brightness" class="optionDescription bootstrapTooltip">Transition Time</span>
</div>
</div>
{{/if}}
--}}
<div id="beatOptionButtonGroup" class="row">
<div class="beatOption col-xs-3">
{{#paper-button raised=true warn=true action="defaultControls"}}Default{{/paper-button}}
</div>
<div class="beatOption col-xs-4">
{{#paper-switch checked=randomTransition disabled=trial}}<span data-toggle="tooltip"
data-placement="bottom auto"
data-title="The transition order of lights on beat"
class="optionDescription bootstrapTooltip">{{randomTransitionLabel}}</span>{{/paper-switch}}
</div>
<div class="beatOption col-xs-5">
{{#paper-switch checked=onBeatBriAndColor disabled=trial}}<span data-toggle="tooltip"
data-placement="bottom auto"
data-title="The properties of the lights to change on beat"
class="optionDescription bootstrapTooltip"> {{onBeatBriAndColorLabel}}</span>{{/paper-switch}}
</div>
<div class="beatOption col-xs-4">
<div class="text-center">[{{#each frequency as |item index|}}{{item}}{{#unless index}}
,{{/unless}}{{/each}}
]
</div>
{{range-slider start=frequency orientation="vertical" step=beatOptions.frequency.step range=beatOptions.frequency.range connect=true slide="frequencyChanged" pips=beatOptions.frequency.pips}}
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The frequency range of sound to listen on for the beat" class="optionDescription bootstrapTooltip">Frequency Range</span>
</div>
<div class="beatOption col-xs-4">
<div class="text-center">{{transitionTime}} sec</div>
{{range-slider start=transitionTime orientation="vertical" step=beatOptions.transitionTime.step range=beatOptions.transitionTime.range slide="transitionTimeChanged" pips=beatOptions.transitionTime.pips}}
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The time it takes for a light to change color or brightness" class="optionDescription bootstrapTooltip">Transition Time</span>
</div>
</div>
<div id="beatOptionButtonGroup" class="row">
<div class="beatOption col-xs-3">
{{#paper-button raised=true warn=true action="defaultControls"}}Default{{/paper-button}}
</div>
<div class="beatOption col-xs-4">
{{#paper-switch checked=randomTransition disabled=trial}}<span data-toggle="tooltip"
data-placement="bottom auto"
data-title="The transition order of lights on beat"
class="optionDescription bootstrapTooltip">{{randomTransitionLabel}}</span>{{/paper-switch}}
</div>
<div class="beatOption col-xs-5">
{{#paper-switch checked=onBeatBriAndColor disabled=trial}}<span data-toggle="tooltip"
data-placement="bottom auto"
data-title="The properties of the lights to change on beat"
class="optionDescription bootstrapTooltip"> {{onBeatBriAndColorLabel}}</span>{{/paper-switch}}
</div>
</div>
</div>
<div id="beatContainer" class="col-sm-5 col-xs-12">
{{#if speakerViewed}}
<div class="bezel">
<div class="rivet1"></div>
<div class="rivet2"></div>
<div class="rivet3"></div>
<div class="rivet4"></div>
<div class="rivet5"></div>
<div class="rivet6"></div>
<div class="rivet7"></div>
<div class="rivet8"></div>
<div id="beatSpeakerCenterOuter">
<div id="beatSpeakerCenterInner" class="cursorPointer" {{action "clickSpeaker"}}>
</div>
</div>
</div>
{{else}}
<div id="beatHistory">
{{#each beatHistory as |item|}}
<p>{{{item}}}</p>
{{/each}}
</div>
{{#paper-switch checked=debugFiltered class="debugFilteredSwitch"}} {{debugFilteredText}} {{/paper-switch}}
{{/if}}
<div id="beatContainer" class="col-sm-5 col-xs-12">
{{#if speakerViewed}}
<div class="bezel">
<div class="rivet1"></div>
<div class="rivet2"></div>
<div class="rivet3"></div>
<div class="rivet4"></div>
<div class="rivet5"></div>
<div class="rivet6"></div>
<div class="rivet7"></div>
<div class="rivet8"></div>
<div id="beatSpeakerCenterOuter">
<div id="beatSpeakerCenterInner" class="cursorPointer" {{action "clickSpeaker"}}>
</div>
</div>
</div>
{{else}}
<div id="beatHistory">
{{#each beatHistory as |item|}}
<p>{{{item}}}</p>
{{/each}}
</div>
{{/if}}
{{#paper-switch checked=speakerViewed}} {{speakerLabel}} {{/paper-switch}}
</div>
{{#paper-switch checked=speakerViewed class="speakerSwitch"}} {{speakerLabel}} {{/paper-switch}}
</div>
</div>
{{ember-notify closeAfter=5000}}
<div id="dimmer" {{action "toggleDimming"}}></div>
{{add-soundcloud-sound-modal action="toggleIsShowingAddSoundCloudModal" isShowingModal=isShowingAddSoundCloudModal}}
{{add-soundcloud-sound-modal action="handleNewSoundCloudURL" isShowingModal=isShowingAddSoundCloudModal}}

View file

@ -711,8 +711,16 @@ md-switch.md-default-theme.md-checked .md-thumb {
-webkit-transform: translate3d(0, 0, 0); // hack for chrome to force hardware acceleration and stop flickering
padding: 0;
height: $playerBottomHeight;
md-switch {
.speakerSwitch {
top: 0;
left: 0;
position: absolute;
margin-left: 0;
margin-bottom: 10px;
}
.debugFilteredSwitch {
top: 0;
right: 0;
position: absolute;
margin-left: 0;
margin-bottom: 10px;
@ -738,11 +746,17 @@ md-switch.md-default-theme.md-checked .md-thumb {
height: 85%;
background-color: white;
border-radius: 10px;
width: 285px;
width: 300px;
margin: 40px auto 0 auto;
overflow: auto;
padding: 10px;
box-shadow: 5px 10px 15px 5px rgba(0, 0, 0, 0.1);
p {
margin-bottom: 5px;
}
.filterBeat {
font-style: italic;
}
}
// FANCY SPEAKER
@ -934,8 +948,13 @@ $vibrateblurouter: 2px;
background: #171717 !important;
}
.noUi-value-vertical {
margin-top: -10px;
}
.noUi-value-vertical, .noUi-pips {
color: inherit !important;
font: 400 14px 'Slabo 27px';
}
.noUi-vertical .noUi-handle {
@ -972,3 +991,7 @@ button.md-warn {
color: #f70 !important;
}
}
.ember-modal-dialog {
padding: 20px;
}

View file

@ -25,7 +25,7 @@ module.exports = function(environment) {
'font-src': "'self' fonts.gstatic.com",
'connect-src': "'self' *",
'img-src': "'self' data:",
'media-src': "'self' blob:",
'media-src': "'self' api.soundcloud.com *.sndcdn.com blob:",
'style-src': "'self' 'unsafe-inline' fonts.googleapis.com",
'object-src': "'self' connect.soundcloud.com",
'frame-src': "'self'"