diff --git a/README.md b/README.md index 4723afa..d4cefcc 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,24 @@ # Huegasm -This README outlines the details of collaborating on this Ember application. -A short introduction of this app could easily go here. +Music awesomeness for hue lights. -## Prerequisites +# TODO +## FEATURES +- finish beat detection light effects +- more granular light controls on the lights tab +- handle multiple bridge IPs for bridge-finder +- save beat detection settings per song +- app intro with intro.js +- music visualizations with three.js +- new favicon -You will need the following things properly installed on your computer. - -* [Git](http://git-scm.com/) -* [Node.js](http://nodejs.org/) (with NPM) -* [Bower](http://bower.io/) -* [Ember CLI](http://www.ember-cli.com/) -* [PhantomJS](http://phantomjs.org/) - -## Installation - -* `git clone ` this repository -* change into the new directory -* `npm install` -* `bower install` - -## Running / Development - -* `ember server` -* Visit your app at [http://localhost:4200](http://localhost:4200). - -### Code Generators - -Make use of the many generators for code, try `ember help generate` for more details - -### Running Tests - -* `ember test` -* `ember test --server` - -### Building - -* `ember build` (development) -* `ember build --environment production` (production) - -### Deploying - -Specify what it takes to deploy your app. - -## Further Reading / Useful Links - -* [ember.js](http://emberjs.com/) -* [ember-cli](http://www.ember-cli.com/) -* Development Browser Extensions - * [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi) - * [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/) +## POSSIBLE FEATURES +- clear localstorage +- help, contact, about, youtube video ??? +- beat settings by interval +- integration with youtube, soundcloud, spotify ??? +## BUGS +- fuckery when listening to music and switching tabs +- can't create groups anymore +- BUGS BUGS BUGS diff --git a/app/components/bridge-controls.js b/app/components/bridge-controls.js index 3641d96..20a223a 100644 --- a/app/components/bridge-controls.js +++ b/app/components/bridge-controls.js @@ -27,16 +27,29 @@ export default Em.Component.extend({ } }, + // automatically close the group menu when the user clicks somewhere else + click: function() { + if(this.get('groupControlDisplayed') && !event.target.classList.contains('menu') && !$(event.target).closest('#groupControls').length) { + this.toggleProperty('groupControlDisplayed'); + } + }, + apiURL: function(){ return 'http://' + this.get('bridgeIp') + '/api/' + this.get('bridgeUsername'); }.property('bridgeIp', 'bridgeUsername'), didInsertElement: function(){ - //TODO: make less shitty + // here's a weird way to automatically initialize bootstrap tooltips var observer = new MutationObserver(function(mutations) { - Em.run.once(this, function(){ - Em.$('.bootstrapTooltip').tooltip(); + var haveTooltip = !mutations.every(function(mutation) { + return Em.isEmpty(mutation.addedNodes) || Em.isNone(mutation.addedNodes[0].classList) || mutation.addedNodes[0].classList.contains('tooltip'); }); + + if(haveTooltip) { + Em.run.once(this, function(){ + Em.$('.bootstrapTooltip').tooltip(); + }); + } }); observer.observe(Em.$('#bridgeControls')[0], {childList: true, subtree: true}); }, diff --git a/app/components/bridge-finder.js b/app/components/bridge-finder.js index 3658fed..37ac0be 100644 --- a/app/components/bridge-finder.js +++ b/app/components/bridge-finder.js @@ -46,7 +46,6 @@ export default Em.Component.extend({ self.set('manualBridgeIpNotFound', true); setTimeout(function(){ self.set('manualBridgeIpNotFound', false); }, 5000); }).then(function () { - debugger; self.set('bridgeIp', manualBridgeIp); }); } diff --git a/app/components/controls/group-control.js b/app/components/controls/group-control.js index 4becc80..18f67e0 100644 --- a/app/components/controls/group-control.js +++ b/app/components/controls/group-control.js @@ -2,7 +2,8 @@ import Em from 'ember'; export default Em.Component.extend({ classNameBindings: ['groupControlDisplayed:on'], - classNames: ['innerControlFrame', 'groupControls'], + classNames: ['innerControlFrame'], + elementId: 'groupControls', tagName: null, diff --git a/app/components/controls/music-control.js b/app/components/controls/music-control.js index b068af6..795c1bc 100644 --- a/app/components/controls/music-control.js +++ b/app/components/controls/music-control.js @@ -64,8 +64,7 @@ export default Em.Component.extend(musicControlMixin, { } }, play: function () { - var dancer = this.get('dancer'), - playQueue = this.get('playQueue'); + var dancer = this.get('dancer'); if(this.get('playQueuePointer') !== -1 ) { if (this.get('playing')) { @@ -120,7 +119,6 @@ export default Em.Component.extend(musicControlMixin, { this.get('dancer').source.currentTime = audioPosition; this.set('timeElapsed', audioPosition); }, - volumeMutedChanged: function (value) { var dancer = this.get('dancer'), volumeMuted = Em.isNone(value) ? !this.get('volumeMuted') : value; @@ -196,20 +194,31 @@ export default Em.Component.extend(musicControlMixin, { if (files.hasOwnProperty(key)) { var file = files[key]; - ID3.loadTags("local", updatePlayQueue.bind(file),{ - dataReader: new FileAPIReader(file) - }); + if(file.type.startsWith('audio')) { + ID3.loadTags("local", updatePlayQueue.bind(file),{ + dataReader: new FileAPIReader(file) + }); + } } } } }, - dragOver: function(){ + dragLeaveTimeoutHandle: null, + + dragOver: function() { + var dragLeaveTimeoutHandle = this.get('dragLeaveTimeoutHandle'); this.set('dragging', true); + + if (dragLeaveTimeoutHandle) { + clearTimeout(dragLeaveTimeoutHandle); + } }, dragLeave: function(){ - this.set('dragging', false); + // need to delay the dragLeave notification to avoid flickering ( hovering over some page elements causes this event to be sent ) + var self = this; + this.set('dragLeaveTimeoutHandle', setTimeout(function(){ self.set('dragging', false); }, 500)); }, changePlayerControl: function(name, value, isOption){ @@ -318,15 +327,17 @@ export default Em.Component.extend(musicControlMixin, { }); // control the volume by scrolling up/down Em.$('#playerArea').on('mousewheel', function(event) { - var scrollSize = 5; + if(self.get('playQueueNotEmpty')) { + var scrollSize = 5; - if(event.deltaY < 0) { - scrollSize *= -1; + if(event.deltaY < 0) { + scrollSize *= -1; + } + var newVolume = self.get('volume') + scrollSize; + + self.send('volumeChanged', newVolume < 0 ? 0 : newVolume); + event.preventDefault(); } - var newVolume = self.get('volume') + scrollSize; - - self.send('volumeChanged', newVolume < 0 ? 0 : newVolume); - event.preventDefault(); }); }, diff --git a/app/components/mixins/music-control.js b/app/components/mixins/music-control.js index 969ade1..06b3a59 100644 --- a/app/components/mixins/music-control.js +++ b/app/components/mixins/music-control.js @@ -118,7 +118,7 @@ export default Em.Mixin.create({ }.property('playing'), playListAreaClass: function(){ - var classes = 'cursorPointer dragArea'; + var classes = 'cursorPointer'; if(this.get('dragging')){ classes += ' dragHereHighlight'; @@ -199,6 +199,18 @@ export default Em.Mixin.create({ this.changeTooltipText(type, tooltipTxt); }.observes('volumeMuted').on('init'), + onPrevChange: function() { + if(this.get('playQueueMultiple')){ + var tooltipTxt = 'Previous', type = 'prev'; + + if(this.get('timeElapsed') > 5) { + tooltipTxt = 'Replay'; + } + + this.changeTooltipText(type, tooltipTxt); + } + }.observes('timeElapsed', 'playQueueMultiple'), + onPlayingChange: function () { var tooltipTxt = 'Play', type = 'playing'; @@ -213,8 +225,11 @@ export default Em.Mixin.create({ // change the tooltip text if it's already visible Em.$('#' + type + 'Tooltip + .tooltip .tooltip-inner').html(text); //change the tooltip text for hover - Em.$('#' + type + 'Tooltip').attr('data-original-title', text).attr('title', text); - this.set(type + 'TooltipTxt', text); + Em.$('#' + type + 'Tooltip').attr('data-original-title', text); + + if(Em.isNone(this.get(type + 'TooltipTxt'))) { + this.set(type + 'TooltipTxt', text); + } }, timeElapsedTxt: function(){ diff --git a/app/styles/app.scss b/app/styles/app.scss index 9135774..0188496 100644 --- a/app/styles/app.scss +++ b/app/styles/app.scss @@ -131,7 +131,7 @@ md-progress-circular { overflow: visible; } -.groupControls { +#groupControls { display: none; border-left: 1px solid #C5C5C5; border-bottom: 1px solid #C5C5C5; @@ -140,7 +140,7 @@ md-progress-circular { border-radius: 0 0 5px 5px; } -.groupControls.on { +#groupControls.on { width: 300px; top: 48px; left: -5px; @@ -210,7 +210,7 @@ md-icon.menu { } .addButton .group-add:hover { - color: darken(#333333, 20%) !important; + color: darken(#333333, 5%) !important; } .removeButton { @@ -267,7 +267,7 @@ md-toolbar { } .close:hover { - color: darken(#333333, 20%) !important; + color: darken(#333333, 5%) !important; } .close:hover { @@ -442,6 +442,7 @@ md-toolbar { height: 333px; margin: 10px auto 0 auto; border-radius: 5px; + transition: 0.1s all ease-in-out; #dragHere { position: absolute; top: 41%; @@ -457,6 +458,15 @@ md-toolbar { } } +#playListArea.dragHereHighlight { + background-color: white; + border: 5px dotted #5383ff; +} +#playListArea.draggingOver { + background-color: darken(white, 5%); + box-shadow: inset 0 0 20px 0 rgba(0,0,0,1); +} + #fileInput { width: 1px; height: 1px; @@ -509,7 +519,7 @@ md-toolbar { .beatOption { display: inline-block; - margin-left: 0.714em; + margin-right: 2em; } #playerBottom { @@ -534,15 +544,23 @@ md-toolbar { background-image: url('images/speaker-outer.png'); width: 284px; height: 283px; -} - -#beatSpeakerCenter { - width: 188px; - height: 186px; - background-image: url('images/speaker-inner.png'); - position: absolute; - top: 16%; - left: 18%; + #beatSpeakerCenter { + width: 188px; + height: 186px; + background-image: url('images/speaker-inner.png'); + position: absolute; + top: 16%; + left: 18%; + } + #beatSpeakerCenterBackground { + width: 188px; + height: 186px; + background-color: black; + position: absolute; + top: 16%; + left: 18%; + z-index: -1; + } } .pop { @@ -585,13 +603,3 @@ md-toolbar { padding: 10px; box-shadow: 5px 10px 15px 5px rgba(0, 0, 0, 0.1); } - -#playListArea.dragArea.dragHereHighlight { - background-color: white; - border: 5px dotted #5383ff; -} - -#playListArea.dragArea.draggingOver { - background-color: darken(white, 5%); - box-shadow: inset 0 0 20px 0 rgba(0,0,0,1); -} diff --git a/app/templates/components/controls/music-control.hbs b/app/templates/components/controls/music-control.hbs index 7b757fa..c29d83e 100644 --- a/app/templates/components/controls/music-control.hbs +++ b/app/templates/components/controls/music-control.hbs @@ -5,17 +5,13 @@ {{range-slider start=seekPosition min=0 max=100 id="seekSlider" slide="seekChanged"}} {{#if playQueueMultiple}} - {{paper-icon icon="skip-previous" class="playerControllIcon"}}{{/if}}{{paper-icon icon=playingIcon class="playerControllIcon"}}{{paper-icon icon=playingIcon class="playerControllIcon"}}{{#if playQueueMultiple}}{{paper-icon icon="skip-next" action="" class="playerControllIcon"}}{{paper-icon icon="skip-next" action="" class="playerControllIcon"}}{{/if}}{{paper-icon icon=volumeClass class="playerControllIcon volumeButton"}}{{paper-icon icon=volumeClass class="playerControllIcon volumeButton"}}{{range-slider start=volume min=0 max=100 slide="volumeChanged" id="volumeBar"}} {{timeElapsedTxt}} / {{timeTotalTxt}} @@ -43,13 +39,13 @@
- {{#if playQueueEmpty}} + {{#if (or playQueueEmpty dragging)}}
Drag your music files here
{{paper-icon icon="library-music"}} {{/if}} {{#each playQueue as |item index|}} -
+
{{#if item.title}} {{item.title}}
{{item.artist}}
@@ -68,21 +64,22 @@
{{light-group lightsData=lightsData activeLights=activeLights action='clickLight' apiURL=apiURL noHover=true}} + {{range-slider start=threshold orientation="vertical" range=beatOptions.threshold.range slide="thresholdChanged" pips=beatOptions.threshold.pips}} - Beat Threshold + Beat Threshold {{range-slider start=decay orientation="vertical" step=beatOptions.decay.step range=beatOptions.decay.range slide="decayChanged" pips=beatOptions.decay.pips}} - Beat Decay + Beat Decay - {{range-slider start=frequency orientation="vertical" step=beatOptions.frequency.step range=beatOptions.frequency.range connect=true slide="frequencyChanged" pips=beatOptions.frequency.pips}} - Beat Frequency Range + Beat Frequency Range +
{{#paper-button raised=true warn=true action="defaultControls"}}Default{{/paper-button}} @@ -90,17 +87,18 @@ - {{#paper-switch checked=speakerViewed noink=true}} {{speakerLabel}} {{/paper-switch}} - {{#liquid-if speakerViewed}} + {{#paper-switch checked=speakerViewed noink=true}} {{speakerLabel}} {{/paper-switch}} + {{#liquid-if speakerViewed}}
- -
+ + +
{{else}}
- {{#each beatHistory as |item|}} -

{{{item}}}

- {{/each}} + {{#each beatHistory as |item|}} +

{{{item}}}

+ {{/each}}
{{/liquid-if}} - -
\ No newline at end of file + +
\ No newline at end of file diff --git a/config/environment.js b/config/environment.js index 588f226..2960aab 100644 --- a/config/environment.js +++ b/config/environment.js @@ -24,7 +24,7 @@ module.exports = function(environment) { 'font-src': "'self' fonts.gstatic.com", 'connect-src': "'self' *", 'img-src': "'self' data:", - 'media-src': "'self'", + 'media-src': "'self' blob:", 'style-src': "'self' 'unsafe-inline' fonts.googleapis.com", 'object-src': "'self'", 'frame-src': "'self'"