diff --git a/chrome/app/index.html b/chrome/app/index.html index e093db1..f2dcb64 100644 --- a/chrome/app/index.html +++ b/chrome/app/index.html @@ -10,7 +10,7 @@ {{content-for 'head'}} - + {{content-for 'head-footer'}} diff --git a/chrome/app/pods/components/bridge-finder/component.js b/chrome/app/pods/components/bridge-finder/component.js index c36715b..2d39803 100644 --- a/chrome/app/pods/components/bridge-finder/component.js +++ b/chrome/app/pods/components/bridge-finder/component.js @@ -59,23 +59,25 @@ export default Component.extend({ .done((result, status) => { let bridgeFindStatus = 'fail'; - if (status === 'success' && result.length === 1) { - this.set('bridgeIp', result[0].internalipaddress); - chrome.storage.local.set({ 'bridgeIp': result[0].internalipaddress }); - bridgeFindStatus = 'success'; - } else if (result.length > 1) { - let multipleBridgeIps = this.get('multipleBridgeIps'); + if (!this.isDestroyed) { + if (status === 'success' && result.length === 1) { + this.set('bridgeIp', result[0].internalipaddress); + chrome.storage.local.set({ 'bridgeIp': result[0].internalipaddress }); + bridgeFindStatus = 'success'; + } else if (result.length > 1) { + let multipleBridgeIps = this.get('multipleBridgeIps'); - result.forEach(function (item) { - multipleBridgeIps.pushObject(item.internalipaddress); - }); + result.forEach(function (item) { + multipleBridgeIps.pushObject(item.internalipaddress); + }); - bridgeFindStatus = 'multiple'; - } else { - bridgeFindStatus = 'fail'; + bridgeFindStatus = 'multiple'; + } else { + bridgeFindStatus = 'fail'; + } + + this.set('bridgeFindStatus', bridgeFindStatus); } - - this.set('bridgeFindStatus', bridgeFindStatus); }) .fail(() => { this.set('bridgeFindStatus', 'fail'); @@ -99,7 +101,6 @@ export default Component.extend({ if (status === 'success' && !result[0].error) { this.clearBridgePingIntervalHandle(); - debugger; chrome.storage.local.set({ 'bridgeUsername': result[0].success.username }); this.set('bridgeUsername', result[0].success.username); } @@ -114,7 +115,9 @@ export default Component.extend({ clearBridgePingIntervalHandle() { clearInterval(this.get('bridgePingIntervalHandle')); - this.set('bridgePingIntervalHandle', null); + if (!this.isDestroyed) { + this.set('bridgePingIntervalHandle', null); + } }, actions: { diff --git a/chrome/app/pods/components/bridge-finder/template.hbs b/chrome/app/pods/components/bridge-finder/template.hbs index ee0852a..cb665cd 100644 --- a/chrome/app/pods/components/bridge-finder/template.hbs +++ b/chrome/app/pods/components/bridge-finder/template.hbs @@ -6,7 +6,7 @@ {{#if isAuthenticating}}

Your bridge IP is {{bridgeIp}} -
Press the button on your bridge to authenticate this application. +
Press the button on your bridge to authenticate Huegasm.

{{else}}

You failed to press the button in time. RETRY

@@ -18,7 +18,7 @@ {{/unless}} {{#if bridgeFindMultiple}} -

Huegasm found multiple hue bridges.
Please select the one you want to use for this application.

+

Huegasm found multiple hue bridges.
Please select the one you want to use for Huegasm.

{{#each multipleBridgeIps as |bridge|}} diff --git a/chrome/app/pods/components/music-tab/component.js b/chrome/app/pods/components/music-tab/component.js index 1672cd1..ca9e98a 100644 --- a/chrome/app/pods/components/music-tab/component.js +++ b/chrome/app/pods/components/music-tab/component.js @@ -8,7 +8,7 @@ const { isNone, $, inject: { service }, - run: { later, next } + run: { later, next, once } } = Ember; export default Component.extend({ @@ -16,8 +16,6 @@ export default Component.extend({ classNameBindings: ['active::hidden'], elementId: 'music-tab', - dancer: null, - notify: service(), beatOptions: { @@ -32,11 +30,11 @@ export default Component.extend({ format: { to: function (value) { if (value === 0) { - value = 'More'; + value = 'High'; } else if (value === 0.25) { value = ''; } else { - value = 'Less'; + value = 'Low'; } return value; @@ -75,10 +73,22 @@ export default Component.extend({ defaultValue: 0, pips: { mode: 'values', - values: [1, 50, 100, 150, 200, 254], + values: [1, 63, 127, 190, 254], density: 10, format: { - to: function (value) { return value; }, + to: function (value) { + if (value === 63) { + value = 25; + } else if (value === 127) { + value = 50; + } else if (value === 190) { + value = 75; + } else if (value === 254) { + value = 100; + } + + return value; + }, from: function (value) { return value; } } } @@ -88,46 +98,48 @@ export default Component.extend({ threshold: 0.3, hueRange: [0, 65535], brightnessRange: [1, 254], - oldThreshold: null, lastLightBopIndex: 0, - playerBottomDisplayed: true, - audioStream: null, - dimmerOn: false, - colorloopMode: false, flashingTransitions: false, - // 0 - no repeat, 1 - repeat all, 2 - repeat one - repeat: 0, - shuffle: false, - volumeMuted: false, - volume: 100, - // beat detection related pausing - paused: false, songBeatPreferences: {}, usingBeatPreferences: false, oldBeatPrefCache: null, - firstVisit: true, + isListenining: false, // noUiSlider connection specification filledConnect: [true, false], hueRangeConnect: [false, true, false], - changePlayerControl(name, value) { - this.set(name, value); + onConfigItemChanged: observer('threshold', 'flashingTransitions', 'colorloopMode', 'hueRange', 'brightnessRange', 'isListenining', function (wtf, name) { + once(this, () => { + let value = this.get(name), + self = this; - if (name === 'threshold') { - this.get('kick').set({ threshold: value }); - } + this.set(name, value); - let toSave = {}; - toSave[name] = value; - chrome.storage.local.set(toSave); - }, + if (name === 'isListenining' && value) { + chrome.runtime.sendMessage({ action: 'start-listening' }, function (response) { + if (response && response.error) { + self.get('notify').warning({ html: '' }); + + self.set('isListenining', false); + chrome.storage.local.set({ isListenining: false }); + } + }); + } + + let toSave = {}; + toSave[name] = value; + chrome.storage.local.set(toSave); + }); + }), + + simulateKick() { + this.speakerBump(); - simulateKick(/*mag, ratioKickMag*/) { let activeLights = this.get('activeLights'), lightsData = this.get('lightsData'), color = null, @@ -194,8 +206,9 @@ export default Component.extend({ later(this, function () { this.set('paused', false); }, 150); + }, - //work the music beat area - simulate the speaker vibration by running a CSS animation on it + 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); }, @@ -203,76 +216,59 @@ export default Component.extend({ init() { this._super(...arguments); - window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame; - window.cancelAnimationFrame = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame; - navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; - - let dancer = new Dancer(), - kick = dancer.createKick({ - threshold: this.get('threshold'), - onKick: (mag, ratioKickMag) => { - if (this.get('paused') === false) { - this.simulateKick(mag, ratioKickMag); - } - } - }); - - kick.on(); - - this.setProperties({ - dancer: dancer, - kick: kick + chrome.storage.local.get('threshold', ({threshold}) => { + if (!isNone(threshold)) { + this.set('threshold', threshold); + } }); - ['threshold', 'playerBottomDisplayed', 'flashingTransitions', 'colorloopMode', 'hueRange', 'brightnessRange'].forEach((item) => { - chrome.storage.local.get(item, ({itemVal}) => { - if (!isNone(itemVal)) { - if (isNone(this.actions[item + 'Changed'])) { - this.set(item, itemVal); - } else { - this.send(item + 'Changed', itemVal); - } - } - }); + 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); + } + }); + + chrome.storage.local.get('brightnessRange', ({brightnessRange}) => { + if (!isNone(brightnessRange)) { + this.set('brightnessRange', brightnessRange); + } + }); + + chrome.storage.local.get('isListenining', ({isListenining}) => { + if (!isNone(isListenining)) { + this.set('isListenining', isListenining); + } }); }, didInsertElement() { - this._super(); - - let self = this; - // prevent space/text selection when the user repeatedly clicks on the center $('#beat-container').on('mousedown', '#beat-speaker-center-inner', function (event) { event.preventDefault(); }); - - if (!this.get('playerBottomDisplayed')) { - $('#player-bottom').hide(); - } }, actions: { - slideTogglePlayerBottom() { - let elem = this.$('#player-bottom'); - - elem.velocity(elem.is(':visible') ? 'slideUp' : 'slideDown', { duration: 300 }); - this.changePlayerControl('playerBottomDisplayed', !this.get('playerBottomDisplayed')); - }, - playerBottomDisplayedChanged(value) { - this.changePlayerControl('playerBottomDisplayed', value); - }, - thresholdChanged(value) { - this.changePlayerControl('threshold', value, true); - }, - brightnessRangeChanged(value) { - this.changePlayerControl('brightnessRange', value); - }, - hueRangeChanged(value) { - this.changePlayerControl('hueRange', value); + toggleListening() { + this.toggleProperty('isListenining'); }, clickSpeaker() { - this.simulateKick(1); + this.simulateKick(); + }, + hideTooltip() { + $('.bootstrap-tooltip').tooltip('hide'); }, toggleDimmer() { this.sendAction('toggleDimmer'); diff --git a/chrome/app/pods/components/music-tab/template.hbs b/chrome/app/pods/components/music-tab/template.hbs index 2dac6a5..acc79a7 100644 --- a/chrome/app/pods/components/music-tab/template.hbs +++ b/chrome/app/pods/components/music-tab/template.hbs @@ -1,10 +1,8 @@ -
-
- {{paper-icon beatDetectionAreaArrowIcon id="beat-detection-area-arrow-icon"}} -
+
+
-
+
@@ -14,7 +12,7 @@ {{range-slider start=hueRange orientation="vertical" step=beatOptions.hueRange.step range=beatOptions.hueRange.range connect=hueRangeConnect - on-change="hueRangeChanged" pips=beatOptions.hueRange.pips}} + on-change=(action (mut hueRange)) pips=beatOptions.hueRange.pips}}
@@ -24,7 +22,7 @@ {{range-slider start=brightnessRange orientation="vertical" step=beatOptions.brightnessRange.step range=beatOptions.brightnessRange.range - on-change="brightnessRangeChanged" pips=beatOptions.brightnessRange.pips}} + on-change=(action (mut brightnessRange)) pips=beatOptions.brightnessRange.pips}}
@@ -33,8 +31,8 @@ Sensitivity - {{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range on-change="thresholdChanged" - pips=beatOptions.threshold.pips}} + {{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range on-change=(action + (mut threshold)) pips=beatOptions.threshold.pips}}
diff --git a/chrome/app/styles/app.scss b/chrome/app/styles/app.scss index 61c4712..8a0b53b 100644 --- a/chrome/app/styles/app.scss +++ b/chrome/app/styles/app.scss @@ -21,12 +21,11 @@ body { body > .ember-view { display: flex; - min-height: 100vh; flex-direction: column; } body, button { - font-family: 'Slabo 27px', serif; + font-family: 'Raleway', sans-serif; } #huegasm { diff --git a/chrome/app/styles/bridge-finder.scss b/chrome/app/styles/bridge-finder.scss index f6ef407..79b355e 100644 --- a/chrome/app/styles/bridge-finder.scss +++ b/chrome/app/styles/bridge-finder.scss @@ -31,7 +31,6 @@ } #bridge-finder { - min-height: 500px; .md-bar { background-color: $secondaryThemeColor !important; } diff --git a/chrome/app/styles/hue-controls.scss b/chrome/app/styles/hue-controls.scss index 90baa9c..8e7e3dd 100644 --- a/chrome/app/styles/hue-controls.scss +++ b/chrome/app/styles/hue-controls.scss @@ -1,6 +1,5 @@ #lights-tab { padding: 0; - margin-top: 5vh; .paper-icon { line-height: 0.8 !important; } @@ -19,7 +18,6 @@ #hue-controls { max-width: 1200px; - height: 90vh; md-progress-circular { position: absolute; top: 50%; @@ -35,7 +33,7 @@ } #navigation { - padding: 15px 0 4vh; + padding: 10px 0 2vh; text-align: center; margin: auto; position: relative; @@ -44,13 +42,13 @@ text-align: right; position: absolute; top: -10px; - right: 10px; + right: -10px; transform: scale(1.1); } } .navigation-item { - font-size: 18px; + font-size: 20px; padding: 0 10px 0 10px; &.active { font-weight: bold; diff --git a/chrome/app/styles/light-group.scss b/chrome/app/styles/light-group.scss index c8e56f8..af8d3e2 100644 --- a/chrome/app/styles/light-group.scss +++ b/chrome/app/styles/light-group.scss @@ -58,7 +58,7 @@ .light-text { width: 60px; word-wrap: break-word; - padding: 0 10px; + padding: 0 7px; } .light-text-content { diff --git a/chrome/app/styles/music-tab.scss b/chrome/app/styles/music-tab.scss index 14a1202..e7af8fd 100644 --- a/chrome/app/styles/music-tab.scss +++ b/chrome/app/styles/music-tab.scss @@ -8,87 +8,6 @@ margin-bottom: 20px; } -#slide-toggle { - font-size: 22px; - color: $playerDefaultIconColor; - background: #730B07; - div .paper-icon { - color: inherit !important; - font-size: 24px; - font-weight: bold; - } -} - -#slide-toggle:hover { - color: lighten($playerDefaultIconColor, 30%) !important; -} - - -#player-area { - height: $playerHeight; - background-color: black; - display: inline-block; - padding: 0; - cursor: pointer; -} - -#playlist { - height: $playerHeight; - background-color: #1E1E1E; - padding: 0 5px 0 5px; -} - -#player-area * .noUi-origin { - background-color: $blackish; - border-radius: 5px; -} - -#player-area * .noUi-base { - background-color: $blackish; - border-radius: 5px; -} - -#volume-bar { - width: 5em; - height: 0.5em; - display: inline-block; -} - -#player-area * .noUi-handle::after, -#player-area * .noUi-handle::before { - content: none; -} - -#seek-slider { - margin-bottom: 15px; - transition-duration: 0.2s; - height: 8px; - .noUi-handle { - opacity: 1 !important; - } -} - -#seek-slider:hover { - height: 8px; -} - -#seek-slider:hover * .noUi-handle { - opacity: 1; -} - -#seek-slider * .noUi-handle { - border: none; - height: 13px; - width: 13px; - border-radius: 50%; - top: -4px; - left: -6px; - opacity: 0; - transition-duration: 0.1s; - background-color: $secondaryThemeColor !important; - box-shadow: none; -} - #beat-area { position: relative; padding: 0; @@ -118,9 +37,10 @@ } .option-description { display: inline-flex; - font-size: 20px; + font-size: 18px; justify-content: center; flex-direction: column; + padding: 10px 0; } button { margin-top: 0; @@ -155,65 +75,6 @@ } } -#add-music-choices { - min-width: initial; - right: 0; - left: initial; - width: 100px; - top: 25px; -} - -.add-new-music { - padding: 0 5px 0 10px; - font-size: 16px; - border-radius: 5px; - background: #f8f8f8; - border: none; -} - -.add-new-music:hover { - background: darken(#f8f8f8, 5%); -} - -.sound-cloud-link { - position: absolute; - right: 55px; - bottom: 22px; -} - - - -#save-beat-preferences-star { - position: absolute; - top: 5px; - left: 5px; - z-index: 1000; - md-icon { - color: $secondaryThemeColor !important; - font-size: 25px; - cursor: default; - } -} - -.visualizers-menu { - left: -135px; -} - -.display-icon { - background: url(images/huegasm.png) center center no-repeat; - background-size: 80px 80px; -} - -.keyboard-arrow-down { - font-size: 20px; -} - -.visualizers-menu .paper-icon { - margin-left: 10px; - position: relative; - top: -4px; -} - .close { font-size: 18px !important; color: rgb(51, 51, 51); @@ -224,36 +85,66 @@ } } -.ember-notify-default.ember-notify-cn { - top: 0; - bottom: initial; +#fancy-button-wrapper { + display: flex; + justify-content: center; } -#soundcloud-logo { - display: block; -} - -#soundcloud-logo-small { - display: none; -} - -#soundcloud-tutorial { - width: 100%; -} - -@media(max-width:1100px) { - #soundcloud-logo { - display: none; - } - #soundcloud-logo-small { +.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); + float:left; + height: 90px; + margin: 0 30px 30px 0; + position: relative; + width: 90px; + -webkit-transition: all .1s linear; + transition: all .1s linear; + &:after { + color:#e9e6e4; + content: ""; display: block; + font-size: 50px; + height: 30px; + text-decoration: none; + text-shadow: 0px -1px 1px #bdb5b4, 1px 1px 1px white; + position: absolute; + width: 30px; + } + &:hover { + background-image: -webkit-linear-gradient(top, #fff, #f4f1ee); + background-image: linear-gradient(top, #fff, #f4f1ee); + color:#0088cc; + } + &:active { + background-image: -webkit-linear-gradient(top, #efedec, #f7f4f4); + background-image: linear-gradient(top, #efedec, #f7f4f4); + box-shadow: 0 3px 5px 0 rgba(0,0,0,.4), inset 0px -3px 1px 1px rgba(204,198,197,.5); + &:after{ + color:#dbd2d2; + text-shadow: 0px -1px 1px #bdb5b4, 0px 1px 1px white; + } + } +} + +.note { + &.active:after { + color: $secondaryThemeColor; + } + &:after{ + content: "♪"; + left: 32px; + top: 14px; + } + &:hover:after { + color: $secondaryThemeColor; + text-shadow: 0px 0px 6px $secondaryThemeColor; } } @media(min-width:767px) and (max-width:1200px) { - #add-new-music-label { - display: none; - } #play-list-controls .paper-button { border: 1px solid $whitish; border-radius: 5px; @@ -289,10 +180,6 @@ .close { display: block; } - #save-beat-preferences-star { - right: 5px; - left: initial; - } md-checkbox { padding-right: 20px !important; } diff --git a/chrome/app/styles/paper.scss b/chrome/app/styles/paper.scss index 901c2b4..8873127 100644 --- a/chrome/app/styles/paper.scss +++ b/chrome/app/styles/paper.scss @@ -18,6 +18,7 @@ md-checkbox .md-label { } .md-button { + font-size: 13px; flex-direction: unset; span { width: 100%; @@ -62,7 +63,7 @@ md-switch.md-default-theme.md-checked .md-thumb { } md-list-item { - margin-bottom: 2vh; + margin-bottom: 1vh; } @media(max-width:500px) { diff --git a/chrome/ember-cli-build.js b/chrome/ember-cli-build.js index e4b3409..b75f4af 100644 --- a/chrome/ember-cli-build.js +++ b/chrome/ember-cli-build.js @@ -14,8 +14,6 @@ module.exports = function (defaults) { destDir: '/fonts/bootstrap' }); - app.import('vendor/dancer.js'); - app.import('bower_components/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js'); app.import('bower_components/velocity/velocity.js'); diff --git a/chrome/public/background.js b/chrome/public/background.js index 7dfbcb5..2c90e13 100644 --- a/chrome/public/background.js +++ b/chrome/public/background.js @@ -1,11 +1,827 @@ -chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { - if (request.action === 'start-listen') { - chrome.tabCapture.capture({ - audio: true, - video: false - }, function (stream) { - console.log('stream', stream); - //I can attach all my filter here... - }); +'use strict'; + +/* + * dancer - v0.4.0 - 2014-02-01 + * https://github.com/jsantell/dancer.js + * Copyright (c) 2014 Jordan Santell + * Licensed MIT + */ +(function () { + + var Dancer = function () { + this.audioAdapter = Dancer._getAdapter(this); + this.events = {}; + this.sections = []; + this.bind('update', update); + }; + + Dancer.version = 'X.X.X'; + Dancer.adapters = {}; + + Dancer.prototype = { + + load: function (source, micBoost, useMic) { + // Loading an Audio element + if (source instanceof HTMLElement) { + this.source = source; + // Loading an object with src, [codecs] + } else if (source instanceof EventTarget) { + this.source = source; + } else { + this.source = window.Audio ? new Audio() : {}; + this.source.src = Dancer._makeSupportedPath(source.src, source.codecs); + } + + this.useMic = useMic === true; + this.boost = micBoost ? micBoost : 1; + this.audio = this.audioAdapter.load(this.source, this.useMic, this.boost); + + return this; + }, + + /* Controls */ + play: function () { + this.audioAdapter.play(); + return this; + }, + + pause: function () { + this.audioAdapter.pause(); + return this; + }, + + setVolume: function (volume) { + this.audioAdapter.setVolume(volume); + return this; + }, + + setBoost: function (boost) { + this.audioAdapter.setBoost(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; + }, + + + /* Getters */ + + getVolume: function () { + return this.audioAdapter.getVolume(); + }, + + getProgress: function () { + return this.audioAdapter.getProgress(); + }, + + getTime: function () { + return this.audioAdapter.getTime(); + }, + + // 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(); + }, + + isLoaded: function () { + return this.audioAdapter.isLoaded; + }, + + isPlaying: function () { + return this.audioAdapter.isPlaying; + }, + + + /* 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); + } } -}); \ No newline at end of file + + 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]; + } + } + }; + + Dancer.isSupported = function () { + if (!window.Float32Array || !window.Uint32Array) { + return null; + } else if (!isUnsupportedSafari() && (window.AudioContext || window.webkitAudioContext)) { + return 'webaudio'; + } else { + return ''; + } + }; + + Dancer.canPlay = function (type) { + var canPlay = audioEl.canPlayType; + return !!( + type.toLowerCase() === 'mp3' || + audioEl.canPlayType && + audioEl.canPlayType(CODECS[type.toLowerCase()]).replace(/no/, '')); + }; + + Dancer.addPlugin = function (name, fn) { + if (Dancer.prototype[name] === undefined) { + Dancer.prototype[name] = fn; + } + }; + + Dancer._makeSupportedPath = function (source, codecs) { + if (!codecs) { return source; } + + for (var i = 0; i < codecs.length; i++) { + if (Dancer.canPlay(codecs[i])) { + return source + '.' + codecs[i]; + } + } + return source; + }; + + Dancer._getAdapter = function (instance) { + switch (Dancer.isSupported()) { + case 'webaudio': + return new Dancer.adapters.webaudio(instance); + default: + return null; + } + }; + + Dancer._getMP3SrcFromAudio = function (audioEl) { + var sources = audioEl.children; + if (audioEl.src) { return audioEl.src; } + for (var i = sources.length; i--;) { + if ((sources[i].type || '').match(/audio\/mpeg/)) return sources[i].src; + } + return null; + }; + + // Browser detection is lame, but Safari 6 has Web Audio API, + // but does not support processing audio from a Media Element Source + // https://gist.github.com/3265344 + function isUnsupportedSafari() { + var + isApple = !!(navigator.vendor || '').match(/Apple/), + version = navigator.userAgent.match(/Version\/([^ ]*)/); + version = version ? parseFloat(version[1]) : 0; + return isApple && version <= 6; + } + +})(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.audio = new Audio(); + this.context = context; + }; + + adapter.prototype = { + + load: function (_source, useMic, boost) { + var _this = this; + this.audio = _source; + this.useMic = useMic; + this.boost = boost; + + 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, this.boost); + this.signal = new Float32Array(SAMPLE_SIZE / 2); + + if (this.audio.readyState < 3) { + this.audio.addEventListener('canplay', function () { + connectContext.call(_this); + }); + } else { + connectContext.call(_this); + } + + this.audio.addEventListener('progress', function (e) { + if (e.currentTarget.duration && e.currentTarget.duration !== Infinity) { + _this.progress = e.currentTarget.seekable.end(0) / e.currentTarget.duration; + } + }); + + return this.audio; + }, + + play: function () { + this.audio.play(); + this.isPlaying = true; + }, + + pause: function () { + this.audio.pause(); + this.isPlaying = false; + }, + + setVolume: function (volume) { + this.gain.gain.value = volume; + }, + + setBoost: function (boost) { + if (this.fft) { + this.fft.setBoost(boost); + } + + this.boost = boost; + }, + + getVolume: function () { + return this.gain.gain.value; + }, + + getProgress: function () { + return this.progress; + }, + + getWaveform: function () { + return this.signal; + }, + + getSpectrum: function () { + return this.fft.spectrum; + }, + + getTime: function () { + return this.audio.currentTime; + }, + + update: function (e) { + if ((!this.isPlaying || !this.isLoaded) && this.useMic !== true) return; + + 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() { + try { + if (this.useMic) { + this.source = this.context.createMediaStreamSource(this.audio); + } else { + this.source = this.context.createMediaElementSource(this.audio); + } + } catch (err) { + console.info('Dancer: ' + err); + return; + } + + 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 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(); +}; + + +chrome.storage.local.get('threshold', ({threshold}) => { + threshold = threshold || 0.3; + + let dancer = new window.Dancer(), + paused = false, + simulateKick = (mag, ratioKickMag) => { + console.log('mag: ' + mag + ', ratioKickMag: ' + ratioKickMag); + }, + kick = dancer.createKick({ + threshold, + onKick: (mag, ratioKickMag) => { + if (paused === false) { + simulateKick(mag, ratioKickMag); + } + } + }); + + kick.on(); + + chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { + if (request.action === 'start-listening') { + chrome.tabCapture.capture({ + audio: true, + video: false + }, function (stream) { + let error = null; + + if (!stream) { + error = chrome.runtime.lastError.message; + } else { + // let audio = new Audio(); + // audio.src = URL.createObjectURL(stream); + // audio.crossOrigin = "anonymous"; + //dancer.load(audio, 1); + } + + sendResponse({ error }); + + return true; + }); + } + + return true; + }); +}); + +// simulateKick(/*mag, ratioKickMag*/) { +// let activeLights = this.get('activeLights'), +// lightsData = this.get('lightsData'), +// color = null, + +// transitiontime = this.get('flashingTransitions'), +// stimulateLight = (light, brightness, hue) => { +// let options = { 'bri': brightness }; + +// if (transitiontime) { +// options['transitiontime'] = 0; +// } else { +// options['transitiontime'] = 1; +// } + +// if (!isNone(hue)) { +// options.hue = hue; +// } + +// if (lightsData[light].state.on === false) { +// options.on = true; +// } + +// $.ajax(this.get('apiURL') + '/lights/' + light + '/state', { +// data: JSON.stringify(options), +// contentType: 'application/json', +// type: 'PUT' +// }); +// }, +// timeToBriOff = 100; + +// if (activeLights.length > 0) { +// let lastLightBopIndex = this.get('lastLightBopIndex'), +// lightBopIndex, +// brightnessRange = this.get('brightnessRange'), +// light; + +// lightBopIndex = Math.floor(Math.random() * activeLights.length); + +// // let's try not to select the same light twice in a row +// if (activeLights.length > 1) { +// while (lightBopIndex === lastLightBopIndex) { +// lightBopIndex = Math.floor(Math.random() * activeLights.length); +// } +// } + +// 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; +// } + +// stimulateLight(light, brightnessRange[1], color); +// later(this, stimulateLight, light, brightnessRange[0], timeToBriOff); +// } + +// this.set('paused', true); +// later(this, function () { +// this.set('paused', false); +// }, 150); +// } \ No newline at end of file diff --git a/chrome/vendor/dancer.js b/chrome/vendor/dancer.js deleted file mode 100644 index 72d2894..0000000 --- a/chrome/vendor/dancer.js +++ /dev/null @@ -1,709 +0,0 @@ -/* - * dancer - v0.4.0 - 2014-02-01 - * https://github.com/jsantell/dancer.js - * Copyright (c) 2014 Jordan Santell - * Licensed MIT - */ -(function() { - - var Dancer = function () { - this.audioAdapter = Dancer._getAdapter( this ); - this.events = {}; - this.sections = []; - this.bind( 'update', update ); - }; - - Dancer.version = 'X.X.X'; - Dancer.adapters = {}; - - Dancer.prototype = { - - load : function ( source, micBoost, useMic ) { - // Loading an Audio element - if ( source instanceof HTMLElement ) { - this.source = source; - // Loading an object with src, [codecs] - } else if(source instanceof EventTarget){ - this.source = source; - } else { - this.source = window.Audio ? new Audio() : {}; - this.source.src = Dancer._makeSupportedPath( source.src, source.codecs ); - } - - this.useMic = useMic === true; - this.boost = micBoost ? micBoost : 1; - this.audio = this.audioAdapter.load(this.source, this.useMic, this.boost); - - return this; - }, - - /* Controls */ - play : function () { - this.audioAdapter.play(); - return this; - }, - - pause : function () { - this.audioAdapter.pause(); - return this; - }, - - setVolume : function ( volume ) { - this.audioAdapter.setVolume( volume ); - return this; - }, - - setBoost : function ( boost ) { - this.audioAdapter.setBoost( 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; - }, - - - /* Getters */ - - getVolume : function () { - return this.audioAdapter.getVolume(); - }, - - getProgress : function () { - return this.audioAdapter.getProgress(); - }, - - getTime : function () { - return this.audioAdapter.getTime(); - }, - - // 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(); - }, - - isLoaded : function () { - return this.audioAdapter.isLoaded; - }, - - isPlaying : function () { - return this.audioAdapter.isPlaying; - }, - - - /* 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 ]; - } - } - }; - - Dancer.isSupported = function () { - if ( !window.Float32Array || !window.Uint32Array ) { - return null; - } else if ( !isUnsupportedSafari() && ( window.AudioContext || window.webkitAudioContext )) { - return 'webaudio'; - } else { - return ''; - } - }; - - Dancer.canPlay = function ( type ) { - var canPlay = audioEl.canPlayType; - return !!( - type.toLowerCase() === 'mp3' || - audioEl.canPlayType && - audioEl.canPlayType( CODECS[ type.toLowerCase() ] ).replace( /no/, '')); - }; - - Dancer.addPlugin = function ( name, fn ) { - if ( Dancer.prototype[ name ] === undefined ) { - Dancer.prototype[ name ] = fn; - } - }; - - Dancer._makeSupportedPath = function ( source, codecs ) { - if ( !codecs ) { return source; } - - for ( var i = 0; i < codecs.length; i++ ) { - if ( Dancer.canPlay( codecs[ i ] ) ) { - return source + '.' + codecs[ i ]; - } - } - return source; - }; - - Dancer._getAdapter = function ( instance ) { - switch ( Dancer.isSupported() ) { - case 'webaudio': - return new Dancer.adapters.webaudio( instance ); - default: - return null; - } - }; - - Dancer._getMP3SrcFromAudio = function ( audioEl ) { - var sources = audioEl.children; - if ( audioEl.src ) { return audioEl.src; } - for ( var i = sources.length; i--; ) { - if (( sources[ i ].type || '' ).match( /audio\/mpeg/ )) return sources[ i ].src; - } - return null; - }; - - // Browser detection is lame, but Safari 6 has Web Audio API, - // but does not support processing audio from a Media Element Source - // https://gist.github.com/3265344 - function isUnsupportedSafari () { - var - isApple = !!( navigator.vendor || '' ).match( /Apple/ ), - version = navigator.userAgent.match( /Version\/([^ ]*)/ ); - version = version ? parseFloat( version[ 1 ] ) : 0; - return isApple && version <= 6; - } - -})( 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.audio = new Audio(); - this.context = context; - }; - - adapter.prototype = { - - load : function (_source, useMic, boost) { - var _this = this; - this.audio = _source; - this.useMic = useMic; - this.boost = boost; - - 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, this.boost ); - this.signal = new Float32Array( SAMPLE_SIZE / 2 ); - - if ( this.audio.readyState < 3 ) { - this.audio.addEventListener( 'canplay', function () { - connectContext.call( _this ); - }); - } else { - connectContext.call( _this ); - } - - this.audio.addEventListener( 'progress', function ( e ) { - if ( e.currentTarget.duration && e.currentTarget.duration !== Infinity ) { - _this.progress = e.currentTarget.seekable.end( 0 ) / e.currentTarget.duration; - } - }); - - return this.audio; - }, - - play : function () { - this.audio.play(); - this.isPlaying = true; - }, - - pause : function () { - this.audio.pause(); - this.isPlaying = false; - }, - - setVolume : function ( volume ) { - this.gain.gain.value = volume; - }, - - setBoost : function( boost ){ - if(this.fft){ - this.fft.setBoost(boost); - } - - this.boost = boost; - }, - - getVolume : function () { - return this.gain.gain.value; - }, - - getProgress : function() { - return this.progress; - }, - - getWaveform : function () { - return this.signal; - }, - - getSpectrum : function () { - return this.fft.spectrum; - }, - - getTime : function () { - return this.audio.currentTime; - }, - - update : function ( e ) { - if ((!this.isPlaying || !this.isLoaded) && this.useMic !== true ) return; - - 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 () { - try { - if(this.useMic){ - this.source = this.context.createMediaStreamSource(this.audio); - } else { - this.source = this.context.createMediaElementSource(this.audio); - } - } catch (err) { - console.info('Dancer: '+ err); - return; - } - - 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 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(); -}; diff --git a/mobile/app/index.html b/mobile/app/index.html index dbe0ee4..9e8be9c 100644 --- a/mobile/app/index.html +++ b/mobile/app/index.html @@ -1,41 +1,42 @@ - - - - Huegasm - - - - - {{content-for 'head'}} + + + + Huegasm + + + + {{content-for 'head'}} - + - - + + {{content-for 'head-footer'}} - {{content-for 'head-footer'}} + - + + - ga('create', 'UA-69470561-1', 'auto'); - ga('send', 'pageview'); - - - - {{content-for 'body'}} + + {{content-for 'body'}} - - + + - {{content-for 'body-footer'}} - - + {{content-for 'body-footer'}} + + + \ No newline at end of file diff --git a/mobile/app/pods/components/bridge-finder/template.hbs b/mobile/app/pods/components/bridge-finder/template.hbs index 3e3fa23..a0af360 100644 --- a/mobile/app/pods/components/bridge-finder/template.hbs +++ b/mobile/app/pods/components/bridge-finder/template.hbs @@ -5,7 +5,7 @@

{{#if isAuthenticating}} Your bridge IP is {{bridgeIp}} -
Press the button on your bridge to authenticate this application. +
Press the button on your bridge to authenticate Huegasm. {{else}} You failed to press the button in time. RETRY {{/if}} @@ -17,7 +17,7 @@ {{/unless}} {{#if bridgeFindMultiple}} -

Huegasm found multiple hue bridges.
Please select the one you want to use for this application.

+

Huegasm found multiple hue bridges.
Please select the one you want to use for Huegasm.

{{#each multipleBridgeIps as |bridge|}} diff --git a/mobile/app/pods/components/music-tab/mixins/helpers.js b/mobile/app/pods/components/music-tab/mixins/helpers.js index c7bd75e..88e90d5 100644 --- a/mobile/app/pods/components/music-tab/mixins/helpers.js +++ b/mobile/app/pods/components/music-tab/mixins/helpers.js @@ -22,7 +22,7 @@ export default Mixin.create({ beatOptions: { threshold: { - range: {min: 0, max: 0.5}, + range: { min: 0, max: 0.5 }, step: 0.01, defaultValue: 0.3, pips: { @@ -30,23 +30,23 @@ export default Mixin.create({ values: [0, 0.25, 0.5], density: 10, format: { - to: function ( value ) { - if(value === 0) { - value = 'More'; - } else if(value === 0.25) { + to: function (value) { + if (value === 0) { + value = 'High'; + } else if (value === 0.25) { value = ''; } else { - value = 'Less'; + value = 'Low'; } return value; }, - from: function ( value ) { return value; } + from: function (value) { return value; } } } }, hueRange: { - range: {min: 0, max: 65535}, + range: { min: 0, max: 65535 }, step: 1, defaultValue: 0.3, pips: { @@ -54,10 +54,10 @@ export default Mixin.create({ values: [0, 25500, 46920, 65535], density: 10, format: { - to: function ( value ) { - if(value === 0 || value === 65535) { + to: function (value) { + if (value === 0 || value === 65535) { value = 'Red'; - } else if(value === 25500 ) { + } else if (value === 25500) { value = 'Green'; } else { value = 'Blue'; @@ -65,12 +65,12 @@ export default Mixin.create({ return value; }, - from: function ( value ) { return value; } + from: function (value) { return value; } } } }, brightnessRange: { - range: {min: 1, max: 254}, + range: { min: 1, max: 254 }, step: 1, defaultValue: 0, pips: { @@ -78,8 +78,16 @@ export default Mixin.create({ values: [1, 50, 100, 150, 200, 254], density: 10, format: { - to: function ( value ) { return value; }, - from: function ( value ) { return value; } + to: function (value) { + if (value === 50) { + value = 20; + } else if (value === 100) { + value = 40; + } else { + value = 'Low'; + } + }, + from: function (value) { return value; } } } } @@ -99,8 +107,6 @@ export default Mixin.create({ playerBottomDisplayed: true, dragging: false, draggingOverPlayListArea: false, - audioStream: null, - dimmerOn: false, isShowingAddSoundCloudModal: false, colorloopMode: false, @@ -133,26 +139,26 @@ export default Mixin.create({ SC_CLIENT_ID: 'aeec0034f58ecd85c2bd1deaecc41594', scUserNotSupportedHtml: '', tooManySoundCloudFuckUps: '', - notStreamableHtml(fileNames){ - let html = ''; + notStreamableHtml(fileNames) { + let html = ''; return html; }, - urlNotFoundHtml(url){ + urlNotFoundHtml(url) { return ''; }, - failedToPlayFileHtml(fileName){ + failedToPlayFileHtml(fileName) { return ''; }, - failedToDecodeFileHtml(fileName){ + failedToDecodeFileHtml(fileName) { return ''; }, - scUrl: computed('playQueuePointer', 'playQueue.[]', function(){ + scUrl: computed('playQueuePointer', 'playQueue.[]', function () { let rtn = null, currentSong = this.get('playQueue')[this.get('playQueuePointer')]; - if(currentSong && currentSong.scUrl){ + if (currentSong && currentSong.scUrl) { rtn = currentSong.scUrl; } @@ -161,11 +167,11 @@ export default Mixin.create({ playQueueEmpty: computed.empty('playQueue'), playQueueNotEmpty: computed.notEmpty('playQueue'), - playQueueMultiple: computed('playQueue.[]', function(){ + playQueueMultiple: computed('playQueue.[]', function () { return this.get('playQueue').length > 1; }), - seekPosition: computed('timeElapsed', 'timeTotal', function(){ + seekPosition: computed('timeElapsed', 'timeTotal', function () { let timeTotal = this.get('timeTotal'), timeElapsed = this.get('timeElapsed'); @@ -173,21 +179,21 @@ export default Mixin.create({ return 0; } - return timeElapsed/timeTotal*100; + return timeElapsed / timeTotal * 100; }), - largeArtworkPic: computed('playQueuePointer', 'currentVisName', function(){ + largeArtworkPic: computed('playQueuePointer', 'currentVisName', function () { let pic = '', currentVisName = this.get('currentVisName'), playQueuePointer = this.get('playQueuePointer'), playQueue = this.get('playQueue'); - if(playQueuePointer !== -1 && currentVisName === 'None'){ + if (playQueuePointer !== -1 && currentVisName === 'None') { let song = playQueue[playQueuePointer]; - if(!isNone(song.picture)){ + if (!isNone(song.picture)) { pic = song.picture; - if(song.scUrl){ + if (song.scUrl) { pic = pic.replace('67x67', '500x500'); } } @@ -196,91 +202,91 @@ export default Mixin.create({ return pic; }), - repeatIcon: computed('repeat', function() { - if(this.get('repeat') === 2) { + repeatIcon: computed('repeat', function () { + if (this.get('repeat') === 2) { return 'repeat-one'; } return 'repeat'; }), - playingIcon: computed('playing', function() { - if(this.get('playing')){ + playingIcon: computed('playing', function () { + if (this.get('playing')) { return 'pause'; - } else if(this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0){ + } else if (this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0) { return 'replay'; } else { return 'play-arrow'; } }), - playerAreaClickIcon: computed('playing', function() { - if(this.get('playing')){ + playerAreaClickIcon: computed('playing', function () { + if (this.get('playing')) { return 'play-arrow'; } else { return 'pause'; } }), - playListAreaClass: computed('dragging', 'draggingOverPlayListArea', 'dimmerOn', function(){ + playListAreaClass: computed('dragging', 'draggingOverPlayListArea', 'dimmerOn', function () { let classes = 'pointer'; - if(this.get('dragging')){ + if (this.get('dragging')) { classes += ' drag-here-highlight'; } - if(this.get('draggingOverPlayListArea')){ + if (this.get('draggingOverPlayListArea')) { classes += ' dragging-over'; } - if(this.get('dimmerOn')){ + if (this.get('dimmerOn')) { classes += ' dimmerOn'; } return classes; }), - dimmerOnClass: computed('dimmerOn', function(){ + dimmerOnClass: computed('dimmerOn', function () { return this.get('dimmerOn') ? 'dimmerOn' : null; }), - repeatClass: computed('repeat', function(){ + repeatClass: computed('repeat', function () { return this.get('repeat') !== 0 ? 'player-control-icon active' : 'player-control-icon'; }), - shuffleClass: computed('shuffle', function(){ + shuffleClass: computed('shuffle', function () { return this.get('shuffle') ? 'player-control-icon active' : 'player-control-icon'; }), - beatDetectionAreaArrowIcon: computed('playerBottomDisplayed', function(){ - if(!this.get('playerBottomDisplayed')){ + beatDetectionAreaArrowIcon: computed('playerBottomDisplayed', function () { + if (!this.get('playerBottomDisplayed')) { return 'keyboard-arrow-down'; } else { return 'keyboard-arrow-up'; } }), - timeElapsedTxt: computed('timeElapsed', function(){ + timeElapsedTxt: computed('timeElapsed', function () { return this.formatTime(this.get('timeElapsed')); }), - timeTotalTxt: computed('timeTotal', function() { + timeTotalTxt: computed('timeTotal', function () { return this.formatTime(this.get('timeTotal')); }), - onPlayQueueChange: observer('playQueue.length', function(){ + onPlayQueueChange: observer('playQueue.length', function () { let playQueueLength = this.get('playQueue.length'); - if(playQueueLength > this.get('oldPlayQueueLength')){ - run.once(this, ()=>{ - run.next(this, function() { - $(`.track${playQueueLength-1}`).velocity('scroll', { container: $('#play-list-area'), duration: 200 }); + if (playQueueLength > this.get('oldPlayQueueLength')) { + run.once(this, () => { + run.next(this, function () { + $(`.track${playQueueLength - 1}`).velocity('scroll', { container: $('#play-list-area'), duration: 200 }); Ps.update(document.getElementById('play-list-area')); }); }); } else { - run.once(this, ()=>{ - run.next(this, function() { + run.once(this, () => { + run.next(this, function () { Ps.update(document.getElementById('play-list-area')); }); }); @@ -289,17 +295,17 @@ export default Mixin.create({ this.set('oldPlayQueueLength', playQueueLength); }), - onColorloopModeChange: observer('colorloopMode', 'playing', function(){ + onColorloopModeChange: observer('colorloopMode', 'playing', function () { this.set('colorLoopOn', this.get('playing') && this.get('colorloopMode')); }), - onOptionChange: observer('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'colorloopMode', function(self, option){ + onOptionChange: observer('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'colorloopMode', function (self, option) { option = option.replace('.[]', ''); let value = this.get(option); // can't really save local music - if(option === 'playQueue'){ - value = value.filter((song)=>{ + if (option === 'playQueue') { + value = value.filter((song) => { return !song.url.startsWith('blob:'); }); } @@ -307,9 +313,9 @@ export default Mixin.create({ this.get('storage').set('huegasm.' + option, value); }), - formatTime(time){ - return this.pad(Math.floor(time/60), 2) + ':' + this.pad(time%60, 2); + formatTime(time) { + return this.pad(Math.floor(time / 60), 2) + ':' + this.pad(time % 60, 2); }, - pad(num, size){ return ('000000000' + num).substr(-size); } + pad(num, size) { return ('000000000' + num).substr(-size); } }); diff --git a/mobile/app/styles/app.scss b/mobile/app/styles/app.scss index 733f5f3..312be8a 100644 --- a/mobile/app/styles/app.scss +++ b/mobile/app/styles/app.scss @@ -26,7 +26,7 @@ } body, button { - font-family: 'Slabo 27px', serif; + font-family: 'Raleway', sans-serif; } .alert { diff --git a/mobile/app/styles/hue-controls.scss b/mobile/app/styles/hue-controls.scss index 580277f..418dcbf 100644 --- a/mobile/app/styles/hue-controls.scss +++ b/mobile/app/styles/hue-controls.scss @@ -33,7 +33,7 @@ text-align: right; position: absolute; top: 5px; - right: 10px; + right: -10px; transform: scale(1.1); } } diff --git a/mobile/app/styles/light-group.scss b/mobile/app/styles/light-group.scss index 85ad491..d9f9519 100644 --- a/mobile/app/styles/light-group.scss +++ b/mobile/app/styles/light-group.scss @@ -51,7 +51,7 @@ .light-text { width: 60px; word-wrap: break-word; - padding: 0 10px; + padding: 0 7px; &.light-inactive::before { left: 10px; } diff --git a/mobile/app/styles/paper.scss b/mobile/app/styles/paper.scss index d8766ab..503c437 100644 --- a/mobile/app/styles/paper.scss +++ b/mobile/app/styles/paper.scss @@ -14,6 +14,7 @@ md-checkbox .md-label { } .md-button { + font-size: 13px; flex-direction: unset; span { width: 100%; diff --git a/web/app/index.html b/web/app/index.html index 32bbe80..c8fc820 100644 --- a/web/app/index.html +++ b/web/app/index.html @@ -1,67 +1,67 @@ - - - - Huegasm - - - - - + - - - - - - + + + + + + - + {{content-for 'head'}} - {{content-for 'head'}} + - + + + + + + + + {{content-for 'head-footer'}} - - - - - - + - - + + - + + {{content-for 'body'}} - + - ga('create', 'UA-69470561-1', 'auto'); - ga('send', 'pageview'); - - - - {{content-for 'body'}} + {{content-for 'body-footer'}} + - - - - {{content-for 'body-footer'}} - - + \ No newline at end of file diff --git a/web/app/pods/components/bridge-finder/template.hbs b/web/app/pods/components/bridge-finder/template.hbs index ee0852a..cb665cd 100644 --- a/web/app/pods/components/bridge-finder/template.hbs +++ b/web/app/pods/components/bridge-finder/template.hbs @@ -6,7 +6,7 @@ {{#if isAuthenticating}}

Your bridge IP is {{bridgeIp}} -
Press the button on your bridge to authenticate this application. +
Press the button on your bridge to authenticate Huegasm.

{{else}}

You failed to press the button in time. RETRY

@@ -18,7 +18,7 @@ {{/unless}} {{#if bridgeFindMultiple}} -

Huegasm found multiple hue bridges.
Please select the one you want to use for this application.

+

Huegasm found multiple hue bridges.
Please select the one you want to use for Huegasm.

{{#each multipleBridgeIps as |bridge|}} diff --git a/web/app/pods/components/huegasm-footer/component.js b/web/app/pods/components/huegasm-footer/component.js index 0d4aa3a..a88ccd2 100644 --- a/web/app/pods/components/huegasm-footer/component.js +++ b/web/app/pods/components/huegasm-footer/component.js @@ -9,12 +9,12 @@ export default Component.extend({ tagName: 'footer', classNames: ['footer'], - year: computed(function(){ + year: computed(function () { return new Date().getFullYear(); }), actions: { - toggleDimmer(){ + toggleDimmer() { this.sendAction(); } } diff --git a/web/app/pods/components/music-tab/mixins/helpers.js b/web/app/pods/components/music-tab/mixins/helpers.js index 2d3d395..b440cb8 100644 --- a/web/app/pods/components/music-tab/mixins/helpers.js +++ b/web/app/pods/components/music-tab/mixins/helpers.js @@ -23,7 +23,7 @@ export default Mixin.create({ beatOptions: { threshold: { - range: {min: 0, max: 0.5}, + range: { min: 0, max: 0.5 }, step: 0.01, defaultValue: 0.3, pips: { @@ -31,23 +31,23 @@ export default Mixin.create({ values: [0, 0.25, 0.5], density: 10, format: { - to: function ( value ) { - if(value === 0) { - value = 'More'; - } else if(value === 0.25) { + to: function (value) { + if (value === 0) { + value = 'High'; + } else if (value === 0.25) { value = ''; } else { - value = 'Less'; + value = 'Low'; } return value; }, - from: function ( value ) { return value; } + from: function (value) { return value; } } } }, hueRange: { - range: {min: 0, max: 65535}, + range: { min: 0, max: 65535 }, step: 1, defaultValue: 0.3, pips: { @@ -55,10 +55,10 @@ export default Mixin.create({ values: [0, 25500, 46920, 65535], density: 10, format: { - to: function ( value ) { - if(value === 0 || value === 65535) { + to: function (value) { + if (value === 0 || value === 65535) { value = 'Red'; - } else if(value === 25500 ) { + } else if (value === 25500) { value = 'Green'; } else { value = 'Blue'; @@ -66,21 +66,33 @@ export default Mixin.create({ return value; }, - from: function ( value ) { return value; } + from: function (value) { return value; } } } }, brightnessRange: { - range: {min: 1, max: 254}, + range: { min: 1, max: 254 }, step: 1, defaultValue: 0, pips: { mode: 'values', - values: [1, 50, 100, 150, 200, 254], + values: [1, 63, 127, 190, 254], density: 10, format: { - to: function ( value ) { return value; }, - from: function ( value ) { return value; } + to: function (value) { + if (value === 63) { + value = 25; + } else if (value === 127) { + value = 50; + } else if (value === 190) { + value = 75; + } else if (value === 254) { + value = 100; + } + + return value; + }, + from: function (value) { return value; } } } } @@ -101,8 +113,6 @@ export default Mixin.create({ dragging: false, draggingOverPlayListArea: false, dragLeaveTimeoutHandle: null, - audioStream: null, - dimmerOn: false, isShowingAddSoundCloudModal: false, colorloopMode: false, @@ -136,26 +146,26 @@ export default Mixin.create({ SC_CLIENT_ID: 'aeec0034f58ecd85c2bd1deaecc41594', scUserNotSupportedHtml: '', tooManySoundCloudFuckUps: '', - notStreamableHtml(fileNames){ - let html = ''; + notStreamableHtml(fileNames) { + let html = ''; return html; }, - urlNotFoundHtml(url){ + urlNotFoundHtml(url) { return ''; }, - failedToPlayFileHtml(fileName){ + failedToPlayFileHtml(fileName) { return ''; }, - failedToDecodeFileHtml(fileName){ + failedToDecodeFileHtml(fileName) { return ''; }, - scUrl: computed('playQueuePointer', 'playQueue.[]', function(){ + scUrl: computed('playQueuePointer', 'playQueue.[]', function () { let rtn = null, currentSong = this.get('playQueue')[this.get('playQueuePointer')]; - if(currentSong && currentSong.scUrl){ + if (currentSong && currentSong.scUrl) { rtn = currentSong.scUrl; } @@ -164,11 +174,11 @@ export default Mixin.create({ playQueueEmpty: computed.empty('playQueue'), playQueueNotEmpty: computed.notEmpty('playQueue'), - playQueueMultiple: computed('playQueue.[]', function(){ + playQueueMultiple: computed('playQueue.[]', function () { return this.get('playQueue').length > 1; }), - seekPosition: computed('timeElapsed', 'timeTotal', function(){ + seekPosition: computed('timeElapsed', 'timeTotal', function () { let timeTotal = this.get('timeTotal'), timeElapsed = this.get('timeElapsed'); @@ -176,21 +186,21 @@ export default Mixin.create({ return 0; } - return timeElapsed/timeTotal*100; + return timeElapsed / timeTotal * 100; }), - largeArtworkPic: computed('playQueuePointer', 'currentVisName', function(){ + largeArtworkPic: computed('playQueuePointer', 'currentVisName', function () { let pic = '', currentVisName = this.get('currentVisName'), playQueuePointer = this.get('playQueuePointer'), playQueue = this.get('playQueue'); - if(playQueuePointer !== -1 && currentVisName === 'None'){ + if (playQueuePointer !== -1 && currentVisName === 'None') { let song = playQueue[playQueuePointer]; - if(!isNone(song.picture)){ + if (!isNone(song.picture)) { pic = song.picture; - if(song.scUrl){ + if (song.scUrl) { pic = pic.replace('67x67', '500x500'); } } @@ -199,73 +209,73 @@ export default Mixin.create({ return pic; }), - repeatIcon: computed('repeat', function() { - if(this.get('repeat') === 2) { + repeatIcon: computed('repeat', function () { + if (this.get('repeat') === 2) { return 'repeat-one'; } return 'repeat'; }), - playingIcon: computed('playing', function() { - if(this.get('playing')){ + playingIcon: computed('playing', function () { + if (this.get('playing')) { return 'pause'; - } else if(this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0){ + } else if (this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0) { return 'replay'; } else { return 'play-arrow'; } }), - playerAreaClickIcon: computed('playing', function() { - if(this.get('playing')){ + playerAreaClickIcon: computed('playing', function () { + if (this.get('playing')) { return 'play-arrow'; } else { return 'pause'; } }), - playListAreaClass: computed('dragging', 'draggingOverPlayListArea', 'dimmerOn', function(){ + playListAreaClass: computed('dragging', 'draggingOverPlayListArea', 'dimmerOn', function () { let classes = 'pointer'; - if(this.get('dragging')){ + if (this.get('dragging')) { classes += ' drag-here-highlight'; } - if(this.get('draggingOverPlayListArea')){ + if (this.get('draggingOverPlayListArea')) { classes += ' dragging-over'; } - if(this.get('dimmerOn')){ + if (this.get('dimmerOn')) { classes += ' dimmerOn'; } return classes; }), - dimmerOnClass: computed('dimmerOn', function(){ + dimmerOnClass: computed('dimmerOn', function () { return this.get('dimmerOn') ? 'dimmerOn' : null; }), - volumeMutedClass: computed('volumeMuted', function(){ + volumeMutedClass: computed('volumeMuted', function () { let classes = 'player-control-icon volumeButton'; - if(this.get('volumeMuted')){ + if (this.get('volumeMuted')) { classes += ' active'; } return classes; }), - repeatClass: computed('repeat', function(){ + repeatClass: computed('repeat', function () { return this.get('repeat') !== 0 ? 'player-control-icon active' : 'player-control-icon'; }), - shuffleClass: computed('shuffle', function(){ + shuffleClass: computed('shuffle', function () { return this.get('shuffle') ? 'player-control-icon active' : 'player-control-icon'; }), - volumeIcon: computed('volumeMuted', 'volume', function() { + volumeIcon: computed('volumeMuted', 'volume', function () { let volume = this.get('volume'); if (this.get('volumeMuted')) { @@ -279,29 +289,29 @@ export default Mixin.create({ } }), - beatDetectionAreaArrowIcon: computed('playerBottomDisplayed', function(){ - if(!this.get('playerBottomDisplayed')){ + beatDetectionAreaArrowIcon: computed('playerBottomDisplayed', function () { + if (!this.get('playerBottomDisplayed')) { return 'keyboard-arrow-down'; } else { return 'keyboard-arrow-up'; } }), - timeElapsedTxt: computed('timeElapsed', function(){ + timeElapsedTxt: computed('timeElapsed', function () { return this.formatTime(this.get('timeElapsed')); }), - timeTotalTxt: computed('timeTotal', function() { + timeTotalTxt: computed('timeTotal', function () { return this.formatTime(this.get('timeTotal')); }), - onPlayQueueChange: observer('playQueue.length', function(){ + onPlayQueueChange: observer('playQueue.length', function () { let playQueueLength = this.get('playQueue.length'); - if(playQueueLength > this.get('oldPlayQueueLength')){ - run.once(this, ()=>{ - run.next(this, function() { - $(`.track${playQueueLength-1}`).velocity('scroll', { container: $('#play-list-area'), duration: 200 }); + if (playQueueLength > this.get('oldPlayQueueLength')) { + run.once(this, () => { + run.next(this, function () { + $(`.track${playQueueLength - 1}`).velocity('scroll', { container: $('#play-list-area'), duration: 200 }); }); }); } @@ -309,17 +319,17 @@ export default Mixin.create({ this.set('oldPlayQueueLength', playQueueLength); }), - onColorloopModeChange: observer('colorloopMode', 'playing', function(){ + onColorloopModeChange: observer('colorloopMode', 'playing', function () { this.set('colorLoopOn', this.get('playing') && this.get('colorloopMode')); }), - onOptionChange: observer('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'colorloopMode', function(self, option){ + onOptionChange: observer('flashingTransitions', 'playQueue.[]', 'playQueuePointer', 'colorloopMode', function (self, option) { option = option.replace('.[]', ''); let value = this.get(option); // can't really save local music - if(option === 'playQueue'){ - value = value.filter((song)=>{ + if (option === 'playQueue') { + value = value.filter((song) => { return !song.url.startsWith('blob:'); }); } @@ -350,30 +360,30 @@ export default Mixin.create({ this.changeTooltipText(type, tooltipTxt); })), - onVolumeMutedChange: on('init', observer('volumeMuted', function() { + onVolumeMutedChange: on('init', observer('volumeMuted', function () { let tooltipTxt = 'Mute', type = 'volumeMuted', volumeMuted = this.get(type), dancer = this.get('dancer'), - volume=0; + volume = 0; if (volumeMuted) { tooltipTxt = 'Unmute'; volume = 0; } else { - volume = this.get('volume')/100; + volume = this.get('volume') / 100; } - if(this.get('playing')){ + if (this.get('playing')) { dancer.setVolume(volume); } this.changeTooltipText(type, tooltipTxt); })), - onPrevChange: on('init', observer('timeElapsed', 'playQueueNotEmpty', 'playQueue.[]', function() { - if(this.get('playQueueNotEmpty')){ + onPrevChange: on('init', observer('timeElapsed', 'playQueueNotEmpty', 'playQueue.[]', function () { + if (this.get('playQueueNotEmpty')) { let tooltipTxt = 'Previous', type = 'prev'; - if(this.get('timeElapsed') > 5 || this.get('playQueue').length === 1) { + if (this.get('timeElapsed') > 5 || this.get('playQueue').length === 1) { tooltipTxt = 'Replay'; } @@ -386,7 +396,7 @@ export default Mixin.create({ if (this.get(type)) { tooltipTxt = 'Pause'; - } else if(this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0){ + } else if (this.get('timeElapsed') === this.get('timeTotal') && this.get('timeTotal') !== 0) { tooltipTxt = 'Replay'; } @@ -399,14 +409,14 @@ export default Mixin.create({ //change the tooltip text for hover $('#' + type + 'Tooltip').attr('data-original-title', text); - if(isNone(this.get(type + 'TooltipTxt'))) { + if (isNone(this.get(type + 'TooltipTxt'))) { this.set(type + 'TooltipTxt', text); } }, - formatTime(time){ - return this.pad(Math.floor(time/60), 2) + ':' + this.pad(time%60, 2); + formatTime(time) { + return this.pad(Math.floor(time / 60), 2) + ':' + this.pad(time % 60, 2); }, - pad(num, size){ return ('000000000' + num).substr(-size); } + pad(num, size) { return ('000000000' + num).substr(-size); } }); diff --git a/web/app/pods/components/music-tab/template.hbs b/web/app/pods/components/music-tab/template.hbs index 8ed2441..c23c0b8 100644 --- a/web/app/pods/components/music-tab/template.hbs +++ b/web/app/pods/components/music-tab/template.hbs @@ -1,86 +1,100 @@
- + -
- -
+
+ +
- {{paper-icon playerAreaClickIcon id="play-notification"}} + {{paper-icon playerAreaClickIcon id="play-notification"}} -
- {{range-slider start=seekPosition min=0 max=100 connect=filledConnect id="seek-slider" on-change="seekChanged"}} +
+ {{range-slider start=seekPosition min=0 max=100 connect=filledConnect id="seek-slider" on-change="seekChanged"}} - {{#if playQueueNotEmpty}} - {{paper-icon "skip-previous" class="player-control-icon"}}{{/if}}{{paper-icon playingIcon class="player-control-icon"}}{{#if playQueueMultiple}}{{paper-icon "skip-next" action="" class="player-control-icon"}}{{/if}}{{paper-icon icon=volumeIcon class=volumeMutedClass}} + {{/if}} + + {{paper-icon playingIcon class="player-control-icon"}} + + {{#if playQueueMultiple}} + {{paper-icon "skip-next" action="" class="player-control-icon"}} + + {{/if}} + + + {{range-slider start=volume min=0 max=100 connect=filledConnect on-change="volumeChanged" id="volume-bar" class="hidden-xs"}} -
{{timeElapsedTxt}} / {{timeTotalTxt}}
+
{{timeElapsedTxt}} / {{timeTotalTxt}}
- {{#paper-menu as |menu|}} - {{#menu.trigger}} - {{#paper-button iconButton=true}} - {{paper-icon "remove-red-eye" class="player-control-icon"}} - {{/paper-button}} - {{/menu.trigger}} - {{#menu.content width=2 as |content|}} - {{#each visNames as |name|}} - {{#content.menu-item onClick=(action "setVisName" name)}} - {{name}} + {{#paper-menu as |menu|}} + {{#menu.trigger}} + {{#paper-button iconButton=true}} + {{paper-icon "remove-red-eye" class="player-control-icon"}} + {{/paper-button}} + {{/menu.trigger}} + {{#menu.content width=2 as |content|}} + {{#each visNames as |name|}} + {{#content.menu-item onClick=(action "setVisName" name)}} + {{name}} - {{#if (eq currentVisName name)}} - {{paper-icon "check" classNames=dimmerOnClass}} - {{/if}} - {{/content.menu-item}} - {{/each}} - {{/menu.content}} - {{/paper-menu}} + {{#if (eq currentVisName name)}} + {{paper-icon "check" classNames=dimmerOnClass}} + {{/if}} + {{/content.menu-item}} + {{/each}} + {{/menu.content}} + {{/paper-menu}} - {{#if scUrl}} - - - - - {{/if}} + {{#if scUrl}} + + + + + {{/if}} +
-
-
- +
+ -
- {{#paper-menu as |menu|}} - {{#menu.trigger}} - {{#paper-button iconButton=false}} - {{paper-icon "playlist add" class="player-control-icon"}} Add new music - {{/paper-button}} - {{/menu.trigger}} - {{#menu.content width=3 as |content|}} - {{#content.menu-item onClick="addLocalAudio"}} - {{paper-icon "attachment" class=shuffleClass}} Local file - {{/content.menu-item}} - {{#content.menu-item onClick="toggleIsShowingAddSoundCloudModal"}} - {{paper-icon "cloud" class=shuffleClass}} SoundCloud - {{/content.menu-item}} - {{/menu.content}} - {{/paper-menu}} +
+ {{#paper-menu as |menu|}} + {{#menu.trigger}} + {{#paper-button iconButton=false}} + {{paper-icon "playlist add" class="player-control-icon"}} Add new music + {{/paper-button}} + {{/menu.trigger}} + {{#menu.content width=3 as |content|}} + {{#content.menu-item onClick="addLocalAudio" }} + {{paper-icon "attachment" class=shuffleClass}} Local file + {{/content.menu-item}} + {{#content.menu-item onClick="toggleIsShowingAddSoundCloudModal" }} + {{paper-icon "cloud" class=shuffleClass}} SoundCloud + {{/content.menu-item}} + {{/menu.content}} + {{/paper-menu}} - {{paper-icon "shuffle" class=shuffleClass}} - {{paper-icon repeatIcon class=repeatClass}} - -
+ {{paper-icon "shuffle" class=shuffleClass}} + {{paper-icon repeatIcon class=repeatClass}} + +
-
+
{{#if (or playQueueEmpty dragging)}}
{{#if dragging}} @@ -95,7 +109,7 @@ {{#each playQueue as |item index|}}
{{#if item.picture}} - + {{else}} {{/if}} @@ -105,9 +119,9 @@
{{item.title}}
{{#if item.artistUrl}} - {{item.artist}} + {{item.artist}} {{else}} - {{item.artist}} + {{item.artist}} {{/if}}
{{else}} @@ -115,10 +129,11 @@ {{/if}}
- {{paper-icon "close" classNames="close"}} + {{paper-icon "close" classNames="close"}}
{{/each}} -
+
@@ -131,44 +146,53 @@
{{#if usingBeatPreferences}} - - {{paper-icon "star" class=dimmerOnClass}} - + + {{paper-icon "star" class=dimmerOnClass}} + {{/if}}
- + Hue Range - + - {{range-slider start=hueRange orientation="vertical" step=beatOptions.hueRange.step range=beatOptions.hueRange.range connect=hueRangeConnect on-change="hueRangeChanged" pips=beatOptions.hueRange.pips}} + {{range-slider start=hueRange orientation="vertical" step=beatOptions.hueRange.step range=beatOptions.hueRange.range connect=hueRangeConnect + on-change="hueRangeChanged" pips=beatOptions.hueRange.pips}}
- + Brightness Range - + - {{range-slider start=brightnessRange orientation="vertical" step=beatOptions.brightnessRange.step range=beatOptions.brightnessRange.range on-change="brightnessRangeChanged" pips=beatOptions.brightnessRange.pips}} + {{range-slider start=brightnessRange orientation="vertical" step=beatOptions.brightnessRange.step range=beatOptions.brightnessRange.range + on-change="brightnessRangeChanged" pips=beatOptions.brightnessRange.pips}}
- + Sensitivity - + - {{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range on-change="thresholdChanged" pips=beatOptions.threshold.pips}} + {{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range on-change="thresholdChanged" + pips=beatOptions.threshold.pips}}
- + {{paper-checkbox value=flashingTransitions onChange=(action (mut flashingTransitions)) label="Flashing Transitions"}} - + - - {{paper-checkbox value=colorloopMode onChange=(action (mut colorloopMode)) label="Colorloop"}} - + + {{paper-checkbox value=colorloopMode onChange=(action (mut colorloopMode)) label="Colorloop"}} +
diff --git a/web/app/styles/app.scss b/web/app/styles/app.scss index 5a02f09..3b2c08b 100644 --- a/web/app/styles/app.scss +++ b/web/app/styles/app.scss @@ -23,7 +23,7 @@ body > .ember-view { } body, button { - font-family: 'Slabo 27px', serif; + font-family: 'Raleway', sans-serif; } #huegasm { @@ -37,12 +37,17 @@ body, button { .footer { margin: 0 auto 10px auto; width: 100%; - max-width: 800px; + max-width: 1200px; text-align: center; display: flex; align-items: center; - justify-content: space-around; + justify-content: space-between; +} +@media(min-width:767px) { + .footer { + padding: 0 9%; + } } .footer-text { diff --git a/web/app/styles/hue-controls.scss b/web/app/styles/hue-controls.scss index e517619..c2051e7 100644 --- a/web/app/styles/hue-controls.scss +++ b/web/app/styles/hue-controls.scss @@ -44,13 +44,13 @@ text-align: right; position: absolute; top: -10px; - right: 10px; + right: -10px; transform: scale(1.1); } } .navigation-item { - font-size: 18px; + font-size: 20px; padding: 0 10px 0 10px; &.active { font-weight: bold; diff --git a/web/app/styles/light-group.scss b/web/app/styles/light-group.scss index c8e56f8..af8d3e2 100644 --- a/web/app/styles/light-group.scss +++ b/web/app/styles/light-group.scss @@ -58,7 +58,7 @@ .light-text { width: 60px; word-wrap: break-word; - padding: 0 10px; + padding: 0 7px; } .light-text-content { diff --git a/web/app/styles/music-tab.scss b/web/app/styles/music-tab.scss index 21b9fc4..89621fa 100644 --- a/web/app/styles/music-tab.scss +++ b/web/app/styles/music-tab.scss @@ -300,9 +300,10 @@ } .option-description { display: inline-flex; - font-size: 20px; + font-size: 18px; justify-content: center; flex-direction: column; + padding: 10px 0; } button { margin-top: 0; @@ -466,6 +467,12 @@ } } +@media(max-width: 950px) and (min-width:768px) { + .option-description { + height: 55px; + } +} + // mobile overrides @media(max-width:767px) { div#player-bottom { diff --git a/web/app/styles/paper.scss b/web/app/styles/paper.scss index 901c2b4..0c39535 100644 --- a/web/app/styles/paper.scss +++ b/web/app/styles/paper.scss @@ -18,6 +18,7 @@ md-checkbox .md-label { } .md-button { + font-size: 13px; flex-direction: unset; span { width: 100%;