diff --git a/js/Volume.jsx b/js/Volume.jsx
new file mode 100644
index 00000000..15c7144f
--- /dev/null
+++ b/js/Volume.jsx
@@ -0,0 +1,51 @@
+// Single line text display that can animate and hold multiple registers
+import React from 'react';
+import {connect} from 'react-redux';
+
+
+class Volume extends React.Component {
+ constructor(props) {
+ super(props);
+ this.setVolume = this.setVolume.bind(this);
+ this.showMarquee = this.showMarquee.bind(this);
+ this.hideMarquee = this.hideMarquee.bind(this);
+ }
+
+ setVolume(e) {
+ this.props.dispatch({type: 'SET_VOLUME', volume: e.target.value});
+ }
+
+ showMarquee() {
+ this.props.dispatch({type: 'SHOW_MARQUEE_REGISTER', register: 'volume'});
+ }
+
+ hideMarquee() {
+ this.props.dispatch({type: 'SHOW_MARQUEE_REGISTER', register: 'songTitle'});
+ }
+
+ render() {
+ const volume = this.props.volume;
+ const percent = volume / 100;
+ const sprite = Math.round(percent * 28);
+ const offset = (sprite - 1) * 15;
+
+ const style = {
+ backgroundPosition: '0 -' + offset + 'px'
+ };
+
+ return ;
+ }
+}
+
+module.exports = connect(state => state.media)(Volume);
diff --git a/js/hotkeys.js b/js/hotkeys.js
index a35077a8..a60bc29b 100644
--- a/js/hotkeys.js
+++ b/js/hotkeys.js
@@ -1,4 +1,4 @@
-module.exports = function(winamp) {
+module.exports = function(winamp, store) {
var keylog = [];
var trigger = [78, 85, 76, 27, 76, 27, 83, 79, 70, 84];
document.addEventListener('keydown', function(e){
@@ -8,25 +8,33 @@ module.exports = function(winamp) {
// XXX FIXME
case 76: winamp.openOptionMenu(); break; // CTRL+L
// CTRL+T
- case 84: winamp.dispath({type: 'TOGGLE_TIME_MODE'}); break;
+ case 84: store.dispath({type: 'TOGGLE_TIME_MODE'}); break;
}
} else {
switch (e.keyCode) {
case 37: winamp.seekForwardBy(-5); break; // left arrow
- case 38: winamp.incrementVolumeBy(1); break; // up arrow
+ // up arrow
+ case 38:
+ const incrementedVolume = Math.min(100, store.getState().media.volume + 1);
+ store.dispatch({type: 'SET_VOLUME', volume: incrementedVolume});
+ break;
case 39: winamp.seekForwardBy(5); break; // right arrow
- case 40: winamp.incrementVolumeBy(-1); break; // down arrow
+ // down arrow
+ case 40:
+ const decrementedVolume = Math.max(0, store.getState().media.volume - 1);
+ store.dispatch({type: 'SET_VOLUME', volume: decrementedVolume});
+ break;
case 66: winamp.next(); break; // B
case 67: winamp.pause(); break; // C
// L
- case 76: winamp.dispatch({type: 'OPEN_FILE_DIALOG'}); break;
+ case 76: store.dispatch({type: 'OPEN_FILE_DIALOG'}); break;
case 82: winamp.toggleRepeat(); break; // R
case 83: winamp.toggleShuffle(); break; // S
case 86: winamp.stop(); break; // V
case 88: winamp.play(); break; // X
case 90: winamp.previous(); break; // Z
// numpad 0
- case 96: winamp.dispatch({type: 'OPEN_FILE_DIALOG'}); break;
+ case 96: store.dispatch({type: 'OPEN_FILE_DIALOG'}); break;
case 97: winamp.previous(10); break; // numpad 1
case 98: winamp.incrementVolumeBy(-1); break; // numpad 2
case 99: winamp.next(10); break; // numpad 3
diff --git a/js/main-window-dom.js b/js/main-window-dom.js
index fddbe670..436bca36 100644
--- a/js/main-window-dom.js
+++ b/js/main-window-dom.js
@@ -52,7 +52,7 @@ module.exports = el('div', {id: 'main-window', class: 'loading stop'}, [
el('div', {id: 'stereo'})
])
]),
- el('input', {id: 'volume', type: 'range', min: '0', max: '100', step: '1', value: '50'}),
+ el('div', {id: 'volume-holder'}),
el('input', {id: 'balance', type: 'range', min: '-100', max: '100', step: '2', value: '0'}),
el('div', {class: 'windows'}, [
el('div', {id: 'equalizer-button'}),
diff --git a/js/main-window.js b/js/main-window.js
index 62b19df0..304f24cf 100644
--- a/js/main-window.js
+++ b/js/main-window.js
@@ -5,6 +5,7 @@ import Time from './Time.jsx';
import ShadeTime from './ShadeTime.jsx';
import Kbps from './Kbps.jsx';
import Khz from './Khz.jsx';
+import Volume from './Volume.jsx';
import '../css/main-window.css';
@@ -20,7 +21,6 @@ module.exports = {
eject: document.getElementById('eject'),
repeat: document.getElementById('repeat'),
shuffle: document.getElementById('shuffle'),
- volume: document.getElementById('volume'),
mono: document.getElementById('mono'),
stereo: document.getElementById('stereo'),
balance: document.getElementById('balance'),
@@ -38,6 +38,7 @@ module.exports = {
this.winamp.renderTo(, document.getElementById('shade-time-holder'));
this.winamp.renderTo(, document.getElementById('kbps-holder'));
this.winamp.renderTo(, document.getElementById('khz-holder'));
+ this.winamp.renderTo(, document.getElementById('volume-holder'));
this._registerListeners();
return this;
@@ -110,18 +111,6 @@ module.exports = {
self.winamp.toggleShuffle();
};
- this.nodes.volume.onmousedown = function() {
- self.winamp.dispatch({type: 'SHOW_MARQUEE_REGISTER', register: 'volume'});
- };
-
- this.nodes.volume.onmouseup = function() {
- self.winamp.dispatch({type: 'SHOW_MARQUEE_REGISTER', register: 'songTitle'});
- };
-
- this.nodes.volume.oninput = function() {
- self.winamp.setVolume(this.value);
- };
-
this.nodes.balance.onmousedown = function() {
self.winamp.dispatch({type: 'SHOW_MARQUEE_REGISTER', register: 'balance'});
};
@@ -165,9 +154,6 @@ module.exports = {
window.addEventListener('channelCountUpdated', function() {
self.updateChannelCount();
});
- window.addEventListener('volumeChanged', function() {
- self.updateVolume();
- });
window.addEventListener('balanceChanged', function() {
self.setBalance();
});
@@ -238,21 +224,6 @@ module.exports = {
this.nodes.window.classList.remove('loading');
},
- updateVolume: function() {
- var volume = this.winamp.getVolume();
- var percent = volume / 100;
- var sprite = Math.round(percent * 28);
- var offset = (sprite - 1) * 15;
- this.nodes.volume.style.backgroundPosition = '0 -' + offset + 'px';
-
- var message = 'Volume: ' + volume + '%';
- this.winamp.dispatch({type: 'SET_MARQUEE_REGISTER', register: 'volume', text: message});
-
- // This shouldn't trigger an infinite loop with volume.onchange(),
- // since the value will be the same
- this.nodes.volume.value = volume;
- },
-
setBalance: function() {
var balance = this.winamp.getBalance();
var string = '';
diff --git a/js/main.js b/js/main.js
index e61f77a7..beb04016 100644
--- a/js/main.js
+++ b/js/main.js
@@ -41,9 +41,7 @@ if (new Browser(window).isCompatible) {
skinUrl: 'https://cdn.rawgit.com/captbaritone/winamp-skins/master/v2/base-2.91.wsz'
});
-
-
- new Hotkeys(winamp);
+ new Hotkeys(winamp, store);
winamp.renderTo(, document.getElementById('context-menu-holder'));
} else {
document.getElementById('winamp').style.display = 'none';
diff --git a/js/media.js b/js/media.js
index 04e27dfc..9c17e33e 100644
--- a/js/media.js
+++ b/js/media.js
@@ -174,11 +174,11 @@ module.exports = {
// From 0-1
setVolume: function(volume) {
- this._gainNode.gain.value = volume;
+ this._gainNode.gain.value = volume / 100;
},
getVolume: function() {
- return this._gainNode.gain.value;
+ return this._gainNode.gain.value * 100;
},
// From -100 to 100
diff --git a/js/reducers.js b/js/reducers.js
index 08c45fa6..3e237655 100644
--- a/js/reducers.js
+++ b/js/reducers.js
@@ -15,6 +15,12 @@ const register = (state, action) => {
return Object.assign({}, state, {step: 0, text: action.text});
}
return state;
+ case 'SET_VOLUME':
+ if (state.id === 'volume') {
+ const text = 'Volume: ' + action.volume + '%';
+ return Object.assign({}, state, {step: 0, text: text});
+ }
+ return state;
case 'STEP_MARQUEE':
return Object.assign({}, state, {step: (state.step + 1) % state.text.length});
default:
@@ -75,7 +81,8 @@ const media = (state, action) => {
timeElapsed: 0,
length: null,
kbps: null,
- khz: null
+ khz: null,
+ volume: 50
};
}
switch (action.type) {
@@ -90,6 +97,8 @@ const media = (state, action) => {
return Object.assign({}, state, {kbps: action.kbps});
case 'SET_MEDIA_KHZ':
return Object.assign({}, state, {khz: action.khz});
+ case 'SET_VOLUME':
+ return Object.assign({}, state, {volume: action.volume});
default:
return state;
}
@@ -116,6 +125,9 @@ const createReducer = (winamp) => {
case 'STOP':
winamp.stop();
return state;
+ case 'SET_VOLUME':
+ winamp.setVolume(action.volume);
+ return state;
case 'CLOSE_WINAMP':
winamp.close();
return state;
diff --git a/js/winamp.js b/js/winamp.js
index f3e7d3ff..a59bfa28 100755
--- a/js/winamp.js
+++ b/js/winamp.js
@@ -29,7 +29,6 @@ module.exports = {
changeState: new Event('changeState'),
titleUpdated: new Event('titleUpdated'),
channelCountUpdated: new Event('channelCountUpdated'),
- volumeChanged: new Event('volumeChanged'),
balanceChanged: new Event('balanceChanged'),
doubledModeToggled: new Event('doubledModeToggled'),
repeatToggled: new Event('repeatToggled'),
@@ -37,7 +36,7 @@ module.exports = {
close: new Event('close')
};
- this.setVolume(options.volume);
+ this.dispatch({type: 'SET_VOLUME', volume: options.volume});
this.setBalance(options.balance);
this.loadFromUrl(options.mediaFile.url, options.mediaFile.name);
var skinFile = new MyFile();
@@ -116,7 +115,7 @@ module.exports = {
},
getVolume: function() {
- return Math.round(this.media.getVolume() * 100);
+ return Math.round(this.media.getVolume());
},
seekToPercentComplete: function(percent) {
@@ -150,14 +149,11 @@ module.exports = {
volume = Math.max(volume, 0);
volume = Math.min(volume, 100);
- var percent = volume / 100;
-
- this.media.setVolume(percent);
- window.dispatchEvent(this.events.volumeChanged);
+ this.media.setVolume(volume);
},
incrementVolumeBy: function(ammount) {
- this.setVolume((this.media.getVolume() * 100) + ammount);
+ this.setVolume((this.media.getVolume()) + ammount);
},
toggleDoubledMode: function() {