Weekend work push

This commit is contained in:
lone-cloud 2015-09-08 00:32:40 -07:00
parent 89942a4639
commit 68d208c6bc
23 changed files with 458 additions and 157 deletions

View file

@ -5,5 +5,5 @@
Setting `disableAnalytics` to true will prevent any data from being sent. Setting `disableAnalytics` to true will prevent any data from being sent.
*/ */
"disableAnalytics": false "disableAnalytics": true
} }

View file

@ -4,7 +4,8 @@
"window", "window",
"-Promise", "-Promise",
"Dancer", "Dancer",
"ID3" "ID3",
"FileAPIReader"
], ],
"browser": true, "browser": true,
"boss": true, "boss": true,

View file

@ -43,8 +43,8 @@ export default Em.Component.extend({
this.toggleProperty('updateGroupsData'); this.toggleProperty('updateGroupsData');
}, },
tabList: ["Lights", "Scenes", "Music"], tabList: ["Music", "Lights"],
selectedTab: 2, selectedTab: 0,
tabData: function(){ tabData: function(){
var tabData = [], selectedTab = this.get('selectedTab'); var tabData = [], selectedTab = this.get('selectedTab');
@ -61,9 +61,8 @@ export default Em.Component.extend({
return tabData; return tabData;
}.property('tabList', 'selectedTab'), }.property('tabList', 'selectedTab'),
lightsTabSelected: Em.computed.equal('selectedTab', 0), lightsTabSelected: Em.computed.equal('selectedTab', 1),
scenesTabSelected: Em.computed.equal('selectedTab', 1), musicTabSelected: Em.computed.equal('selectedTab', 0),
musicTabSelected: Em.computed.equal('selectedTab', 2),
actions: { actions: {
changeTab: function(tabName){ changeTab: function(tabName){

View file

@ -46,7 +46,7 @@ export default Em.Component.extend({
} }
return groupsArrData; return groupsArrData;
}.property('groupsData', 'lightsData', 'groupSelection'), }.property('groupsData', 'lightsData', 'groupIdSelection'),
onGroupIdSelectionChanged: function(){ onGroupIdSelectionChanged: function(){
var groupIdSelection = this.get('groupIdSelection'), lights = []; var groupIdSelection = this.get('groupIdSelection'), lights = [];

View file

@ -5,63 +5,58 @@ export default Em.Component.extend({
classNames: ['container-fluid'], classNames: ['container-fluid'],
actions: { beatOptions: {
play: function () { threshold: {
if (this.get('playing')) { range: {min: 0.1, max: 0.6},
this.get('dancer').pause(); defaultValue: 0.3,
} else { pips: {
this.get('dancer').play(); mode: 'positions',
values: [0,20,40,60,80,100],
density: 3,
format: {
to: function ( value ) {return value;},
from: function ( value ) { return value; }
}
} }
this.toggleProperty('playing');
}, },
volumeSliderChanged: function (volume) { decay: {
this.set('volume', volume); range: {min: 0.01, max: 0.1},
localStorage.setItem('huegasm.volume', volume); step: 0.01,
}, defaultValue: 0.02,
pips: {
next: function () { mode: 'positions',
values: [0,20,40,60,80,100],
}, density: 3,
previous: function () { format: {
to: function ( value ) {return value;},
}, from: function ( value ) { return value; }
}
fullscreen: function () {
},
seekChanged: function () {
},
toggleMute: function () {
this.toggleProperty('volumeMuted');
if(this.get('volumeMuted')){
dancer.setVolume(0);
} else {
dancer.setVolume(this.get('volume')/100);
} }
localStorage.setItem('huegasm.volumeMuted', this.get('volumeMuted'));
}, },
frequency: {
toggleShuffle: function () { range: {min: 0, max: 10},
this.toggleProperty('shuffle'); step: 1,
localStorage.setItem('huegasm.shuffle', this.get('shuffle')); defaultValue: [0,5],
}, pips: {
mode: 'values',
toggleRepeat: function () { values: [0,2,4,6,8,10],
var repeat = (this.get('repeat') + 1) % 3; density: 10,
this.set('repeat', repeat); format: {
localStorage.setItem('huegasm.repeat', repeat); to: function ( value ) {return value;},
}, from: function ( value ) { return value; }
}
addAudio: function () { }
Em.$('#fileInput').click();
} }
}, },
threshold: 0.3,
decay: 0.02,
frequency: [0,5],
playQueue: [],
timeElapsed: 0,
timeTotal: 0,
// 0 - no repeat, 1 - repeat all, 2 - repeat one // 0 - no repeat, 1 - repeat all, 2 - repeat one
repeat: 0, repeat: 0,
shuffle: false, shuffle: false,
@ -70,6 +65,110 @@ export default Em.Component.extend({
paused: false, paused: false,
playing: false, playing: false,
incrementElapseTimeHandle: null,
incrementElapseTime: function(){
this.incrementProperty('timeElapsed');
},
actions: {
defaultControls: function(){
var beatOptions = this.get('beatOptions');
this.changePlayerControl('threshold', beatOptions.threshold.defaultValue, true);
this.changePlayerControl('decay', beatOptions.decay.defaultValue, true);
this.changePlayerControl('frequency', beatOptions.frequency.defaultValue, true);
},
clickLight:function() {
debugger;
},
play: function () {
var dancer = this.get('dancer'),
playQueue = this.get('playQueue');
if (this.get('playing')) {
dancer.pause();
clearInterval(this.get('incrementElapseTimeHandle'));
this.toggleProperty('playing');
this.set('timeElapsed', Math.floor(dancer.getTime()));
} else if(playQueue.length > 0) {
if(this.get('volumeMuted')) {
dancer.setVolume(0);
} else {
dancer.setVolume(this.get('volume')/100);
}
dancer.play();
this.set('incrementElapseTimeHandle', window.setInterval(this.incrementElapseTime.bind(this), 1000));
this.toggleProperty('playing');
}
},
volumeChanged: function (value) {
this.changePlayerControl('volume', value);
if(this.get('playing')) {
this.get('dancer').setVolume(value/100);
}
},
next: function () {
},
previous: function () {
},
fullscreen: function () {
},
seekChanged: function () {
},
volumeMutedChanged: function (value) {
var dancer = this.get('dancer'),
volumeMuted = Em.isNone(value) ? !this.get('volumeMuted') : value;
this.changePlayerControl('volumeMuted', volumeMuted);
if(this.get('playing')){
if(volumeMuted){
dancer.setVolume(0);
} else {
dancer.setVolume(this.get('volume')/100);
}
}
},
shuffleChanged: function (value) {
this.changePlayerControl('shuffle', Em.isNone(value) ? !this.get('shuffle') : value);
},
repeatChanged: function (value) {
this.changePlayerControl('repeat', Em.isNone(value) ? (this.get('repeat') + 1) % 3 : value);
},
thresholdChanged: function(value) {
this.changePlayerControl('threshold', value, true);
},
decayChanged: function(value){
this.changePlayerControl('decay', value, true);
},
frequencyChanged: function(value){
this.changePlayerControl('frequency', value, true);
},
addAudio: function () {
Em.$('#fileInput').click();
},
clickSpeaker: function(){
// simulate the speaker vibration by running a CSS animation on it
Em.$('#beatSpeakerCenter').removeClass('pop').prop('offsetWidth', Em.$('#beatSpeakerCenter').prop('offsetWidth')).addClass('pop');
}
},
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);
},
repeatIcon: function () { repeatIcon: function () {
if (this.get('repeat') === 2) { if (this.get('repeat') === 2) {
return 'repeat-one'; return 'repeat-one';
@ -159,12 +258,6 @@ export default Em.Component.extend({
this.changeTooltipText(type, tooltipTxt); this.changeTooltipText(type, tooltipTxt);
}.observes('playing').on('init'), }.observes('playing').on('init'),
onVolumeChange: function(){
if(this.get('playing')){
this.get('dancer').setVolume(this.get('volume')/100);
}
}.observes('volume').on('init'),
changeTooltipText: function (type, text) { changeTooltipText: function (type, text) {
// change the tooltip text if it's already visible // change the tooltip text if it's already visible
Em.$('#' + type + 'Tooltip + .tooltip .tooltip-inner').html(text); Em.$('#' + type + 'Tooltip + .tooltip .tooltip-inner').html(text);
@ -177,39 +270,49 @@ export default Em.Component.extend({
return this.get('playQueue').length > 1; return this.get('playQueue').length > 1;
}.property('playQueue.[]'), }.property('playQueue.[]'),
playQueue: [], timeElapsedTxt: function(){
timeElapsed: 0, return this.formatTime(this.get('timeElapsed'));
timeReamining: 0, }.property('timeElapsed'),
timeElapsedTxt: '0:00', timeTotalTxt: function() {
timeRemainingTxt: '0:00', return this.formatTime(this.get('timeTotal'));
}.property('timeTotal'),
formatTime: function(time){
return this.pad(Math.floor(time/60), 2) + ':' + this.pad(time%60, 2);
},
pad: function(num, size){ return ('000000000' + num).substr(-size); },
init: function () { init: function () {
this._super(); this._super();
var dancer = new Dancer(), var dancer = new Dancer(),
self = this, self = this,
briOff = function (i) { threshold = this.get('threshold'),
Em.$.ajax(self.get('apiURL') + '/lights/' + i + '/state', { decay = this.get('decay'),
data: JSON.stringify({'bri': 1, 'transitiontime': 0}), frequency = this.get('frequency'),
contentType: 'application/json', //briOff = function (i) {
type: 'PUT' // Em.$.ajax(self.get('apiURL') + '/lights/' + i + '/state', {
}); // data: JSON.stringify({'bri': 1, 'transitiontime': 0}),
}, // contentType: 'application/json',
// type: 'PUT'
// });
//},
kick = dancer.createKick({ kick = dancer.createKick({
threshold: 0.45, threshold: threshold,
frequency: [0, 3], decay: decay,
frequency: frequency,
onKick: function (mag) { onKick: function (mag) {
if (self.get('paused') === false) { if (self.get('paused') === false) {
for (let i = 1; i <= 1; i++) { //for (let i = 1; i <= 1; i++) {
Em.$.ajax(self.get('apiURL') + '/lights/' + i + '/state', { // Em.$.ajax(self.get('apiURL') + '/lights/' + i + '/state', {
data: JSON.stringify({'bri': 254, 'transitiontime': 0}), // data: JSON.stringify({'bri': 254, 'transitiontime': 0}),
contentType: 'application/json', // contentType: 'application/json',
type: 'PUT' // type: 'PUT'
}); // });
//
setTimeout(briOff, 50, i); // setTimeout(briOff, 50, i);
} //}
self.set('paused', true); self.set('paused', true);
@ -217,6 +320,8 @@ export default Em.Component.extend({
self.set('paused', false); self.set('paused', false);
}, 150); }, 150);
self.send('clickSpeaker');
console.log('Kick at ' + mag); console.log('Kick at ' + mag);
} }
@ -225,42 +330,57 @@ export default Em.Component.extend({
kick.on(); kick.on();
['volume', 'shuffle', 'repeat', 'volumeMuted'].forEach(function (item) { dancer.bind('loaded', function(){
if (localStorage.getItem('huegasm.' + item)) { self.set('timeTotal', dancer.audio.duration);
var itemVal = localStorage.getItem('huegasm.' + item);
if (item === 'repeat' || item === 'volume') {
itemVal = Number(itemVal);
} else {
itemVal = (itemVal === 'true');
}
self.set(item, itemVal);
}
}); });
this.setProperties({ this.setProperties({
dancer: dancer, dancer: dancer,
kick: kick kick: kick
}); });
['volume', 'shuffle', 'repeat', 'volumeMuted', 'threshold', 'decay', 'frequency'].forEach(function (item) {
if (localStorage.getItem('huegasm.' + item)) {
var itemVal = localStorage.getItem('huegasm.' + item);
if (item === 'repeat' || item === 'volume' || item === 'decay' || item === 'threshold') {
itemVal = Number(itemVal);
} else if(item === 'frequency') {
itemVal = itemVal.split(',').map(function(val){return Number(val);});
} else {
itemVal = (itemVal === 'true');
}
self.send(item+'Changed', itemVal);
}
});
}, },
didInsertElement: function () { didInsertElement: function () {
var dancer = this.get('dancer'), self = this, playQueue = this.get('playQueue'); var self = this, playQueue = this.get('playQueue');
Em.$('#fileInput').on('change', function () { Em.$('#fileInput').on('change', function () {
var files = this.files, var files = this.files,
updatePlayQueue = function(){ updatePlayQueue = function(){
var tags = ID3.getAllTags("local"); var tags = ID3.getAllTags("local");
playQueue.push({filaneme: this.name, url: URL.createObjectURL(this), artist: tags.artist, title: tags.title }); playQueue.push({filename: this.name.replace(/\.[^/.]+$/, ""), url: URL.createObjectURL(this), artist: tags.artist, title: tags.title });
ID3.clearAll();
self.notifyPropertyChange('playQueue'); self.notifyPropertyChange('playQueue');
// make sure to init the first song
if(playQueue.length > 0 && !self.get('dancer').isLoaded()){
var a = new Audio();
a.src = playQueue[0].url;
self.get('dancer').load(a);
}
}; };
for (var key in files) { for (var key in files) {
if (files.hasOwnProperty(key)) { if (files.hasOwnProperty(key)) {
var file = files[key]; var file = files[key];
ID3.loadTags("local", updatePlayQueue.bind(file),{ ID3.loadTags("local", updatePlayQueue.bind(file),{
dataReader: FileAPIReader(file) dataReader: new FileAPIReader(file)
}); });
} }
} }

View file

@ -1,5 +1,4 @@
import Em from 'ember'; import Em from 'ember';
export default Em.Component.extend({ export default Em.Component.extend({
classNames: ['innerControlFrame']
}); });

View file

@ -82,12 +82,12 @@ export default Em.Component.extend({
type = 'a19'; type = 'a19';
} }
var activeClass = 'active'; var activeClass = 'lightActive';
if(!this.get('activeLights').contains(key)){ if(!this.get('activeLights').contains(key)){
activeClass = 'inactive'; activeClass = 'lightInactive';
} else if(!lightsData[key].state.reachable){ } else if(!lightsData[key].state.reachable){
activeClass = 'unreachable'; activeClass = 'lightUnreachable';
} }
lightsList.push({type: type, name: lightsData[key].name, id: key, data: lightsData[key], activeClass: activeClass}); lightsList.push({type: type, name: lightsData[key].name, id: key, data: lightsData[key], activeClass: activeClass});

View file

View file

@ -5,10 +5,21 @@
$playerBackColor: #F12B24; $playerBackColor: #F12B24;
$playerHeight: 400px; $playerHeight: 400px;
$playerBeatAreaHeight: 320px;
$playListBackgroundColor: #1E1E1E; $playListBackgroundColor: #1E1E1E;
$playerDefaultIconColor: #BBBBBB; $playerDefaultIconColor: #BBBBBB;
// BRIDGE FINDER // BRIDGE FINDER
.footer .container {
padding-left: 0;
margin-top: 30px;
text-align: center;
}
.cursorPointer {
cursor: pointer;
}
#finderContainer { #finderContainer {
text-align: center; text-align: center;
margin-top: 40px; margin-top: 40px;
@ -16,7 +27,8 @@ $playerDefaultIconColor: #BBBBBB;
#finderContainer .title { #finderContainer .title {
font-family: 'Slabo 27px', serif; font-family: 'Slabo 27px', serif;
font-size: 22px; font-size: 30px;
margin-bottom: 30px;
} }
#bridgeInput { #bridgeInput {
@ -55,7 +67,6 @@ md-content {
} }
.navigationItem { .navigationItem {
cursor: pointer;
font-family: 'Slabo 27px', serif; font-family: 'Slabo 27px', serif;
font-size: 18px; font-size: 18px;
padding: 0 10px 0 10px; padding: 0 10px 0 10px;
@ -76,6 +87,10 @@ md-content {
} }
// LIGHT GROUP // LIGHT GROUP
.paper-sidenav {
overflow: visible;
}
.groupPanel { .groupPanel {
//border-right: 1px solid black; //border-right: 1px solid black;
} }
@ -87,18 +102,31 @@ md-content {
.hueLight { .hueLight {
margin-right: 10px; margin-right: 10px;
border-radius: 20px; border-radius: 20px;
background-color: white;
} }
.hueLight.inactive { .lightInactive {
cursor: pointer; cursor: pointer;
background-color: rgba(192, 192, 192, 0.7); position: relative;
} }
.hueLight.unreachable { .lightInactive::before {
font-weight: bold;
position: absolute;
content: "X";
top: -20px;
left: 6px;
font-size: 40px;
color: rgba(255, 0, 0, 0.37);
font-family: cursive;
}
.lightUnreachable {
background-color: rgba(255, 0, 0, 0.7); background-color: rgba(255, 0, 0, 0.7);
} }
.hueLight.active:hover { .lightActive:hover {
cursor: pointer; cursor: pointer;
-webkit-transition-duration: 0.5s; -webkit-transition-duration: 0.5s;
transition-duration: 0.5s; transition-duration: 0.5s;
@ -120,13 +148,15 @@ md-icon.menu {
margin: 30px 0 0 16px; margin: 30px 0 0 16px;
} }
.addButton { .addButton .group-add {
cursor: pointer;
margin-right: 16px; margin-right: 16px;
} }
.addButton .group-add:hover {
color: darken(#333333, 20%) !important;
}
.removeButton { .removeButton {
cursor: pointer;
margin: 10px 0 10px auto; margin: 10px 0 10px auto;
} }
@ -159,7 +189,6 @@ md-toolbar {
.groupSelect { .groupSelect {
padding: 10px 0 10px 0; padding: 10px 0 10px 0;
cursor: pointer;
width: 70%; width: 70%;
font-family: 'Open Sans', sans-serif; font-family: 'Open Sans', sans-serif;
} }
@ -218,9 +247,9 @@ md-toolbar {
.playerControllIcon { .playerControllIcon {
color: $playerDefaultIconColor !important; color: $playerDefaultIconColor !important;
cursor: pointer;
transition-duration: 0.1s; transition-duration: 0.1s;
margin-right: 5px; margin-right: 5px;
cursor: pointer;
} }
.playerControllIcon.active { .playerControllIcon.active {
@ -246,29 +275,36 @@ md-toolbar {
background-color: $playListBackgroundColor; background-color: $playListBackgroundColor;
} }
.noUi-origin { #playerArea * .noUi-origin {
background-color: black; background-color: black;
border-radius: 5px; border-radius: 5px;
} }
.noUi-base { #playerArea * .noUi-base {
background-color: $playerBackColor; background-color: $playerBackColor;
border-radius: 5px; border-radius: 5px;
cursor: pointer; cursor: pointer;
} }
.noUi-connect {
background-color: $playerBackColor;
}
#volumeBar { #volumeBar {
width: 100px; width: 100px;
height: 8px; height: 8px;
display: inline-block; display: inline-block;
} }
.noUi-handle {
cursor: pointer;
}
.noUi-horizontal .noUi-handle { .noUi-horizontal .noUi-handle {
width: 7px; width: 7px;
height: 21px; height: 21px;
left: -1px; left: -1px;
top: -8px; top: -8px;
cursor: pointer;
transition-duration: 0.1s; transition-duration: 0.1s;
background: $playerDefaultIconColor !important; background: $playerDefaultIconColor !important;
} }
@ -277,7 +313,7 @@ md-toolbar {
background: white !important; background: white !important;
} }
.noUi-handle:after, .noUi-handle:before { #playerArea * .noUi-handle:after, #playerArea * .noUi-handle:before {
content: none; content: none;
} }
@ -330,5 +366,83 @@ md-toolbar {
.playlistItem { .playlistItem {
color: darken(white, 20%); color: darken(white, 20%);
margin: 10px 5px 10px 5px; margin: 0.714em 0.357em 0.714em 0.357em;
}
#beatArea {
position: relative;
height: $playerBeatAreaHeight;
}
#beatArea * .noUi-target {
margin: 0 auto;
}
#beatArea * .noUi-base, #beatArea * .noUi-background {
background-color: #3F3F3F;
}
#beatArea * .noUi-vertical {
height: 150px;
margin-top: 20px;
}
.beatOption {
display: inline-block;
margin-left: 0.714em;
}
#playerBottom {
background-color: grey;
}
#beatSpeakerContainer {
position: relative;
height: $playerBeatAreaHeight;
}
#beatSpeaker {
margin: 20px auto 0 auto;
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: 21%;
left: 22%;
}
.pop {
animation-name: pop;
animation-duration: 0.1s;
animation-timing-function: linear;
animation-iteration-count: 1;
}
@keyframes pop {
50% {
transform: scale(1.1);
}
}
#beatArea .lightGroup {
margin: 10px 0 20px 40px;
}
#playerButtonGroup {
margin-top: 10px;
}
#vertDivider {
position: absolute;
right: 40px;
top: 25%;
width: 1px;
height: 50%;
background-color: white;
} }

View file

@ -1,8 +1,8 @@
{{#liquid-if lightsData}} {{#liquid-if lightsData}}
{{#paper-nav-container open=drawerOpen class="ember-app"}} {{#paper-nav-container class="ember-app"}}
{{#paper-sidenav class="md-sidenav-left md-whiteframe-z2" flex-layout="column" flex=true}} {{#paper-sidenav class="md-sidenav-left md-whiteframe-z2" flex-layout="column" flex=true locked-open="lg"}}
{{controls/group-control lightsData=lightsData groupsData=groupsData activeLights=activeLights apiURL=apiURL updateGroupsData=updateGroupsData}} {{controls/group-control lightsData=lightsData groupsData=groupsData activeLights=activeLights apiURL=apiURL updateGroupsData=updateGroupsData}}
{{/paper-sidenav}} {{/paper-sidenav}}
@ -14,7 +14,7 @@
{{#paper-content flex-layout="column" flex=true}} {{#paper-content flex-layout="column" flex=true}}
<div class="navigation"> <div class="navigation">
{{#each tabData as |tab|}} {{#each tabData as |tab|}}
<span class="navigationItem {{if tab.selected "active" ""}} text-uppercase" {{action "changeTab" tab.name}}>{{tab.name}}</span> <span class="navigationItem cursorPointer {{if tab.selected "active" ""}} text-uppercase" {{action "changeTab" tab.name}}>{{tab.name}}</span>
{{/each}} {{/each}}
</div> </div>
@ -22,10 +22,6 @@
{{controls/light-control apiURL=apiURL lightsData=lightsData activeLights=activeLights}} {{controls/light-control apiURL=apiURL lightsData=lightsData activeLights=activeLights}}
{{/liquid-if}} {{/liquid-if}}
{{#liquid-if scenesTabSelected class="tabSwitch"}}
{{controls/scene-control apiURL=apiURL lightsData=lightsData activeLights=activeLights}}
{{/liquid-if}}
{{#liquid-if musicTabSelected class="tabSwitch"}} {{#liquid-if musicTabSelected class="tabSwitch"}}
{{controls/music-control apiURL=apiURL lightsData=lightsData activeLights=activeLights}} {{controls/music-control apiURL=apiURL lightsData=lightsData activeLights=activeLights}}
{{/liquid-if}} {{/liquid-if}}
@ -34,4 +30,5 @@
{{/paper-nav-container}} {{/paper-nav-container}}
{{huegasm-footer}}
{{/liquid-if}} {{/liquid-if}}

View file

@ -1,10 +1,10 @@
<span class="title">Huegasm</span> <div class="title">Huegasm</div>
{{#unless bridgeUsername}} {{#unless bridgeUsername}}
{{#if bridgeIp}} {{#if bridgeIp}}
<img src="assets/images/pressButtonBridge.png" id="pressButtonBridgeImg"> <img src="assets/images/pressButtonBridge.png" id="pressButtonBridgeImg">
{{paper-progress-linear warn=true value=bridgeUserNamePingIntervalProgress}} {{paper-progress-linear warn=true value=bridgeUserNamePingIntervalProgress}}
{{#if isAuthenticating}} {{#if isAuthenticating}}
<p>Your bridge IP is <b>{{bridgeIp}}</b> <p>Your bridge IP is <b>{{bridgeIp}}</b> <br>
Press the button on your bridge to authenticate this application.</p> Press the button on your bridge to authenticate this application.</p>
{{else}} {{else}}
<p>You failed to press the button. <a class="noTextDecoration" href="#" {{action 'retry'}}>RETRY</a></p> <p>You failed to press the button. <a class="noTextDecoration" href="#" {{action 'retry'}}>RETRY</a></p>

View file

@ -1,10 +1,10 @@
{{#paper-content}} {{#paper-content}}
<h3 class="sideNavTitle">Light Groups<span title="Add Group" class="addButton pull-right" {{action "toggleAddGroupsModal"}}>{{paper-icon icon="group-add"}}</span></h3> <h3 class="sideNavTitle">Light Groups<span data-toggle="tooltip" data-placement="top auto" title="Add Group" class="addButton pull-right cursorPointer" {{action "toggleAddGroupsModal"}}>{{paper-icon icon="group-add"}}</span></h3>
{{#paper-list}} {{#paper-list}}
{{#each groupsArrData as |group|}} {{#each groupsArrData as |group|}}
{{#paper-item class=group.rowClass}} {{#paper-item class=group.rowClass}}
<div class="groupSelect" {{action "selectGroup" group.data.key}}>{{group.name}}</div> {{#if group.deletable}}<span title="Remove Group" class="removeButton" {{action "toggleConfirmDeleteGroupsModal" group.name group.data.key}}>{{paper-icon icon="close"}}</span>{{/if}} <div class="groupSelect cursorPointer" {{action "selectGroup" group.data.key}}>{{group.name}}</div> {{#if group.deletable}}<span data-toggle="tooltip" data-placement="bottom auto" title="Remove Group" class="removeButton cursorPointer" {{action "toggleConfirmDeleteGroupsModal" group.name group.data.key}}>{{paper-icon icon="close"}}</span>{{/if}}
{{/paper-item}} {{/paper-item}}
{{/each}} {{/each}}
{{/paper-list}} {{/paper-list}}

View file

@ -1,20 +1,23 @@
<div class="row" xmlns="http://www.w3.org/1999/html"> <div class="row">
<div id="playerArea" class="col-xs-8"> <div id="playerArea" class="col-xs-8">
<div id="playerControls"> <div id="playerControls">
{{range-slider start=0 min=0 max=100 id="seekSlider" change="seekChanged" }} {{range-slider start=0 min=0 max=100 id="seekSlider" slide="seekChanged" }}
<!-- This code is intentionally unindented to avoid creating white spaces which would later be removed by bootstrap's tooltip plugin and cause the content to slightly shift -->
{{#if nextPrevEnabled}} {{#if nextPrevEnabled}}
<span data-toggle="tooltip" data-placement="top" title="Previous" <span data-toggle="tooltip" data-placement="top" title="Previous"
id="prevTooltip" {{action "previous"}}>{{paper-icon icon="skip-previous" class="playerControllIcon"}} </span>{{/if}}<span data-toggle="tooltip" data-placement="top" id="prevTooltip" {{action "previous"}}>{{paper-icon icon="skip-previous" class="playerControllIcon"}} </span>{{/if}}<!--
title={{playingTooltipTxt}} id="playingTooltip" {{action "play"}}>{{paper-icon icon=playingIcon class="playerControllIcon"}}</span>{{#if nextPrevEnabled}} --><span data-toggle="tooltip" data-placement="top"
<span data-toggle="tooltip" data-placement="top" title={{playingTooltipTxt}} id="playingTooltip" {{action "play"}}>{{paper-icon icon=playingIcon class="playerControllIcon"}}</span><!--
title="Next song" {{action "next"}}>{{paper-icon icon="skip-next" action="" class="playerControllIcon"}}</span> -->{{#if nextPrevEnabled}}
{{/if}}<span data-toggle="tooltip" data-placement="top" <span data-toggle="tooltip" data-placement="top"
title={{volumeMutedTooltipTxt}} id="volumeMutedTooltip" {{action "toggleMute"}}>{{paper-icon icon=volumeClass class="playerControllIcon volumeButton"}}</span>{{range-slider start=volume min=0 max=100 change="volumeSliderChanged" id="volumeBar"}} title="Next song" {{action "next"}}>{{paper-icon icon="skip-next" action="" class="playerControllIcon"}}</span>
{{/if}}<!--
--><span data-toggle="tooltip" data-placement="top"
title={{volumeMutedTooltipTxt}} id="volumeMutedTooltip" {{action "volumeMutedChanged"}}>{{paper-icon icon=volumeClass class="playerControllIcon volumeButton"}}</span><!--
-->{{range-slider start=volume min=0 max=100 slide="volumeChanged" id="volumeBar"}}
<span id="playerTimeControls">{{timeElapsedTxt}} / {{timeRemainingTxt}}</span> <span id="playerTimeControls">{{timeElapsedTxt}} / {{timeTotalTxt}}</span>
<span class="pull-right"> <span class="pull-right">
<span data-toggle="tooltip" data-placement="top" <span data-toggle="tooltip" data-placement="top"
@ -25,13 +28,14 @@
</div> </div>
<div id="playlist" class="col-xs-4"> <div id="playlist" class="col-xs-4">
<input id="fileInput" type="file" accept="audio/*" multiple="true" /> <input id="fileInput" type="file" accept="audio/*" multiple="true"/>
<div id="playListControls"> <div id="playListControls">
<span data-toggle="tooltip" data-placement="bottom" title={{shuffleTooltipTxt}} id="shuffleTooltip" {{action "toggleShuffle"}}>{{paper-icon icon="shuffle" class=shuffleClass}}</span> <span data-toggle="tooltip" data-placement="bottom auto"
title={{shuffleTooltipTxt}} id="shuffleTooltip" {{action "shuffleChanged"}}>{{paper-icon icon="shuffle" class=shuffleClass}}</span>
<span data-toggle="tooltip" data-placement="bottom" <span data-toggle="tooltip" data-placement="bottom auto"
title={{repeatTooltipTxt}} id="repeatTooltip" {{action "toggleRepeat"}}>{{paper-icon icon=repeatIcon class=repeatClass}}</span> title={{repeatTooltipTxt}} id="repeatTooltip" {{action "repeatChanged"}}>{{paper-icon icon=repeatIcon class=repeatClass}}</span>
<span data-toggle="tooltip" data-placement="bottom" title="Add new music" <span data-toggle="tooltip" data-placement="bottom" title="Add new music"
class="pull-right" {{action "addAudio"}}>{{paper-icon icon="add" class="playerControllIcon" }}</span> class="pull-right" {{action "addAudio"}}>{{paper-icon icon="add" class="playerControllIcon" }}</span>
@ -39,12 +43,48 @@
<div id="playListArea"> <div id="playListArea">
{{#each playQueue as |item|}} {{#each playQueue as |item|}}
<div class="playlistItem">{{#if item.title}} <div class="playlistItem">
{{item.artist}} - {{item.title}} {{#if item.title}}
{{else}} {{item.artist}} - {{item.title}}
{{item.filename}} {{else}}
{{/if}}</div> {{item.filename}}
{{/if}}</div>
{{/each}} {{/each}}
</div> </div>
</div> </div>
</div> </div>
<div id="playerBottom" class="row">
<span id="beatArea" class="col-xs-7">
<div id="vertDivider"></div>
{{light-group lightsData=lightsData activeLights=activeLights action='clickLight' apiURL=apiURL noHover=true}}
<span class="beatOption">
{{range-slider start=threshold orientation="vertical" range=beatOptions.threshold.range slide="thresholdChanged" pips=beatOptions.threshold.pips}}
Beat Threshold
</span>
<span class="beatOption">
{{range-slider start=decay orientation="vertical" step=beatOptions.decay.step range=beatOptions.decay.range slide="decayChanged" pips=beatOptions.decay.pips}}
Beat Decay
</span>
<span class="beatOption">
{{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
</span>
<div id="playerButtonGroup">
{{#paper-button raised=true warn=true action="defaultControls"}}Default{{/paper-button}}
</div>
</span>
<span id="beatSpeakerContainer" class="col-xs-5">
<div id="beatSpeaker">
<span id="beatSpeakerCenter"
class="beatSpeakerCenter cursorPointer" {{action "clickSpeaker"}}></span>
</div>
</span>
</div>

View file

@ -1,5 +0,0 @@
{{#paper-list}}
{{#paper-item}}
TODO
{{/paper-item}}
{{/paper-list}}

View file

@ -2,4 +2,6 @@
{{bridge-controls bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial}} {{bridge-controls bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial}}
{{else}} {{else}}
{{bridge-finder bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial}} {{bridge-finder bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial}}
{{huegasm-footer}}
{{/liquid-if}} {{/liquid-if}}

View file

@ -0,0 +1,5 @@
<footer class="footer">
<div class="container">
<p class="text-muted">Made with ¯\_(ツ)_/¯ by <a href="//egorphilippov.me">egorphilippov.me</a> © 2015 Huegasm</p>
</div>
</footer>

View file

@ -1,3 +1,5 @@
{{#each lightsList as |light|}} {{#each lightsList as |light|}}
<img class="hueLight light.id {{light.activeClass}}" {{action "clickLight" light.id light.data}} {{action "lightStartHover" light.id on="mouseEnter"}} {{action "lightStopHover" light.id on="mouseLeave"}} width="40" title="{{light.name}}" src="assets/images/lights/{{light.type}}.svg"> <span class="{{light.activeClass}}" data-toggle="tooltip" data-placement="top auto" title="{{light.name}}" {{action "clickLight" light.id light.data}} {{action "lightStartHover" light.id on="mouseEnter"}} {{action "lightStopHover" light.id on="mouseLeave"}}>
<img class="hueLight" width="40" src="assets/images/lights/{{light.type}}.svg">
</span>
{{/each}} {{/each}}

BIN
assets/speaker.psd Normal file

Binary file not shown.

BIN
assets/speaker2.psd Normal file

Binary file not shown.

View file

@ -14,6 +14,7 @@
"JavaScript-ID3-Reader": "https://github.com/aadsm/JavaScript-ID3-Reader.git", "JavaScript-ID3-Reader": "https://github.com/aadsm/JavaScript-ID3-Reader.git",
"jquery": "^1.11.1", "jquery": "^1.11.1",
"loader.js": "ember-cli/loader.js#3.2.0", "loader.js": "ember-cli/loader.js#3.2.0",
"material-design-icons": "~2.0.0",
"nouislider": "^8.0.1", "nouislider": "^8.0.1",
"qunit": "~1.18.0" "qunit": "~1.18.0"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -0,0 +1,26 @@
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('huegasm-footer', 'Integration | Component | huegasm footer', {
integration: true
});
test('it renders', function(assert) {
assert.expect(2);
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });
this.render(hbs`{{huegasm-footer}}`);
assert.equal(this.$().text().trim(), '');
// Template block usage:
this.render(hbs`
{{#huegasm-footer}}
template block text
{{/huegasm-footer}}
`);
assert.equal(this.$().text().trim(), 'template block text');
});