summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/SOURCES4
-rw-r--r--apps/eq_menu.c1182
-rw-r--r--apps/menu.c232
-rw-r--r--apps/menu.h31
-rw-r--r--apps/menus/eq_menu.c787
-rw-r--r--apps/menus/eq_menu.h (renamed from apps/eq_menu.h)30
-rw-r--r--apps/menus/exported_menus.h7
-rw-r--r--apps/menus/sound_menu.c11
-rw-r--r--apps/onplay.c2
-rw-r--r--apps/recorder/icons.c1
-rw-r--r--apps/recorder/icons.h1
-rw-r--r--apps/settings.c2
-rw-r--r--apps/settings_list.c159
-rw-r--r--apps/sound_menu.c2
14 files changed, 1083 insertions, 1368 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index c186614733..83f41cda3a 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -12,6 +12,9 @@ main.c
12main_menu.c 12main_menu.c
13menu.c 13menu.c
14menus/display_menu.c 14menus/display_menu.c
15#if CONFIG_CODEC == SWCODEC
16menus/eq_menu.c
17#endif
15menus/main_menu.c 18menus/main_menu.c
16menus/playback_menu.c 19menus/playback_menu.c
17menus/playlist_menu.c 20menus/playlist_menu.c
@@ -94,7 +97,6 @@ eq_cf.S
94dsp_arm.S 97dsp_arm.S
95eq_arm.S 98eq_arm.S
96#endif 99#endif
97eq_menu.c
98#endif 100#endif
99metadata.c 101metadata.c
100#ifdef HAVE_TAGCACHE 102#ifdef HAVE_TAGCACHE
diff --git a/apps/eq_menu.c b/apps/eq_menu.c
deleted file mode 100644
index beaf385366..0000000000
--- a/apps/eq_menu.c
+++ /dev/null
@@ -1,1182 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Dan Everton
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include <stdio.h>
22#include <stdbool.h>
23#include <string.h>
24#include "eq_menu.h"
25#include "system.h"
26#include "kernel.h"
27#include "lcd.h"
28#include "menu.h"
29#include "action.h"
30#include "mp3_playback.h"
31#include "settings.h"
32#include "statusbar.h"
33#include "screens.h"
34#include "icons.h"
35#include "font.h"
36#include "lang.h"
37#include "sprintf.h"
38#include "talk.h"
39#include "misc.h"
40#include "sound.h"
41#include "splash.h"
42#include "dsp.h"
43#include "tree.h"
44#include "talk.h"
45#include "screen_access.h"
46#include "keyboard.h"
47#include "gui/scrollbar.h"
48#ifdef HAVE_WM8758
49#include "wm8758.h"
50#endif
51
52/* Various user interface limits and sizes */
53#define EQ_CUTOFF_MIN 20
54#define EQ_CUTOFF_MAX 22040
55#define EQ_CUTOFF_STEP 10
56#define EQ_CUTOFF_FAST_STEP 100
57#define EQ_GAIN_MIN (-240)
58#define EQ_GAIN_MAX 240
59#define EQ_GAIN_STEP 5
60#define EQ_GAIN_FAST_STEP 10
61#define EQ_Q_MIN 5
62#define EQ_Q_MAX 64
63#define EQ_Q_STEP 1
64#define EQ_Q_FAST_STEP 10
65
66#define EQ_USER_DIVISOR 10
67
68/*
69 * Utility functions
70 */
71
72static void eq_gain_format(char* buffer, int buffer_size, int value, const char* unit)
73{
74 int v = abs(value);
75
76 snprintf(buffer, buffer_size, "%s%d.%d %s", value < 0 ? "-" : "",
77 v / EQ_USER_DIVISOR, v % EQ_USER_DIVISOR, unit);
78}
79
80static void eq_q_format(char* buffer, int buffer_size, int value, const char* unit)
81{
82 snprintf(buffer, buffer_size, "%d.%d %s", value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit);
83}
84
85static void eq_precut_format(char* buffer, int buffer_size, int value, const char* unit)
86{
87 snprintf(buffer, buffer_size, "%s%d.%d %s", value == 0 ? " " : "-",
88 value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit);
89}
90
91/*
92 * Settings functions
93 */
94
95static bool eq_enabled(void)
96{
97 int i;
98
99 bool result = set_bool(str(LANG_EQUALIZER_ENABLED),
100 &global_settings.eq_enabled);
101
102 dsp_set_eq(global_settings.eq_enabled);
103
104 dsp_set_eq_precut(global_settings.eq_precut);
105
106 /* Update all bands */
107 for(i = 0; i < 5; i++) {
108 dsp_set_eq_coefs(i);
109 }
110
111 return result;
112}
113
114static bool eq_precut(void)
115{
116 bool result = set_int(str(LANG_EQUALIZER_PRECUT), str(LANG_UNIT_DB),
117 UNIT_DB, &global_settings.eq_precut, dsp_set_eq_precut, 5, 0, 240,
118 eq_precut_format);
119
120 return result;
121}
122
123/* Possibly dodgy way of simplifying the code a bit. */
124#define eq_make_gain_label(buf, bufsize, frequency) snprintf((buf), \
125 (bufsize), str(LANG_EQUALIZER_GAIN_ITEM), (frequency))
126
127#define eq_set_center(band) \
128static bool eq_set_band ## band ## _center(void) \
129{ \
130 bool result = set_int(str(LANG_EQUALIZER_BAND_CENTER), "Hertz", \
131 UNIT_HERTZ, &global_settings.eq_band ## band ## _cutoff, NULL, \
132 EQ_CUTOFF_STEP, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, NULL); \
133 dsp_set_eq_coefs(band); \
134 return result; \
135}
136
137#define eq_set_cutoff(band) \
138static bool eq_set_band ## band ## _cutoff(void) \
139{ \
140 bool result = set_int(str(LANG_EQUALIZER_BAND_CUTOFF), "Hertz", \
141 UNIT_HERTZ, &global_settings.eq_band ## band ## _cutoff, NULL, \
142 EQ_CUTOFF_STEP, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, NULL); \
143 dsp_set_eq_coefs(band); \
144 return result; \
145}
146
147#define eq_set_q(band) \
148static bool eq_set_band ## band ## _q(void) \
149{ \
150 bool result = set_int(str(LANG_EQUALIZER_BAND_Q), "Q", UNIT_INT, \
151 &global_settings.eq_band ## band ## _q, NULL, \
152 EQ_Q_STEP, EQ_Q_MIN, EQ_Q_MAX, eq_q_format); \
153 dsp_set_eq_coefs(band); \
154 return result; \
155}
156
157#define eq_set_gain(band) \
158static bool eq_set_band ## band ## _gain(void) \
159{ \
160 bool result = set_int("Band " #band, str(LANG_UNIT_DB), UNIT_DB, \
161 &global_settings.eq_band ## band ## _gain, NULL, \
162 EQ_GAIN_STEP, EQ_GAIN_MIN, EQ_GAIN_MAX, eq_gain_format); \
163 dsp_set_eq_coefs(band); \
164 return result; \
165}
166
167eq_set_cutoff(0);
168eq_set_center(1);
169eq_set_center(2);
170eq_set_center(3);
171eq_set_cutoff(4);
172
173eq_set_q(0);
174eq_set_q(1);
175eq_set_q(2);
176eq_set_q(3);
177eq_set_q(4);
178
179eq_set_gain(0);
180eq_set_gain(1);
181eq_set_gain(2);
182eq_set_gain(3);
183eq_set_gain(4);
184
185static bool eq_gain_menu(void)
186{
187 int m, i;
188 int *setting;
189 bool result;
190 char gain_label[5][32];
191 static struct menu_item items[5] = {
192 { NULL, eq_set_band0_gain },
193 { NULL, eq_set_band1_gain },
194 { NULL, eq_set_band2_gain },
195 { NULL, eq_set_band3_gain },
196 { NULL, eq_set_band4_gain },
197 };
198
199 setting = &global_settings.eq_band0_cutoff;
200
201 /* Construct menu labels */
202 for(i = 0; i < 5; i++) {
203 eq_make_gain_label(gain_label[i], sizeof(gain_label[i]),
204 *setting);
205 items[i].desc = gain_label[i];
206
207 /* Skip to next band */
208 setting += 3;
209 }
210
211 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
212 NULL, NULL, NULL);
213 result = menu_run(m);
214 menu_exit(m);
215
216 return result;
217}
218
219static bool eq_set_band0(void)
220{
221 int m;
222 bool result;
223 static const struct menu_item items[] = {
224 { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band0_cutoff },
225 { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band0_q },
226 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band0_gain },
227 };
228
229 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
230 NULL, NULL, NULL);
231 result = menu_run(m);
232 menu_exit(m);
233
234 return result;
235}
236
237static bool eq_set_band1(void)
238{
239 int m;
240 bool result;
241 static const struct menu_item items[] = {
242 { ID2P(LANG_EQUALIZER_BAND_CENTER), eq_set_band1_center },
243 { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band1_q },
244 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band1_gain },
245 };
246
247 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
248 NULL, NULL, NULL);
249 result = menu_run(m);
250 menu_exit(m);
251
252 return result;
253}
254
255static bool eq_set_band2(void)
256{
257 int m;
258 bool result;
259 static const struct menu_item items[] = {
260 { ID2P(LANG_EQUALIZER_BAND_CENTER), eq_set_band2_center },
261 { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band2_q },
262 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band2_gain },
263 };
264
265 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
266 NULL, NULL, NULL);
267 result = menu_run(m);
268 menu_exit(m);
269
270 return result;
271}
272
273static bool eq_set_band3(void)
274{
275 int m;
276 bool result;
277 static const struct menu_item items[] = {
278 { ID2P(LANG_EQUALIZER_BAND_CENTER), eq_set_band3_center },
279 { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band3_q },
280 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band3_gain },
281 };
282
283 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
284 NULL, NULL, NULL);
285 result = menu_run(m);
286 menu_exit(m);
287
288 return result;
289}
290
291static bool eq_set_band4(void)
292{
293 int m;
294 bool result;
295 static const struct menu_item items[] = {
296 { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band4_cutoff },
297 { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band4_q },
298 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band4_gain },
299 };
300
301 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
302 NULL, NULL, NULL);
303 result = menu_run(m);
304 menu_exit(m);
305
306 return result;
307}
308
309static bool eq_advanced_menu(void)
310{
311 int m, i;
312 bool result;
313 char peak_band_label[3][32];
314 static struct menu_item items[] = {
315 { ID2P(LANG_EQUALIZER_BAND_LOW_SHELF), eq_set_band0 },
316 { NULL, eq_set_band1 },
317 { NULL, eq_set_band2 },
318 { NULL, eq_set_band3 },
319 { ID2P(LANG_EQUALIZER_BAND_HIGH_SHELF), eq_set_band4 },
320 };
321
322 /* Construct menu labels */
323 for(i = 1; i < 4; i++) {
324 snprintf(peak_band_label[i-1], sizeof(peak_band_label[i-1]),
325 str(LANG_EQUALIZER_BAND_PEAK), i);
326 items[i].desc = peak_band_label[i-1];
327 }
328
329 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
330 NULL, NULL, NULL);
331 result = menu_run(m);
332 menu_exit(m);
333
334 return result;
335}
336
337enum eq_slider_mode {
338 GAIN,
339 CUTOFF,
340 Q,
341};
342
343enum eq_type {
344 LOW_SHELF,
345 PEAK,
346 HIGH_SHELF
347};
348
349/* Draw the UI for a whole EQ band */
350static int draw_eq_slider(struct screen * screen, int x, int y,
351 int width, int cutoff, int q, int gain, bool selected,
352 enum eq_slider_mode mode, enum eq_type type)
353{
354 char buf[26];
355 const char separator[2] = " ";
356 int steps, min_item, max_item;
357 int abs_gain = abs(gain);
358 int current_x, total_height, separator_width, separator_height;
359 int w, h;
360 const int slider_height = 6;
361
362 switch(mode) {
363 case Q:
364 steps = EQ_Q_MAX - EQ_Q_MIN;
365 min_item = q - EQ_Q_STEP - EQ_Q_MIN;
366 max_item = q + EQ_Q_STEP - EQ_Q_MIN;
367 break;
368 case CUTOFF:
369 steps = EQ_CUTOFF_MAX - EQ_CUTOFF_MIN;
370 min_item = cutoff - EQ_CUTOFF_FAST_STEP * 2;
371 max_item = cutoff + EQ_CUTOFF_FAST_STEP * 2;
372 break;
373 case GAIN:
374 default:
375 steps = EQ_GAIN_MAX - EQ_GAIN_MIN;
376 min_item = abs(EQ_GAIN_MIN) + gain - EQ_GAIN_STEP * 5;
377 max_item = abs(EQ_GAIN_MIN) + gain + EQ_GAIN_STEP * 5;
378 break;
379 }
380
381 /* Start two pixels in, one for border, one for margin */
382 current_x = x + 2;
383
384 /* Figure out how large our separator string is */
385 screen->getstringsize(separator, &separator_width, &separator_height);
386
387 /* Total height includes margins, text, and line selector */
388 total_height = separator_height + slider_height + 2 + 3;
389
390 /* Print out the band label */
391 if (type == LOW_SHELF) {
392 screen->putsxy(current_x, y + 2, "LS:");
393 screen->getstringsize("LS:", &w, &h);
394 } else if (type == HIGH_SHELF) {
395 screen->putsxy(current_x, y + 2, "HS:");
396 screen->getstringsize("HS:", &w, &h);
397 } else {
398 screen->putsxy(current_x, y + 2, "PK:");
399 screen->getstringsize("PK:", &w, &h);
400 }
401 current_x += w;
402
403 /* Print separator */
404 screen->set_drawmode(DRMODE_SOLID);
405 screen->putsxy(current_x, y + 2, separator);
406 current_x += separator_width;
407#if NB_SCREENS > 1
408 if (screen->screen_type == SCREEN_REMOTE) {
409 if (mode == GAIN) {
410 screen->putsxy(current_x, y + 2, str(LANG_EQUALIZER_BAND_GAIN));
411 screen->getstringsize(str(LANG_EQUALIZER_BAND_GAIN), &w, &h);
412 } else if (mode == CUTOFF) {
413 screen->putsxy(current_x, y + 2, str(LANG_EQUALIZER_BAND_CUTOFF));
414 screen->getstringsize(str(LANG_EQUALIZER_BAND_CUTOFF), &w, &h);
415 } else {
416 screen->putsxy(current_x, y + 2, str(LANG_EQUALIZER_BAND_Q));
417 screen->getstringsize(str(LANG_EQUALIZER_BAND_Q), &w, &h);
418 }
419
420 /* Draw horizontal slider. Reuse scrollbar for this */
421 gui_scrollbar_draw(screen, x + 3, y + h + 3, width - 6, slider_height, steps,
422 min_item, max_item, HORIZONTAL);
423
424 /* Print out cutoff part */
425 snprintf(buf, sizeof(buf), "%sGain %s%2d.%ddB",mode==GAIN?" > ":" ", gain < 0 ? "-" : " ",
426 abs_gain / EQ_USER_DIVISOR, abs_gain % EQ_USER_DIVISOR);
427 screen->getstringsize(buf, &w, &h);
428 y = 3*h;
429 screen->putsxy(0, y, buf);
430 /* Print out cutoff part */
431 snprintf(buf, sizeof(buf), "%sCutoff %5dHz",mode==CUTOFF?" > ":" ", cutoff);
432 y += h;
433 screen->putsxy(0, y, buf);
434 snprintf(buf, sizeof(buf), "%sQ setting %d.%d Q",mode==Q?" > ":" ", q / EQ_USER_DIVISOR,
435 q % EQ_USER_DIVISOR);
436 y += h;
437 screen->putsxy(0, y, buf);
438 return y;
439 }
440#endif
441
442 /* Print out gain part of status line */
443 snprintf(buf, sizeof(buf), "%s%2d.%ddB", gain < 0 ? "-" : " ",
444 abs_gain / EQ_USER_DIVISOR, abs_gain % EQ_USER_DIVISOR);
445
446 if (mode == GAIN && selected)
447 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
448
449 screen->putsxy(current_x, y + 2, buf);
450 screen->getstringsize(buf, &w, &h);
451 current_x += w;
452
453 /* Print separator */
454 screen->set_drawmode(DRMODE_SOLID);
455 screen->putsxy(current_x, y + 2, separator);
456 current_x += separator_width;
457
458 /* Print out cutoff part of status line */
459 snprintf(buf, sizeof(buf), "%5dHz", cutoff);
460
461 if (mode == CUTOFF && selected)
462 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
463
464 screen->putsxy(current_x, y + 2, buf);
465 screen->getstringsize(buf, &w, &h);
466 current_x += w;
467
468 /* Print separator */
469 screen->set_drawmode(DRMODE_SOLID);
470 screen->putsxy(current_x, y + 2, separator);
471 current_x += separator_width;
472
473 /* Print out Q part of status line */
474 snprintf(buf, sizeof(buf), "%d.%d Q", q / EQ_USER_DIVISOR,
475 q % EQ_USER_DIVISOR);
476
477 if (mode == Q && selected)
478 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
479
480 screen->putsxy(current_x, y + 2, buf);
481 screen->getstringsize(buf, &w, &h);
482 current_x += w;
483
484 screen->set_drawmode(DRMODE_SOLID);
485
486 /* Draw selection box */
487 if (selected) {
488 screen->drawrect(x, y, width, total_height);
489 }
490
491 /* Draw horizontal slider. Reuse scrollbar for this */
492 gui_scrollbar_draw(screen, x + 3, y + h + 3, width - 6, slider_height, steps,
493 min_item, max_item, HORIZONTAL);
494
495 return total_height;
496}
497
498/* Draw's all the EQ sliders. Returns the total height of the sliders drawn */
499static int draw_eq_sliders(int current_band, enum eq_slider_mode mode)
500{
501 int i, gain, q, cutoff;
502 int height = 2; /* Two pixel margin */
503 int slider_width[NB_SCREENS];
504 int *setting = &global_settings.eq_band0_cutoff;
505 enum eq_type type;
506
507 FOR_NB_SCREENS(i)
508 slider_width[i] = screens[i].width - 4; /* two pixel margin on each side */
509
510 for (i=0; i<5; i++) {
511 cutoff = *setting++;
512 q = *setting++;
513 gain = *setting++;
514
515 if (i == 0) {
516 type = LOW_SHELF;
517 } else if (i == 4) {
518 type = HIGH_SHELF;
519 } else {
520 type = PEAK;
521 }
522 height += draw_eq_slider(&(screens[SCREEN_MAIN]), 2, height,
523 slider_width[SCREEN_MAIN], cutoff, q, gain,
524 i == current_band, mode, type);
525#if NB_SCREENS > 1
526 if (i == current_band)
527 draw_eq_slider(&(screens[SCREEN_REMOTE]), 2, 0,
528 slider_width[SCREEN_REMOTE], cutoff, q, gain,1, mode, type);
529#endif
530 /* add a margin */
531 height += 2;
532 }
533
534 return height;
535}
536
537/* Provides a graphical means of editing the EQ settings */
538bool eq_menu_graphical(void)
539{
540 bool exit_request = false;
541 bool result = true;
542 bool has_changed = false;
543 int button;
544 int *setting;
545 int current_band, y, step, fast_step, min, max, voice_unit;
546 enum eq_slider_mode mode;
547 enum eq_type current_type;
548 char buf[24];
549 int i;
550
551 FOR_NB_SCREENS(i) {
552 screens[i].setfont(FONT_SYSFIXED);
553 screens[i].clear_display();
554 }
555
556 /* Start off editing gain on the first band */
557 mode = GAIN;
558 current_type = LOW_SHELF;
559 current_band = 0;
560
561 while (!exit_request) {
562
563 FOR_NB_SCREENS(i) {
564 /* Clear the screen. The drawing routines expect this */
565 screens[i].clear_display();
566 /* Draw equalizer band details */
567 y = draw_eq_sliders(current_band, mode);
568 }
569
570 /* Set pointer to the band data currently editable */
571 if (mode == GAIN) {
572 /* gain */
573 setting = &global_settings.eq_band0_gain;
574 setting += current_band * 3;
575
576 step = EQ_GAIN_STEP;
577 fast_step = EQ_GAIN_FAST_STEP;
578 min = EQ_GAIN_MIN;
579 max = EQ_GAIN_MAX;
580 voice_unit = UNIT_DB;
581
582 snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
583 str(LANG_SYSFONT_EQUALIZER_BAND_GAIN));
584
585 screens[SCREEN_MAIN].putsxy(2, y, buf);
586 } else if (mode == CUTOFF) {
587 /* cutoff */
588 setting = &global_settings.eq_band0_cutoff;
589 setting += current_band * 3;
590
591 step = EQ_CUTOFF_STEP;
592 fast_step = EQ_CUTOFF_FAST_STEP;
593 min = EQ_CUTOFF_MIN;
594 max = EQ_CUTOFF_MAX;
595 voice_unit = UNIT_HERTZ;
596
597 snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
598 str(LANG_SYSFONT_EQUALIZER_BAND_CUTOFF));
599
600 screens[SCREEN_MAIN].putsxy(2, y, buf);
601 } else {
602 /* Q */
603 setting = &global_settings.eq_band0_q;
604 setting += current_band * 3;
605
606 step = EQ_Q_STEP;
607 fast_step = EQ_Q_FAST_STEP;
608 min = EQ_Q_MIN;
609 max = EQ_Q_MAX;
610 voice_unit = UNIT_INT;
611
612 snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
613 str(LANG_EQUALIZER_BAND_Q));
614
615 screens[SCREEN_MAIN].putsxy(2, y, buf);
616 }
617
618 FOR_NB_SCREENS(i) {
619 screens[i].update();
620 }
621
622 button = get_action(CONTEXT_SETTINGS_EQ,TIMEOUT_BLOCK);
623
624 switch (button) {
625 case ACTION_SETTINGS_DEC:
626 case ACTION_SETTINGS_DECREPEAT:
627 *(setting) -= step;
628 has_changed = true;
629 if (*(setting) < min)
630 *(setting) = min;
631 break;
632
633 case ACTION_SETTINGS_INC:
634 case ACTION_SETTINGS_INCREPEAT:
635 *(setting) += step;
636 has_changed = true;
637 if (*(setting) > max)
638 *(setting) = max;
639 break;
640
641 case ACTION_SETTINGS_INCBIGSTEP:
642 *(setting) += fast_step;
643 has_changed = true;
644 if (*(setting) > max)
645 *(setting) = max;
646 break;
647
648 case ACTION_SETTINGS_DECBIGSTEP:
649 *(setting) -= fast_step;
650 has_changed = true;
651 if (*(setting) < min)
652 *(setting) = min;
653 break;
654
655 case ACTION_STD_PREV:
656 case ACTION_STD_PREVREPEAT:
657 current_band--;
658 if (current_band < 0)
659 current_band = 4; /* wrap around */
660 break;
661
662 case ACTION_STD_NEXT:
663 case ACTION_STD_NEXTREPEAT:
664 current_band++;
665 if (current_band > 4)
666 current_band = 0; /* wrap around */
667 break;
668
669 case ACTION_STD_OK:
670 mode++;
671 if (mode > Q)
672 mode = GAIN; /* wrap around */
673 break;
674
675 case ACTION_STD_CANCEL:
676 exit_request = true;
677 result = false;
678 break;
679
680 default:
681 if(default_event_handler(button) == SYS_USB_CONNECTED) {
682 exit_request = true;
683 result = true;
684 }
685 break;
686 }
687
688 /* Update the filter if the user changed something */
689 if (has_changed) {
690 dsp_set_eq_coefs(current_band);
691 has_changed = false;
692 }
693 }
694
695 action_signalscreenchange();
696 /* Reset screen settings */
697 FOR_NB_SCREENS(i) {
698 screens[i].setfont(FONT_UI);
699 screens[i].clear_display();
700 }
701 return result;
702}
703
704/* Preset saver.
705 * TODO: Can the settings system be used to do this instead?
706 */
707static bool eq_save_preset(void)
708{
709 int fd, i;
710 char filename[MAX_PATH];
711 int *setting;
712
713 create_numbered_filename(filename, EQS_DIR, "eq", ".cfg", 2
714 IF_CNFN_NUM_(, NULL));
715
716 /* allow user to modify filename */
717 while (true) {
718 if (!kbd_input(filename, sizeof filename)) {
719 fd = creat(filename);
720 if (fd < 0)
721 gui_syncsplash(HZ, true, str(LANG_FAILED));
722 else
723 break;
724 }
725 else {
726 gui_syncsplash(HZ, true, str(LANG_MENU_SETTING_CANCEL));
727 return false;
728 }
729 }
730
731 /* TODO: Should we really do this? */
732 fdprintf(fd, "eq enabled: on\r\n");
733 fdprintf(fd, "eq precut: %d\r\n", global_settings.eq_precut);
734
735 setting = &global_settings.eq_band0_cutoff;
736
737 for(i = 0; i < 5; ++i) {
738 fdprintf(fd, "eq band %d cutoff: %d\r\n", i, *setting++);
739 fdprintf(fd, "eq band %d q: %d\r\n", i, *setting++);
740 fdprintf(fd, "eq band %d gain: %d\r\n", i, *setting++);
741 }
742
743 close(fd);
744
745 gui_syncsplash(HZ, true, str(LANG_SETTINGS_SAVED));
746
747 return true;
748}
749
750/* Allows browsing of preset files */
751bool eq_browse_presets(void)
752{
753 return rockbox_browse(EQS_DIR, SHOW_CFG);
754}
755
756#ifdef HAVE_WM8758
757
758/* WM8758 equalizer supports -12 to +12 dB gain in 1 dB increments. */
759#define EQ_HW_GAIN_STEP 1
760#define EQ_HW_GAIN_MIN -12
761#define EQ_HW_GAIN_MAX 12
762
763static const struct opt_items BANDWIDTH_NAMES[] = {
764 { STR(LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW) },
765 { STR(LANG_EQUALIZER_HARDWARE_BANDWIDTH_WIDE) },
766};
767
768static const int BANDWIDTH_NAMES_SIZE = sizeof(BANDWIDTH_NAMES) /
769 sizeof(*BANDWIDTH_NAMES);
770
771static void eq_hw_gain_format(char* buffer, int buffer_size, int value,
772 const char* unit)
773{
774 snprintf(buffer, buffer_size, "%d %s", value, unit);
775}
776
777static bool eq_hw_set_band0_cutoff(void)
778{
779 static const struct opt_items names[] = {
780 { (unsigned char *)"80 Hz", TALK_ID(80, UNIT_HERTZ) },
781 { (unsigned char *)"105 Hz", TALK_ID(105, UNIT_HERTZ) },
782 { (unsigned char *)"135 Hz", TALK_ID(135, UNIT_HERTZ) },
783 { (unsigned char *)"175 Hz", TALK_ID(175, UNIT_HERTZ) },
784 };
785
786 bool result = set_option(str(LANG_EQUALIZER_BANDWIDTH),
787 &global_settings.eq_hw_band0_cutoff, INT, names,
788 sizeof(names) / sizeof(*names), NULL);
789
790#ifndef SIMULATOR
791 audiohw_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff, 0,
792 global_settings.eq_hw_band0_gain);
793#endif
794
795 return result;
796}
797
798static bool eq_hw_set_band0_gain(void)
799{
800 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
801 &global_settings.eq_hw_band0_gain, NULL,
802 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
803 eq_hw_gain_format);
804
805#ifndef SIMULATOR
806 audiohw_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff, 0,
807 global_settings.eq_hw_band0_gain);
808#endif
809
810 return result;
811}
812
813static bool eq_hw_set_band1_center(void)
814{
815 static const struct opt_items names[] = {
816 { (unsigned char *)"230 Hz", TALK_ID(230, UNIT_HERTZ) },
817 { (unsigned char *)"300 Hz", TALK_ID(300, UNIT_HERTZ) },
818 { (unsigned char *)"385 Hz", TALK_ID(385, UNIT_HERTZ) },
819 { (unsigned char *)"500 Hz", TALK_ID(500, UNIT_HERTZ) },
820 };
821
822 bool result = set_option(str(LANG_EQUALIZER_BAND_CENTER),
823 &global_settings.eq_hw_band1_center, INT, names,
824 sizeof(names) / sizeof(*names), NULL);
825
826#ifndef SIMULATOR
827 audiohw_set_equalizer_band(1, global_settings.eq_hw_band1_center,
828 global_settings.eq_hw_band1_bandwidth,
829 global_settings.eq_hw_band1_gain);
830#endif
831
832 return result;
833}
834
835static bool eq_hw_set_band1_bandwidth(void)
836{
837 bool result = set_option(str(LANG_EQUALIZER_BANDWIDTH),
838 &global_settings.eq_hw_band1_bandwidth, INT, BANDWIDTH_NAMES,
839 BANDWIDTH_NAMES_SIZE, NULL);
840
841#ifndef SIMULATOR
842 audiohw_set_equalizer_band(1, global_settings.eq_hw_band1_center,
843 global_settings.eq_hw_band1_bandwidth,
844 global_settings.eq_hw_band1_gain);
845#endif
846
847 return result;
848}
849
850static bool eq_hw_set_band1_gain(void)
851{
852 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
853 &global_settings.eq_hw_band1_gain, NULL,
854 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
855 eq_hw_gain_format);
856
857#ifndef SIMULATOR
858 audiohw_set_equalizer_band(1, global_settings.eq_hw_band1_center,
859 global_settings.eq_hw_band1_bandwidth,
860 global_settings.eq_hw_band1_gain);
861#endif
862
863 return result;
864}
865
866static bool eq_hw_set_band2_center(void)
867{
868 static const struct opt_items names[] = {
869 { (unsigned char *)"650 Hz", TALK_ID(650, UNIT_HERTZ) },
870 { (unsigned char *)"850 Hz", TALK_ID(850, UNIT_HERTZ) },
871 { (unsigned char *)"1.1 kHz", TALK_ID(1100, UNIT_HERTZ) },
872 { (unsigned char *)"1.4 kHz", TALK_ID(1400, UNIT_HERTZ) },
873 };
874
875 bool result = set_option(str(LANG_EQUALIZER_BAND_CENTER),
876 &global_settings.eq_hw_band2_center, INT, names,
877 sizeof(names) / sizeof(*names), NULL);
878
879#ifndef SIMULATOR
880 audiohw_set_equalizer_band(2, global_settings.eq_hw_band2_center,
881 global_settings.eq_hw_band2_bandwidth,
882 global_settings.eq_hw_band2_gain);
883#endif
884
885 return result;
886}
887
888static bool eq_hw_set_band2_bandwidth(void)
889{
890 bool result = set_option(str(LANG_EQUALIZER_BANDWIDTH),
891 &global_settings.eq_hw_band2_bandwidth, INT, BANDWIDTH_NAMES,
892 BANDWIDTH_NAMES_SIZE, NULL);
893
894#ifndef SIMULATOR
895 audiohw_set_equalizer_band(2, global_settings.eq_hw_band2_center,
896 global_settings.eq_hw_band2_bandwidth,
897 global_settings.eq_hw_band2_gain);
898#endif
899
900 return result;
901}
902
903static bool eq_hw_set_band2_gain(void)
904{
905 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
906 &global_settings.eq_hw_band2_gain, NULL,
907 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
908 eq_hw_gain_format);
909
910#ifndef SIMULATOR
911 audiohw_set_equalizer_band(2, global_settings.eq_hw_band2_center,
912 global_settings.eq_hw_band2_bandwidth,
913 global_settings.eq_hw_band2_gain);
914#endif
915
916 return result;
917}
918
919static bool eq_hw_set_band3_center(void)
920{
921 static const struct opt_items names[] = {
922 { (unsigned char *)"1.8 kHz", TALK_ID(1800, UNIT_HERTZ) },
923 { (unsigned char *)"2.4 kHz", TALK_ID(2400, UNIT_HERTZ) },
924 { (unsigned char *)"3.2 kHz", TALK_ID(3200, UNIT_HERTZ) },
925 { (unsigned char *)"4.1 kHz", TALK_ID(4100, UNIT_HERTZ) },
926 };
927
928 bool result = set_option(str(LANG_EQUALIZER_BAND_CENTER),
929 &global_settings.eq_hw_band3_center, INT, names,
930 sizeof(names) / sizeof(*names), NULL);
931
932#ifndef SIMULATOR
933 audiohw_set_equalizer_band(3, global_settings.eq_hw_band3_center,
934 global_settings.eq_hw_band3_bandwidth,
935 global_settings.eq_hw_band3_gain);
936#endif
937
938 return result;
939}
940
941static bool eq_hw_set_band3_bandwidth(void)
942{
943 bool result = set_option(str(LANG_EQUALIZER_BANDWIDTH),
944 &global_settings.eq_hw_band3_bandwidth, INT, BANDWIDTH_NAMES,
945 BANDWIDTH_NAMES_SIZE, NULL);
946
947#ifndef SIMULATOR
948 audiohw_set_equalizer_band(3, global_settings.eq_hw_band3_center,
949 global_settings.eq_hw_band3_bandwidth,
950 global_settings.eq_hw_band3_gain);
951#endif
952
953 return result;
954}
955
956static bool eq_hw_set_band3_gain(void)
957{
958 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
959 &global_settings.eq_hw_band3_gain, NULL,
960 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
961 eq_hw_gain_format);
962
963#ifndef SIMULATOR
964 audiohw_set_equalizer_band(3, global_settings.eq_hw_band3_center,
965 global_settings.eq_hw_band3_bandwidth,
966 global_settings.eq_hw_band3_gain);
967#endif
968
969 return result;
970}
971
972static bool eq_hw_set_band4_cutoff(void)
973{
974 static const struct opt_items names[] = {
975 { (unsigned char *)"5.3 kHz", TALK_ID(5300, UNIT_HERTZ) },
976 { (unsigned char *)"6.9 kHz", TALK_ID(6900, UNIT_HERTZ) },
977 { (unsigned char *)"9.0 kHz", TALK_ID(9000, UNIT_HERTZ) },
978 { (unsigned char *)"11.7 kHz", TALK_ID(11700, UNIT_HERTZ) },
979 };
980
981 bool result = set_option(str(LANG_EQUALIZER_BAND_CUTOFF),
982 &global_settings.eq_hw_band4_cutoff, INT, names,
983 sizeof(names) / sizeof(*names), NULL);
984
985#ifndef SIMULATOR
986 audiohw_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff, 0,
987 global_settings.eq_hw_band4_gain);
988#endif
989
990 return result;
991}
992
993static bool eq_hw_set_band4_gain(void)
994{
995 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
996 &global_settings.eq_hw_band4_gain, NULL,
997 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
998 eq_hw_gain_format);
999
1000#ifndef SIMULATOR
1001 audiohw_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff, 0,
1002 global_settings.eq_hw_band4_gain);
1003#endif
1004
1005 return result;
1006}
1007
1008void eq_hw_enable(bool enable)
1009{
1010#ifdef SIMULATOR
1011 (void) enable;
1012#else
1013 if (enable) {
1014 audiohw_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff,
1015 0, global_settings.eq_hw_band0_gain);
1016 audiohw_set_equalizer_band(1, global_settings.eq_hw_band1_center,
1017 global_settings.eq_hw_band1_bandwidth,
1018 global_settings.eq_hw_band1_gain);
1019 audiohw_set_equalizer_band(2, global_settings.eq_hw_band2_center,
1020 global_settings.eq_hw_band2_bandwidth,
1021 global_settings.eq_hw_band2_gain);
1022 audiohw_set_equalizer_band(3, global_settings.eq_hw_band3_center,
1023 global_settings.eq_hw_band3_bandwidth,
1024 global_settings.eq_hw_band3_gain);
1025 audiohw_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff,
1026 0, global_settings.eq_hw_band4_gain);
1027 } else {
1028 audiohw_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff, 0, 0);
1029 audiohw_set_equalizer_band(1, global_settings.eq_hw_band1_center,
1030 global_settings.eq_hw_band1_bandwidth, 0);
1031 audiohw_set_equalizer_band(2, global_settings.eq_hw_band2_center,
1032 global_settings.eq_hw_band2_bandwidth, 0);
1033 audiohw_set_equalizer_band(3, global_settings.eq_hw_band3_center,
1034 global_settings.eq_hw_band3_bandwidth, 0);
1035 audiohw_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff, 0, 0);
1036 }
1037#endif
1038}
1039
1040static bool eq_hw_enabled(void)
1041{
1042 bool result = set_bool(str(LANG_EQUALIZER_HARDWARE_ENABLED),
1043 &global_settings.eq_hw_enabled);
1044
1045 eq_hw_enable(global_settings.eq_hw_enabled);
1046
1047 return result;
1048}
1049
1050static bool eq_hw_set_band0(void)
1051{
1052 int m;
1053 bool result;
1054 static const struct menu_item items[] = {
1055 { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_hw_set_band0_cutoff },
1056 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band0_gain },
1057 };
1058
1059 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1060 NULL, NULL, NULL);
1061 result = menu_run(m);
1062 menu_exit(m);
1063
1064 return result;
1065}
1066
1067static bool eq_hw_set_band1(void)
1068{
1069 int m;
1070 bool result;
1071 static const struct menu_item items[] = {
1072 { ID2P(LANG_EQUALIZER_BAND_CENTER), eq_hw_set_band1_center },
1073 { ID2P(LANG_EQUALIZER_BANDWIDTH), eq_hw_set_band1_bandwidth },
1074 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band1_gain },
1075 };
1076
1077 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1078 NULL, NULL, NULL);
1079 result = menu_run(m);
1080 menu_exit(m);
1081
1082 return result;
1083}
1084
1085static bool eq_hw_set_band2(void)
1086{
1087 int m;
1088 bool result;
1089 static const struct menu_item items[] = {
1090 { ID2P(LANG_EQUALIZER_BAND_CENTER), eq_hw_set_band2_center },
1091 { ID2P(LANG_EQUALIZER_BANDWIDTH), eq_hw_set_band2_bandwidth },
1092 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band2_gain },
1093 };
1094
1095 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1096 NULL, NULL, NULL);
1097 result = menu_run(m);
1098 menu_exit(m);
1099
1100 return result;
1101}
1102
1103static bool eq_hw_set_band3(void)
1104{
1105 int m;
1106 bool result;
1107 static const struct menu_item items[] = {
1108 { ID2P(LANG_EQUALIZER_BAND_CENTER), eq_hw_set_band3_center },
1109 { ID2P(LANG_EQUALIZER_BANDWIDTH), eq_hw_set_band3_bandwidth },
1110 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band3_gain },
1111 };
1112
1113 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1114 NULL, NULL, NULL);
1115 result = menu_run(m);
1116 menu_exit(m);
1117
1118 return result;
1119}
1120
1121static bool eq_hw_set_band4(void)
1122{
1123 int m;
1124 bool result;
1125 static const struct menu_item items[] = {
1126 { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_hw_set_band4_cutoff },
1127 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band4_gain },
1128 };
1129
1130 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1131 NULL, NULL, NULL);
1132 result = menu_run(m);
1133 menu_exit(m);
1134
1135 return result;
1136}
1137
1138bool eq_hw_menu(void)
1139{
1140 int m;
1141 bool result;
1142 static const struct menu_item items[] = {
1143 { ID2P(LANG_EQUALIZER_HARDWARE_ENABLED), eq_hw_enabled },
1144 { ID2P(LANG_EQUALIZER_BAND_LOW_SHELF), eq_hw_set_band0 },
1145 { "Peak Filter 1", eq_hw_set_band1 },
1146 { "Peak Filter 2", eq_hw_set_band2 },
1147 { "Peak Filter 3", eq_hw_set_band3 },
1148 { ID2P(LANG_EQUALIZER_BAND_HIGH_SHELF), eq_hw_set_band4 },
1149 };
1150
1151 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1152 NULL, NULL, NULL);
1153 result = menu_run(m);
1154 menu_exit(m);
1155
1156 return result;
1157}
1158#endif
1159
1160/* Full equalizer menu */
1161bool eq_menu(void)
1162{
1163 int m;
1164 bool result;
1165 static const struct menu_item items[] = {
1166 { ID2P(LANG_EQUALIZER_ENABLED), eq_enabled },
1167 { ID2P(LANG_EQUALIZER_GRAPHICAL), eq_menu_graphical },
1168 { ID2P(LANG_EQUALIZER_PRECUT), eq_precut },
1169 { ID2P(LANG_EQUALIZER_GAIN), eq_gain_menu },
1170 { ID2P(LANG_EQUALIZER_ADVANCED), eq_advanced_menu },
1171 { ID2P(LANG_EQUALIZER_SAVE), eq_save_preset },
1172 { ID2P(LANG_EQUALIZER_BROWSE), eq_browse_presets },
1173 };
1174
1175 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1176 NULL, NULL, NULL);
1177 result = menu_run(m);
1178 menu_exit(m);
1179
1180 return result;
1181}
1182
diff --git a/apps/menu.c b/apps/menu.c
index 6728481a9f..a45567415d 100644
--- a/apps/menu.c
+++ b/apps/menu.c
@@ -290,7 +290,7 @@ static int current_subitems_count = 0;
290void get_menu_callback(const struct menu_item_ex *m, 290void get_menu_callback(const struct menu_item_ex *m,
291 menu_callback_type *menu_callback) 291 menu_callback_type *menu_callback)
292{ 292{
293 if (m->flags&MENU_HAS_DESC) 293 if (m->flags&(MENU_HAS_DESC|MENU_DYNAMIC_DESC))
294 *menu_callback= m->callback_and_desc->menu_callback; 294 *menu_callback= m->callback_and_desc->menu_callback;
295 else 295 else
296 *menu_callback = m->menu_callback; 296 *menu_callback = m->menu_callback;
@@ -318,6 +318,11 @@ static char * get_menu_item_name(int selected_item,void * data, char *buffer)
318 } 318 }
319 319
320 menu = menu->submenus[selected_item]; 320 menu = menu->submenus[selected_item];
321
322 if (menu->flags&MENU_DYNAMIC_DESC)
323 return menu->menu_get_name_and_icon->list_get_name(selected_item,
324 menu->menu_get_name_and_icon->list_get_name_data, buffer);
325
321 type = (menu->flags&MENU_TYPE_MASK); 326 type = (menu->flags&MENU_TYPE_MASK);
322 if (type == MT_SETTING) 327 if (type == MT_SETTING)
323 { 328 {
@@ -333,26 +338,32 @@ static char * get_menu_item_name(int selected_item,void * data, char *buffer)
333static void menu_get_icon(int selected_item, void * data, ICON * icon) 338static void menu_get_icon(int selected_item, void * data, ICON * icon)
334{ 339{
335 const struct menu_item_ex *menu = (const struct menu_item_ex *)data; 340 const struct menu_item_ex *menu = (const struct menu_item_ex *)data;
341 ICON menu_icon = NOICON;
336 selected_item = get_menu_selection(selected_item, menu); 342 selected_item = get_menu_selection(selected_item, menu);
337 343
338 menu = menu->submenus[selected_item]; 344 menu = menu->submenus[selected_item];
345 if (menu->flags&MENU_HAS_DESC)
346 menu_icon = menu->callback_and_desc->icon;
347 else if (menu->flags&MENU_DYNAMIC_DESC)
348 menu_icon = menu->menu_get_name_and_icon->icon;
349
339 switch (menu->flags&MENU_TYPE_MASK) 350 switch (menu->flags&MENU_TYPE_MASK)
340 { 351 {
341 case MT_SETTING: 352 case MT_SETTING:
342 *icon = bitmap_icons_6x8[Icon_Menu_setting]; 353 *icon = bitmap_icons_6x8[Icon_Menu_setting];
343 break; 354 break;
344 case MT_MENU: 355 case MT_MENU:
345 if (menu->callback_and_desc->icon == NOICON) 356 if (menu_icon == NOICON)
346 *icon = bitmap_icons_6x8[Icon_Submenu]; 357 *icon = bitmap_icons_6x8[Icon_Submenu];
347 else 358 else
348 *icon = menu->callback_and_desc->icon; 359 *icon = menu_icon;
349 break; 360 break;
350 case MT_FUNCTION_CALL: 361 case MT_FUNCTION_CALL:
351 case MT_FUNCTION_WITH_PARAM: 362 case MT_FUNCTION_WITH_PARAM:
352 if (menu->callback_and_desc->icon == NOICON) 363 if (menu_icon == NOICON)
353 *icon = bitmap_icons_6x8[Icon_Menu_functioncall]; 364 *icon = bitmap_icons_6x8[Icon_Menu_functioncall];
354 else 365 else
355 *icon = menu->callback_and_desc->icon; 366 *icon = menu_icon;
356 break; 367 break;
357 default: 368 default:
358 *icon = NOICON; 369 *icon = NOICON;
@@ -432,6 +443,113 @@ static void talk_menu_item(const struct menu_item_ex *menu,
432 } 443 }
433} 444}
434#define MAX_OPTIONS 32 445#define MAX_OPTIONS 32
446/* returns true if the menu needs to be redrwan */
447bool do_setting_from_menu(const struct menu_item_ex *temp)
448{
449 int setting_id;
450 const struct settings_list *setting = find_setting(
451 temp->variable,
452 &setting_id);
453 bool ret_val = false;
454 if (setting)
455 {
456 if ((setting->flags&F_BOOL_SETTING) == F_BOOL_SETTING)
457 {
458 bool temp_var, *var;
459 bool show_icons = global_settings.show_icons;
460 if (setting->flags&F_TEMPVAR)
461 {
462 temp_var = *(bool*)setting->setting;
463 var = &temp_var;
464 }
465 else
466 {
467 var = (bool*)setting->setting;
468 }
469 set_bool_options(str(setting->lang_id),var,
470 STR(setting->bool_setting->lang_yes),
471 STR(setting->bool_setting->lang_no),
472 setting->bool_setting->option_callback);
473 if (setting->flags&F_TEMPVAR)
474 *(bool*)setting->setting = temp_var;
475 if (show_icons != global_settings.show_icons)
476 ret_val = true;
477 }
478 else if (setting->flags&F_T_SOUND)
479 {
480 set_sound(str(setting->lang_id), setting->setting,
481 setting->sound_setting->setting);
482 }
483 else /* other setting, must be an INT type */
484 {
485 int temp_var, *var;
486 if (setting->flags&F_TEMPVAR)
487 {
488 temp_var = *(int*)setting->setting;
489 var = &temp_var;
490 }
491 else
492 {
493 var = (int*)setting->setting;
494 }
495 if (setting->flags&F_INT_SETTING)
496 {
497 set_int_ex(str(setting->lang_id),
498 NULL,
499 setting->int_setting->unit,var,
500 setting->int_setting->option_callback,
501 setting->int_setting->step,
502 setting->int_setting->min,
503 setting->int_setting->max,
504 setting->int_setting->formatter,
505 setting->int_setting->get_talk_id);
506 }
507 else if (setting->flags&F_CHOICE_SETTING)
508 {
509 static struct opt_items options[MAX_OPTIONS];
510 char buffer[256];
511 char *buf_start = buffer;
512 int buf_free = 256;
513 int i,j, count = setting->choice_setting->count;
514 for (i=0, j=0; i<count && i<MAX_OPTIONS; i++)
515 {
516 if (setting->flags&F_CHOICETALKS)
517 {
518 if (cfg_int_to_string(setting_id, i,
519 buf_start, buf_free))
520 {
521 int len = strlen(buf_start) +1;
522 options[j].string = buf_start;
523 buf_start += len;
524 buf_free -= len;
525 options[j].voice_id =
526 setting->choice_setting->talks[i];
527 j++;
528 }
529 }
530 else
531 {
532 options[j].string =
533 P2STR(setting->
534 choice_setting->desc[i]);
535 options[j].voice_id =
536 P2ID(setting->
537 choice_setting->desc[i]);
538 j++;
539 }
540 }
541 set_option(str(setting->lang_id), var, INT,
542 options,j,
543 setting->
544 choice_setting->option_callback);
545 }
546 if (setting->flags&F_TEMPVAR)
547 *(int*)setting->setting = temp_var;
548 }
549 }
550 return ret_val;
551}
552
435int do_menu(const struct menu_item_ex *start_menu) 553int do_menu(const struct menu_item_ex *start_menu)
436{ 554{
437 int action; 555 int action;
@@ -551,106 +669,8 @@ int do_menu(const struct menu_item_ex *start_menu)
551 break; 669 break;
552 case MT_SETTING: 670 case MT_SETTING:
553 { 671 {
554 int setting_id; 672 if (do_setting_from_menu(temp))
555 const struct settings_list *setting = find_setting( 673 init_menu_lists(menu, &lists, 0, true);
556 temp->variable,
557 &setting_id);
558 if (setting)
559 {
560 if ((setting->flags&F_BOOL_SETTING) == F_BOOL_SETTING)
561 {
562 bool temp_var, *var;
563 bool show_icons = global_settings.show_icons;
564 if (setting->flags&F_TEMPVAR)
565 {
566 temp_var = *(bool*)setting->setting;
567 var = &temp_var;
568 }
569 else
570 {
571 var = (bool*)setting->setting;
572 }
573 set_bool_options(str(setting->lang_id),var,
574 STR(setting->bool_setting->lang_yes),
575 STR(setting->bool_setting->lang_no),
576 setting->bool_setting->option_callback);
577 if (setting->flags&F_TEMPVAR)
578 *(bool*)setting->setting = temp_var;
579 if (show_icons != global_settings.show_icons)
580 init_menu_lists(menu, &lists, 0, true);
581 }
582 else if (setting->flags&F_T_SOUND)
583 {
584 set_sound(str(setting->lang_id), setting->setting,
585 setting->sound_setting->setting);
586 }
587 else /* other setting, must be an INT type */
588 {
589 int temp_var, *var;
590 if (setting->flags&F_TEMPVAR)
591 {
592 temp_var = *(int*)setting->setting;
593 var = &temp_var;
594 }
595 else
596 {
597 var = (int*)setting->setting;
598 }
599 if (setting->flags&F_INT_SETTING)
600 {
601 set_int_ex(str(setting->lang_id),
602 NULL,
603 setting->int_setting->unit,var,
604 setting->int_setting->option_callback,
605 setting->int_setting->step,
606 setting->int_setting->min,
607 setting->int_setting->max,
608 setting->int_setting->formatter,
609 setting->int_setting->get_talk_id);
610 }
611 else if (setting->flags&F_CHOICE_SETTING)
612 {
613 static struct opt_items options[MAX_OPTIONS];
614 char buffer[256];
615 char *buf_start = buffer;
616 int buf_free = 256;
617 int i,j, count = setting->choice_setting->count;
618 for (i=0, j=0; i<count && i<MAX_OPTIONS; i++)
619 {
620 if (setting->flags&F_CHOICETALKS)
621 {
622 if (cfg_int_to_string(setting_id, i,
623 buf_start, buf_free))
624 {
625 int len = strlen(buf_start) +1;
626 options[j].string = buf_start;
627 buf_start += len;
628 buf_free -= len;
629 options[j].voice_id =
630 setting->choice_setting->talks[i];
631 j++;
632 }
633 }
634 else
635 {
636 options[j].string =
637 P2STR(setting->
638 choice_setting->desc[i]);
639 options[j].voice_id =
640 P2ID(setting->
641 choice_setting->desc[i]);
642 j++;
643 }
644 }
645 set_option(str(setting->lang_id), var, INT,
646 options,j,
647 setting->
648 choice_setting->option_callback);
649 }
650 if (setting->flags&F_TEMPVAR)
651 *(int*)setting->setting = temp_var;
652 }
653 }
654 break; 674 break;
655 } 675 }
656 case MT_RETURN_ID: 676 case MT_RETURN_ID:
diff --git a/apps/menu.h b/apps/menu.h
index 3555cd2de6..c7d6cdbeed 100644
--- a/apps/menu.h
+++ b/apps/menu.h
@@ -72,9 +72,12 @@ struct menu_func_with_param {
72}; 72};
73 73
74#define MENU_TYPE_MASK 0xF /* MT_* type */ 74#define MENU_TYPE_MASK 0xF /* MT_* type */
75/* these next two are mutually exclusive */
75#define MENU_HAS_DESC 0x10 76#define MENU_HAS_DESC 0x10
76#define MENU_COUNT_MASK (~(MENU_TYPE_MASK|MENU_HAS_DESC)) /* unless we need more flags*/ 77#define MENU_DYNAMIC_DESC 0x20
77#define MENU_COUNT_SHIFT 5 78/* unless we need more flags*/
79#define MENU_COUNT_MASK (~(MENU_TYPE_MASK|MENU_HAS_DESC|MENU_DYNAMIC_DESC))
80#define MENU_COUNT_SHIFT 6
78 81
79struct menu_item_ex { 82struct menu_item_ex {
80 int flags; /* above defines */ 83 int flags; /* above defines */
@@ -88,7 +91,9 @@ struct menu_item_ex {
88 const char **strings; /* used with MT_RETURN_ID */ 91 const char **strings; /* used with MT_RETURN_ID */
89 }; 92 };
90 union { 93 union {
94 /* For settings */
91 int (*menu_callback)(int action, const struct menu_item_ex *this_item); 95 int (*menu_callback)(int action, const struct menu_item_ex *this_item);
96 /* For everything else, except if the text is dynamic */
92 const struct menu_callback_with_desc { 97 const struct menu_callback_with_desc {
93 int (*menu_callback)(int action, 98 int (*menu_callback)(int action,
94 const struct menu_item_ex *this_item); 99 const struct menu_item_ex *this_item);
@@ -97,12 +102,23 @@ struct menu_item_ex {
97 ICON icon; /* Icon to display */ 102 ICON icon; /* Icon to display */
98#endif 103#endif
99 } *callback_and_desc; 104 } *callback_and_desc;
105 /* For when the item text is dynamic */
106 const struct menu_get_name_and_icon {
107 int (*menu_callback)(int action,
108 const struct menu_item_ex *this_item);
109 char *(*list_get_name)(int selected_item, void * data, char *buffer);
110 void *list_get_name_data;
111#ifdef HAVE_LCD_BITMAP
112 ICON icon; /* Icon to display */
113#endif
114 } *menu_get_name_and_icon;
100 }; 115 };
101}; 116};
102 117
103typedef int (*menu_callback_type)(int action, 118typedef int (*menu_callback_type)(int action,
104 const struct menu_item_ex *this_item); 119 const struct menu_item_ex *this_item);
105int do_menu(const struct menu_item_ex *menu); 120int do_menu(const struct menu_item_ex *menu);
121bool do_setting_from_menu(const struct menu_item_ex *temp);
106 122
107#define MENU_ITEM_COUNT(c) (c<<MENU_COUNT_SHIFT) 123#define MENU_ITEM_COUNT(c) (c<<MENU_COUNT_SHIFT)
108/* In all the following macros the argument names are as follows: 124/* In all the following macros the argument names are as follows:
@@ -152,6 +168,17 @@ int do_menu(const struct menu_item_ex *menu);
152 { MT_FUNCTION_WITH_PARAM|MENU_HAS_DESC, \ 168 { MT_FUNCTION_WITH_PARAM|MENU_HAS_DESC, \
153 { .func_with_param = &name##__}, \ 169 { .func_with_param = &name##__}, \
154 {.callback_and_desc = & name##_}}; 170 {.callback_and_desc = & name##_}};
171
172/* As above, except the text is dynamic */
173#define MENUITEM_FUNCTION_WPARAM_DYNTEXT(name, func, param, callback, \
174 text_callback, text_cb_data, icon) \
175 static const struct menu_get_name_and_icon name##_ \
176 = {callback,text_callback,text_cb_data,icon};\
177 static const struct menu_func_with_param name##__ = {func, param}; \
178 static const struct menu_item_ex name = \
179 { MT_FUNCTION_WITH_PARAM|MENU_DYNAMIC_DESC, \
180 { .func_with_param = &name##__}, \
181 {.menu_get_name_and_icon = & name##_}};
155 182
156/* Use this to actually create a menu. the ... argument is a list of pointers 183/* Use this to actually create a menu. the ... argument is a list of pointers
157 to any of the above macro'd variables. (It can also have other menus in the list. */ 184 to any of the above macro'd variables. (It can also have other menus in the list. */
diff --git a/apps/menus/eq_menu.c b/apps/menus/eq_menu.c
new file mode 100644
index 0000000000..8473b6b233
--- /dev/null
+++ b/apps/menus/eq_menu.c
@@ -0,0 +1,787 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: eq_menu.c 12179 2007-02-01 23:08:15Z amiconn $
9 *
10 * Copyright (C) 2006 Dan Everton
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include <stdio.h>
22#include <stdbool.h>
23#include <string.h>
24#include "eq_menu.h"
25#include "system.h"
26#include "kernel.h"
27#include "lcd.h"
28#include "menu.h"
29#include "action.h"
30#include "mp3_playback.h"
31#include "settings.h"
32#include "statusbar.h"
33#include "screens.h"
34#include "icons.h"
35#include "font.h"
36#include "lang.h"
37#include "sprintf.h"
38#include "talk.h"
39#include "misc.h"
40#include "sound.h"
41#include "splash.h"
42#include "dsp.h"
43#include "tree.h"
44#include "talk.h"
45#include "screen_access.h"
46#include "keyboard.h"
47#include "gui/scrollbar.h"
48#include "eq_menu.h"
49#ifdef HAVE_WM8758
50#include "wm8758.h"
51#endif
52
53
54
55/*
56 * Utility functions
57 */
58
59void eq_gain_format(char* buffer, int buffer_size, int value, const char* unit)
60{
61 int v = abs(value);
62
63 snprintf(buffer, buffer_size, "%s%d.%d %s", value < 0 ? "-" : "",
64 v / EQ_USER_DIVISOR, v % EQ_USER_DIVISOR, unit);
65}
66
67void eq_q_format(char* buffer, int buffer_size, int value, const char* unit)
68{
69 snprintf(buffer, buffer_size, "%d.%d %s", value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit);
70}
71
72void eq_precut_format(char* buffer, int buffer_size, int value, const char* unit)
73{
74 snprintf(buffer, buffer_size, "%s%d.%d %s", value == 0 ? " " : "-",
75 value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit);
76}
77
78/*
79 * Settings functions
80 */
81int enable_callback(int action, const struct menu_item_ex *this_item)
82{
83 int i;
84 (void)this_item;
85 if (action == ACTION_EXIT_MENUITEM)
86 {
87 dsp_set_eq(global_settings.eq_enabled);
88 dsp_set_eq_precut(global_settings.eq_precut);
89 /* Update all bands */
90 for(i = 0; i < 5; i++) {
91 dsp_set_eq_coefs(i);
92 }
93 }
94 return action;
95}
96MENUITEM_SETTING(eq_enable, &global_settings.eq_enabled, enable_callback);
97MENUITEM_SETTING(eq_precut, &global_settings.eq_precut, NULL);
98
99int dsp_set_coefs_callback(int action, const struct menu_item_ex *this_item)
100{
101 (void)this_item;
102 if (action == ACTION_EXIT_MENUITEM)
103 {
104 /* for now, set every band... figure out a better way later */
105 int i=0;
106 for (i=0; i<5; i++)
107 dsp_set_eq_coefs(i);
108 }
109 return action;
110}
111
112char* gainitem_get_name(int selected_item, void * data, char *buffer)
113{
114 (void)selected_item;
115 int *setting = (int*)data;
116 snprintf(buffer, MAX_PATH, str(LANG_EQUALIZER_GAIN_ITEM), *setting);
117 return buffer;
118}
119
120int do_option(void* param)
121{
122 const struct menu_item_ex *setting = (const struct menu_item_ex*)param;
123 do_setting_from_menu(setting);
124 return 0;
125}
126
127MENUITEM_SETTING(cutoff_0, &global_settings.eq_band0_cutoff, dsp_set_coefs_callback);
128MENUITEM_SETTING(cutoff_1, &global_settings.eq_band1_cutoff, dsp_set_coefs_callback);
129MENUITEM_SETTING(cutoff_2, &global_settings.eq_band2_cutoff, dsp_set_coefs_callback);
130MENUITEM_SETTING(cutoff_3, &global_settings.eq_band3_cutoff, dsp_set_coefs_callback);
131MENUITEM_SETTING(cutoff_4, &global_settings.eq_band4_cutoff, dsp_set_coefs_callback);
132
133MENUITEM_SETTING(q_0, &global_settings.eq_band0_q, dsp_set_coefs_callback);
134MENUITEM_SETTING(q_1, &global_settings.eq_band1_q, dsp_set_coefs_callback);
135MENUITEM_SETTING(q_2, &global_settings.eq_band2_q, dsp_set_coefs_callback);
136MENUITEM_SETTING(q_3, &global_settings.eq_band3_q, dsp_set_coefs_callback);
137MENUITEM_SETTING(q_4, &global_settings.eq_band4_q, dsp_set_coefs_callback);
138
139MENUITEM_SETTING(gain_0, &global_settings.eq_band0_gain, dsp_set_coefs_callback);
140MENUITEM_SETTING(gain_1, &global_settings.eq_band1_gain, dsp_set_coefs_callback);
141MENUITEM_SETTING(gain_2, &global_settings.eq_band2_gain, dsp_set_coefs_callback);
142MENUITEM_SETTING(gain_3, &global_settings.eq_band3_gain, dsp_set_coefs_callback);
143MENUITEM_SETTING(gain_4, &global_settings.eq_band4_gain, dsp_set_coefs_callback);
144
145MENUITEM_FUNCTION_WPARAM_DYNTEXT(gain_item_0, do_option, (void*)&gain_0, NULL,
146 gainitem_get_name,
147 &global_settings.eq_band0_cutoff, NOICON);
148MENUITEM_FUNCTION_WPARAM_DYNTEXT(gain_item_1, do_option, (void*)&gain_1, NULL,
149 gainitem_get_name,
150 &global_settings.eq_band1_cutoff, NOICON);
151MENUITEM_FUNCTION_WPARAM_DYNTEXT(gain_item_2, do_option, (void*)&gain_2, NULL,
152 gainitem_get_name,
153 &global_settings.eq_band2_cutoff, NOICON);
154MENUITEM_FUNCTION_WPARAM_DYNTEXT(gain_item_3, do_option, (void*)&gain_3, NULL,
155 gainitem_get_name,
156 &global_settings.eq_band3_cutoff, NOICON);
157MENUITEM_FUNCTION_WPARAM_DYNTEXT(gain_item_4, do_option, (void*)&gain_4, NULL,
158 gainitem_get_name,
159 &global_settings.eq_band4_cutoff, NOICON);
160
161MAKE_MENU(gain_menu, ID2P(LANG_EQUALIZER_GAIN), NULL, NOICON, &gain_item_0,
162 &gain_item_1, &gain_item_2, &gain_item_3, &gain_item_4);
163
164static const struct menu_item_ex *band_items[3][3] = {
165 { &cutoff_1, &q_1, &gain_1 },
166 { &cutoff_2, &q_2, &gain_2 },
167 { &cutoff_3, &q_3, &gain_3 }
168};
169char* centerband_get_name(int selected_item, void * data, char *buffer)
170{
171 (void)selected_item;
172 int band = (int)data;
173 snprintf(buffer, MAX_PATH, str(LANG_EQUALIZER_BAND_PEAK), band);
174 return buffer;
175}
176int do_center_band_menu(void* param)
177{
178 int band = (int)param;
179 struct menu_item_ex menu;
180 struct menu_callback_with_desc cb_and_desc;
181 char desc[MAX_PATH];
182
183 cb_and_desc.menu_callback = NULL;
184 snprintf(desc, MAX_PATH, str(LANG_EQUALIZER_BAND_PEAK), band);
185 cb_and_desc.desc = desc;
186 cb_and_desc.icon = bitmap_icons_6x8[Icon_EQ];
187 menu.flags = MT_MENU|(3<<MENU_COUNT_SHIFT)|MENU_HAS_DESC;
188 menu.submenus = band_items[band-1];
189 menu.callback_and_desc = &cb_and_desc;
190 do_menu(&menu);
191 return 0;
192}
193MAKE_MENU(band_0_menu, ID2P(LANG_EQUALIZER_BAND_LOW_SHELF), NULL,
194 bitmap_icons_6x8[Icon_EQ], &cutoff_0, &q_0, &gain_0);
195MENUITEM_FUNCTION_WPARAM_DYNTEXT(band_1_menu, do_center_band_menu, (void*)1, NULL,
196 centerband_get_name, (void*)1, bitmap_icons_6x8[Icon_EQ]);
197MENUITEM_FUNCTION_WPARAM_DYNTEXT(band_2_menu, do_center_band_menu, (void*)2, NULL,
198 centerband_get_name, (void*)2, bitmap_icons_6x8[Icon_EQ]);
199MENUITEM_FUNCTION_WPARAM_DYNTEXT(band_3_menu, do_center_band_menu, (void*)3, NULL,
200 centerband_get_name, (void*)3, bitmap_icons_6x8[Icon_EQ]);
201MAKE_MENU(band_4_menu, ID2P(LANG_EQUALIZER_BAND_HIGH_SHELF), NULL,
202 bitmap_icons_6x8[Icon_EQ], &cutoff_4, &q_4, &gain_4);
203
204MAKE_MENU(advanced_eq_menu_, ID2P(LANG_EQUALIZER_ADVANCED), NULL, bitmap_icons_6x8[Icon_EQ],
205 &band_0_menu, &band_1_menu, &band_2_menu, &band_3_menu, &band_4_menu);
206
207
208enum eq_slider_mode {
209 GAIN,
210 CUTOFF,
211 Q,
212};
213
214enum eq_type {
215 LOW_SHELF,
216 PEAK,
217 HIGH_SHELF
218};
219
220/* Draw the UI for a whole EQ band */
221static int draw_eq_slider(struct screen * screen, int x, int y,
222 int width, int cutoff, int q, int gain, bool selected,
223 enum eq_slider_mode mode, enum eq_type type)
224{
225 char buf[26];
226 const char separator[2] = " ";
227 int steps, min_item, max_item;
228 int abs_gain = abs(gain);
229 int current_x, total_height, separator_width, separator_height;
230 int w, h;
231 const int slider_height = 6;
232
233 switch(mode) {
234 case Q:
235 steps = EQ_Q_MAX - EQ_Q_MIN;
236 min_item = q - EQ_Q_STEP - EQ_Q_MIN;
237 max_item = q + EQ_Q_STEP - EQ_Q_MIN;
238 break;
239 case CUTOFF:
240 steps = EQ_CUTOFF_MAX - EQ_CUTOFF_MIN;
241 min_item = cutoff - EQ_CUTOFF_FAST_STEP * 2;
242 max_item = cutoff + EQ_CUTOFF_FAST_STEP * 2;
243 break;
244 case GAIN:
245 default:
246 steps = EQ_GAIN_MAX - EQ_GAIN_MIN;
247 min_item = abs(EQ_GAIN_MIN) + gain - EQ_GAIN_STEP * 5;
248 max_item = abs(EQ_GAIN_MIN) + gain + EQ_GAIN_STEP * 5;
249 break;
250 }
251
252 /* Start two pixels in, one for border, one for margin */
253 current_x = x + 2;
254
255 /* Figure out how large our separator string is */
256 screen->getstringsize(separator, &separator_width, &separator_height);
257
258 /* Total height includes margins, text, and line selector */
259 total_height = separator_height + slider_height + 2 + 3;
260
261 /* Print out the band label */
262 if (type == LOW_SHELF) {
263 screen->putsxy(current_x, y + 2, "LS:");
264 screen->getstringsize("LS:", &w, &h);
265 } else if (type == HIGH_SHELF) {
266 screen->putsxy(current_x, y + 2, "HS:");
267 screen->getstringsize("HS:", &w, &h);
268 } else {
269 screen->putsxy(current_x, y + 2, "PK:");
270 screen->getstringsize("PK:", &w, &h);
271 }
272 current_x += w;
273
274 /* Print separator */
275 screen->set_drawmode(DRMODE_SOLID);
276 screen->putsxy(current_x, y + 2, separator);
277 current_x += separator_width;
278#if NB_SCREENS > 1
279 if (screen->screen_type == SCREEN_REMOTE) {
280 if (mode == GAIN) {
281 screen->putsxy(current_x, y + 2, str(LANG_EQUALIZER_BAND_GAIN));
282 screen->getstringsize(str(LANG_EQUALIZER_BAND_GAIN), &w, &h);
283 } else if (mode == CUTOFF) {
284 screen->putsxy(current_x, y + 2, str(LANG_EQUALIZER_BAND_CUTOFF));
285 screen->getstringsize(str(LANG_EQUALIZER_BAND_CUTOFF), &w, &h);
286 } else {
287 screen->putsxy(current_x, y + 2, str(LANG_EQUALIZER_BAND_Q));
288 screen->getstringsize(str(LANG_EQUALIZER_BAND_Q), &w, &h);
289 }
290
291 /* Draw horizontal slider. Reuse scrollbar for this */
292 gui_scrollbar_draw(screen, x + 3, y + h + 3, width - 6, slider_height, steps,
293 min_item, max_item, HORIZONTAL);
294
295 /* Print out cutoff part */
296 snprintf(buf, sizeof(buf), "%sGain %s%2d.%ddB",mode==GAIN?" > ":" ", gain < 0 ? "-" : " ",
297 abs_gain / EQ_USER_DIVISOR, abs_gain % EQ_USER_DIVISOR);
298 screen->getstringsize(buf, &w, &h);
299 y = 3*h;
300 screen->putsxy(0, y, buf);
301 /* Print out cutoff part */
302 snprintf(buf, sizeof(buf), "%sCutoff %5dHz",mode==CUTOFF?" > ":" ", cutoff);
303 y += h;
304 screen->putsxy(0, y, buf);
305 snprintf(buf, sizeof(buf), "%sQ setting %d.%d Q",mode==Q?" > ":" ", q / EQ_USER_DIVISOR,
306 q % EQ_USER_DIVISOR);
307 y += h;
308 screen->putsxy(0, y, buf);
309 return y;
310 }
311#endif
312
313 /* Print out gain part of status line */
314 snprintf(buf, sizeof(buf), "%s%2d.%ddB", gain < 0 ? "-" : " ",
315 abs_gain / EQ_USER_DIVISOR, abs_gain % EQ_USER_DIVISOR);
316
317 if (mode == GAIN && selected)
318 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
319
320 screen->putsxy(current_x, y + 2, buf);
321 screen->getstringsize(buf, &w, &h);
322 current_x += w;
323
324 /* Print separator */
325 screen->set_drawmode(DRMODE_SOLID);
326 screen->putsxy(current_x, y + 2, separator);
327 current_x += separator_width;
328
329 /* Print out cutoff part of status line */
330 snprintf(buf, sizeof(buf), "%5dHz", cutoff);
331
332 if (mode == CUTOFF && selected)
333 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
334
335 screen->putsxy(current_x, y + 2, buf);
336 screen->getstringsize(buf, &w, &h);
337 current_x += w;
338
339 /* Print separator */
340 screen->set_drawmode(DRMODE_SOLID);
341 screen->putsxy(current_x, y + 2, separator);
342 current_x += separator_width;
343
344 /* Print out Q part of status line */
345 snprintf(buf, sizeof(buf), "%d.%d Q", q / EQ_USER_DIVISOR,
346 q % EQ_USER_DIVISOR);
347
348 if (mode == Q && selected)
349 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
350
351 screen->putsxy(current_x, y + 2, buf);
352 screen->getstringsize(buf, &w, &h);
353 current_x += w;
354
355 screen->set_drawmode(DRMODE_SOLID);
356
357 /* Draw selection box */
358 if (selected) {
359 screen->drawrect(x, y, width, total_height);
360 }
361
362 /* Draw horizontal slider. Reuse scrollbar for this */
363 gui_scrollbar_draw(screen, x + 3, y + h + 3, width - 6, slider_height, steps,
364 min_item, max_item, HORIZONTAL);
365
366 return total_height;
367}
368
369/* Draw's all the EQ sliders. Returns the total height of the sliders drawn */
370static int draw_eq_sliders(int current_band, enum eq_slider_mode mode)
371{
372 int i, gain, q, cutoff;
373 int height = 2; /* Two pixel margin */
374 int slider_width[NB_SCREENS];
375 int *setting = &global_settings.eq_band0_cutoff;
376 enum eq_type type;
377
378 FOR_NB_SCREENS(i)
379 slider_width[i] = screens[i].width - 4; /* two pixel margin on each side */
380
381 for (i=0; i<5; i++) {
382 cutoff = *setting++;
383 q = *setting++;
384 gain = *setting++;
385
386 if (i == 0) {
387 type = LOW_SHELF;
388 } else if (i == 4) {
389 type = HIGH_SHELF;
390 } else {
391 type = PEAK;
392 }
393 height += draw_eq_slider(&(screens[SCREEN_MAIN]), 2, height,
394 slider_width[SCREEN_MAIN], cutoff, q, gain,
395 i == current_band, mode, type);
396#if NB_SCREENS > 1
397 if (i == current_band)
398 draw_eq_slider(&(screens[SCREEN_REMOTE]), 2, 0,
399 slider_width[SCREEN_REMOTE], cutoff, q, gain,1, mode, type);
400#endif
401 /* add a margin */
402 height += 2;
403 }
404
405 return height;
406}
407
408/* Provides a graphical means of editing the EQ settings */
409bool eq_menu_graphical(void)
410{
411 bool exit_request = false;
412 bool result = true;
413 bool has_changed = false;
414 int button;
415 int *setting;
416 int current_band, y, step, fast_step, min, max, voice_unit;
417 enum eq_slider_mode mode;
418 enum eq_type current_type;
419 char buf[24];
420 int i;
421
422 FOR_NB_SCREENS(i) {
423 screens[i].setfont(FONT_SYSFIXED);
424 screens[i].clear_display();
425 }
426
427 /* Start off editing gain on the first band */
428 mode = GAIN;
429 current_type = LOW_SHELF;
430 current_band = 0;
431
432 while (!exit_request) {
433
434 FOR_NB_SCREENS(i) {
435 /* Clear the screen. The drawing routines expect this */
436 screens[i].clear_display();
437 /* Draw equalizer band details */
438 y = draw_eq_sliders(current_band, mode);
439 }
440
441 /* Set pointer to the band data currently editable */
442 if (mode == GAIN) {
443 /* gain */
444 setting = &global_settings.eq_band0_gain;
445 setting += current_band * 3;
446
447 step = EQ_GAIN_STEP;
448 fast_step = EQ_GAIN_FAST_STEP;
449 min = EQ_GAIN_MIN;
450 max = EQ_GAIN_MAX;
451 voice_unit = UNIT_DB;
452
453 snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
454 str(LANG_SYSFONT_EQUALIZER_BAND_GAIN));
455
456 screens[SCREEN_MAIN].putsxy(2, y, buf);
457 } else if (mode == CUTOFF) {
458 /* cutoff */
459 setting = &global_settings.eq_band0_cutoff;
460 setting += current_band * 3;
461
462 step = EQ_CUTOFF_STEP;
463 fast_step = EQ_CUTOFF_FAST_STEP;
464 min = EQ_CUTOFF_MIN;
465 max = EQ_CUTOFF_MAX;
466 voice_unit = UNIT_HERTZ;
467
468 snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
469 str(LANG_SYSFONT_EQUALIZER_BAND_CUTOFF));
470
471 screens[SCREEN_MAIN].putsxy(2, y, buf);
472 } else {
473 /* Q */
474 setting = &global_settings.eq_band0_q;
475 setting += current_band * 3;
476
477 step = EQ_Q_STEP;
478 fast_step = EQ_Q_FAST_STEP;
479 min = EQ_Q_MIN;
480 max = EQ_Q_MAX;
481 voice_unit = UNIT_INT;
482
483 snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
484 str(LANG_EQUALIZER_BAND_Q));
485
486 screens[SCREEN_MAIN].putsxy(2, y, buf);
487 }
488
489 FOR_NB_SCREENS(i) {
490 screens[i].update();
491 }
492
493 button = get_action(CONTEXT_SETTINGS_EQ,TIMEOUT_BLOCK);
494
495 switch (button) {
496 case ACTION_SETTINGS_DEC:
497 case ACTION_SETTINGS_DECREPEAT:
498 *(setting) -= step;
499 has_changed = true;
500 if (*(setting) < min)
501 *(setting) = min;
502 break;
503
504 case ACTION_SETTINGS_INC:
505 case ACTION_SETTINGS_INCREPEAT:
506 *(setting) += step;
507 has_changed = true;
508 if (*(setting) > max)
509 *(setting) = max;
510 break;
511
512 case ACTION_SETTINGS_INCBIGSTEP:
513 *(setting) += fast_step;
514 has_changed = true;
515 if (*(setting) > max)
516 *(setting) = max;
517 break;
518
519 case ACTION_SETTINGS_DECBIGSTEP:
520 *(setting) -= fast_step;
521 has_changed = true;
522 if (*(setting) < min)
523 *(setting) = min;
524 break;
525
526 case ACTION_STD_PREV:
527 case ACTION_STD_PREVREPEAT:
528 current_band--;
529 if (current_band < 0)
530 current_band = 4; /* wrap around */
531 break;
532
533 case ACTION_STD_NEXT:
534 case ACTION_STD_NEXTREPEAT:
535 current_band++;
536 if (current_band > 4)
537 current_band = 0; /* wrap around */
538 break;
539
540 case ACTION_STD_OK:
541 mode++;
542 if (mode > Q)
543 mode = GAIN; /* wrap around */
544 break;
545
546 case ACTION_STD_CANCEL:
547 exit_request = true;
548 result = false;
549 break;
550
551 default:
552 if(default_event_handler(button) == SYS_USB_CONNECTED) {
553 exit_request = true;
554 result = true;
555 }
556 break;
557 }
558
559 /* Update the filter if the user changed something */
560 if (has_changed) {
561 dsp_set_eq_coefs(current_band);
562 has_changed = false;
563 }
564 }
565
566 action_signalscreenchange();
567 /* Reset screen settings */
568 FOR_NB_SCREENS(i) {
569 screens[i].setfont(FONT_UI);
570 screens[i].clear_display();
571 }
572 return result;
573}
574
575/* Preset saver.
576 * TODO: Can the settings system be used to do this instead?
577 */
578static bool eq_save_preset(void)
579{
580 int fd, i;
581 char filename[MAX_PATH];
582 int *setting;
583
584 create_numbered_filename(filename, EQS_DIR, "eq", ".cfg", 2
585 IF_CNFN_NUM_(, NULL));
586
587 /* allow user to modify filename */
588 while (true) {
589 if (!kbd_input(filename, sizeof filename)) {
590 fd = creat(filename);
591 if (fd < 0)
592 gui_syncsplash(HZ, true, str(LANG_FAILED));
593 else
594 break;
595 }
596 else {
597 gui_syncsplash(HZ, true, str(LANG_MENU_SETTING_CANCEL));
598 return false;
599 }
600 }
601
602 /* TODO: Should we really do this? */
603 fdprintf(fd, "eq enabled: on\r\n");
604 fdprintf(fd, "eq precut: %d\r\n", global_settings.eq_precut);
605
606 setting = &global_settings.eq_band0_cutoff;
607
608 for(i = 0; i < 5; ++i) {
609 fdprintf(fd, "eq band %d cutoff: %d\r\n", i, *setting++);
610 fdprintf(fd, "eq band %d q: %d\r\n", i, *setting++);
611 fdprintf(fd, "eq band %d gain: %d\r\n", i, *setting++);
612 }
613
614 close(fd);
615
616 gui_syncsplash(HZ, true, str(LANG_SETTINGS_SAVED));
617
618 return true;
619}
620
621/* Allows browsing of preset files */
622bool eq_browse_presets(void)
623{
624 return rockbox_browse(EQS_DIR, SHOW_CFG);
625}
626
627
628MENUITEM_FUNCTION(eq_graphical, ID2P(LANG_EQUALIZER_GRAPHICAL),
629 (int(*)(void))eq_menu_graphical, NULL,
630 bitmap_icons_6x8[Icon_EQ]);
631MENUITEM_FUNCTION(eq_save, ID2P(LANG_EQUALIZER_SAVE),
632 (int(*)(void))eq_save_preset, NULL, NOICON);
633MENUITEM_FUNCTION(eq_browse, ID2P(LANG_EQUALIZER_BROWSE),
634 (int(*)(void))eq_browse_presets, NULL, NOICON);
635
636MAKE_MENU(equalizer_menu, ID2P(LANG_EQUALIZER), NULL, bitmap_icons_6x8[Icon_EQ],
637 &eq_enable, &eq_graphical, &eq_precut, &gain_menu,
638 &advanced_eq_menu_, &eq_save, &eq_browse);
639
640
641#ifdef HAVE_WM8758
642
643void eq_hw_gain_format(char* buffer, int buffer_size, int value,
644 const char* unit)
645{
646 snprintf(buffer, buffer_size, "%d %s", value, unit);
647}
648
649static int band0_callback(int action, const struct menu_item_ex *this_item)
650{
651 (void)this_item;
652 if (action == ACTION_EXIT_MENUITEM)
653 {
654#ifndef SIMULATOR
655 audiohw_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff, 0,
656 global_settings.eq_hw_band0_gain);
657#endif
658 }
659 return action;
660}
661static int band1_callback(int action, const struct menu_item_ex *this_item)
662{
663 (void)this_item;
664 if (action == ACTION_EXIT_MENUITEM)
665 {
666#ifndef SIMULATOR
667 audiohw_set_equalizer_band(1, global_settings.eq_hw_band1_center,
668 global_settings.eq_hw_band1_bandwidth,
669 global_settings.eq_hw_band1_gain);
670#endif
671 }
672 return action;
673}
674static int band2_callback(int action, const struct menu_item_ex *this_item)
675{
676 (void)this_item;
677 if (action == ACTION_EXIT_MENUITEM)
678 {
679#ifndef SIMULATOR
680 audiohw_set_equalizer_band(2, global_settings.eq_hw_band2_center,
681 global_settings.eq_hw_band2_bandwidth,
682 global_settings.eq_hw_band2_gain);
683#endif
684 }
685 return action;
686}
687static int band3_callback(int action, const struct menu_item_ex *this_item)
688{
689 (void)this_item;
690 if (action == ACTION_EXIT_MENUITEM)
691 {
692#ifndef SIMULATOR
693 audiohw_set_equalizer_band(3, global_settings.eq_hw_band3_center,
694 global_settings.eq_hw_band3_bandwidth,
695 global_settings.eq_hw_band3_gain);
696#endif
697 }
698 return action;
699}
700static int band4_callback(int action, const struct menu_item_ex *this_item)
701{
702 (void)this_item;
703 if (action == ACTION_EXIT_MENUITEM)
704 {
705#ifndef SIMULATOR
706 audiohw_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff, 0,
707 global_settings.eq_hw_band4_gain);
708#endif
709 }
710 return action;
711}
712void eq_hw_enable(bool enable)
713{
714#ifdef SIMULATOR
715 (void) enable;
716#else
717 if (enable) {
718 audiohw_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff,
719 0, global_settings.eq_hw_band0_gain);
720 audiohw_set_equalizer_band(1, global_settings.eq_hw_band1_center,
721 global_settings.eq_hw_band1_bandwidth,
722 global_settings.eq_hw_band1_gain);
723 audiohw_set_equalizer_band(2, global_settings.eq_hw_band2_center,
724 global_settings.eq_hw_band2_bandwidth,
725 global_settings.eq_hw_band2_gain);
726 audiohw_set_equalizer_band(3, global_settings.eq_hw_band3_center,
727 global_settings.eq_hw_band3_bandwidth,
728 global_settings.eq_hw_band3_gain);
729 audiohw_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff,
730 0, global_settings.eq_hw_band4_gain);
731 } else {
732 audiohw_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff, 0, 0);
733 audiohw_set_equalizer_band(1, global_settings.eq_hw_band1_center,
734 global_settings.eq_hw_band1_bandwidth, 0);
735 audiohw_set_equalizer_band(2, global_settings.eq_hw_band2_center,
736 global_settings.eq_hw_band2_bandwidth, 0);
737 audiohw_set_equalizer_band(3, global_settings.eq_hw_band3_center,
738 global_settings.eq_hw_band3_bandwidth, 0);
739 audiohw_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff, 0, 0);
740 }
741#endif
742}
743static int hweq_enable_callback(int action, const struct menu_item_ex *this_item)
744{
745 (void)this_item;
746 if (action == ACTION_EXIT_MENUITEM)
747 {
748 eq_hw_enable(global_settings.eq_hw_enabled);
749 }
750 return action;
751}
752MENUITEM_SETTING(hw_eq_enable, &global_settings.eq_hw_enabled, hweq_enable_callback);
753
754MENUITEM_SETTING(hw_eq_cutoff_0, &global_settings.eq_hw_band0_cutoff, band0_callback);
755MENUITEM_SETTING(hw_eq_gain_0, &global_settings.eq_hw_band0_gain, band0_callback);
756MAKE_MENU(hw_eq_band0, ID2P(LANG_EQUALIZER_BAND_LOW_SHELF), NULL, NOICON,
757 &hw_eq_cutoff_0, &hw_eq_gain_0);
758
759MENUITEM_SETTING(hw_eq_cutoff_1, &global_settings.eq_hw_band1_center, band1_callback);
760MENUITEM_SETTING(hw_eq_bandwidth_1, &global_settings.eq_hw_band1_bandwidth, band1_callback);
761MENUITEM_SETTING(hw_eq_gain_1, &global_settings.eq_hw_band1_gain, band1_callback);
762MAKE_MENU(hw_eq_band1, "Peak Filter 1", NULL, NOICON,
763 &hw_eq_cutoff_1, &hw_eq_bandwidth_1, &hw_eq_gain_1);
764
765MENUITEM_SETTING(hw_eq_cutoff_2, &global_settings.eq_hw_band2_center, band2_callback);
766MENUITEM_SETTING(hw_eq_bandwidth_2, &global_settings.eq_hw_band2_bandwidth, band2_callback);
767MENUITEM_SETTING(hw_eq_gain_2, &global_settings.eq_hw_band2_gain, band2_callback);
768MAKE_MENU(hw_eq_band2, "Peak Filter 2", NULL, NOICON,
769 &hw_eq_cutoff_2, &hw_eq_bandwidth_2, &hw_eq_gain_2);
770
771MENUITEM_SETTING(hw_eq_cutoff_3, &global_settings.eq_hw_band3_center, band3_callback);
772MENUITEM_SETTING(hw_eq_bandwidth_3, &global_settings.eq_hw_band3_bandwidth, band3_callback);
773MENUITEM_SETTING(hw_eq_gain_3, &global_settings.eq_hw_band3_gain, band3_callback);
774MAKE_MENU(hw_eq_band3, "Peak Filter 3", NULL, NOICON,
775 &hw_eq_cutoff_3, &hw_eq_bandwidth_3, &hw_eq_gain_3);
776
777MENUITEM_SETTING(hw_eq_cutoff_4, &global_settings.eq_hw_band4_cutoff, band4_callback);
778MENUITEM_SETTING(hw_eq_gain_4, &global_settings.eq_hw_band4_gain, band4_callback);
779MAKE_MENU(hw_eq_band4, ID2P(LANG_EQUALIZER_BAND_HIGH_SHELF), NULL, NOICON,
780 &hw_eq_cutoff_4, &hw_eq_gain_4);
781
782MAKE_MENU(hw_eq_menu, ID2P(LANG_EQUALIZER_HARDWARE), NULL, bitmap_icons_6x8[Icon_EQ],
783 &hw_eq_enable, &hw_eq_band0, &hw_eq_band1,
784 &hw_eq_band2, &hw_eq_band3, &hw_eq_band4);
785
786
787#endif
diff --git a/apps/eq_menu.h b/apps/menus/eq_menu.h
index e432ea91e3..8f3cb834d8 100644
--- a/apps/eq_menu.h
+++ b/apps/menus/eq_menu.h
@@ -5,7 +5,7 @@
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id: eq_menu.h 10888 2006-09-05 11:48:17Z dan $
9 * 9 *
10 * Copyright (C) 2006 Dan Everton 10 * Copyright (C) 2006 Dan Everton
11 * 11 *
@@ -21,11 +21,37 @@
21 21
22#include "menu.h" 22#include "menu.h"
23#include "config.h" 23#include "config.h"
24/* Various user interface limits and sizes */
25#define EQ_CUTOFF_MIN 20
26#define EQ_CUTOFF_MAX 22040
27#define EQ_CUTOFF_STEP 10
28#define EQ_CUTOFF_FAST_STEP 100
29#define EQ_GAIN_MIN (-240)
30#define EQ_GAIN_MAX 240
31#define EQ_GAIN_STEP 5
32#define EQ_GAIN_FAST_STEP 10
33#define EQ_Q_MIN 5
34#define EQ_Q_MAX 64
35#define EQ_Q_STEP 1
36#define EQ_Q_FAST_STEP 10
37
38#define EQ_USER_DIVISOR 10
24 39
25bool eq_browse_presets(void); 40bool eq_browse_presets(void);
26bool eq_menu_graphical(void); 41bool eq_menu_graphical(void);
27bool eq_menu(void); 42
43/* utility functions for settings_list.c */
44void eq_gain_format(char* buffer, int buffer_size, int value, const char* unit);
45void eq_q_format(char* buffer, int buffer_size, int value, const char* unit);
46void eq_precut_format(char* buffer, int buffer_size, int value, const char* unit);
28#ifdef HAVE_WM8758 47#ifdef HAVE_WM8758
48void eq_hw_gain_format(char* buffer, int buffer_size, int value,
49 const char* unit);
50/* WM8758 equalizer supports -12 to +12 dB gain in 1 dB increments. */
51#define EQ_HW_GAIN_STEP 1
52#define EQ_HW_GAIN_MIN -12
53#define EQ_HW_GAIN_MAX 12
54
29bool eq_hw_menu(void); 55bool eq_hw_menu(void);
30void eq_hw_enable(bool enable); 56void eq_hw_enable(bool enable);
31#endif 57#endif
diff --git a/apps/menus/exported_menus.h b/apps/menus/exported_menus.h
index d2023771a8..ec5a28af21 100644
--- a/apps/menus/exported_menus.h
+++ b/apps/menus/exported_menus.h
@@ -32,7 +32,12 @@ extern const struct menu_item_ex
32#endif 32#endif
33 sound_settings, /* sound_menu.c */ 33 sound_settings, /* sound_menu.c */
34 settings_menu_item, /* settings_menu.c */ 34 settings_menu_item, /* settings_menu.c */
35 playlist_menu_item; /* playlist_menu.c */ 35 playlist_menu_item, /* playlist_menu.c */
36 equalizer_menu; /* eq_menu.c */
37
38#ifdef HAVE_WM8758
39extern const struct menu_item_ex hw_eq_menu; /* eq_menu.c */
40#endif
36 41
37 42
38 43
diff --git a/apps/menus/sound_menu.c b/apps/menus/sound_menu.c
index a8e86a7eed..fd366f1176 100644
--- a/apps/menus/sound_menu.c
+++ b/apps/menus/sound_menu.c
@@ -31,6 +31,7 @@
31#if CONFIG_CODEC == SWCODEC 31#if CONFIG_CODEC == SWCODEC
32#include "pcmbuf.h" 32#include "pcmbuf.h"
33#endif 33#endif
34#include "exported_menus.h"
34 35
35/***********************************/ 36/***********************************/
36/* SOUND MENU */ 37/* SOUND MENU */
@@ -79,14 +80,8 @@ MENUITEM_SETTING(stereo_width, &global_settings.stereo_width, soundmenu_callback
79 &crossfeed, &crossfeed_direct_gain, &crossfeed_cross_gain, 80 &crossfeed, &crossfeed_direct_gain, &crossfeed_cross_gain,
80 &crossfeed_hf_attenuation, &crossfeed_hf_cutoff); 81 &crossfeed_hf_attenuation, &crossfeed_hf_cutoff);
81 82
82 MENUITEM_FUNCTION(equalizer_menu, ID2P(LANG_EQUALIZER),
83 (int(*)(void))eq_menu, NULL, NOICON);
84 MENUITEM_SETTING(dithering_enabled, 83 MENUITEM_SETTING(dithering_enabled,
85 &global_settings.dithering_enabled, soundmenu_callback); 84 &global_settings.dithering_enabled, soundmenu_callback);
86#ifdef HAVE_WM8758
87 MENUITEM_FUNCTION(hw_equalizer_menu, ID2P(LANG_EQUALIZER_HARDWARE),
88 (int(*)(void))eq_hw_menu, NULL, NOICON);
89#endif
90#endif 85#endif
91 86
92#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) 87#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
@@ -109,10 +104,10 @@ MAKE_MENU(sound_settings, ID2P(LANG_SOUND_SETTINGS), NULL, bitmap_icons_6x8[Icon
109#endif 104#endif
110 &balance,&channel_config,&stereo_width 105 &balance,&channel_config,&stereo_width
111#if CONFIG_CODEC == SWCODEC 106#if CONFIG_CODEC == SWCODEC
112 ,&crossfeed_menu, &equalizer_menu,&dithering_enabled 107 ,&crossfeed_menu, &equalizer_menu, &dithering_enabled
113#endif 108#endif
114#ifdef HAVE_WM8758 109#ifdef HAVE_WM8758
115 ,&hw_equalizer_menu 110 ,&hw_eq_menu
116#endif 111#endif
117#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) 112#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
118 ,&loudness,&avc,&superbass,&mdb_enable,&mdb_strength 113 ,&loudness,&avc,&superbass,&mdb_enable,&mdb_strength
diff --git a/apps/onplay.c b/apps/onplay.c
index 14fbdb8a17..18a0ff6e63 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -59,7 +59,7 @@
59#include "main_menu.h" 59#include "main_menu.h"
60#include "sound_menu.h" 60#include "sound_menu.h"
61#if CONFIG_CODEC == SWCODEC 61#if CONFIG_CODEC == SWCODEC
62#include "eq_menu.h" 62#include "menus/eq_menu.h"
63#endif 63#endif
64#include "playlist_menu.h" 64#include "playlist_menu.h"
65#include "playlist_catalog.h" 65#include "playlist_catalog.h"
diff --git a/apps/recorder/icons.c b/apps/recorder/icons.c
index 3c66fbd129..8f2ecc4b80 100644
--- a/apps/recorder/icons.c
+++ b/apps/recorder/icons.c
@@ -78,6 +78,7 @@ const unsigned char bitmap_icons_6x8[][6] =
78 { 0x03, 0x05, 0x7f, 0x05, 0x03, 0x00 }, /* radio */ 78 { 0x03, 0x05, 0x7f, 0x05, 0x03, 0x00 }, /* radio */
79#endif 79#endif
80 { 0x1f, 0x11, 0x7d, 0x46, 0x44, 0x78 }, /* File View Menu */ 80 { 0x1f, 0x11, 0x7d, 0x46, 0x44, 0x78 }, /* File View Menu */
81 { 0x06, 0x7f, 0x06, 0x18, 0x7f, 0x18 }, /* EQ menu */
81}; 82};
82 83
83const unsigned char bitmap_icons_7x8[][7] = 84const unsigned char bitmap_icons_7x8[][7] =
diff --git a/apps/recorder/icons.h b/apps/recorder/icons.h
index a2a0e95aa6..782dc9a1e3 100644
--- a/apps/recorder/icons.h
+++ b/apps/recorder/icons.h
@@ -82,6 +82,7 @@ enum icons_6x8 {
82 Icon_Radio_screen, 82 Icon_Radio_screen,
83#endif 83#endif
84 Icon_file_view_menu, 84 Icon_file_view_menu,
85 Icon_EQ,
85 Icon6x8Last, 86 Icon6x8Last,
86}; 87};
87 88
diff --git a/apps/settings.c b/apps/settings.c
index 2001c354d3..cb969e7fdf 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -89,7 +89,7 @@ const char rec_base_directory[] = REC_BASE_DIR;
89#endif /* CONFIG_CODEC == SWCODEC */ 89#endif /* CONFIG_CODEC == SWCODEC */
90 90
91#ifdef HAVE_WM8758 91#ifdef HAVE_WM8758
92#include "eq_menu.h" 92#include "menus/eq_menu.h"
93#endif 93#endif
94 94
95#define NVRAM_BLOCK_SIZE 44 95#define NVRAM_BLOCK_SIZE 44
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 9f24c63a84..a505232643 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -42,6 +42,7 @@
42#ifdef HAVE_LCD_BITMAP 42#ifdef HAVE_LCD_BITMAP
43#include "peakmeter.h" 43#include "peakmeter.h"
44#endif 44#endif
45#include "menus/eq_menu.h"
45 46
46/* some sets of values which are used more than once, to save memory */ 47/* some sets of values which are used more than once, to save memory */
47static const char off_on[] = "off,on"; 48static const char off_on[] = "off,on";
@@ -349,6 +350,7 @@ static long jumpscroll_getlang(int value)
349 return -1; 350 return -1;
350} 351}
351#endif /* HAVE_LCD_CHARCELLS */ 352#endif /* HAVE_LCD_CHARCELLS */
353
352 354
353const struct settings_list settings[] = { 355const struct settings_list settings[] = {
354 /* sound settings */ 356 /* sound settings */
@@ -857,41 +859,56 @@ const struct settings_list settings[] = {
857 crossfeed_format, NULL, crossfeed_hf_cutoff_helper), 859 crossfeed_format, NULL, crossfeed_hf_cutoff_helper),
858 /* equalizer */ 860 /* equalizer */
859 OFFON_SETTING(0,eq_enabled,LANG_EQUALIZER_ENABLED,false,"eq enabled",NULL), 861 OFFON_SETTING(0,eq_enabled,LANG_EQUALIZER_ENABLED,false,"eq enabled",NULL),
860 {F_T_INT,&global_settings.eq_precut,LANG_EQUALIZER_PRECUT,INT(0), 862 INT_SETTING(0, eq_precut, LANG_EQUALIZER_PRECUT, 0, "eq precut",
861 "eq precut",NULL,UNUSED}, 863 UNIT_DB, 0, 240, 5, eq_precut_format, NULL, dsp_set_eq_precut),
862 /* 0..32768 Hz */ 864 /* 0..32768 Hz */
863 {F_T_INT,&global_settings.eq_band0_cutoff,LANG_EQUALIZER_BAND_CUTOFF,INT(60), 865 INT_SETTING(0, eq_band0_cutoff, LANG_EQUALIZER_BAND_CUTOFF, 60, "eq band 0 cutoff",
864 "eq band 0 cutoff",NULL,UNUSED}, 866 UNIT_HERTZ, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, EQ_CUTOFF_STEP,
865 {F_T_INT,&global_settings.eq_band1_cutoff,LANG_EQUALIZER_BAND_CUTOFF,INT(200), 867 NULL, NULL, NULL),
866 "eq band 1 cutoff",NULL,UNUSED}, 868 INT_SETTING(0, eq_band1_cutoff, LANG_EQUALIZER_BAND_CENTER, 200, "eq band 1 cutoff",
867 {F_T_INT,&global_settings.eq_band2_cutoff,LANG_EQUALIZER_BAND_CUTOFF,INT(800), 869 UNIT_HERTZ, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, EQ_CUTOFF_STEP,
868 "eq band 2 cutoff",NULL,UNUSED}, 870 NULL, NULL, NULL),
869 {F_T_INT,&global_settings.eq_band3_cutoff,LANG_EQUALIZER_BAND_CUTOFF,INT(4000), 871 INT_SETTING(0, eq_band2_cutoff, LANG_EQUALIZER_BAND_CENTER, 800, "eq band 2 cutoff",
870 "eq band 3 cutoff",NULL,UNUSED}, 872 UNIT_HERTZ, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, EQ_CUTOFF_STEP,
871 {F_T_INT,&global_settings.eq_band4_cutoff,LANG_EQUALIZER_BAND_CUTOFF,INT(12000), 873 NULL, NULL, NULL),
872 "eq band 4 cutoff",NULL,UNUSED}, 874 INT_SETTING(0, eq_band3_cutoff, LANG_EQUALIZER_BAND_CENTER, 4000, "eq band 3 cutoff",
875 UNIT_HERTZ, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, EQ_CUTOFF_STEP,
876 NULL, NULL, NULL),
877 INT_SETTING(0, eq_band4_cutoff, LANG_EQUALIZER_BAND_CUTOFF, 12000, "eq band 4 cutoff",
878 UNIT_HERTZ, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, EQ_CUTOFF_STEP,
879 NULL, NULL, NULL),
873 /* 0..64 (or 0.0 to 6.4) */ 880 /* 0..64 (or 0.0 to 6.4) */
874 {F_T_INT,&global_settings.eq_band0_q,LANG_EQUALIZER_BAND_Q,INT(7), 881 INT_SETTING(0, eq_band0_q, LANG_EQUALIZER_BAND_Q, 7, "eq band 0 q",
875 "eq band 0 q",NULL,UNUSED}, 882 UNIT_INT, EQ_Q_MIN, EQ_Q_MAX, EQ_Q_STEP,
876 {F_T_INT,&global_settings.eq_band1_q,LANG_EQUALIZER_BAND_Q,INT(10), 883 eq_q_format, NULL, NULL),
877 "eq band 1 q",NULL,UNUSED}, 884 INT_SETTING(0, eq_band1_q, LANG_EQUALIZER_BAND_Q, 10, "eq band 1 q",
878 {F_T_INT,&global_settings.eq_band2_q,LANG_EQUALIZER_BAND_Q,INT(10), 885 UNIT_INT, EQ_Q_MIN, EQ_Q_MAX, EQ_Q_STEP,
879 "eq band 2 q",NULL,UNUSED}, 886 eq_q_format, NULL, NULL),
880 {F_T_INT,&global_settings.eq_band3_q,LANG_EQUALIZER_BAND_Q,INT(10), 887 INT_SETTING(0, eq_band2_q, LANG_EQUALIZER_BAND_Q, 10, "eq band 2 q",
881 "eq band 3 q",NULL,UNUSED}, 888 UNIT_INT, EQ_Q_MIN, EQ_Q_MAX, EQ_Q_STEP,
882 {F_T_INT,&global_settings.eq_band4_q,LANG_EQUALIZER_BAND_Q,INT(7), 889 eq_q_format, NULL, NULL),
883 "eq band 4 q",NULL,UNUSED}, 890 INT_SETTING(0, eq_band3_q, LANG_EQUALIZER_BAND_Q, 10, "eq band 3 q",
891 UNIT_INT, EQ_Q_MIN, EQ_Q_MAX, EQ_Q_STEP,
892 eq_q_format, NULL, NULL),
893 INT_SETTING(0, eq_band4_q, LANG_EQUALIZER_BAND_Q, 7, "eq band 4 q",
894 UNIT_INT, EQ_Q_MIN, EQ_Q_MAX, EQ_Q_STEP,
895 eq_q_format, NULL, NULL),
884 /* -240..240 (or -24db to +24db) */ 896 /* -240..240 (or -24db to +24db) */
885 {F_T_INT,&global_settings.eq_band0_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 897 INT_SETTING(0, eq_band0_gain, LANG_EQUALIZER_BAND_GAIN, 0, "eq band 0 gain",
886 "eq band 0 gain",NULL,UNUSED}, 898 UNIT_DB, EQ_GAIN_MIN, EQ_GAIN_MAX, EQ_GAIN_STEP,
887 {F_T_INT,&global_settings.eq_band1_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 899 eq_gain_format, NULL, NULL),
888 "eq band 1 gain",NULL,UNUSED}, 900 INT_SETTING(0, eq_band1_gain, LANG_EQUALIZER_BAND_GAIN, 0, "eq band 1 gain",
889 {F_T_INT,&global_settings.eq_band2_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 901 UNIT_DB, EQ_GAIN_MIN, EQ_GAIN_MAX, EQ_GAIN_STEP,
890 "eq band 2 gain",NULL,UNUSED}, 902 eq_gain_format, NULL, NULL),
891 {F_T_INT,&global_settings.eq_band3_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 903 INT_SETTING(0, eq_band2_gain, LANG_EQUALIZER_BAND_GAIN, 0, "eq band 2 gain",
892 "eq band 3 gain",NULL,UNUSED}, 904 UNIT_DB, EQ_GAIN_MIN, EQ_GAIN_MAX, EQ_GAIN_STEP,
893 {F_T_INT,&global_settings.eq_band4_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 905 eq_gain_format, NULL, NULL),
894 "eq band 4 gain",NULL,UNUSED}, 906 INT_SETTING(0, eq_band3_gain, LANG_EQUALIZER_BAND_GAIN, 0, "eq band 3 gain",
907 UNIT_DB, EQ_GAIN_MIN, EQ_GAIN_MAX, EQ_GAIN_STEP,
908 eq_gain_format, NULL, NULL),
909 INT_SETTING(0, eq_band4_gain, LANG_EQUALIZER_BAND_GAIN, 0, "eq band 4 gain",
910 UNIT_DB, EQ_GAIN_MIN, EQ_GAIN_MAX, EQ_GAIN_STEP,
911 eq_gain_format, NULL, NULL),
895 912
896 /* dithering */ 913 /* dithering */
897 OFFON_SETTING(0, dithering_enabled, LANG_DITHERING, 914 OFFON_SETTING(0, dithering_enabled, LANG_DITHERING,
@@ -949,41 +966,57 @@ const struct settings_list settings[] = {
949 OFFON_SETTING(0,eq_hw_enabled,LANG_EQUALIZER_HARDWARE_ENABLED,false, 966 OFFON_SETTING(0,eq_hw_enabled,LANG_EQUALIZER_HARDWARE_ENABLED,false,
950 "eq hardware enabled",NULL), 967 "eq hardware enabled",NULL),
951 968
952 {F_T_INT,&global_settings.eq_hw_band0_cutoff,LANG_EQUALIZER_BAND_CUTOFF,INT(1), 969 STRINGCHOICE_SETTING(0, eq_hw_band0_cutoff, LANG_EQUALIZER_BAND_CUTOFF, 1,
953 "eq hardware band 0 cutoff", 970 "eq hardware band 0 cutoff", "80Hz,105Hz,135Hz,175Hz", NULL, 4,
954 "80Hz,105Hz,135Hz,175Hz",UNUSED}, 971 TALK_ID(80, UNIT_HERTZ), TALK_ID(105, UNIT_HERTZ),
955 {F_T_INT,&global_settings.eq_hw_band0_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 972 TALK_ID(135, UNIT_HERTZ), TALK_ID(175, UNIT_HERTZ)),
956 "eq hardware band 0 gain",NULL,UNUSED}, 973 INT_SETTING(0, eq_hw_band0_gain, LANG_EQUALIZER_BAND_GAIN, 0,
974 "eq hardware band 0 gain", UNIT_DB, EQ_HW_GAIN_MIN,
975 EQ_HW_GAIN_MAX, EQ_HW_GAIN_STEP, eq_hw_gain_format, NULL, NULL),
957 976
958 {F_T_INT,&global_settings.eq_hw_band1_center,LANG_EQUALIZER_BAND_CENTER,INT(1), 977 STRINGCHOICE_SETTING(0, eq_hw_band1_center, LANG_EQUALIZER_BAND_CENTER, 1,
959 "eq hardware band 1 center", 978 "eq hardware band 1 center", "230Hz,300Hz,385Hz,500Hz", NULL, 4,
960 "230Hz,300Hz,385Hz,500Hz",UNUSED}, 979 TALK_ID(230, UNIT_HERTZ), TALK_ID(300, UNIT_HERTZ),
961 {F_T_INT,&global_settings.eq_hw_band1_bandwidth,LANG_EQUALIZER_BANDWIDTH,INT(0), 980 TALK_ID(385, UNIT_HERTZ), TALK_ID(500, UNIT_HERTZ)),
962 "eq hardware band 1 bandwidth","narrow,wide",UNUSED}, 981 CHOICE_SETTING(0, eq_hw_band1_bandwidth, LANG_EQUALIZER_BANDWIDTH, 0,
963 {F_T_INT,&global_settings.eq_hw_band1_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 982 "eq hardware band 1 bandwidth", "narrow,wide", NULL, 2,
964 "eq hardware band 1 gain",NULL,UNUSED}, 983 ID2P(LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW),
984 ID2P(LANG_EQUALIZER_HARDWARE_BANDWIDTH_WIDE)),
985 INT_SETTING(0, eq_hw_band1_gain, LANG_EQUALIZER_BAND_GAIN, 0,
986 "eq hardware band 1 gain", UNIT_DB, EQ_HW_GAIN_MIN,
987 EQ_HW_GAIN_MAX, EQ_HW_GAIN_STEP, eq_hw_gain_format, NULL, NULL),
965 988
966 {F_T_INT,&global_settings.eq_hw_band2_center,LANG_EQUALIZER_BAND_CENTER,INT(1), 989 STRINGCHOICE_SETTING(0, eq_hw_band2_center, LANG_EQUALIZER_BAND_CENTER, 1,
967 "eq hardware band 2 center", 990 "eq hardware band 2 center", "650Hz,850Hz,1.1kHz,1.4kHz", NULL, 4,
968 "650Hz,850Hz,1.1kHz,1.4kHz",UNUSED}, 991 TALK_ID(650, UNIT_HERTZ), TALK_ID(850, UNIT_HERTZ),
969 {F_T_INT,&global_settings.eq_hw_band2_bandwidth,LANG_EQUALIZER_BANDWIDTH,INT(0), 992 TALK_ID(1100, UNIT_HERTZ), TALK_ID(1400, UNIT_HERTZ)),
970 "eq hardware band 2 bandwidth","narrow,wide",UNUSED}, 993 CHOICE_SETTING(0, eq_hw_band2_bandwidth, LANG_EQUALIZER_BANDWIDTH, 0,
971 {F_T_INT,&global_settings.eq_hw_band2_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 994 "eq hardware band 2 bandwidth", "narrow,wide", NULL, 2,
972 "eq hardware band 2 gain",NULL,UNUSED}, 995 ID2P(LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW),
996 ID2P(LANG_EQUALIZER_HARDWARE_BANDWIDTH_WIDE)),
997 INT_SETTING(0, eq_hw_band2_gain, LANG_EQUALIZER_BAND_GAIN, 0,
998 "eq hardware band 2 gain", UNIT_DB, EQ_HW_GAIN_MIN,
999 EQ_HW_GAIN_MAX, EQ_HW_GAIN_STEP, eq_hw_gain_format, NULL, NULL),
973 1000
974 {F_T_INT,&global_settings.eq_hw_band3_center,LANG_EQUALIZER_BAND_CENTER,INT(1), 1001 STRINGCHOICE_SETTING(0, eq_hw_band3_center, LANG_EQUALIZER_BAND_CENTER, 1,
975 "eq hardware band 3 center", 1002 "eq hardware band 3 center", "1.8kHz,2.4kHz,3.2kHz,4.1kHz", NULL, 4,
976 "1.8kHz,2.4kHz,3.2kHz,4.1kHz",UNUSED}, 1003 TALK_ID(1800, UNIT_HERTZ), TALK_ID(2400, UNIT_HERTZ),
977 {F_T_INT,&global_settings.eq_hw_band3_bandwidth,LANG_EQUALIZER_BANDWIDTH,INT(0), 1004 TALK_ID(3200, UNIT_HERTZ), TALK_ID(4100, UNIT_HERTZ)),
978 "eq hardware band 3 bandwidth","narrow,wide",UNUSED}, 1005 CHOICE_SETTING(0, eq_hw_band3_bandwidth, LANG_EQUALIZER_BANDWIDTH, 0,
979 {F_T_INT,&global_settings.eq_hw_band3_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 1006 "eq hardware band 3 bandwidth", "narrow,wide", NULL, 2,
980 "eq hardware band 3 gain",NULL,UNUSED}, 1007 ID2P(LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW),
1008 ID2P(LANG_EQUALIZER_HARDWARE_BANDWIDTH_WIDE)),
1009 INT_SETTING(0, eq_hw_band3_gain, LANG_EQUALIZER_BAND_GAIN, 0,
1010 "eq hardware band 3 gain", UNIT_DB, EQ_HW_GAIN_MIN,
1011 EQ_HW_GAIN_MAX, EQ_HW_GAIN_STEP, eq_hw_gain_format, NULL, NULL),
981 1012
982 {F_T_INT,&global_settings.eq_hw_band4_cutoff,LANG_EQUALIZER_BAND_CUTOFF,INT(1), 1013 STRINGCHOICE_SETTING(0, eq_hw_band4_cutoff, LANG_EQUALIZER_BAND_CUTOFF, 1,
983 "eq hardware band 4 cutoff", 1014 "eq hardware band 4 cutoff", "5.3kHz,6.9kHz,9kHz,11.7kHz", NULL, 4,
984 "5.3kHz,6.9kHz,9kHz,11.7kHz",UNUSED}, 1015 TALK_ID(5300, UNIT_HERTZ), TALK_ID(6900, UNIT_HERTZ),
985 {F_T_INT,&global_settings.eq_hw_band4_gain,LANG_EQUALIZER_BAND_GAIN,INT(0), 1016 TALK_ID(9000, UNIT_HERTZ), TALK_ID(11700, UNIT_HERTZ)),
986 "eq hardware band 4 gain",NULL,UNUSED}, 1017 INT_SETTING(0, eq_hw_band4_gain, LANG_EQUALIZER_BAND_GAIN, 0,
1018 "eq hardware band 4 gain", UNIT_DB, EQ_HW_GAIN_MIN,
1019 EQ_HW_GAIN_MAX, EQ_HW_GAIN_STEP, eq_hw_gain_format, NULL, NULL),
987#endif 1020#endif
988 1021
989 OFFON_SETTING(0,hold_lr_for_scroll_in_list,-1,true, 1022 OFFON_SETTING(0,hold_lr_for_scroll_in_list,-1,true,
diff --git a/apps/sound_menu.c b/apps/sound_menu.c
index 74618b1348..c73472a83c 100644
--- a/apps/sound_menu.c
+++ b/apps/sound_menu.c
@@ -52,7 +52,7 @@
52#include "splash.h" 52#include "splash.h"
53#if CONFIG_CODEC == SWCODEC 53#if CONFIG_CODEC == SWCODEC
54#include "dsp.h" 54#include "dsp.h"
55#include "eq_menu.h" 55#include "menus/eq_menu.h"
56#include "pcmbuf.h" 56#include "pcmbuf.h"
57#ifdef HAVE_RECORDING 57#ifdef HAVE_RECORDING
58#include "enc_config.h" 58#include "enc_config.h"