diff --git a/README.md b/README.md index 773cf9c..99553ab 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,4 @@ Music awesomeness for hue lights. - integration with youtube, soundcloud, spotify ??? - auto beat detection mode - lights on/off switch + diff --git a/app/components/bridge-controls.js b/app/components/bridge-controls.js index 20a223a..89ed2bf 100644 --- a/app/components/bridge-controls.js +++ b/app/components/bridge-controls.js @@ -29,7 +29,7 @@ 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) { + if(this.get('groupControlDisplayed') && !event.target.classList.contains('group') && !$(event.target).closest('#groupControls').length) { this.toggleProperty('groupControlDisplayed'); } }, diff --git a/app/components/controls/light-control.js b/app/components/controls/light-control.js index afd453f..820eabe 100644 --- a/app/components/controls/light-control.js +++ b/app/components/controls/light-control.js @@ -3,23 +3,26 @@ import Em from 'ember'; export default Em.Component.extend({ classNames: ['innerControlFrame'], classNameBindings: ['active::hidden'], + elementId: 'lightControl', activeLights: [], lightsData: null, lightsDataIntervalHandle: null, - modalData: null, - isShowingLightsModal: false, isShowingAddGroupsModal: false, - actions: { - clickLight: function(id, data){ - if(this.get('isShowingLightsModal')){ - this.set('modalData', {data:data, id:id}); - } - this.toggleProperty('isShowingLightsModal'); - } + didInsertElement: function(){ + // handle color changes + var self = this; + + Em.$('.color').colorPicker({ + opacity: false, + + renderCallback: function(elem){ + console.log(elem[0].value); + } + }); }, // determines whether the lights are on/off for the lights switch @@ -35,6 +38,18 @@ export default Em.Component.extend({ }); }.property('lightsData', 'activeLights', 'strobeOn'), + // color of the lights in the group + color: function(){ + var lightsData = this.get('lightsData'), + color = [0,0,0]; + + if(this.get('strobeOn') || this.get('activeLights').length === 0){ + return color; + } + + return [lightsData[0].state.hue, lightsData[0].state.sat, lightsData[0].state.bri]; + }.property('lightsData', 'activeLights', 'strobeOn'), + // determines the average brightness of the hue system for the brightness slider lightsBrightness: function(){ var lightsData = this.get('lightsData'), activeLights = this.get('activeLights'), lightsBrightness = 0; diff --git a/app/components/controls/music-control.js b/app/components/controls/music-control.js index 5f13d28..7c6f261 100644 --- a/app/components/controls/music-control.js +++ b/app/components/controls/music-control.js @@ -12,7 +12,7 @@ export default Em.Component.extend(musicControlMixin, { audio.src = this.get('playQueue')[index].url; if(dancer.audio) { - this.send('clearCurrentAudio'); + this.clearCurrentAudio(true); } dancer.load(audio); @@ -24,22 +24,9 @@ export default Em.Component.extend(musicControlMixin, { this.send('play'); } }, - clearCurrentAudio: function() { - var dancer = this.get('dancer'); - - dancer.pause(); - clearInterval(this.get('incrementElapseTimeHandle')); - - this.setProperties({ - playQueuePointer: -1, - timeElapsed: 0, - timeTotal: 0, - playing: false - }); - }, removeAudio: function(index){ if(index === this.get('playQueuePointer')) { - this.send('clearCurrentAudio'); + this.clearCurrentAudio(true); } this.get('playQueue').removeAt(index); @@ -94,9 +81,13 @@ export default Em.Component.extend(musicControlMixin, { }, next: function () { var playQueuePointer = this.get('playQueuePointer'), playQueueLength = this.get('playQueue.length'); - var nextSong = (playQueuePointer + 1) % playQueueLength; + var nextSong = (playQueuePointer + 1); - this.send('goToSong', nextSong); + if(nextSong > playQueueLength-1 && this.get('repeat') === 1){ + nextSong = nextSong % playQueueLength; + + this.send('goToSong', nextSong); + } }, previous: function () { if(this.get('timeElapsed') > 5) { @@ -112,13 +103,15 @@ export default Em.Component.extend(musicControlMixin, { this.send('goToSong', nextSong); } }, - fullscreen: function () { - - }, + fullscreen: function () {}, seekChanged: function (position) { - var audioPosition = Math.floor(this.get('timeTotal') * position / 100); - this.get('dancer').source.currentTime = audioPosition; - this.set('timeElapsed', audioPosition); + var dancer = this.get('dancer'); + + if(dancer.audio){ + var audioPosition = Math.floor(this.get('timeTotal') * position / 100); + dancer.audio.currentTime = audioPosition; + this.set('timeElapsed', audioPosition); + } }, volumeMutedChanged: function (value) { var dancer = this.get('dancer'), @@ -205,7 +198,33 @@ export default Em.Component.extend(musicControlMixin, { } }, - dragLeaveTimeoutHandle: null, + clearCurrentAudio: function(resetPointer) { + var dancer = this.get('dancer'); + + dancer.pause(); + clearInterval(this.get('incrementElapseTimeHandle')); + + if(resetPointer){ + this.set('playQueuePointer', -1); + } + + this.setProperties({ + timeElapsed: 0, + timeTotal: 0, + playing: false + }); + }, + + goToNextSong: function() { + this.get('beatHistory').clear(); + + if(this.get('repeat') === 2){ + this.send('goToSong', this.get('playQueuePointer')); + } else { + this.get('timeElapsed') + this.send('next'); + } + }, dragOver: function() { var dragLeaveTimeoutHandle = this.get('dragLeaveTimeoutHandle'); @@ -222,17 +241,6 @@ export default Em.Component.extend(musicControlMixin, { this.set('dragLeaveTimeoutHandle', setTimeout(function(){ self.set('dragging', false); }, 500)); }, - changePlayerControl: function(name, value, isOption){ - if(isOption){ - var options = {}; - options[name] = value; - this.get('kick').set(options); - } - - this.set(name, value); - localStorage.setItem('huegasm.' + name, value); - }, - init: function () { this._super(); diff --git a/app/components/mixins/music-control.js b/app/components/mixins/music-control.js index d182d0e..72c19a5 100644 --- a/app/components/mixins/music-control.js +++ b/app/components/mixins/music-control.js @@ -5,11 +5,11 @@ export default Em.Mixin.create({ beatOptions: { threshold: { - range: {min: 0.1, max: 0.6}, + range: {min: 0.1, max: 0.9}, defaultValue: 0.3, pips: { mode: 'positions', - values: [0,20,40,60,80,100], + values: [0,25,50,75,100], density: 3, format: { to: function ( value ) {return value;}, @@ -34,7 +34,7 @@ export default Em.Mixin.create({ frequency: { range: {min: 0, max: 10}, step: 1, - defaultValue: [0,5], + defaultValue: [0,10], pips: { mode: 'values', values: [0,2,4,6,8,10], @@ -61,6 +61,7 @@ export default Em.Mixin.create({ dragging: false, draggingOverPlayListArea: false, + dragLeaveTimeoutHandle: null, playQueueEmpty: Em.computed.empty('playQueue'), playQueueNotEmpty: Em.computed.notEmpty('playQueue'), @@ -97,9 +98,23 @@ export default Em.Mixin.create({ } }.property('speakerViewed'), + changePlayerControl: function(name, value, isOption){ + if(isOption){ + var options = {}; + options[name] = value; + this.get('kick').set(options); + } + + this.set(name, value); + localStorage.setItem('huegasm.' + name, value); + }, + incrementElapseTimeHandle: null, incrementElapseTime: function(){ this.incrementProperty('timeElapsed'); + if(this.get('timeElapsed') > this.get('timeTotal')){ + this.goToNextSong(); + } }, repeatIcon: function () { diff --git a/app/components/modals/light-control-modal.js b/app/components/modals/light-control-modal.js deleted file mode 100644 index f50df47..0000000 --- a/app/components/modals/light-control-modal.js +++ /dev/null @@ -1,9 +0,0 @@ -import Em from 'ember'; - -export default Em.Component.extend({ - actions: { - close: function(){ - this.sendAction(); - } - } -}); diff --git a/app/styles/app.scss b/app/styles/app.scss index b6dcd18..11ad9f4 100644 --- a/app/styles/app.scss +++ b/app/styles/app.scss @@ -11,6 +11,12 @@ $playerDefaultIconColor: #BBBBBB; $footerHeight: 40px; // BRIDGE FINDER +* { + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + html { min-height: 100%; height: auto; @@ -122,21 +128,40 @@ md-progress-linear { padding: 0 10px 0 10px; } -.navigationItem:hover{ - text-decoration: underline; -} - .navigationItem.active { font-weight: bold; cursor: default; } -.navigationItem.active:hover { - color: #000; - text-decoration: none; +.navigationItem:hover { + font-weight: bold; +} + +.cp-color-picker{ + z-index: 100; +} + +#lightControl{ + min-height: 500px; +} + +.color { + width: 50px; + padding: 22px; + cursor: pointer; + font-size: 0; + margin-right: 20px; +} + // LIGHT GROUP +md-slider { + cursor: pointer; +} + +md-slider.md-default-theme .md-thumb:after { + border-color: #F12B24; + background-color: #F12B24; } -// LIGHT GROUP .paper-sidenav { overflow: visible; } @@ -165,7 +190,7 @@ md-progress-linear { .lightGroup { margin: 0 auto 0 auto; .tooltip.top { - margin-top: -10px; + margin-top: 8px; } } @@ -176,28 +201,35 @@ md-progress-linear { } .lightInactive { - cursor: pointer; position: relative; - } .lightInactive::before { font-weight: bold; position: absolute; content: "X"; - top: -20px; - left: 6px; + top: 0; + left: 15px; font-size: 40px; color: rgba(255, 0, 0, 0.37); font-family: cursive; } +.horizontalLightGroup { + .lightInactive::before { + top: -21px; + left: 6px; + } + .tooltip.top { + margin-top: -10px; + } +} + .lightUnreachable { background-color: rgba(255, 0, 0, 0.7); } .lightActive img { - cursor: pointer; transition-duration: 0.3s; transition-property: transform; box-shadow: 0 0 1px rgba(0, 0, 0, 0); @@ -215,7 +247,7 @@ md-icon { color: rgba(0, 0, 0, 0.54) !important; } -md-icon.menu { +md-icon.group { margin: 30px 0 0 16px; } @@ -240,10 +272,6 @@ md-toolbar { background-color: inherit !important; } -//.innerControlFrame { -// height: 100vh; -//} - // GROUP CONTROL .groupRow.selectedRow { background-color: #7F7F7F !important; @@ -296,6 +324,13 @@ md-toolbar { } // MUSIC CONTROL +md-switch.md-default-theme.md-checked .md-bar { + background-color: rgba(241, 43, 36, 0.5); +} + +md-switch.md-default-theme.md-checked .md-thumb{ + background-color: #F12B24; +} #playerControls { opacity: 0; transition: all 0.2s ease-in-out; @@ -500,7 +535,6 @@ md-toolbar { } .playlistItem { - border-bottom: 1px solid #9E9E9E; height: 45px; font-family: 'Open Sans', sans-serif; padding: 5px; @@ -541,16 +575,20 @@ md-toolbar { #beatArea * .noUi-vertical { height: 170px; margin-top: 20px; - margin-bottom: 5px; + margin-bottom: 15px; } -.beatOption { - display: inline-block; - margin-right: 2em; +#beatOptionGroup { + margin-top: 20px; + .beatOption { + display: inline-block; + margin-right: 2em; + } } #playerBottom { - background-color: grey; + color: white; + background-color: #5D5D5D; } #beatSpeakerContainer { @@ -567,27 +605,35 @@ md-toolbar { #beatSpeaker { position: relative; - margin: 20px auto 0 auto; + margin: 10px auto 0 auto; + border-radius: 50%; + width: 280px; + height: 280px; background-image: url('images/speaker-outer.png'); - width: 284px; - height: 283px; + //border: 1px solid white; + //background: black; #beatSpeakerCenter { width: 188px; height: 186px; + position: absolute; + top: 17%; + left: 17%; + border-radius: 50%; + //border: 3px solid brown; + //background: orange; 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; } + //#beatSpeakerCenter::before { + // position: absolute; + // top: 28%; + // left: 28%; + // width: 80px; + // height: 80px; + // content: ''; + // background-color: black; + // border: 1px solid white; + // border-radius: 50%; + //} } .pop { @@ -603,7 +649,12 @@ md-toolbar { } } #beatArea .lightGroup { - margin: 10px 0 0 40px; + margin: 10px 50px 0 40px; + float: right; + span { + display: block; + padding: 10px; + } } #playerButtonGroup { @@ -621,7 +672,7 @@ md-toolbar { #beatHistory { height: 250px; - background-color: #CFCFCF; + background-color: white; border-radius: 10px; width: 80%; margin: 20px auto; diff --git a/app/templates/components/bridge-controls.hbs b/app/templates/components/bridge-controls.hbs index 642eceb..f1b2457 100644 --- a/app/templates/components/bridge-controls.hbs +++ b/app/templates/components/bridge-controls.hbs @@ -1,6 +1,6 @@ {{#if ready}} - {{paper-icon icon="menu"}} + {{paper-icon icon="group"}} {{controls/group-control lightsData=lightsData groupsData=groupsData activeLights=activeLights apiURL=apiURL updateGroupsData=updateGroupsData groupControlDisplayed=groupControlDisplayed}} diff --git a/app/templates/components/controls/light-control.hbs b/app/templates/components/controls/light-control.hbs index 288ba8a..db58a85 100644 --- a/app/templates/components/controls/light-control.hbs +++ b/app/templates/components/controls/light-control.hbs @@ -1,6 +1,6 @@ {{#paper-list}} {{#paper-item class="item"}} - {{light-group lightsData=lightsData activeLights=activeLights action='clickLight' apiURL=apiURL}} + {{light-group lightsData=lightsData activeLights=activeLights action='clickLight' apiURL=apiURL classNames="horizontalLightGroup"}} {{/paper-item}} {{#paper-item class="item"}} @@ -15,11 +15,15 @@ {{paper-slider flex=true min='1' max='254' value=lightsBrightness disabled=brightnessControlDisabled}} {{/paper-item}} + {{#paper-item class="item"}} + {{paper-icon icon="color-lens"}} +
Color
+ + {{/paper-item}} + {{#paper-item class="item"}} {{paper-icon icon="flare"}}Strobe
{{#paper-switch checked=strobeOn disabled=trial}} {{strobeOnTxt}} {{/paper-switch}} {{/paper-item}} - - {{modals/light-control-modal modalData=modalData apiURL=apiURL action="clickLight" isShowingLightsModal=isShowingLightsModal}} {{/paper-list}} \ No newline at end of file diff --git a/app/templates/components/controls/music-control.hbs b/app/templates/components/controls/music-control.hbs index 0dae7f3..34aba5e 100644 --- a/app/templates/components/controls/music-control.hbs +++ b/app/templates/components/controls/music-control.hbs @@ -58,13 +58,12 @@ -