Weekend work push
This commit is contained in:
parent
2ef9a62a38
commit
8f2e697b24
23 changed files with 458 additions and 157 deletions
|
|
@ -5,5 +5,5 @@
|
|||
|
||||
Setting `disableAnalytics` to true will prevent any data from being sent.
|
||||
*/
|
||||
"disableAnalytics": false
|
||||
"disableAnalytics": true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
"window",
|
||||
"-Promise",
|
||||
"Dancer",
|
||||
"ID3"
|
||||
"ID3",
|
||||
"FileAPIReader"
|
||||
],
|
||||
"browser": true,
|
||||
"boss": true,
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ export default Em.Component.extend({
|
|||
this.toggleProperty('updateGroupsData');
|
||||
},
|
||||
|
||||
tabList: ["Lights", "Scenes", "Music"],
|
||||
selectedTab: 2,
|
||||
tabList: ["Music", "Lights"],
|
||||
selectedTab: 0,
|
||||
tabData: function(){
|
||||
var tabData = [], selectedTab = this.get('selectedTab');
|
||||
|
||||
|
|
@ -61,9 +61,8 @@ export default Em.Component.extend({
|
|||
return tabData;
|
||||
}.property('tabList', 'selectedTab'),
|
||||
|
||||
lightsTabSelected: Em.computed.equal('selectedTab', 0),
|
||||
scenesTabSelected: Em.computed.equal('selectedTab', 1),
|
||||
musicTabSelected: Em.computed.equal('selectedTab', 2),
|
||||
lightsTabSelected: Em.computed.equal('selectedTab', 1),
|
||||
musicTabSelected: Em.computed.equal('selectedTab', 0),
|
||||
|
||||
actions: {
|
||||
changeTab: function(tabName){
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ export default Em.Component.extend({
|
|||
}
|
||||
|
||||
return groupsArrData;
|
||||
}.property('groupsData', 'lightsData', 'groupSelection'),
|
||||
}.property('groupsData', 'lightsData', 'groupIdSelection'),
|
||||
|
||||
onGroupIdSelectionChanged: function(){
|
||||
var groupIdSelection = this.get('groupIdSelection'), lights = [];
|
||||
|
|
|
|||
|
|
@ -5,63 +5,58 @@ export default Em.Component.extend({
|
|||
|
||||
classNames: ['container-fluid'],
|
||||
|
||||
actions: {
|
||||
play: function () {
|
||||
if (this.get('playing')) {
|
||||
this.get('dancer').pause();
|
||||
} else {
|
||||
this.get('dancer').play();
|
||||
beatOptions: {
|
||||
threshold: {
|
||||
range: {min: 0.1, max: 0.6},
|
||||
defaultValue: 0.3,
|
||||
pips: {
|
||||
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) {
|
||||
this.set('volume', volume);
|
||||
localStorage.setItem('huegasm.volume', volume);
|
||||
},
|
||||
|
||||
next: function () {
|
||||
|
||||
},
|
||||
previous: function () {
|
||||
|
||||
},
|
||||
|
||||
fullscreen: function () {
|
||||
|
||||
},
|
||||
|
||||
seekChanged: function () {
|
||||
|
||||
},
|
||||
|
||||
toggleMute: function () {
|
||||
this.toggleProperty('volumeMuted');
|
||||
|
||||
if(this.get('volumeMuted')){
|
||||
dancer.setVolume(0);
|
||||
} else {
|
||||
dancer.setVolume(this.get('volume')/100);
|
||||
decay: {
|
||||
range: {min: 0.01, max: 0.1},
|
||||
step: 0.01,
|
||||
defaultValue: 0.02,
|
||||
pips: {
|
||||
mode: 'positions',
|
||||
values: [0,20,40,60,80,100],
|
||||
density: 3,
|
||||
format: {
|
||||
to: function ( value ) {return value;},
|
||||
from: function ( value ) { return value; }
|
||||
}
|
||||
}
|
||||
|
||||
localStorage.setItem('huegasm.volumeMuted', this.get('volumeMuted'));
|
||||
},
|
||||
|
||||
toggleShuffle: function () {
|
||||
this.toggleProperty('shuffle');
|
||||
localStorage.setItem('huegasm.shuffle', this.get('shuffle'));
|
||||
},
|
||||
|
||||
toggleRepeat: function () {
|
||||
var repeat = (this.get('repeat') + 1) % 3;
|
||||
this.set('repeat', repeat);
|
||||
localStorage.setItem('huegasm.repeat', repeat);
|
||||
},
|
||||
|
||||
addAudio: function () {
|
||||
Em.$('#fileInput').click();
|
||||
frequency: {
|
||||
range: {min: 0, max: 10},
|
||||
step: 1,
|
||||
defaultValue: [0,5],
|
||||
pips: {
|
||||
mode: 'values',
|
||||
values: [0,2,4,6,8,10],
|
||||
density: 10,
|
||||
format: {
|
||||
to: function ( value ) {return value;},
|
||||
from: function ( value ) { return value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
threshold: 0.3,
|
||||
decay: 0.02,
|
||||
frequency: [0,5],
|
||||
|
||||
playQueue: [],
|
||||
timeElapsed: 0,
|
||||
timeTotal: 0,
|
||||
|
||||
// 0 - no repeat, 1 - repeat all, 2 - repeat one
|
||||
repeat: 0,
|
||||
shuffle: false,
|
||||
|
|
@ -70,6 +65,110 @@ export default Em.Component.extend({
|
|||
paused: 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 () {
|
||||
if (this.get('repeat') === 2) {
|
||||
return 'repeat-one';
|
||||
|
|
@ -159,12 +258,6 @@ export default Em.Component.extend({
|
|||
this.changeTooltipText(type, tooltipTxt);
|
||||
}.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) {
|
||||
// change the tooltip text if it's already visible
|
||||
Em.$('#' + type + 'Tooltip + .tooltip .tooltip-inner').html(text);
|
||||
|
|
@ -177,39 +270,49 @@ export default Em.Component.extend({
|
|||
return this.get('playQueue').length > 1;
|
||||
}.property('playQueue.[]'),
|
||||
|
||||
playQueue: [],
|
||||
timeElapsed: 0,
|
||||
timeReamining: 0,
|
||||
timeElapsedTxt: '0:00',
|
||||
timeRemainingTxt: '0:00',
|
||||
timeElapsedTxt: function(){
|
||||
return this.formatTime(this.get('timeElapsed'));
|
||||
}.property('timeElapsed'),
|
||||
timeTotalTxt: function() {
|
||||
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 () {
|
||||
this._super();
|
||||
|
||||
var dancer = new Dancer(),
|
||||
self = this,
|
||||
briOff = function (i) {
|
||||
Em.$.ajax(self.get('apiURL') + '/lights/' + i + '/state', {
|
||||
data: JSON.stringify({'bri': 1, 'transitiontime': 0}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
},
|
||||
threshold = this.get('threshold'),
|
||||
decay = this.get('decay'),
|
||||
frequency = this.get('frequency'),
|
||||
//briOff = function (i) {
|
||||
// Em.$.ajax(self.get('apiURL') + '/lights/' + i + '/state', {
|
||||
// data: JSON.stringify({'bri': 1, 'transitiontime': 0}),
|
||||
// contentType: 'application/json',
|
||||
// type: 'PUT'
|
||||
// });
|
||||
//},
|
||||
kick = dancer.createKick({
|
||||
threshold: 0.45,
|
||||
frequency: [0, 3],
|
||||
threshold: threshold,
|
||||
decay: decay,
|
||||
frequency: frequency,
|
||||
onKick: function (mag) {
|
||||
|
||||
if (self.get('paused') === false) {
|
||||
for (let i = 1; i <= 1; i++) {
|
||||
Em.$.ajax(self.get('apiURL') + '/lights/' + i + '/state', {
|
||||
data: JSON.stringify({'bri': 254, 'transitiontime': 0}),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
|
||||
setTimeout(briOff, 50, i);
|
||||
}
|
||||
//for (let i = 1; i <= 1; i++) {
|
||||
// Em.$.ajax(self.get('apiURL') + '/lights/' + i + '/state', {
|
||||
// data: JSON.stringify({'bri': 254, 'transitiontime': 0}),
|
||||
// contentType: 'application/json',
|
||||
// type: 'PUT'
|
||||
// });
|
||||
//
|
||||
// setTimeout(briOff, 50, i);
|
||||
//}
|
||||
|
||||
self.set('paused', true);
|
||||
|
||||
|
|
@ -217,6 +320,8 @@ export default Em.Component.extend({
|
|||
self.set('paused', false);
|
||||
}, 150);
|
||||
|
||||
self.send('clickSpeaker');
|
||||
|
||||
console.log('Kick at ' + mag);
|
||||
}
|
||||
|
||||
|
|
@ -225,42 +330,57 @@ export default Em.Component.extend({
|
|||
|
||||
kick.on();
|
||||
|
||||
['volume', 'shuffle', 'repeat', 'volumeMuted'].forEach(function (item) {
|
||||
if (localStorage.getItem('huegasm.' + item)) {
|
||||
var itemVal = localStorage.getItem('huegasm.' + item);
|
||||
if (item === 'repeat' || item === 'volume') {
|
||||
itemVal = Number(itemVal);
|
||||
} else {
|
||||
itemVal = (itemVal === 'true');
|
||||
}
|
||||
self.set(item, itemVal);
|
||||
}
|
||||
dancer.bind('loaded', function(){
|
||||
self.set('timeTotal', dancer.audio.duration);
|
||||
});
|
||||
|
||||
this.setProperties({
|
||||
dancer: dancer,
|
||||
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 () {
|
||||
var dancer = this.get('dancer'), self = this, playQueue = this.get('playQueue');
|
||||
var self = this, playQueue = this.get('playQueue');
|
||||
|
||||
Em.$('#fileInput').on('change', function () {
|
||||
var files = this.files,
|
||||
updatePlayQueue = function(){
|
||||
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');
|
||||
|
||||
// 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) {
|
||||
if (files.hasOwnProperty(key)) {
|
||||
var file = files[key];
|
||||
|
||||
ID3.loadTags("local", updatePlayQueue.bind(file),{
|
||||
dataReader: FileAPIReader(file)
|
||||
ID3.loadTags("local", updatePlayQueue.bind(file),{
|
||||
dataReader: new FileAPIReader(file)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import Em from 'ember';
|
||||
|
||||
export default Em.Component.extend({
|
||||
classNames: ['innerControlFrame']
|
||||
});
|
||||
|
|
@ -82,12 +82,12 @@ export default Em.Component.extend({
|
|||
type = 'a19';
|
||||
}
|
||||
|
||||
var activeClass = 'active';
|
||||
var activeClass = 'lightActive';
|
||||
|
||||
if(!this.get('activeLights').contains(key)){
|
||||
activeClass = 'inactive';
|
||||
activeClass = 'lightInactive';
|
||||
} 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});
|
||||
|
|
|
|||
|
|
@ -5,10 +5,21 @@
|
|||
|
||||
$playerBackColor: #F12B24;
|
||||
$playerHeight: 400px;
|
||||
$playerBeatAreaHeight: 320px;
|
||||
$playListBackgroundColor: #1E1E1E;
|
||||
$playerDefaultIconColor: #BBBBBB;
|
||||
|
||||
// BRIDGE FINDER
|
||||
.footer .container {
|
||||
padding-left: 0;
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cursorPointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#finderContainer {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
|
|
@ -16,7 +27,8 @@ $playerDefaultIconColor: #BBBBBB;
|
|||
|
||||
#finderContainer .title {
|
||||
font-family: 'Slabo 27px', serif;
|
||||
font-size: 22px;
|
||||
font-size: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#bridgeInput {
|
||||
|
|
@ -55,7 +67,6 @@ md-content {
|
|||
}
|
||||
|
||||
.navigationItem {
|
||||
cursor: pointer;
|
||||
font-family: 'Slabo 27px', serif;
|
||||
font-size: 18px;
|
||||
padding: 0 10px 0 10px;
|
||||
|
|
@ -76,6 +87,10 @@ md-content {
|
|||
}
|
||||
|
||||
// LIGHT GROUP
|
||||
.paper-sidenav {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.groupPanel {
|
||||
//border-right: 1px solid black;
|
||||
}
|
||||
|
|
@ -87,18 +102,31 @@ md-content {
|
|||
.hueLight {
|
||||
margin-right: 10px;
|
||||
border-radius: 20px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.hueLight.inactive {
|
||||
.lightInactive {
|
||||
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);
|
||||
}
|
||||
|
||||
.hueLight.active:hover {
|
||||
.lightActive:hover {
|
||||
cursor: pointer;
|
||||
-webkit-transition-duration: 0.5s;
|
||||
transition-duration: 0.5s;
|
||||
|
|
@ -120,13 +148,15 @@ md-icon.menu {
|
|||
margin: 30px 0 0 16px;
|
||||
}
|
||||
|
||||
.addButton {
|
||||
cursor: pointer;
|
||||
.addButton .group-add {
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.addButton .group-add:hover {
|
||||
color: darken(#333333, 20%) !important;
|
||||
}
|
||||
|
||||
.removeButton {
|
||||
cursor: pointer;
|
||||
margin: 10px 0 10px auto;
|
||||
}
|
||||
|
||||
|
|
@ -159,7 +189,6 @@ md-toolbar {
|
|||
|
||||
.groupSelect {
|
||||
padding: 10px 0 10px 0;
|
||||
cursor: pointer;
|
||||
width: 70%;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
}
|
||||
|
|
@ -218,9 +247,9 @@ md-toolbar {
|
|||
|
||||
.playerControllIcon {
|
||||
color: $playerDefaultIconColor !important;
|
||||
cursor: pointer;
|
||||
transition-duration: 0.1s;
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.playerControllIcon.active {
|
||||
|
|
@ -246,29 +275,36 @@ md-toolbar {
|
|||
background-color: $playListBackgroundColor;
|
||||
}
|
||||
|
||||
.noUi-origin {
|
||||
#playerArea * .noUi-origin {
|
||||
background-color: black;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.noUi-base {
|
||||
#playerArea * .noUi-base {
|
||||
background-color: $playerBackColor;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.noUi-connect {
|
||||
background-color: $playerBackColor;
|
||||
}
|
||||
|
||||
#volumeBar {
|
||||
width: 100px;
|
||||
height: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.noUi-handle {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.noUi-horizontal .noUi-handle {
|
||||
width: 7px;
|
||||
height: 21px;
|
||||
left: -1px;
|
||||
top: -8px;
|
||||
cursor: pointer;
|
||||
transition-duration: 0.1s;
|
||||
background: $playerDefaultIconColor !important;
|
||||
}
|
||||
|
|
@ -277,7 +313,7 @@ md-toolbar {
|
|||
background: white !important;
|
||||
}
|
||||
|
||||
.noUi-handle:after, .noUi-handle:before {
|
||||
#playerArea * .noUi-handle:after, #playerArea * .noUi-handle:before {
|
||||
content: none;
|
||||
}
|
||||
|
||||
|
|
@ -330,5 +366,83 @@ md-toolbar {
|
|||
|
||||
.playlistItem {
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{{#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}}
|
||||
{{/paper-sidenav}}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
{{#paper-content flex-layout="column" flex=true}}
|
||||
<div class="navigation">
|
||||
{{#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}}
|
||||
</div>
|
||||
|
||||
|
|
@ -22,10 +22,6 @@
|
|||
{{controls/light-control apiURL=apiURL lightsData=lightsData activeLights=activeLights}}
|
||||
{{/liquid-if}}
|
||||
|
||||
{{#liquid-if scenesTabSelected class="tabSwitch"}}
|
||||
{{controls/scene-control apiURL=apiURL lightsData=lightsData activeLights=activeLights}}
|
||||
{{/liquid-if}}
|
||||
|
||||
{{#liquid-if musicTabSelected class="tabSwitch"}}
|
||||
{{controls/music-control apiURL=apiURL lightsData=lightsData activeLights=activeLights}}
|
||||
{{/liquid-if}}
|
||||
|
|
@ -34,4 +30,5 @@
|
|||
|
||||
{{/paper-nav-container}}
|
||||
|
||||
{{huegasm-footer}}
|
||||
{{/liquid-if}}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
<span class="title">Huegasm</span>
|
||||
<div class="title">Huegasm</div>
|
||||
{{#unless bridgeUsername}}
|
||||
{{#if bridgeIp}}
|
||||
<img src="assets/images/pressButtonBridge.png" id="pressButtonBridgeImg">
|
||||
{{paper-progress-linear warn=true value=bridgeUserNamePingIntervalProgress}}
|
||||
{{#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>
|
||||
{{else}}
|
||||
<p>You failed to press the button. <a class="noTextDecoration" href="#" {{action 'retry'}}>RETRY</a></p>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
{{#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}}
|
||||
{{#each groupsArrData as |group|}}
|
||||
{{#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}}
|
||||
{{/each}}
|
||||
{{/paper-list}}
|
||||
|
|
|
|||
|
|
@ -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="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}}
|
||||
<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"
|
||||
title={{playingTooltipTxt}} id="playingTooltip" {{action "play"}}>{{paper-icon icon=playingIcon class="playerControllIcon"}}</span>{{#if nextPrevEnabled}}
|
||||
<span data-toggle="tooltip" data-placement="top"
|
||||
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 "toggleMute"}}>{{paper-icon icon=volumeClass class="playerControllIcon volumeButton"}}</span>{{range-slider start=volume min=0 max=100 change="volumeSliderChanged" id="volumeBar"}}
|
||||
id="prevTooltip" {{action "previous"}}>{{paper-icon icon="skip-previous" class="playerControllIcon"}} </span>{{/if}}<!--
|
||||
--><span data-toggle="tooltip" data-placement="top"
|
||||
title={{playingTooltipTxt}} id="playingTooltip" {{action "play"}}>{{paper-icon icon=playingIcon class="playerControllIcon"}}</span><!--
|
||||
-->{{#if nextPrevEnabled}}
|
||||
<span data-toggle="tooltip" data-placement="top"
|
||||
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 data-toggle="tooltip" data-placement="top"
|
||||
|
|
@ -25,13 +28,14 @@
|
|||
</div>
|
||||
|
||||
<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">
|
||||
<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"
|
||||
title={{repeatTooltipTxt}} id="repeatTooltip" {{action "toggleRepeat"}}>{{paper-icon icon=repeatIcon class=repeatClass}}</span>
|
||||
<span data-toggle="tooltip" data-placement="bottom auto"
|
||||
title={{repeatTooltipTxt}} id="repeatTooltip" {{action "repeatChanged"}}>{{paper-icon icon=repeatIcon class=repeatClass}}</span>
|
||||
|
||||
<span data-toggle="tooltip" data-placement="bottom" title="Add new music"
|
||||
class="pull-right" {{action "addAudio"}}>{{paper-icon icon="add" class="playerControllIcon" }}</span>
|
||||
|
|
@ -39,12 +43,48 @@
|
|||
|
||||
<div id="playListArea">
|
||||
{{#each playQueue as |item|}}
|
||||
<div class="playlistItem">{{#if item.title}}
|
||||
{{item.artist}} - {{item.title}}
|
||||
{{else}}
|
||||
{{item.filename}}
|
||||
{{/if}}</div>
|
||||
<div class="playlistItem">
|
||||
{{#if item.title}}
|
||||
{{item.artist}} - {{item.title}}
|
||||
{{else}}
|
||||
{{item.filename}}
|
||||
{{/if}}</div>
|
||||
{{/each}}
|
||||
</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>
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{{#paper-list}}
|
||||
{{#paper-item}}
|
||||
TODO
|
||||
{{/paper-item}}
|
||||
{{/paper-list}}
|
||||
|
|
@ -2,4 +2,6 @@
|
|||
{{bridge-controls bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial}}
|
||||
{{else}}
|
||||
{{bridge-finder bridgeIp=bridgeIp bridgeUsername=bridgeUsername trial=trial}}
|
||||
{{huegasm-footer}}
|
||||
{{/liquid-if}}
|
||||
|
||||
|
|
|
|||
5
app/templates/components/huegasm-footer.hbs
Normal file
5
app/templates/components/huegasm-footer.hbs
Normal 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>
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
{{#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}}
|
||||
BIN
assets/speaker.psd
Normal file
BIN
assets/speaker.psd
Normal file
Binary file not shown.
BIN
assets/speaker2.psd
Normal file
BIN
assets/speaker2.psd
Normal file
Binary file not shown.
|
|
@ -14,6 +14,7 @@
|
|||
"JavaScript-ID3-Reader": "https://github.com/aadsm/JavaScript-ID3-Reader.git",
|
||||
"jquery": "^1.11.1",
|
||||
"loader.js": "ember-cli/loader.js#3.2.0",
|
||||
"material-design-icons": "~2.0.0",
|
||||
"nouislider": "^8.0.1",
|
||||
"qunit": "~1.18.0"
|
||||
}
|
||||
|
|
|
|||
BIN
public/assets/images/speaker-inner.png
Normal file
BIN
public/assets/images/speaker-inner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
BIN
public/assets/images/speaker-outer.png
Normal file
BIN
public/assets/images/speaker-outer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
26
tests/integration/components/huegasm-footer-test.js
Normal file
26
tests/integration/components/huegasm-footer-test.js
Normal 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');
|
||||
});
|
||||
Reference in a new issue