diff --git a/js/actionTypes.js b/js/actionTypes.js
index eee6db84..50edef2b 100644
--- a/js/actionTypes.js
+++ b/js/actionTypes.js
@@ -13,6 +13,7 @@ export const SEEK_TO_PERCENT_COMPLETE = "SEEK_TO_PERCENT_COMPLETE";
export const SET_BALANCE = "SET_BALANCE";
export const SET_BAND_VALUE = "SET_BAND_VALUE";
export const SET_FOCUS = "SET_FOCUS";
+export const SET_BAND_FOCUS = "SET_BAND_FOCUS";
export const SET_FOCUSED_WINDOW = "SET_FOCUSED_WINDOW";
export const SET_MEDIA = "SET_MEDIA";
export const SET_SCRUB_POSITION = "SET_SCRUB_POSITION";
diff --git a/js/components/EqualizerWindow/Band.js b/js/components/EqualizerWindow/Band.js
index 781e6169..e78c1e1e 100644
--- a/js/components/EqualizerWindow/Band.js
+++ b/js/components/EqualizerWindow/Band.js
@@ -1,6 +1,7 @@
import React from "react";
import { connect } from "react-redux";
import Slider from "rc-slider/lib/Slider";
+import { SET_BAND_FOCUS, UNSET_FOCUS } from "../../actionTypes";
const MAX_VALUE = 100;
// Given a value between 1-100, return the sprite number (0-27)
@@ -18,7 +19,14 @@ export const spriteOffsets = number => {
const Handle = () =>
;
-const Band = ({ value, backgroundPosition, id, onChange }) => (
+const Band = ({
+ value,
+ backgroundPosition,
+ id,
+ onChange,
+ handleMouseDown,
+ handleMouseUp
+}) => (
(
value={MAX_VALUE - value}
vertical
onChange={onChange}
+ onBeforeChange={handleMouseDown}
+ onAfterChange={handleMouseUp}
handle={Handle}
/>
@@ -46,4 +56,10 @@ const mapStateToProps = (state, ownProps) => {
};
};
-export default connect(mapStateToProps)(Band);
+const mapDispatchToProps = (dispatch, ownProps) => ({
+ handleMouseDown: () =>
+ dispatch({ type: SET_BAND_FOCUS, input: "eq", bandFocused: ownProps.band }),
+ handleMouseUp: () => dispatch({ type: UNSET_FOCUS })
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(Band);
diff --git a/js/components/MainWindow/Marquee.js b/js/components/MainWindow/Marquee.js
index c095402e..acc404d2 100644
--- a/js/components/MainWindow/Marquee.js
+++ b/js/components/MainWindow/Marquee.js
@@ -35,7 +35,19 @@ export const getMediaText = (name, duration) =>
export const getDoubleSizeModeText = enabled =>
`${enabled ? "Disable" : "Enable"} doublesize mode`;
-// TODO: Handle EQ text
+const formatHz = hz => (hz < 1000 ? `${hz}HZ` : `${hz / 1000}KHZ`);
+
+// Format a number as a string, ensuring it has a + or - sign
+const ensureSign = num => (num > 0 ? `+${num}` : num.toString());
+
+// Round to 1 and exactly 1 decimal point
+const roundToTenths = num => (Math.round(num * 10) / 10).toFixed(1);
+
+export const getEqText = (band, level) => {
+ const db = roundToTenths((level - 50) / 50 * 12);
+ const label = band === "preamp" ? "Preamp" : formatHz(band);
+ return `EQ: ${label} ${ensureSign(db)} DB`;
+};
const isLong = text => text.length > 30;
@@ -93,6 +105,9 @@ class Marquee extends React.Component {
);
case "double":
return getDoubleSizeModeText(this.props.display.doubled);
+ case "eq":
+ const band = this.props.userInput.bandFocused;
+ return getEqText(band, this.props.equalizer.sliders[band]);
default:
break;
}
diff --git a/js/reducers.js b/js/reducers.js
index 4005b4a3..9042f017 100644
--- a/js/reducers.js
+++ b/js/reducers.js
@@ -7,6 +7,7 @@ import {
SET_BALANCE,
SET_BAND_VALUE,
SET_FOCUS,
+ SET_BAND_FOCUS,
SET_FOCUSED_WINDOW,
SET_MEDIA,
SET_SCRUB_POSITION,
@@ -37,18 +38,20 @@ import {
} from "./actionTypes";
import { equalizerEnabled, playlistEnabled } from "./config";
-export const userInput = (state, action) => {
- if (!state) {
- return {
- focus: null,
- scrubPosition: 0
- };
- }
+const defaultUserInput = {
+ focus: null,
+ bandFocused: null,
+ scrubPosition: 0
+};
+
+export const userInput = (state = defaultUserInput, action) => {
switch (action.type) {
case SET_FOCUS:
- return { ...state, focus: action.input };
+ return { ...state, focus: action.input, bandFocused: null };
+ case SET_BAND_FOCUS:
+ return { ...state, focus: action.input, bandFocused: action.bandFocused };
case UNSET_FOCUS:
- return { ...state, focus: null };
+ return { ...state, focus: null, bandFocused: null };
case SET_SCRUB_POSITION:
return { ...state, scrubPosition: action.position };
default: