finishing up the chrome extension, egorphilippov -> nidratech in the footer
This commit is contained in:
parent
f6dc26fd0e
commit
a1bd34ca67
22 changed files with 821 additions and 1071 deletions
|
|
@ -27,8 +27,8 @@ storePassword=...
|
|||
|
||||
pluginManager.onStop();
|
||||
}
|
||||
- channel.onStop = cordova.addDocumentEventHandler('stop'); from channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');
|
||||
- channel.onStop = cordova.addDocumentEventHandler('stop');
|
||||
- case 'stop': after case 'pause':
|
||||
- add <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> to Android manifest
|
||||
- add <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> to Android manifest
|
||||
|
||||
Just search for 'pause' and add the same type of event stuff for 'stop'. This is needed for properly split screening Huegasm with other apps.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default Component.extend({
|
|||
|
||||
activeLights: A(),
|
||||
tabList: ["Lights", "Music"],
|
||||
selectedTab: 1,
|
||||
selectedTab: 0,
|
||||
pauseLightUpdates: false,
|
||||
|
||||
displayFailure: true,
|
||||
|
|
@ -105,6 +105,7 @@ export default Component.extend({
|
|||
fail();
|
||||
} else if (status === 'success' && JSON.stringify(this.get('lightsData')) !== JSON.stringify(result)) {
|
||||
this.set('lightsData', result);
|
||||
chrome.storage.local.set({ 'lightsData': result });
|
||||
}
|
||||
}).fail(fail);
|
||||
}
|
||||
|
|
@ -120,6 +121,7 @@ export default Component.extend({
|
|||
chrome.storage.local.remove('bridgeUsername');
|
||||
chrome.storage.local.remove('bridgeIp');
|
||||
location.reload();
|
||||
chrome.runtime.sendMessage({ action: 'stop-listening' });
|
||||
},
|
||||
toggleDimmer() {
|
||||
this.sendAction('toggleDimmer');
|
||||
|
|
@ -130,6 +132,7 @@ export default Component.extend({
|
|||
clearAllSettings() {
|
||||
chrome.storage.local.clear();
|
||||
location.reload();
|
||||
chrome.runtime.sendMessage({ action: 'stop-listening' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -93,19 +93,19 @@ export default Component.extend({
|
|||
this._super(...arguments);
|
||||
|
||||
let lightsData = this.get('lightsData'),
|
||||
activeLights = this.get('activeLights');
|
||||
_activeLights = this.get('activeLights');
|
||||
|
||||
chrome.storage.local.get('activeLights', ({activeLightsCache}) => {
|
||||
if (!isNone(activeLightsCache)) {
|
||||
activeLightsCache.forEach(function (i) {
|
||||
chrome.storage.local.get('activeLights', ({activeLights}) => {
|
||||
if (!isNone(activeLights)) {
|
||||
activeLights.forEach(function (i) {
|
||||
if (!isNone(lightsData) && lightsData.hasOwnProperty(i) && lightsData[i].state.reachable) {
|
||||
activeLights.pushObject(i);
|
||||
_activeLights.pushObject(i);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (let key in lightsData) {
|
||||
if (lightsData.hasOwnProperty(key) && lightsData[key].state.reachable) {
|
||||
activeLights.pushObject(key);
|
||||
_activeLights.pushObject(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ const {
|
|||
isNone,
|
||||
$,
|
||||
inject: { service },
|
||||
run: { later, next, once }
|
||||
run: { later, once, next }
|
||||
} = Ember;
|
||||
|
||||
export default Component.extend({
|
||||
|
|
@ -101,34 +101,57 @@ export default Component.extend({
|
|||
|
||||
lastLightBopIndex: 0,
|
||||
|
||||
colorloopMode: false,
|
||||
flashingTransitions: false,
|
||||
|
||||
songBeatPreferences: {},
|
||||
usingBeatPreferences: false,
|
||||
oldBeatPrefCache: null,
|
||||
isListenining: false,
|
||||
firstVisit: true,
|
||||
|
||||
// noUiSlider connection specification
|
||||
filledConnect: [true, false],
|
||||
hueRangeConnect: [false, true, false],
|
||||
|
||||
onConfigItemChanged: observer('threshold', 'flashingTransitions', 'colorloopMode', 'hueRange', 'brightnessRange', 'isListenining', function (wtf, name) {
|
||||
onActive: observer('active', function () {
|
||||
if (this.get('active') && this.get('firstVisit')) {
|
||||
chrome.storage.local.set({ firstVisit: false });
|
||||
this.set('firstVisit', false);
|
||||
|
||||
next(this, () => {
|
||||
this.$('#fancy-button-wrapper a').popover('show');
|
||||
|
||||
later(this, () => {
|
||||
this.$('#fancy-button-wrapper a').popover('hide');
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
onConfigItemChanged: observer('threshold', 'hueRange', 'brightnessRange', 'isListenining', function (wtf, name) {
|
||||
once(this, () => {
|
||||
let value = this.get(name),
|
||||
self = this;
|
||||
|
||||
this.set(name, value);
|
||||
|
||||
if (name === 'isListenining' && value) {
|
||||
chrome.runtime.sendMessage({ action: 'start-listening' }, function (response) {
|
||||
if (response && response.error) {
|
||||
self.get('notify').warning({ html: '<div class="alert alert-warning" role="alert">' + response.error + '</div>' });
|
||||
if (name === 'isListenining') {
|
||||
if (value) {
|
||||
chrome.storage.local.get('currentlyListenining', ({currentlyListenining}) => {
|
||||
if (!currentlyListenining) {
|
||||
chrome.runtime.sendMessage({ action: 'start-listening' }, function (response) {
|
||||
if (response && response.error) {
|
||||
self.get('notify').warning({ html: '<div class="alert alert-warning" role="alert">' + response.error + '</div>' });
|
||||
|
||||
self.set('isListenining', false);
|
||||
chrome.storage.local.set({ isListenining: false });
|
||||
}
|
||||
});
|
||||
self.set('isListenining', false);
|
||||
chrome.storage.local.set({ isListenining: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
chrome.runtime.sendMessage({ action: 'stop-listening' });
|
||||
}
|
||||
|
||||
this.set('pauseLightUpdates', value);
|
||||
}
|
||||
|
||||
let toSave = {};
|
||||
|
|
@ -138,13 +161,11 @@ export default Component.extend({
|
|||
}),
|
||||
|
||||
simulateKick() {
|
||||
this.speakerBump();
|
||||
this.buttonBump();
|
||||
|
||||
let activeLights = this.get('activeLights'),
|
||||
lightsData = this.get('lightsData'),
|
||||
color = null,
|
||||
|
||||
transitiontime = this.get('flashingTransitions'),
|
||||
stimulateLight = (light, brightness, hue) => {
|
||||
let options = { 'bri': brightness };
|
||||
|
||||
|
|
@ -173,6 +194,7 @@ export default Component.extend({
|
|||
if (activeLights.length > 0) {
|
||||
let lastLightBopIndex = this.get('lastLightBopIndex'),
|
||||
lightBopIndex,
|
||||
hueRange = this.get('hueRange'),
|
||||
brightnessRange = this.get('brightnessRange'),
|
||||
light;
|
||||
|
||||
|
|
@ -188,15 +210,7 @@ export default Component.extend({
|
|||
light = activeLights[lightBopIndex];
|
||||
this.set('lastLightBopIndex', lightBopIndex);
|
||||
|
||||
if (!this.get('colorloopMode')) {
|
||||
let hueRange = this.get('hueRange');
|
||||
|
||||
color = Math.floor(Math.random() * (hueRange[1] - hueRange[0] + 1) + hueRange[0]);
|
||||
}
|
||||
|
||||
if (transitiontime) {
|
||||
timeToBriOff = 80;
|
||||
}
|
||||
color = Math.floor(Math.random() * (hueRange[1] - hueRange[0] + 1) + hueRange[0]);
|
||||
|
||||
stimulateLight(light, brightnessRange[1], color);
|
||||
later(this, stimulateLight, light, brightnessRange[0], timeToBriOff);
|
||||
|
|
@ -205,35 +219,28 @@ export default Component.extend({
|
|||
this.set('paused', true);
|
||||
later(this, function () {
|
||||
this.set('paused', false);
|
||||
}, 150);
|
||||
}, 200);
|
||||
},
|
||||
|
||||
speakerBump() {
|
||||
$('#beat-speaker-center-outer').velocity({ blur: 3 }, 100).velocity({ blur: 0 }, 100);
|
||||
$('#beat-speaker-center-inner').velocity({ scale: 1.05 }, 100).velocity({ scale: 1 }, 100);
|
||||
buttonBump() {
|
||||
$('.fancy-button').velocity({ scale: 1.05 }, 100).velocity({ scale: 1 }, 100);
|
||||
},
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
if (request.action === 'button-bump') {
|
||||
this.buttonBump();
|
||||
}
|
||||
});
|
||||
|
||||
chrome.storage.local.get('threshold', ({threshold}) => {
|
||||
if (!isNone(threshold)) {
|
||||
this.set('threshold', threshold);
|
||||
}
|
||||
});
|
||||
|
||||
chrome.storage.local.get('flashingTransitions', ({flashingTransitions}) => {
|
||||
if (!isNone(flashingTransitions)) {
|
||||
this.set('flashingTransitions', flashingTransitions);
|
||||
}
|
||||
});
|
||||
|
||||
chrome.storage.local.get('colorloopMode', ({colorloopMode}) => {
|
||||
if (!isNone(colorloopMode)) {
|
||||
this.set('colorloopMode', colorloopMode);
|
||||
}
|
||||
});
|
||||
|
||||
chrome.storage.local.get('hueRange', ({hueRange}) => {
|
||||
if (!isNone(hueRange)) {
|
||||
this.set('hueRange', hueRange);
|
||||
|
|
@ -251,6 +258,12 @@ export default Component.extend({
|
|||
this.set('isListenining', isListenining);
|
||||
}
|
||||
});
|
||||
|
||||
chrome.storage.local.get('firstVisit', ({firstVisit}) => {
|
||||
if (!isNone(firstVisit)) {
|
||||
this.set('firstVisit', firstVisit);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
|
|
@ -264,12 +277,6 @@ export default Component.extend({
|
|||
toggleListening() {
|
||||
this.toggleProperty('isListenining');
|
||||
},
|
||||
clickSpeaker() {
|
||||
this.simulateKick();
|
||||
},
|
||||
hideTooltip() {
|
||||
$('.bootstrap-tooltip').tooltip('hide');
|
||||
},
|
||||
toggleDimmer() {
|
||||
this.sendAction('toggleDimmer');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<div id="fancy-button-wrapper">
|
||||
<a href="#" class="fancy-button note {{if isListenining "active"}}" {{action "toggleListening"}}></a>
|
||||
<a href="#" data-content="Click here for Huegasm to start listening to your current tab" class="fancy-button note {{if isListenining "active"}}"
|
||||
{{action "toggleListening"}}></a>
|
||||
</div>
|
||||
|
||||
<div class="row {{if dimmerOn "dimmerOn"}}">
|
||||
|
|
@ -34,35 +35,6 @@
|
|||
{{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range on-change=(action
|
||||
(mut threshold)) pips=beatOptions.threshold.pips}}
|
||||
</div>
|
||||
|
||||
<div id="light-option" class="col-xs-12">
|
||||
<span data-toggle="tooltip" data-placement="top auto" data-title="Quickly flash the lights on beat" class="bootstrap-tooltip"
|
||||
{{action "hideTooltip" on="mouseLeave"}}>
|
||||
{{paper-checkbox value=flashingTransitions onChange=(action (mut flashingTransitions)) label="Flashing Transitions"}}
|
||||
</span>
|
||||
|
||||
<span data-toggle="tooltip" data-placement="top auto" data-title="Slowly cycle the lights through all the colors" class="bootstrap-tooltip"
|
||||
{{action "hideTooltip" on="mouseLeave"}}>
|
||||
{{paper-checkbox value=colorloopMode onChange=(action (mut colorloopMode)) label="Colorloop"}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="beat-container" class="col-sm-5 col-xs-12">
|
||||
<div class="bezel">
|
||||
<div class="rivet1"></div>
|
||||
<div class="rivet2"></div>
|
||||
<div class="rivet3"></div>
|
||||
<div class="rivet4"></div>
|
||||
<div class="rivet5"></div>
|
||||
<div class="rivet6"></div>
|
||||
<div class="rivet7"></div>
|
||||
<div class="rivet8"></div>
|
||||
|
||||
<div id="beat-speaker-center-outer">
|
||||
<div id="beat-speaker-center-inner" class="pointer" {{action "clickSpeaker"}}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -9,7 +9,6 @@
|
|||
@import 'bridge-finder';
|
||||
@import 'common';
|
||||
@import 'dimmer';
|
||||
@import 'fancy-speaker';
|
||||
@import 'hue-controls';
|
||||
@import 'light-group';
|
||||
@import 'music-tab';
|
||||
|
|
@ -17,6 +16,7 @@
|
|||
|
||||
body {
|
||||
min-width: 500px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
body > .ember-view {
|
||||
|
|
|
|||
2
chrome/app/styles/bootstrap.scss
vendored
2
chrome/app/styles/bootstrap.scss
vendored
|
|
@ -48,7 +48,7 @@
|
|||
// Components w/ JavaScript
|
||||
//@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/modals";
|
||||
@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/tooltip";
|
||||
//@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/popovers";
|
||||
@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/popovers";
|
||||
//@import "bower_components/bootstrap-sass/assets/stylesheets/bootstrap/carousel";
|
||||
|
||||
// Utility classes
|
||||
|
|
|
|||
|
|
@ -1,101 +0,0 @@
|
|||
$centersize: 80px;
|
||||
$center1size: 205px;
|
||||
$bezelsize: 240px;
|
||||
|
||||
%base {
|
||||
border-radius: 100%;
|
||||
}
|
||||
%rivet {
|
||||
position: absolute;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
background-color: #555;
|
||||
border-radius: 100%;
|
||||
box-shadow: inset 0 0 3px #000, 0 0 2px #000;
|
||||
}
|
||||
|
||||
#beat-speaker-center-inner {
|
||||
@extend %base;
|
||||
height: $centersize;
|
||||
width: $centersize;
|
||||
position: absolute;
|
||||
bottom: 47px;
|
||||
right: 47px;
|
||||
-webkit-filter: blur(1px);
|
||||
filter: blur(1px);
|
||||
background: rgb(0,0,0);
|
||||
background: -moz-radial-gradient(center, ellipse cover, rgba(0,0,0,1) 0%, rgba(79,79,79,1) 0%, rgba(0,0,0,1) 100%);
|
||||
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(0,0,0,1)), color-stop(0%,rgba(79,79,79,1)), color-stop(100%,rgba(0,0,0,1)));
|
||||
background: -webkit-radial-gradient(center, ellipse cover, rgba(0,0,0,1) 0%,rgba(79,79,79,1) 0%,rgba(0,0,0,1) 100%);
|
||||
background: -o-radial-gradient(center, ellipse cover, rgba(0,0,0,1) 0%,rgba(79,79,79,1) 0%,rgba(0,0,0,1) 100%);
|
||||
background: -ms-radial-gradient(center, ellipse cover, rgba(0,0,0,1) 0%,rgba(79,79,79,1) 0%,rgba(0,0,0,1) 100%);
|
||||
background: radial-gradient(ellipse at center, rgba(0,0,0,1) 0%,rgba(79,79,79,1) 0%,rgba(0,0,0,1) 100%);
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 1);
|
||||
}
|
||||
|
||||
#beat-speaker-center-outer {
|
||||
@extend %base;
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 16px;
|
||||
height: $center1size;
|
||||
width: $center1size;
|
||||
border: 15px solid #333;
|
||||
box-shadow: -3px -3px 15px rgba(0, 0, 0, 0.4), inset -3px -3px 15px rgba(0, 0, 0, 0.5);
|
||||
background: -moz-linear-gradient(130deg, rgba(117, 117, 117, 1) 55%, rgba(220, 220, 220, 1) 100%);
|
||||
background: -webkit-linear-gradient(130deg, rgba(117, 117, 117, 1) 55%, rgba(220, 220, 220, 1) 100%);
|
||||
background: -o-linear-gradient(130deg, rgba(117, 117, 117, 1) 55%, rgba(220, 220, 220, 1) 100%);
|
||||
background: -ms-linear-gradient(130deg, rgba(117, 117, 117, 1) 55%, rgba(220, 220, 220, 1) 100%);
|
||||
background: linear-gradient(130deg, rgba(117, 117, 117, 1) 55%, rgba(220, 220, 220, 1) 100%);
|
||||
}
|
||||
|
||||
.bezel {
|
||||
@extend %base;
|
||||
margin: 0 auto;
|
||||
height: $bezelsize;
|
||||
width: $bezelsize;
|
||||
position: relative;
|
||||
background-color: #A8A8A8;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.8), inset 3px 3px 10px rgba(0, 0, 0, 0.8), 0 0 2px rgba(0, 0, 0, 0.8), inset 0 0 30px -5px rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
.rivet1 {
|
||||
@extend %rivet;
|
||||
top: 6px;
|
||||
left: 50%;
|
||||
}
|
||||
.rivet2 {
|
||||
@extend %rivet;
|
||||
bottom: 6px;
|
||||
left: 50%;
|
||||
}
|
||||
.rivet3 {
|
||||
@extend %rivet;
|
||||
top: 50%;
|
||||
left: 6px;
|
||||
}
|
||||
.rivet4 {
|
||||
@extend %rivet;
|
||||
top: 50%;
|
||||
right: 6px;
|
||||
}
|
||||
.rivet5 {
|
||||
@extend %rivet;
|
||||
top: 18%;
|
||||
left: 13.7%;
|
||||
}
|
||||
.rivet6 {
|
||||
@extend %rivet;
|
||||
top: 18%;
|
||||
right: 13.5%;
|
||||
}
|
||||
.rivet7 {
|
||||
@extend %rivet;
|
||||
bottom: 17%;
|
||||
left: 13.5%;
|
||||
}
|
||||
.rivet8 {
|
||||
@extend %rivet;
|
||||
bottom: 17%;
|
||||
right: 13.5%;
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
}
|
||||
|
||||
#navigation {
|
||||
padding: 10px 0 2vh;
|
||||
padding: 5px 0 2vh;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
}
|
||||
|
||||
.navigation-item {
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
padding: 0 10px 0 10px;
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
|
|
@ -102,7 +102,7 @@
|
|||
|
||||
@media(min-width:767px) {
|
||||
#lights-tab {
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
.paper-icon {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,28 +4,18 @@
|
|||
|
||||
#music-tab {
|
||||
padding: 0;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#beat-area {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
padding: 0 0 10px;
|
||||
}
|
||||
|
||||
#beat-option-button-group {
|
||||
margin: 20px 0 10px 0;
|
||||
}
|
||||
|
||||
#light-option {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
.md-label {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.beat-option {
|
||||
padding: 5px 0;
|
||||
text-align: center;
|
||||
|
|
@ -37,7 +27,7 @@
|
|||
}
|
||||
.option-description {
|
||||
display: inline-flex;
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
padding: 10px 0;
|
||||
|
|
@ -61,11 +51,6 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
#beat-container {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#beat-area .light-group {
|
||||
margin: 10px 20px 0 40px;
|
||||
float: right;
|
||||
|
|
@ -91,22 +76,18 @@
|
|||
}
|
||||
|
||||
.fancy-button {
|
||||
background-image: -webkit-linear-gradient(top, #f4f1ee, #fff);
|
||||
background-image: linear-gradient(top, #f4f1ee, #fff);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0px 8px 10px 0px rgba(0, 0, 0, .3), inset 0px 4px 1px 1px white, inset 0px -3px 1px 1px rgba(204,198,197,.5);
|
||||
box-shadow: 0 2px 10px 2px rgba(0, 0, 0, .3), inset 0 4px 1px 1px white, inset 0 -3px 1px 1px rgba(204,198,197,.5);
|
||||
float:left;
|
||||
height: 90px;
|
||||
margin: 0 30px 30px 0;
|
||||
position: relative;
|
||||
width: 90px;
|
||||
-webkit-transition: all .1s linear;
|
||||
width: 90px;
|
||||
transition: all .1s linear;
|
||||
&:after {
|
||||
color:#e9e6e4;
|
||||
color:rgba(255, 0, 0, 0);
|
||||
content: "";
|
||||
display: block;
|
||||
font-size: 50px;
|
||||
font-size: 55px;
|
||||
height: 30px;
|
||||
text-decoration: none;
|
||||
text-shadow: 0px -1px 1px #bdb5b4, 1px 1px 1px white;
|
||||
|
|
@ -136,7 +117,7 @@
|
|||
&:after{
|
||||
content: "♪";
|
||||
left: 32px;
|
||||
top: 14px;
|
||||
top: 5px;
|
||||
}
|
||||
&:hover:after {
|
||||
color: $secondaryThemeColor;
|
||||
|
|
@ -152,9 +133,6 @@
|
|||
}
|
||||
|
||||
@media(max-width: 500px) {
|
||||
#sensitivity-settings .noUi-value-vertical {
|
||||
display: none;
|
||||
}
|
||||
.option-description {
|
||||
height: 55px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,6 @@
|
|||
}
|
||||
|
||||
.noUi-vertical {
|
||||
height: 200px;
|
||||
height: 180px;
|
||||
margin: 15px auto 10px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ module.exports = function (defaults) {
|
|||
});
|
||||
|
||||
app.import('bower_components/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js');
|
||||
app.import('bower_components/bootstrap-sass/assets/javascripts/bootstrap/popover.js');
|
||||
app.import('bower_components/velocity/velocity.js');
|
||||
|
||||
return app.toTree(extraAssets);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
519
chrome/public/dancer.js
Normal file
519
chrome/public/dancer.js
Normal file
|
|
@ -0,0 +1,519 @@
|
|||
'use strict';
|
||||
|
||||
(function () {
|
||||
|
||||
var Dancer = function () {
|
||||
this.audioAdapter = new Dancer.adapters.webaudio(this);
|
||||
this.events = {};
|
||||
this.sections = [];
|
||||
this.bind('update', update);
|
||||
};
|
||||
|
||||
Dancer.version = 'X.X.X';
|
||||
Dancer.adapters = {};
|
||||
|
||||
Dancer.prototype = {
|
||||
|
||||
load: function (source, boost) {
|
||||
this.audio = this.audioAdapter.load(source, boost);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/* Actions */
|
||||
createKick: function (options) {
|
||||
return new Dancer.Kick(this, options);
|
||||
},
|
||||
|
||||
bind: function (name, callback) {
|
||||
if (!this.events[name]) {
|
||||
this.events[name] = [];
|
||||
}
|
||||
this.events[name].push(callback);
|
||||
return this;
|
||||
},
|
||||
|
||||
unbind: function (name) {
|
||||
if (this.events[name]) {
|
||||
delete this.events[name];
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
trigger: function (name) {
|
||||
var _this = this;
|
||||
if (this.events[name]) {
|
||||
this.events[name].forEach(function (callback) {
|
||||
callback.call(_this);
|
||||
});
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// Returns the magnitude of a frequency or average over a range of frequencies
|
||||
getFrequency: function (freq, endFreq) {
|
||||
var sum = 0;
|
||||
if (endFreq !== undefined) {
|
||||
for (var i = freq; i <= endFreq; i++) {
|
||||
sum += this.getSpectrum()[i];
|
||||
}
|
||||
return sum / (endFreq - freq + 1);
|
||||
} else {
|
||||
return this.getSpectrum()[freq];
|
||||
}
|
||||
},
|
||||
|
||||
getWaveform: function () {
|
||||
return this.audioAdapter.getWaveform();
|
||||
},
|
||||
|
||||
getSpectrum: function () {
|
||||
return this.audioAdapter.getSpectrum();
|
||||
},
|
||||
|
||||
/* Sections */
|
||||
|
||||
after: function (time, callback) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition: function () {
|
||||
return _this.getTime() > time;
|
||||
},
|
||||
callback: callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
before: function (time, callback) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition: function () {
|
||||
return _this.getTime() < time;
|
||||
},
|
||||
callback: callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
between: function (startTime, endTime, callback) {
|
||||
var _this = this;
|
||||
this.sections.push({
|
||||
condition: function () {
|
||||
return _this.getTime() > startTime && _this.getTime() < endTime;
|
||||
},
|
||||
callback: callback
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
onceAt: function (time, callback) {
|
||||
var
|
||||
_this = this,
|
||||
thisSection = null;
|
||||
this.sections.push({
|
||||
condition: function () {
|
||||
return _this.getTime() > time && !this.called;
|
||||
},
|
||||
callback: function () {
|
||||
callback.call(this);
|
||||
thisSection.called = true;
|
||||
},
|
||||
called: false
|
||||
});
|
||||
// Baking the section in the closure due to callback's this being the dancer instance
|
||||
thisSection = this.sections[this.sections.length - 1];
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
function update() {
|
||||
for (var i in this.sections) {
|
||||
if (this.sections[i].condition && this.sections[i].condition())
|
||||
this.sections[i].callback.call(this);
|
||||
}
|
||||
}
|
||||
|
||||
window.Dancer = Dancer;
|
||||
})();
|
||||
|
||||
(function (Dancer) {
|
||||
|
||||
var CODECS = {
|
||||
'mp3': 'audio/mpeg;',
|
||||
'ogg': 'audio/ogg; codecs="vorbis"',
|
||||
'wav': 'audio/wav; codecs="1"',
|
||||
'aac': 'audio/mp4; codecs="mp4a.40.2"'
|
||||
},
|
||||
audioEl = document.createElement('audio');
|
||||
|
||||
Dancer.options = {};
|
||||
|
||||
Dancer.setOptions = function (o) {
|
||||
for (var option in o) {
|
||||
if (o.hasOwnProperty(option)) {
|
||||
Dancer.options[option] = o[option];
|
||||
}
|
||||
}
|
||||
};
|
||||
})(window.Dancer);
|
||||
|
||||
(function (undefined) {
|
||||
var Kick = function (dancer, o) {
|
||||
o = o || {};
|
||||
this.dancer = dancer;
|
||||
this.frequency = o.frequency !== undefined ? o.frequency : [0, 5];
|
||||
this.threshold = o.threshold !== undefined ? o.threshold : 0.3;
|
||||
this.decay = o.decay !== undefined ? o.decay : 0.02;
|
||||
this.onKick = o.onKick;
|
||||
this.offKick = o.offKick;
|
||||
this.isOn = false;
|
||||
this.currentThreshold = this.threshold;
|
||||
this.previousMag = 0;
|
||||
this.canUseRatio = true;
|
||||
this.canUseRatioHandle = null;
|
||||
|
||||
var _this = this;
|
||||
this.dancer.bind('update', function () {
|
||||
_this.onUpdate();
|
||||
});
|
||||
};
|
||||
|
||||
Kick.prototype = {
|
||||
on: function () {
|
||||
this.isOn = true;
|
||||
return this;
|
||||
},
|
||||
off: function () {
|
||||
this.isOn = false;
|
||||
return this;
|
||||
},
|
||||
|
||||
set: function (o) {
|
||||
o = o || {};
|
||||
this.frequency = o.frequency !== undefined ? o.frequency : this.frequency;
|
||||
this.threshold = o.threshold !== undefined ? o.threshold : this.threshold;
|
||||
this.decay = o.decay !== undefined ? o.decay : this.decay;
|
||||
this.onKick = o.onKick || this.onKick;
|
||||
this.offKick = o.offKick || this.offKick;
|
||||
},
|
||||
|
||||
onUpdate: function () {
|
||||
if (!this.isOn) { return; }
|
||||
|
||||
var magnitude = this.maxAmplitude(this.frequency);
|
||||
if (magnitude >= this.currentThreshold && magnitude >= this.threshold) {
|
||||
this.currentThreshold = magnitude;
|
||||
this.onKick && this.onKick.call(this.dancer, magnitude);
|
||||
this.canUseRatio = false;
|
||||
|
||||
if (this.canUseRatioHandle) {
|
||||
clearTimeout(this.canUseRatioHandle);
|
||||
this.canUseRatioHandle = null;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
this.canUseRatioHandle = setTimeout(function () {
|
||||
self.canUseRatio = true;
|
||||
}, 5000);
|
||||
} else {
|
||||
if (magnitude / this.previousMag > this.threshold * 5 && magnitude > 0.1 && this.canUseRatio) {
|
||||
this.onKick && this.onKick.call(this.dancer, magnitude, magnitude / this.previousMag);
|
||||
} else {
|
||||
this.offKick && this.offKick.call(this.dancer, magnitude);
|
||||
}
|
||||
|
||||
this.currentThreshold -= this.decay;
|
||||
this.previousMag = (magnitude > 0) ? magnitude : 0.0001;
|
||||
}
|
||||
},
|
||||
maxAmplitude: function (frequency) {
|
||||
var max = 0, fft = this.dancer.getSpectrum();
|
||||
|
||||
// Sloppy array check
|
||||
if (!frequency.length) {
|
||||
return frequency < fft.length ?
|
||||
fft[~~frequency] :
|
||||
null;
|
||||
}
|
||||
|
||||
for (var i = frequency[0], l = frequency[1]; i <= l; i++) {
|
||||
if (fft[i] > max) { max = fft[i]; }
|
||||
}
|
||||
return max;
|
||||
}
|
||||
};
|
||||
|
||||
window.Dancer.Kick = Kick;
|
||||
})();
|
||||
|
||||
(function () {
|
||||
var
|
||||
SAMPLE_SIZE = 2048,
|
||||
SAMPLE_RATE = 44100;
|
||||
|
||||
var adapter = function (dancer) {
|
||||
var context;
|
||||
|
||||
if ('AudioContext' in window) {
|
||||
context = new AudioContext();
|
||||
} else {
|
||||
context = new webkitAudioContext();
|
||||
}
|
||||
|
||||
this.dancer = dancer;
|
||||
this.context = context;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
|
||||
load: function (_source, boost) {
|
||||
var _this = this;
|
||||
this.source = this.context.createMediaStreamSource(_source);
|
||||
|
||||
this.isLoaded = false;
|
||||
this.progress = 0;
|
||||
|
||||
if (this.proc) {
|
||||
this.proc.onaudioprocess = null;
|
||||
delete this.proc;
|
||||
}
|
||||
|
||||
this.proc = this.context.createScriptProcessor(SAMPLE_SIZE / 2, 1, 1);
|
||||
|
||||
this.proc.onaudioprocess = function (e) {
|
||||
_this.update.call(_this, e);
|
||||
};
|
||||
|
||||
this.gain = this.context.createGain();
|
||||
|
||||
this.fft = new FFT(SAMPLE_SIZE / 2, SAMPLE_RATE, boost);
|
||||
this.signal = new Float32Array(SAMPLE_SIZE / 2);
|
||||
|
||||
connectContext.call(_this);
|
||||
|
||||
return this.source;
|
||||
},
|
||||
|
||||
getWaveform: function () {
|
||||
return this.signal;
|
||||
},
|
||||
|
||||
getSpectrum: function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
update: function (e) {
|
||||
var
|
||||
buffers = [],
|
||||
channels = e.inputBuffer.numberOfChannels,
|
||||
resolution = SAMPLE_SIZE / channels,
|
||||
sum = function (prev, curr) {
|
||||
return prev[i] + curr[i];
|
||||
}, i;
|
||||
|
||||
for (i = channels; i--;) {
|
||||
buffers.push(e.inputBuffer.getChannelData(i));
|
||||
}
|
||||
|
||||
for (i = 0; i < resolution; i++) {
|
||||
this.signal[i] = channels > 1 ?
|
||||
buffers.reduce(sum) / channels :
|
||||
buffers[0][i];
|
||||
}
|
||||
|
||||
this.fft.forward(this.signal);
|
||||
this.dancer.trigger('update');
|
||||
}
|
||||
};
|
||||
|
||||
function connectContext() {
|
||||
this.source.connect(this.proc);
|
||||
this.source.connect(this.gain);
|
||||
this.gain.connect(this.context.destination);
|
||||
this.proc.connect(this.context.destination);
|
||||
|
||||
this.isLoaded = true;
|
||||
this.progress = 1;
|
||||
this.dancer.trigger('loaded');
|
||||
}
|
||||
|
||||
Dancer.adapters.webaudio = adapter;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
/*
|
||||
* DSP.js - a comprehensive digital signal processing library for javascript
|
||||
*
|
||||
* Created by Corban Brook <corbanbrook@gmail.com> on 2010-01-01.
|
||||
* Copyright 2010 Corban Brook. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
// Fourier Transform Module used by DFT, FFT, RFFT
|
||||
function FourierTransform(bufferSize, sampleRate, boost) {
|
||||
this.bufferSize = bufferSize;
|
||||
this.sampleRate = sampleRate;
|
||||
this.bandwidth = 2 / bufferSize * sampleRate / 2;
|
||||
this.boost = boost ? boost : 1;
|
||||
|
||||
this.spectrum = new Float32Array(bufferSize / 2);
|
||||
this.real = new Float32Array(bufferSize);
|
||||
this.imag = new Float32Array(bufferSize);
|
||||
|
||||
this.peakBand = 0;
|
||||
this.peak = 0;
|
||||
|
||||
/**
|
||||
* Calculates the *middle* frequency of an FFT band.
|
||||
*
|
||||
* @param {Number} index The index of the FFT band.
|
||||
*
|
||||
* @returns The middle frequency in Hz.
|
||||
*/
|
||||
this.getBandFrequency = function (index) {
|
||||
return this.bandwidth * index + this.bandwidth / 2;
|
||||
};
|
||||
|
||||
this.setBoost = function (boost) {
|
||||
this.boost = boost;
|
||||
};
|
||||
|
||||
this.calculateSpectrum = function () {
|
||||
var spectrum = this.spectrum,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
boost = this.boost,
|
||||
bSi = 2 / this.bufferSize,
|
||||
sqrt = Math.sqrt,
|
||||
rval,
|
||||
ival,
|
||||
mag;
|
||||
|
||||
for (var i = 0, N = bufferSize / 2; i < N; i++) {
|
||||
rval = real[i];
|
||||
ival = imag[i];
|
||||
mag = bSi * sqrt(rval * rval + ival * ival);
|
||||
|
||||
if (mag > this.peak) {
|
||||
this.peakBand = i;
|
||||
this.peak = mag;
|
||||
}
|
||||
|
||||
spectrum[i] = mag * boost;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* FFT is a class for calculating the Discrete Fourier Transform of a signal
|
||||
* with the Fast Fourier Transform algorithm.
|
||||
*
|
||||
* @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
|
||||
* @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
|
||||
* @param {Number} boost The coefficient
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function FFT(bufferSize, sampleRate, boost) {
|
||||
FourierTransform.call(this, bufferSize, sampleRate, boost);
|
||||
|
||||
this.reverseTable = new Uint32Array(bufferSize);
|
||||
|
||||
var limit = 1;
|
||||
var bit = bufferSize >> 1;
|
||||
|
||||
var i;
|
||||
|
||||
while (limit < bufferSize) {
|
||||
for (i = 0; i < limit; i++) {
|
||||
this.reverseTable[i + limit] = this.reverseTable[i] + bit;
|
||||
}
|
||||
|
||||
limit = limit << 1;
|
||||
bit = bit >> 1;
|
||||
}
|
||||
|
||||
this.sinTable = new Float32Array(bufferSize);
|
||||
this.cosTable = new Float32Array(bufferSize);
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
this.sinTable[i] = Math.sin(-Math.PI / i);
|
||||
this.cosTable[i] = Math.cos(-Math.PI / i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a forward transform on the sample buffer.
|
||||
* Converts a time domain signal to frequency domain spectra.
|
||||
*
|
||||
* @param {Array} buffer The sample buffer. Buffer Length must be power of 2
|
||||
*
|
||||
* @returns The frequency spectrum array
|
||||
*/
|
||||
FFT.prototype.forward = function (buffer) {
|
||||
// Locally scope variables for speed up
|
||||
var bufferSize = this.bufferSize,
|
||||
cosTable = this.cosTable,
|
||||
sinTable = this.sinTable,
|
||||
reverseTable = this.reverseTable,
|
||||
real = this.real,
|
||||
imag = this.imag,
|
||||
spectrum = this.spectrum;
|
||||
|
||||
var k = Math.floor(Math.log(bufferSize) / Math.LN2);
|
||||
|
||||
if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; }
|
||||
if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; }
|
||||
|
||||
var halfSize = 1,
|
||||
phaseShiftStepReal,
|
||||
phaseShiftStepImag,
|
||||
currentPhaseShiftReal,
|
||||
currentPhaseShiftImag,
|
||||
off,
|
||||
tr,
|
||||
ti,
|
||||
tmpReal,
|
||||
i;
|
||||
|
||||
for (i = 0; i < bufferSize; i++) {
|
||||
real[i] = buffer[reverseTable[i]];
|
||||
imag[i] = 0;
|
||||
}
|
||||
|
||||
while (halfSize < bufferSize) {
|
||||
//phaseShiftStepReal = Math.cos(-Math.PI/halfSize);
|
||||
//phaseShiftStepImag = Math.sin(-Math.PI/halfSize);
|
||||
phaseShiftStepReal = cosTable[halfSize];
|
||||
phaseShiftStepImag = sinTable[halfSize];
|
||||
|
||||
currentPhaseShiftReal = 1;
|
||||
currentPhaseShiftImag = 0;
|
||||
|
||||
for (var fftStep = 0; fftStep < halfSize; fftStep++) {
|
||||
i = fftStep;
|
||||
|
||||
while (i < bufferSize) {
|
||||
off = i + halfSize;
|
||||
tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
|
||||
ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
|
||||
|
||||
real[off] = real[i] - tr;
|
||||
imag[off] = imag[i] - ti;
|
||||
real[i] += tr;
|
||||
imag[i] += ti;
|
||||
|
||||
i += halfSize << 1;
|
||||
}
|
||||
|
||||
tmpReal = currentPhaseShiftReal;
|
||||
currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
|
||||
currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
|
||||
}
|
||||
|
||||
halfSize = halfSize << 1;
|
||||
}
|
||||
|
||||
return this.calculateSpectrum();
|
||||
};
|
||||
4
chrome/public/jquery-3.1.1.min.js
vendored
Normal file
4
chrome/public/jquery-3.1.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Huegasm",
|
||||
"description": "Huegasm is a free web application for managing and synchronizing your Philips Hue lights with the beat of your music.",
|
||||
"description": "Manage and synchronize your Philips Hue lights with the beat of your music.",
|
||||
"version": "1.0",
|
||||
"icons": {
|
||||
"16": "16x16.png",
|
||||
|
|
@ -10,6 +10,8 @@
|
|||
},
|
||||
"background": {
|
||||
"scripts": [
|
||||
"dancer.js",
|
||||
"jquery-3.1.1.min.js",
|
||||
"background.js"
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -16,18 +16,6 @@
|
|||
<link rel="stylesheet" integrity="" href="assets/huegasm_mobile.css"> {{content-for 'head-footer'}}
|
||||
|
||||
<script src="https://connect.soundcloud.com/sdk/sdk-3.1.2.js"></script>
|
||||
|
||||
<script>
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date(); a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0]; a.async = 1; a.src = g; m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-69470561-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -165,10 +165,8 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
|||
|
||||
this.set('paused', true);
|
||||
later(this, function () {
|
||||
{
|
||||
this.set('paused', false);
|
||||
}
|
||||
}, 150);
|
||||
this.set('paused', false);
|
||||
}, 200);
|
||||
|
||||
//work the music beat area - simulate the speaker vibration by running a CSS animation on it
|
||||
$('#beat-speaker-center-outer').velocity({ blur: 3 }, 100).velocity({ blur: 0 }, 100);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<widget id="com.hoboman313.huegasm" version="1.1.6" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||
<widget id="com.hoboman313.huegasm" version="1.1.7" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||
<name>Huegasm</name>
|
||||
<content src="index.html" />
|
||||
<plugin name="cordova-plugin-inappbrowser" spec="~1.6.1" />
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<div class="footer-text">
|
||||
© {{year}}
|
||||
|
||||
<a href="http://www.egorphilippov.me" target="_blank" rel="noopener noreferrer">
|
||||
Egor Philippov
|
||||
<a href="https://www.nidratech.com/" target="_blank" rel="noopener noreferrer">
|
||||
Nidratech Ltd
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ export default Component.extend(helperMixin, visualizerMixin, {
|
|||
this.set('paused', true);
|
||||
later(this, function () {
|
||||
this.set('paused', false);
|
||||
}, 150);
|
||||
}, 200);
|
||||
|
||||
//work the music beat area - simulate the speaker vibration by running a CSS animation on it
|
||||
$('#beat-speaker-center-outer').velocity({ blur: 3 }, 100).velocity({ blur: 0 }, 100);
|
||||
|
|
|
|||
|
|
@ -13,28 +13,16 @@
|
|||
|
||||
{{#if playQueueNotEmpty}}
|
||||
<span data-toggle="tooltip" data-placement="top" class="bootstrap-tooltip" id="prevTooltip" data-title= {{prevTooltipTxt}}
|
||||
{{action "previous"}}>{{paper-icon "skip-previous" class="player-control-icon"}}</span>
|
||||
<!--
|
||||
-->
|
||||
{{/if}}
|
||||
<!--
|
||||
-->
|
||||
<span data-toggle="tooltip" data-placement="top" id="playingTooltip" class="bootstrap-tooltip" data-title= {{playingTooltipTxt}}
|
||||
{{action "play"}}>{{paper-icon playingIcon class="player-control-icon"}}</span>
|
||||
<!--
|
||||
-->
|
||||
{{#if playQueueMultiple}}
|
||||
<!--
|
||||
--><span data-toggle="tooltip" data-placement="top" class="bootstrap-tooltip" data-title="Next" {{action "next" true}}>{{paper-icon "skip-next" action="" class="player-control-icon"}}</span>
|
||||
<!--
|
||||
-->
|
||||
{{/if}}
|
||||
<!--
|
||||
-->
|
||||
<span data-toggle="tooltip" data-placement="top" class="bootstrap-tooltip hidden-xs" id="volumeMutedTooltip" data-title= {{volumeMutedTooltipTxt}}
|
||||
{{action "volumeMutedChanged"}}>{{paper-icon icon=volumeIcon class=volumeMutedClass}}</span>
|
||||
<!--
|
||||
-->{{range-slider start=volume min=0 max=100 connect=filledConnect on-change="volumeChanged" id="volume-bar" class="hidden-xs"}}
|
||||
{{action "previous"}}>{{paper-icon "skip-previous" class="player-control-icon"}}</span><!--
|
||||
-->{{/if}}<!--
|
||||
--><span data-toggle="tooltip" data-placement="top" id="playingTooltip" class="bootstrap-tooltip" data-title= {{playingTooltipTxt}}
|
||||
{{action "play"}}>{{paper-icon playingIcon class="player-control-icon"}}</span><!--
|
||||
-->{{#if playQueueMultiple}}<!--
|
||||
--><span data-toggle="tooltip" data-placement="top" class="bootstrap-tooltip" data-title="Next" {{action "next" true}}>{{paper-icon "skip-next" action="" class="player-control-icon"}}</span><!--
|
||||
-->{{/if}}<!--
|
||||
--><span data-toggle="tooltip" data-placement="top" class="bootstrap-tooltip hidden-xs" id="volumeMutedTooltip" data-title= {{volumeMutedTooltipTxt}}
|
||||
{{action "volumeMutedChanged"}}>{{paper-icon icon=volumeIcon class=volumeMutedClass}}</span><!--
|
||||
-->{{range-slider start=volume min=0 max=100 connect=filledConnect on-change="volumeChanged" id="volume-bar" class="hidden-xs"}}
|
||||
|
||||
<div id="player-time-controls">{{timeElapsedTxt}} / {{timeTotalTxt}}</div>
|
||||
|
||||
|
|
|
|||
Reference in a new issue