Update several codec Makefiles so that the codec libs build again on Coldfire targets...
[Rockbox.git] / apps / eq_menu.c
blobb062dd719d56561fd60846d76842007eccd7a266
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 Dan Everton
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
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
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
66 #define EQ_USER_DIVISOR 10
69 * Utility functions
72 static void eq_gain_format(char* buffer, int buffer_size, int value, const char* unit)
74 int v = abs(value);
76 snprintf(buffer, buffer_size, "%s%d.%d %s", value < 0 ? "-" : "",
77 v / EQ_USER_DIVISOR, v % EQ_USER_DIVISOR, unit);
80 static void eq_q_format(char* buffer, int buffer_size, int value, const char* unit)
82 snprintf(buffer, buffer_size, "%d.%d %s", value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit);
85 static void eq_precut_format(char* buffer, int buffer_size, int value, const char* unit)
87 snprintf(buffer, buffer_size, "%s%d.%d %s", value == 0 ? " " : "-",
88 value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit);
92 * Settings functions
95 static bool eq_enabled(void)
97 int i;
99 bool result = set_bool(str(LANG_EQUALIZER_ENABLED),
100 &global_settings.eq_enabled);
102 dsp_set_eq(global_settings.eq_enabled);
104 dsp_set_eq_precut(global_settings.eq_precut);
106 /* Update all bands */
107 for(i = 0; i < 5; i++) {
108 dsp_set_eq_coefs(i);
111 return result;
114 static bool eq_precut(void)
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);
120 return result;
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))
127 #define eq_set_center(band) \
128 static bool eq_set_band ## band ## _center(void) \
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; \
137 #define eq_set_cutoff(band) \
138 static bool eq_set_band ## band ## _cutoff(void) \
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; \
147 #define eq_set_q(band) \
148 static bool eq_set_band ## band ## _q(void) \
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; \
157 #define eq_set_gain(band) \
158 static bool eq_set_band ## band ## _gain(void) \
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; \
167 eq_set_cutoff(0);
168 eq_set_center(1);
169 eq_set_center(2);
170 eq_set_center(3);
171 eq_set_cutoff(4);
173 eq_set_q(0);
174 eq_set_q(1);
175 eq_set_q(2);
176 eq_set_q(3);
177 eq_set_q(4);
179 eq_set_gain(0);
180 eq_set_gain(1);
181 eq_set_gain(2);
182 eq_set_gain(3);
183 eq_set_gain(4);
185 static bool eq_gain_menu(void)
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 },
199 setting = &global_settings.eq_band0_cutoff;
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];
207 /* Skip to next band */
208 setting += 3;
211 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
212 NULL, NULL, NULL);
213 result = menu_run(m);
214 menu_exit(m);
216 return result;
219 static bool eq_set_band0(void)
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 },
229 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
230 NULL, NULL, NULL);
231 result = menu_run(m);
232 menu_exit(m);
234 return result;
237 static bool eq_set_band1(void)
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 },
247 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
248 NULL, NULL, NULL);
249 result = menu_run(m);
250 menu_exit(m);
252 return result;
255 static bool eq_set_band2(void)
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 },
265 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
266 NULL, NULL, NULL);
267 result = menu_run(m);
268 menu_exit(m);
270 return result;
273 static bool eq_set_band3(void)
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 },
283 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
284 NULL, NULL, NULL);
285 result = menu_run(m);
286 menu_exit(m);
288 return result;
291 static bool eq_set_band4(void)
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 },
301 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
302 NULL, NULL, NULL);
303 result = menu_run(m);
304 menu_exit(m);
306 return result;
309 static bool eq_advanced_menu(void)
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 },
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];
329 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
330 NULL, NULL, NULL);
331 result = menu_run(m);
332 menu_exit(m);
334 return result;
337 enum eq_slider_mode {
338 GAIN,
339 CUTOFF,
343 enum eq_type {
344 LOW_SHELF,
345 PEAK,
346 HIGH_SHELF
349 /* Draw the UI for a whole EQ band */
350 static 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)
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;
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;
381 /* Start two pixels in, one for border, one for margin */
382 current_x = x + 2;
384 /* Figure out how large our separator string is */
385 screen->getstringsize(separator, &separator_width, &separator_height);
387 /* Total height includes margins, text, and line selector */
388 total_height = separator_height + slider_height + 2 + 3;
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);
401 current_x += w;
403 /* Print separator */
404 screen->set_drawmode(DRMODE_SOLID);
405 screen->putsxy(current_x, y + 2, separator);
406 current_x += separator_width;
407 #ifdef HAVE_REMOTE_LCD
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);
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);
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;
440 #endif
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);
446 if (mode == GAIN && selected)
447 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
449 screen->putsxy(current_x, y + 2, buf);
450 screen->getstringsize(buf, &w, &h);
451 current_x += w;
453 /* Print separator */
454 screen->set_drawmode(DRMODE_SOLID);
455 screen->putsxy(current_x, y + 2, separator);
456 current_x += separator_width;
458 /* Print out cutoff part of status line */
459 snprintf(buf, sizeof(buf), "%5dHz", cutoff);
461 if (mode == CUTOFF && selected)
462 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
464 screen->putsxy(current_x, y + 2, buf);
465 screen->getstringsize(buf, &w, &h);
466 current_x += w;
468 /* Print separator */
469 screen->set_drawmode(DRMODE_SOLID);
470 screen->putsxy(current_x, y + 2, separator);
471 current_x += separator_width;
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);
477 if (mode == Q && selected)
478 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
480 screen->putsxy(current_x, y + 2, buf);
481 screen->getstringsize(buf, &w, &h);
482 current_x += w;
484 screen->set_drawmode(DRMODE_SOLID);
486 /* Draw selection box */
487 if (selected) {
488 screen->drawrect(x, y, width, total_height);
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);
495 return total_height;
498 /* Draw's all the EQ sliders. Returns the total height of the sliders drawn */
499 static int draw_eq_sliders(int current_band, enum eq_slider_mode mode)
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;
507 FOR_NB_SCREENS(i)
508 slider_width[i] = screens[i].width - 4; /* two pixel margin on each side */
510 for (i=0; i<5; i++) {
511 cutoff = *setting++;
512 q = *setting++;
513 gain = *setting++;
515 if (i == 0) {
516 type = LOW_SHELF;
517 } else if (i == 4) {
518 type = HIGH_SHELF;
519 } else {
520 type = PEAK;
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 #ifdef HAVE_REMOTE_LCD
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;
534 return height;
537 /* Provides a graphical means of editing the EQ settings */
538 bool eq_menu_graphical(void)
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;
551 FOR_NB_SCREENS(i) {
552 screens[i].setfont(FONT_SYSFIXED);
553 screens[i].clear_display();
556 /* Start off editing gain on the first band */
557 mode = GAIN;
558 current_type = LOW_SHELF;
559 current_band = 0;
561 while (!exit_request) {
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);
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;
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;
582 snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
583 str(LANG_SYSFONT_EQUALIZER_BAND_GAIN));
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;
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;
597 snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
598 str(LANG_SYSFONT_EQUALIZER_BAND_CUTOFF));
600 screens[SCREEN_MAIN].putsxy(2, y, buf);
601 } else {
602 /* Q */
603 setting = &global_settings.eq_band0_q;
604 setting += current_band * 3;
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;
612 snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
613 str(LANG_EQUALIZER_BAND_Q));
615 screens[SCREEN_MAIN].putsxy(2, y, buf);
618 FOR_NB_SCREENS(i) {
619 screens[i].update();
622 button = get_action(CONTEXT_SETTINGS_EQ,TIMEOUT_BLOCK);
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;
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;
641 case ACTION_SETTINGS_INCBIGSTEP:
642 *(setting) += fast_step;
643 has_changed = true;
644 if (*(setting) > max)
645 *(setting) = max;
646 break;
648 case ACTION_SETTINGS_DECBIGSTEP:
649 *(setting) -= fast_step;
650 has_changed = true;
651 if (*(setting) < min)
652 *(setting) = min;
653 break;
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;
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;
669 case ACTION_STD_OK:
670 mode++;
671 if (mode > Q)
672 mode = GAIN; /* wrap around */
673 break;
675 case ACTION_STD_CANCEL:
676 exit_request = true;
677 result = false;
678 break;
680 default:
681 if(default_event_handler(button) == SYS_USB_CONNECTED) {
682 exit_request = true;
683 result = true;
685 break;
688 /* Update the filter if the user changed something */
689 if (has_changed) {
690 dsp_set_eq_coefs(current_band);
691 has_changed = false;
695 action_signalscreenchange();
696 /* Reset screen settings */
697 FOR_NB_SCREENS(i) {
698 screens[i].setfont(FONT_UI);
699 screens[i].clear_display();
701 return result;
704 /* Preset saver.
705 * TODO: Can the settings system be used to do this instead?
707 static bool eq_save_preset(void)
709 int fd, i;
710 char filename[MAX_PATH];
711 int *setting;
713 create_numbered_filename(filename, EQS_DIR, "eq", ".cfg", 2);
715 /* allow user to modify filename */
716 while (true) {
717 if (!kbd_input(filename, sizeof filename)) {
718 fd = creat(filename, O_WRONLY);
719 if (fd < 0)
720 gui_syncsplash(HZ, true, str(LANG_FAILED));
721 else
722 break;
724 else {
725 gui_syncsplash(HZ, true, str(LANG_MENU_SETTING_CANCEL));
726 return false;
730 /* TODO: Should we really do this? */
731 fdprintf(fd, "eq enabled: on\r\n");
732 fdprintf(fd, "eq precut: %d\r\n", global_settings.eq_precut);
734 setting = &global_settings.eq_band0_cutoff;
736 for(i = 0; i < 5; ++i) {
737 fdprintf(fd, "eq band %d cutoff: %d\r\n", i, *setting++);
738 fdprintf(fd, "eq band %d q: %d\r\n", i, *setting++);
739 fdprintf(fd, "eq band %d gain: %d\r\n", i, *setting++);
742 close(fd);
744 gui_syncsplash(HZ, true, str(LANG_SETTINGS_SAVED));
746 return true;
749 /* Allows browsing of preset files */
750 bool eq_browse_presets(void)
752 return rockbox_browse(EQS_DIR, SHOW_CFG);
755 #ifdef HAVE_WM8758
757 /* WM8758 equalizer supports -12 to +12 dB gain in 1 dB increments. */
758 #define EQ_HW_GAIN_STEP 1
759 #define EQ_HW_GAIN_MIN -12
760 #define EQ_HW_GAIN_MAX 12
762 static const struct opt_items BANDWIDTH_NAMES[] = {
763 { STR(LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW) },
764 { STR(LANG_EQUALIZER_HARDWARE_BANDWIDTH_WIDE) },
767 static const int BANDWIDTH_NAMES_SIZE = sizeof(BANDWIDTH_NAMES) /
768 sizeof(*BANDWIDTH_NAMES);
770 static void eq_hw_gain_format(char* buffer, int buffer_size, int value,
771 const char* unit)
773 snprintf(buffer, buffer_size, "%d %s", value, unit);
776 static bool eq_hw_set_band0_cutoff(void)
778 static const struct opt_items names[] = {
779 { (unsigned char *)"80 Hz", TALK_ID(80, UNIT_HERTZ) },
780 { (unsigned char *)"105 Hz", TALK_ID(105, UNIT_HERTZ) },
781 { (unsigned char *)"135 Hz", TALK_ID(135, UNIT_HERTZ) },
782 { (unsigned char *)"175 Hz", TALK_ID(175, UNIT_HERTZ) },
785 bool result = set_option(str(LANG_EQUALIZER_BANDWIDTH),
786 &global_settings.eq_hw_band0_cutoff, INT, names,
787 sizeof(names) / sizeof(*names), NULL);
789 #ifndef SIMULATOR
790 wmcodec_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff, 0,
791 global_settings.eq_hw_band0_gain);
792 #endif
794 return result;
797 static bool eq_hw_set_band0_gain(void)
799 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
800 &global_settings.eq_hw_band0_gain, NULL,
801 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
802 eq_hw_gain_format);
804 #ifndef SIMULATOR
805 wmcodec_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff, 0,
806 global_settings.eq_hw_band0_gain);
807 #endif
809 return result;
812 static bool eq_hw_set_band1_center(void)
814 static const struct opt_items names[] = {
815 { (unsigned char *)"230 Hz", TALK_ID(230, UNIT_HERTZ) },
816 { (unsigned char *)"300 Hz", TALK_ID(300, UNIT_HERTZ) },
817 { (unsigned char *)"385 Hz", TALK_ID(385, UNIT_HERTZ) },
818 { (unsigned char *)"500 Hz", TALK_ID(500, UNIT_HERTZ) },
821 bool result = set_option(str(LANG_EQUALIZER_BAND_CENTER),
822 &global_settings.eq_hw_band1_center, INT, names,
823 sizeof(names) / sizeof(*names), NULL);
825 #ifndef SIMULATOR
826 wmcodec_set_equalizer_band(1, global_settings.eq_hw_band1_center,
827 global_settings.eq_hw_band1_bandwidth,
828 global_settings.eq_hw_band1_gain);
829 #endif
831 return result;
834 static bool eq_hw_set_band1_bandwidth(void)
836 bool result = set_option(str(LANG_EQUALIZER_BANDWIDTH),
837 &global_settings.eq_hw_band1_bandwidth, INT, BANDWIDTH_NAMES,
838 BANDWIDTH_NAMES_SIZE, NULL);
840 #ifndef SIMULATOR
841 wmcodec_set_equalizer_band(1, global_settings.eq_hw_band1_center,
842 global_settings.eq_hw_band1_bandwidth,
843 global_settings.eq_hw_band1_gain);
844 #endif
846 return result;
849 static bool eq_hw_set_band1_gain(void)
851 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
852 &global_settings.eq_hw_band1_gain, NULL,
853 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
854 eq_hw_gain_format);
856 #ifndef SIMULATOR
857 wmcodec_set_equalizer_band(1, global_settings.eq_hw_band1_center,
858 global_settings.eq_hw_band1_bandwidth,
859 global_settings.eq_hw_band1_gain);
860 #endif
862 return result;
865 static bool eq_hw_set_band2_center(void)
867 static const struct opt_items names[] = {
868 { (unsigned char *)"650 Hz", TALK_ID(650, UNIT_HERTZ) },
869 { (unsigned char *)"850 Hz", TALK_ID(850, UNIT_HERTZ) },
870 { (unsigned char *)"1.1 kHz", TALK_ID(1100, UNIT_HERTZ) },
871 { (unsigned char *)"1.4 kHz", TALK_ID(1400, UNIT_HERTZ) },
874 bool result = set_option(str(LANG_EQUALIZER_BAND_CENTER),
875 &global_settings.eq_hw_band2_center, INT, names,
876 sizeof(names) / sizeof(*names), NULL);
878 #ifndef SIMULATOR
879 wmcodec_set_equalizer_band(2, global_settings.eq_hw_band2_center,
880 global_settings.eq_hw_band2_bandwidth,
881 global_settings.eq_hw_band2_gain);
882 #endif
884 return result;
887 static bool eq_hw_set_band2_bandwidth(void)
889 bool result = set_option(str(LANG_EQUALIZER_BANDWIDTH),
890 &global_settings.eq_hw_band2_bandwidth, INT, BANDWIDTH_NAMES,
891 BANDWIDTH_NAMES_SIZE, NULL);
893 #ifndef SIMULATOR
894 wmcodec_set_equalizer_band(2, global_settings.eq_hw_band2_center,
895 global_settings.eq_hw_band2_bandwidth,
896 global_settings.eq_hw_band2_gain);
897 #endif
899 return result;
902 static bool eq_hw_set_band2_gain(void)
904 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
905 &global_settings.eq_hw_band2_gain, NULL,
906 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
907 eq_hw_gain_format);
909 #ifndef SIMULATOR
910 wmcodec_set_equalizer_band(2, global_settings.eq_hw_band2_center,
911 global_settings.eq_hw_band2_bandwidth,
912 global_settings.eq_hw_band2_gain);
913 #endif
915 return result;
918 static bool eq_hw_set_band3_center(void)
920 static const struct opt_items names[] = {
921 { (unsigned char *)"1.8 kHz", TALK_ID(1800, UNIT_HERTZ) },
922 { (unsigned char *)"2.4 kHz", TALK_ID(2400, UNIT_HERTZ) },
923 { (unsigned char *)"3.2 kHz", TALK_ID(3200, UNIT_HERTZ) },
924 { (unsigned char *)"4.1 kHz", TALK_ID(4100, UNIT_HERTZ) },
927 bool result = set_option(str(LANG_EQUALIZER_BAND_CENTER),
928 &global_settings.eq_hw_band3_center, INT, names,
929 sizeof(names) / sizeof(*names), NULL);
931 #ifndef SIMULATOR
932 wmcodec_set_equalizer_band(3, global_settings.eq_hw_band3_center,
933 global_settings.eq_hw_band3_bandwidth,
934 global_settings.eq_hw_band3_gain);
935 #endif
937 return result;
940 static bool eq_hw_set_band3_bandwidth(void)
942 bool result = set_option(str(LANG_EQUALIZER_BANDWIDTH),
943 &global_settings.eq_hw_band3_bandwidth, INT, BANDWIDTH_NAMES,
944 BANDWIDTH_NAMES_SIZE, NULL);
946 #ifndef SIMULATOR
947 wmcodec_set_equalizer_band(3, global_settings.eq_hw_band3_center,
948 global_settings.eq_hw_band3_bandwidth,
949 global_settings.eq_hw_band3_gain);
950 #endif
952 return result;
955 static bool eq_hw_set_band3_gain(void)
957 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
958 &global_settings.eq_hw_band3_gain, NULL,
959 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
960 eq_hw_gain_format);
962 #ifndef SIMULATOR
963 wmcodec_set_equalizer_band(3, global_settings.eq_hw_band3_center,
964 global_settings.eq_hw_band3_bandwidth,
965 global_settings.eq_hw_band3_gain);
966 #endif
968 return result;
971 static bool eq_hw_set_band4_cutoff(void)
973 static const struct opt_items names[] = {
974 { (unsigned char *)"5.3 kHz", TALK_ID(5300, UNIT_HERTZ) },
975 { (unsigned char *)"6.9 kHz", TALK_ID(6900, UNIT_HERTZ) },
976 { (unsigned char *)"9.0 kHz", TALK_ID(9000, UNIT_HERTZ) },
977 { (unsigned char *)"11.7 kHz", TALK_ID(11700, UNIT_HERTZ) },
980 bool result = set_option(str(LANG_EQUALIZER_BAND_CUTOFF),
981 &global_settings.eq_hw_band4_cutoff, INT, names,
982 sizeof(names) / sizeof(*names), NULL);
984 #ifndef SIMULATOR
985 wmcodec_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff, 0,
986 global_settings.eq_hw_band4_gain);
987 #endif
989 return result;
992 static bool eq_hw_set_band4_gain(void)
994 bool result = set_int(str(LANG_EQUALIZER_BAND_GAIN), str(LANG_UNIT_DB), UNIT_DB,
995 &global_settings.eq_hw_band4_gain, NULL,
996 EQ_HW_GAIN_STEP, EQ_HW_GAIN_MIN, EQ_HW_GAIN_MAX,
997 eq_hw_gain_format);
999 #ifndef SIMULATOR
1000 wmcodec_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff, 0,
1001 global_settings.eq_hw_band4_gain);
1002 #endif
1004 return result;
1007 void eq_hw_enable(bool enable)
1009 #ifdef SIMULATOR
1010 (void) enable;
1011 #else
1012 if (enable) {
1013 wmcodec_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff,
1014 0, global_settings.eq_hw_band0_gain);
1015 wmcodec_set_equalizer_band(1, global_settings.eq_hw_band1_center,
1016 global_settings.eq_hw_band1_bandwidth,
1017 global_settings.eq_hw_band1_gain);
1018 wmcodec_set_equalizer_band(2, global_settings.eq_hw_band2_center,
1019 global_settings.eq_hw_band2_bandwidth,
1020 global_settings.eq_hw_band2_gain);
1021 wmcodec_set_equalizer_band(3, global_settings.eq_hw_band3_center,
1022 global_settings.eq_hw_band3_bandwidth,
1023 global_settings.eq_hw_band3_gain);
1024 wmcodec_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff,
1025 0, global_settings.eq_hw_band4_gain);
1026 } else {
1027 wmcodec_set_equalizer_band(0, global_settings.eq_hw_band0_cutoff, 0, 0);
1028 wmcodec_set_equalizer_band(1, global_settings.eq_hw_band1_center,
1029 global_settings.eq_hw_band1_bandwidth, 0);
1030 wmcodec_set_equalizer_band(2, global_settings.eq_hw_band2_center,
1031 global_settings.eq_hw_band2_bandwidth, 0);
1032 wmcodec_set_equalizer_band(3, global_settings.eq_hw_band3_center,
1033 global_settings.eq_hw_band3_bandwidth, 0);
1034 wmcodec_set_equalizer_band(4, global_settings.eq_hw_band4_cutoff, 0, 0);
1036 #endif
1039 static bool eq_hw_enabled(void)
1041 bool result = set_bool(str(LANG_EQUALIZER_HARDWARE_ENABLED),
1042 &global_settings.eq_hw_enabled);
1044 eq_hw_enable(global_settings.eq_hw_enabled);
1046 return result;
1049 static bool eq_hw_set_band0(void)
1051 int m;
1052 bool result;
1053 static const struct menu_item items[] = {
1054 { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_hw_set_band0_cutoff },
1055 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band0_gain },
1058 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1059 NULL, NULL, NULL);
1060 result = menu_run(m);
1061 menu_exit(m);
1063 return result;
1066 static bool eq_hw_set_band1(void)
1068 int m;
1069 bool result;
1070 static const struct menu_item items[] = {
1071 { ID2P(LANG_EQUALIZER_BAND_CENTER), eq_hw_set_band1_center },
1072 { ID2P(LANG_EQUALIZER_BANDWIDTH), eq_hw_set_band1_bandwidth },
1073 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band1_gain },
1076 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1077 NULL, NULL, NULL);
1078 result = menu_run(m);
1079 menu_exit(m);
1081 return result;
1084 static bool eq_hw_set_band2(void)
1086 int m;
1087 bool result;
1088 static const struct menu_item items[] = {
1089 { ID2P(LANG_EQUALIZER_BAND_CENTER), eq_hw_set_band2_center },
1090 { ID2P(LANG_EQUALIZER_BANDWIDTH), eq_hw_set_band2_bandwidth },
1091 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band2_gain },
1094 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1095 NULL, NULL, NULL);
1096 result = menu_run(m);
1097 menu_exit(m);
1099 return result;
1102 static bool eq_hw_set_band3(void)
1104 int m;
1105 bool result;
1106 static const struct menu_item items[] = {
1107 { ID2P(LANG_EQUALIZER_BAND_CENTER), eq_hw_set_band3_center },
1108 { ID2P(LANG_EQUALIZER_BANDWIDTH), eq_hw_set_band3_bandwidth },
1109 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band3_gain },
1112 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1113 NULL, NULL, NULL);
1114 result = menu_run(m);
1115 menu_exit(m);
1117 return result;
1120 static bool eq_hw_set_band4(void)
1122 int m;
1123 bool result;
1124 static const struct menu_item items[] = {
1125 { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_hw_set_band4_cutoff },
1126 { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_hw_set_band4_gain },
1129 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1130 NULL, NULL, NULL);
1131 result = menu_run(m);
1132 menu_exit(m);
1134 return result;
1137 bool eq_hw_menu(void)
1139 int m;
1140 bool result;
1141 static const struct menu_item items[] = {
1142 { ID2P(LANG_EQUALIZER_HARDWARE_ENABLED), eq_hw_enabled },
1143 { ID2P(LANG_EQUALIZER_BAND_LOW_SHELF), eq_hw_set_band0 },
1144 { "Peak Filter 1", eq_hw_set_band1 },
1145 { "Peak Filter 2", eq_hw_set_band2 },
1146 { "Peak Filter 3", eq_hw_set_band3 },
1147 { ID2P(LANG_EQUALIZER_BAND_HIGH_SHELF), eq_hw_set_band4 },
1150 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1151 NULL, NULL, NULL);
1152 result = menu_run(m);
1153 menu_exit(m);
1155 return result;
1157 #endif
1159 /* Full equalizer menu */
1160 bool eq_menu(void)
1162 int m;
1163 bool result;
1164 static const struct menu_item items[] = {
1165 { ID2P(LANG_EQUALIZER_ENABLED), eq_enabled },
1166 { ID2P(LANG_EQUALIZER_GRAPHICAL), eq_menu_graphical },
1167 { ID2P(LANG_EQUALIZER_PRECUT), eq_precut },
1168 { ID2P(LANG_EQUALIZER_GAIN), eq_gain_menu },
1169 { ID2P(LANG_EQUALIZER_ADVANCED), eq_advanced_menu },
1170 { ID2P(LANG_EQUALIZER_SAVE), eq_save_preset },
1171 { ID2P(LANG_EQUALIZER_BROWSE), eq_browse_presets },
1174 m = menu_init( items, sizeof(items) / sizeof(*items), NULL,
1175 NULL, NULL, NULL);
1176 result = menu_run(m);
1177 menu_exit(m);
1179 return result;