diff options
author | Dan Everton <dan@iocaine.org> | 2006-02-07 14:07:46 +0000 |
---|---|---|
committer | Dan Everton <dan@iocaine.org> | 2006-02-07 14:07:46 +0000 |
commit | 88abdd97b25eb458466a84f614a518b7173265a8 (patch) | |
tree | 4a70e3d0d829125e458c80fb21ccf82c77733e36 /apps/eq_menu.c | |
parent | 27f69db40494ca63887fce941dfe02dbd5f24d5b (diff) | |
download | rockbox-88abdd97b25eb458466a84f614a518b7173265a8.tar.gz rockbox-88abdd97b25eb458466a84f614a518b7173265a8.zip |
Add Equalizer configuration to Sound Settings menu.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8606 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/eq_menu.c')
-rw-r--r-- | apps/eq_menu.c | 678 |
1 files changed, 678 insertions, 0 deletions
diff --git a/apps/eq_menu.c b/apps/eq_menu.c new file mode 100644 index 0000000000..0e3355fcd9 --- /dev/null +++ b/apps/eq_menu.c | |||
@@ -0,0 +1,678 @@ | |||
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 "button.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 "widgets.h" | ||
37 | #include "lang.h" | ||
38 | #include "sprintf.h" | ||
39 | #include "talk.h" | ||
40 | #include "misc.h" | ||
41 | #include "sound.h" | ||
42 | #include "splash.h" | ||
43 | #include "dsp.h" | ||
44 | #include "tree.h" | ||
45 | #include "talk.h" | ||
46 | #include "screen_access.h" | ||
47 | #include "keyboard.h" | ||
48 | |||
49 | /* Key definitions */ | ||
50 | #if (CONFIG_KEYPAD == IRIVER_H100_PAD || \ | ||
51 | CONFIG_KEYPAD == IRIVER_H300_PAD) | ||
52 | |||
53 | #define EQ_BTN_NEXT_BAND BUTTON_DOWN | ||
54 | #define EQ_BTN_PREV_BAND BUTTON_UP | ||
55 | #define EQ_BTN_CHANGE_MODE BUTTON_SELECT | ||
56 | #define EQ_BTN_EXIT BUTTON_OFF | ||
57 | |||
58 | #elif (CONFIG_KEYPAD == IPOD_4G_PAD) | ||
59 | |||
60 | #define EQ_BTN_NEXT_BAND BUTTON_SCROLL_FWD | ||
61 | #define EQ_BTN_PREV_BAND BUTTON_SCROLL_BACK | ||
62 | #define EQ_BTN_CHANGE_MODE BUTTON_SELECT | ||
63 | #define EQ_BTN_EXIT BUTTON_MENU | ||
64 | |||
65 | #endif | ||
66 | |||
67 | |||
68 | #define EQ_CUTOFF_MIN 20 | ||
69 | #define EQ_CUTOFF_MAX 22040 | ||
70 | #define EQ_CUTOFF_STEP 10 | ||
71 | #define EQ_GAIN_MIN (-240) | ||
72 | #define EQ_GAIN_MAX 240 | ||
73 | #define EQ_GAIN_STEP 1 | ||
74 | #define EQ_Q_MIN 5 | ||
75 | #define EQ_Q_MAX 64 | ||
76 | #define EQ_Q_STEP 1 | ||
77 | |||
78 | #define EQ_USER_DIVISOR 10 | ||
79 | |||
80 | static bool eq_enabled(void) | ||
81 | { | ||
82 | bool result = set_bool(str(LANG_EQUALIZER_ENABLED), | ||
83 | &global_settings.eq_enabled); | ||
84 | |||
85 | dsp_eq_update_data(global_settings.eq_enabled); | ||
86 | |||
87 | return result; | ||
88 | } | ||
89 | |||
90 | static void eq_gain_format(char* buffer, int buffer_size, int value, const char* unit) | ||
91 | { | ||
92 | int v = abs(value); | ||
93 | |||
94 | snprintf(buffer, buffer_size, "%s%d.%d %s", value < 0 ? "-" : "", | ||
95 | v / EQ_USER_DIVISOR, v % EQ_USER_DIVISOR, unit); | ||
96 | } | ||
97 | |||
98 | static void eq_q_format(char* buffer, int buffer_size, int value, const char* unit) | ||
99 | { | ||
100 | snprintf(buffer, buffer_size, "%d.%d %s", value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit); | ||
101 | } | ||
102 | |||
103 | /* Possibly dodgy way of simplifying the code a bit. */ | ||
104 | #define eq_make_gain_label(buf, bufsize, frequency) snprintf((buf), \ | ||
105 | (bufsize), str(LANG_EQUALIZER_GAIN_ITEM), (frequency)) | ||
106 | |||
107 | #define eq_set_cutoff(band) \ | ||
108 | static bool eq_set_band ## band ## _cutoff(void) \ | ||
109 | { \ | ||
110 | bool result = set_int(str(LANG_EQUALIZER_BAND_CUTOFF), "Hertz", UNIT_HERTZ, \ | ||
111 | &global_settings.eq_band ## band ## _cutoff, NULL, \ | ||
112 | EQ_CUTOFF_STEP, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, NULL); \ | ||
113 | dsp_eq_update_data(global_settings.eq_enabled); \ | ||
114 | return result; \ | ||
115 | } | ||
116 | |||
117 | #define eq_set_q(band) \ | ||
118 | static bool eq_set_band ## band ## _q(void) \ | ||
119 | { \ | ||
120 | bool result = set_int(str(LANG_EQUALIZER_BAND_Q), "Q", UNIT_INT, \ | ||
121 | &global_settings.eq_band ## band ## _q, NULL, \ | ||
122 | EQ_Q_STEP, EQ_Q_MIN, EQ_Q_MAX, eq_q_format); \ | ||
123 | dsp_eq_update_data(global_settings.eq_enabled); \ | ||
124 | return result; \ | ||
125 | } | ||
126 | |||
127 | #define eq_set_gain(band) \ | ||
128 | static bool eq_set_band ## band ## _gain(void) \ | ||
129 | { \ | ||
130 | bool result = set_int("Band " #band, str(LANG_UNIT_DB), UNIT_DB, \ | ||
131 | &global_settings.eq_band ## band ## _gain, NULL, \ | ||
132 | EQ_GAIN_STEP, EQ_GAIN_MIN, EQ_GAIN_MAX, eq_gain_format); \ | ||
133 | dsp_eq_update_data(global_settings.eq_enabled); \ | ||
134 | return result; \ | ||
135 | } | ||
136 | |||
137 | eq_set_cutoff(0); | ||
138 | eq_set_cutoff(1); | ||
139 | eq_set_cutoff(2); | ||
140 | eq_set_cutoff(3); | ||
141 | eq_set_cutoff(4); | ||
142 | |||
143 | eq_set_q(0); | ||
144 | eq_set_q(1); | ||
145 | eq_set_q(2); | ||
146 | eq_set_q(3); | ||
147 | eq_set_q(4); | ||
148 | |||
149 | eq_set_gain(0); | ||
150 | eq_set_gain(1); | ||
151 | eq_set_gain(2); | ||
152 | eq_set_gain(3); | ||
153 | eq_set_gain(4); | ||
154 | |||
155 | static bool eq_gain_menu(void) | ||
156 | { | ||
157 | int m, i; | ||
158 | int *setting; | ||
159 | bool result; | ||
160 | char gain_label[5][24]; | ||
161 | static struct menu_item items[5] = { | ||
162 | { NULL, eq_set_band0_gain }, | ||
163 | { NULL, eq_set_band1_gain }, | ||
164 | { NULL, eq_set_band2_gain }, | ||
165 | { NULL, eq_set_band3_gain }, | ||
166 | { NULL, eq_set_band4_gain }, | ||
167 | }; | ||
168 | |||
169 | setting = &global_settings.eq_band0_cutoff; | ||
170 | |||
171 | /* Construct menu labels */ | ||
172 | for(i = 0; i < 5; i++) { | ||
173 | eq_make_gain_label(gain_label[i], sizeof(gain_label[i]), | ||
174 | *setting); | ||
175 | items[i].desc = gain_label[i]; | ||
176 | |||
177 | /* Skip to next band */ | ||
178 | setting += 3; | ||
179 | } | ||
180 | |||
181 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
182 | NULL, NULL, NULL); | ||
183 | result = menu_run(m); | ||
184 | menu_exit(m); | ||
185 | |||
186 | return result; | ||
187 | } | ||
188 | |||
189 | static bool eq_set_band0(void) | ||
190 | { | ||
191 | int m; | ||
192 | bool result; | ||
193 | static const struct menu_item items[] = { | ||
194 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band0_cutoff }, | ||
195 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band0_q }, | ||
196 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band0_gain }, | ||
197 | }; | ||
198 | |||
199 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
200 | NULL, NULL, NULL); | ||
201 | result = menu_run(m); | ||
202 | menu_exit(m); | ||
203 | |||
204 | return result; | ||
205 | } | ||
206 | |||
207 | static bool eq_set_band1(void) | ||
208 | { | ||
209 | int m; | ||
210 | bool result; | ||
211 | static const struct menu_item items[] = { | ||
212 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band1_cutoff }, | ||
213 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band1_q }, | ||
214 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band1_gain }, | ||
215 | }; | ||
216 | |||
217 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
218 | NULL, NULL, NULL); | ||
219 | result = menu_run(m); | ||
220 | menu_exit(m); | ||
221 | |||
222 | return result; | ||
223 | } | ||
224 | |||
225 | static bool eq_set_band2(void) | ||
226 | { | ||
227 | int m; | ||
228 | bool result; | ||
229 | static const struct menu_item items[] = { | ||
230 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band2_cutoff }, | ||
231 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band2_q }, | ||
232 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band2_gain }, | ||
233 | }; | ||
234 | |||
235 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
236 | NULL, NULL, NULL); | ||
237 | result = menu_run(m); | ||
238 | menu_exit(m); | ||
239 | |||
240 | return result; | ||
241 | } | ||
242 | |||
243 | static bool eq_set_band3(void) | ||
244 | { | ||
245 | int m; | ||
246 | bool result; | ||
247 | static const struct menu_item items[] = { | ||
248 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band3_cutoff }, | ||
249 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band3_q }, | ||
250 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band3_gain }, | ||
251 | }; | ||
252 | |||
253 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
254 | NULL, NULL, NULL); | ||
255 | result = menu_run(m); | ||
256 | menu_exit(m); | ||
257 | |||
258 | return result; | ||
259 | } | ||
260 | |||
261 | static bool eq_set_band4(void) | ||
262 | { | ||
263 | int m; | ||
264 | bool result; | ||
265 | static const struct menu_item items[] = { | ||
266 | { ID2P(LANG_EQUALIZER_BAND_CUTOFF), eq_set_band4_cutoff }, | ||
267 | { ID2P(LANG_EQUALIZER_BAND_Q), eq_set_band4_q }, | ||
268 | { ID2P(LANG_EQUALIZER_BAND_GAIN), eq_set_band4_gain }, | ||
269 | }; | ||
270 | |||
271 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
272 | NULL, NULL, NULL); | ||
273 | result = menu_run(m); | ||
274 | menu_exit(m); | ||
275 | |||
276 | return result; | ||
277 | } | ||
278 | |||
279 | static bool eq_advanced_menu(void) | ||
280 | { | ||
281 | int m, i; | ||
282 | bool result; | ||
283 | char peak_band_label[3][32]; | ||
284 | static struct menu_item items[] = { | ||
285 | { ID2P(LANG_EQUALIZER_BAND_LOW_SHELF), eq_set_band0 }, | ||
286 | { NULL, eq_set_band1 }, | ||
287 | { NULL, eq_set_band2 }, | ||
288 | { NULL, eq_set_band3 }, | ||
289 | { ID2P(LANG_EQUALIZER_BAND_HIGH_SHELF), eq_set_band4 }, | ||
290 | }; | ||
291 | |||
292 | /* Construct menu labels */ | ||
293 | for(i = 1; i < 4; i++) { | ||
294 | snprintf(peak_band_label[i-1], sizeof(peak_band_label[i-1]), | ||
295 | str(LANG_EQUALIZER_BAND_PEAK), i); | ||
296 | items[i].desc = peak_band_label[i-1]; | ||
297 | } | ||
298 | |||
299 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
300 | NULL, NULL, NULL); | ||
301 | result = menu_run(m); | ||
302 | menu_exit(m); | ||
303 | |||
304 | return result; | ||
305 | } | ||
306 | |||
307 | #define SLIDER_KNOB_HEIGHT 6 | ||
308 | #define SLIDER_KNOB_WIDTH 4 | ||
309 | |||
310 | enum eq_slider_mode { | ||
311 | GAIN, | ||
312 | CUTOFF, | ||
313 | Q, | ||
314 | }; | ||
315 | |||
316 | enum eq_type { | ||
317 | LOW_SHELF, | ||
318 | PEAK, | ||
319 | HIGH_SHELF | ||
320 | }; | ||
321 | |||
322 | /* Draw a slider */ | ||
323 | static void draw_slider(const struct screen * screen, int x, int y, | ||
324 | int width, int steps, int current_step) | ||
325 | { | ||
326 | |||
327 | int knob_x = (width / steps) * current_step + (SLIDER_KNOB_WIDTH / 2); | ||
328 | |||
329 | /* Draw groove */ | ||
330 | screen->fillrect(x, y + 2, width, 2); | ||
331 | |||
332 | /* Draw knob */ | ||
333 | screen->fillrect(x + knob_x, y, SLIDER_KNOB_WIDTH, SLIDER_KNOB_HEIGHT); | ||
334 | } | ||
335 | |||
336 | /* Draw the UI for a whole EQ band */ | ||
337 | static int draw_eq_slider(const struct screen * screen, int x, int y, | ||
338 | int width, int cutoff, int q, int gain, bool selected, | ||
339 | enum eq_slider_mode mode, enum eq_type type) | ||
340 | { | ||
341 | char buf[26]; | ||
342 | const char separator[2] = " "; | ||
343 | int steps = (abs(EQ_GAIN_MIN) + abs(EQ_GAIN_MAX)) / EQ_USER_DIVISOR; | ||
344 | int abs_q = abs(q); | ||
345 | int abs_gain = abs(gain); | ||
346 | int current_x, total_height, separator_width, separator_height; | ||
347 | int w, h; | ||
348 | |||
349 | /* Start two pixels in, one for border, one for margin */ | ||
350 | current_x = x + 2; | ||
351 | |||
352 | /* Figure out how large our separator string is */ | ||
353 | screen->getstringsize(separator, &separator_width, &separator_height); | ||
354 | |||
355 | /* Total height includes margins, text, and line selector */ | ||
356 | total_height = separator_height + SLIDER_KNOB_HEIGHT + 2 + 3; | ||
357 | |||
358 | /* Print out the band label */ | ||
359 | if (type == LOW_SHELF) { | ||
360 | screen->putsxy(current_x, y + 2, "LS:"); | ||
361 | screen->getstringsize("LS:", &w, &h); | ||
362 | } else if (type == HIGH_SHELF) { | ||
363 | screen->putsxy(current_x, y + 2, "HS:"); | ||
364 | screen->getstringsize("HS:", &w, &h); | ||
365 | } else { | ||
366 | screen->putsxy(current_x, y + 2, "PK:"); | ||
367 | screen->getstringsize("PK:", &w, &h); | ||
368 | } | ||
369 | current_x += w; | ||
370 | |||
371 | /* Print separator */ | ||
372 | screen->set_drawmode(DRMODE_SOLID); | ||
373 | screen->putsxy(current_x, y + 2, separator); | ||
374 | current_x += separator_width; | ||
375 | |||
376 | /* Print out gain part of status line */ | ||
377 | snprintf(buf, sizeof(buf), "%s%2d.%ddB", gain < 0 ? "-" : " ", | ||
378 | abs_gain / EQ_USER_DIVISOR, abs_gain % EQ_USER_DIVISOR); | ||
379 | |||
380 | if (mode == GAIN && selected) | ||
381 | screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); | ||
382 | |||
383 | screen->putsxy(current_x, y + 2, buf); | ||
384 | screen->getstringsize(buf, &w, &h); | ||
385 | current_x += w; | ||
386 | |||
387 | /* Print separator */ | ||
388 | screen->set_drawmode(DRMODE_SOLID); | ||
389 | screen->putsxy(current_x, y + 2, separator); | ||
390 | current_x += separator_width; | ||
391 | |||
392 | /* Print out cutoff part of status line */ | ||
393 | snprintf(buf, sizeof(buf), "%5dHz", cutoff); | ||
394 | |||
395 | if (mode == CUTOFF && selected) | ||
396 | screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); | ||
397 | |||
398 | screen->putsxy(current_x, y + 2, buf); | ||
399 | screen->getstringsize(buf, &w, &h); | ||
400 | current_x += w; | ||
401 | |||
402 | /* Print separator */ | ||
403 | screen->set_drawmode(DRMODE_SOLID); | ||
404 | screen->putsxy(current_x, y + 2, separator); | ||
405 | current_x += separator_width; | ||
406 | |||
407 | /* Print out Q part of status line */ | ||
408 | snprintf(buf, sizeof(buf), "%d.%d Q", abs_q / EQ_USER_DIVISOR, | ||
409 | abs_q % EQ_USER_DIVISOR); | ||
410 | |||
411 | if (mode == Q && selected) | ||
412 | screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); | ||
413 | |||
414 | screen->putsxy(current_x, y + 2, buf); | ||
415 | screen->getstringsize(buf, &w, &h); | ||
416 | current_x += w; | ||
417 | |||
418 | screen->set_drawmode(DRMODE_SOLID); | ||
419 | |||
420 | /* Draw selection box */ | ||
421 | if (selected) { | ||
422 | screen->drawrect(x, y, width, total_height); | ||
423 | } | ||
424 | |||
425 | /* Draw horizontal slider */ | ||
426 | draw_slider(screen, x + 3, y + h + 3, width - 6, steps, | ||
427 | (EQ_GAIN_MAX + gain) / EQ_USER_DIVISOR); | ||
428 | |||
429 | return total_height; | ||
430 | } | ||
431 | |||
432 | /* Draw's all the EQ sliders. Returns the total height of the sliders drawn */ | ||
433 | static int draw_eq_sliders(int current_band, enum eq_slider_mode mode) | ||
434 | { | ||
435 | int i, gain, q, cutoff; | ||
436 | int height = 2; /* Two pixel margin */ | ||
437 | int slider_width = screens[SCREEN_MAIN].width - 4; /* two pixel margin on each side */ | ||
438 | int *setting = &global_settings.eq_band0_cutoff; | ||
439 | enum eq_type type; | ||
440 | |||
441 | for( i = 0; i < 5; ++i) | ||
442 | { | ||
443 | cutoff = *setting++; | ||
444 | q = *setting++; | ||
445 | gain = *setting++; | ||
446 | |||
447 | if (i == 0) { | ||
448 | type = LOW_SHELF; | ||
449 | } else if (i == 4) { | ||
450 | type = HIGH_SHELF; | ||
451 | } else { | ||
452 | type = PEAK; | ||
453 | } | ||
454 | |||
455 | height += draw_eq_slider(&(screens[SCREEN_MAIN]), 2, height, | ||
456 | slider_width, cutoff, q, gain, i == current_band, mode, type); | ||
457 | |||
458 | /* add a margin */ | ||
459 | height += 2; | ||
460 | } | ||
461 | |||
462 | return height; | ||
463 | } | ||
464 | |||
465 | /* Provides a graphical means of editing the EQ settings */ | ||
466 | bool eq_menu_graphical(void) | ||
467 | { | ||
468 | bool exit_request = false; | ||
469 | bool result = true; | ||
470 | bool has_changed = false; | ||
471 | int button; | ||
472 | int *setting; | ||
473 | int current_band, y, step, min, max, voice_unit; | ||
474 | enum eq_slider_mode mode; | ||
475 | enum eq_type current_type; | ||
476 | char buf[24]; | ||
477 | |||
478 | screens[SCREEN_MAIN].setfont(FONT_SYSFIXED); | ||
479 | screens[SCREEN_MAIN].clear_display(); | ||
480 | |||
481 | /* Start off editing gain on the first band */ | ||
482 | mode = GAIN; | ||
483 | current_type = LOW_SHELF; | ||
484 | current_band = 0; | ||
485 | |||
486 | while (!exit_request) { | ||
487 | /* Clear the screen. The drawing routines expect this */ | ||
488 | screens[SCREEN_MAIN].clear_display(); | ||
489 | |||
490 | /* Draw equalizer band details */ | ||
491 | y = draw_eq_sliders(current_band, mode); | ||
492 | |||
493 | /* Set pointer to the band data currently editable */ | ||
494 | if (mode == GAIN) { | ||
495 | /* gain */ | ||
496 | setting = &global_settings.eq_band0_gain; | ||
497 | setting += current_band * 3; | ||
498 | |||
499 | step = EQ_GAIN_STEP; | ||
500 | min = EQ_GAIN_MIN; | ||
501 | max = EQ_GAIN_MAX; | ||
502 | voice_unit = UNIT_DB; | ||
503 | |||
504 | snprintf(buf, sizeof(buf), str(LANG_EQUALIZER_EDIT_MODE), | ||
505 | str(LANG_EQUALIZER_BAND_GAIN)); | ||
506 | |||
507 | screens[SCREEN_MAIN].putsxy(2, y, buf); | ||
508 | } else if (mode == CUTOFF) { | ||
509 | /* cutoff */ | ||
510 | setting = &global_settings.eq_band0_cutoff; | ||
511 | setting += current_band * 3; | ||
512 | |||
513 | step = EQ_CUTOFF_STEP; | ||
514 | min = EQ_CUTOFF_MIN; | ||
515 | max = EQ_CUTOFF_MAX; | ||
516 | voice_unit = UNIT_HERTZ; | ||
517 | |||
518 | snprintf(buf, sizeof(buf), str(LANG_EQUALIZER_EDIT_MODE), | ||
519 | str(LANG_EQUALIZER_BAND_CUTOFF)); | ||
520 | |||
521 | screens[SCREEN_MAIN].putsxy(2, y, buf); | ||
522 | } else { | ||
523 | /* Q */ | ||
524 | setting = &global_settings.eq_band0_q; | ||
525 | setting += current_band * 3; | ||
526 | |||
527 | step = EQ_Q_STEP; | ||
528 | min = EQ_Q_MIN; | ||
529 | max = EQ_Q_MAX; | ||
530 | voice_unit = UNIT_INT; | ||
531 | |||
532 | snprintf(buf, sizeof(buf), str(LANG_EQUALIZER_EDIT_MODE), | ||
533 | str(LANG_EQUALIZER_BAND_Q)); | ||
534 | |||
535 | screens[SCREEN_MAIN].putsxy(2, y, buf); | ||
536 | } | ||
537 | |||
538 | screens[SCREEN_MAIN].update(); | ||
539 | |||
540 | button = button_get_w_tmo(HZ/10); | ||
541 | |||
542 | switch (button) { | ||
543 | case BUTTON_LEFT: | ||
544 | case BUTTON_LEFT | BUTTON_REPEAT: | ||
545 | *(setting) -= step; | ||
546 | has_changed = true; | ||
547 | if (*(setting) < min) | ||
548 | *(setting) = min; | ||
549 | break; | ||
550 | |||
551 | case BUTTON_RIGHT: | ||
552 | case BUTTON_RIGHT | BUTTON_REPEAT: | ||
553 | *(setting) += step; | ||
554 | has_changed = true; | ||
555 | if (*(setting) > max) | ||
556 | *(setting) = max; | ||
557 | break; | ||
558 | |||
559 | case EQ_BTN_PREV_BAND: | ||
560 | case EQ_BTN_PREV_BAND | BUTTON_REPEAT: | ||
561 | current_band--; | ||
562 | if (current_band < 0) | ||
563 | current_band = 4; /* wrap around */ | ||
564 | break; | ||
565 | |||
566 | case EQ_BTN_NEXT_BAND: | ||
567 | case EQ_BTN_NEXT_BAND | BUTTON_REPEAT: | ||
568 | current_band++; | ||
569 | if (current_band > 4) | ||
570 | current_band = 0; /* wrap around */ | ||
571 | break; | ||
572 | |||
573 | case EQ_BTN_CHANGE_MODE: | ||
574 | case EQ_BTN_CHANGE_MODE | BUTTON_REPEAT: | ||
575 | mode++; | ||
576 | if (mode > Q) | ||
577 | mode = GAIN; /* wrap around */ | ||
578 | break; | ||
579 | |||
580 | case EQ_BTN_EXIT: | ||
581 | case EQ_BTN_EXIT | BUTTON_REPEAT: | ||
582 | exit_request = true; | ||
583 | result = false; | ||
584 | break; | ||
585 | |||
586 | default: | ||
587 | if(default_event_handler(button) == SYS_USB_CONNECTED) { | ||
588 | exit_request = true; | ||
589 | result = true; | ||
590 | } | ||
591 | break; | ||
592 | } | ||
593 | |||
594 | /* Update the filter if the user changed something */ | ||
595 | if (has_changed) | ||
596 | dsp_eq_update_data(global_settings.eq_enabled); | ||
597 | } | ||
598 | |||
599 | /* Reset screen settings */ | ||
600 | screens[SCREEN_MAIN].setfont(FONT_UI); | ||
601 | screens[SCREEN_MAIN].clear_display(); | ||
602 | |||
603 | return result; | ||
604 | } | ||
605 | |||
606 | /* Preset saver. | ||
607 | * TODO: Can the settings system be used to do this instead? | ||
608 | */ | ||
609 | static bool eq_save_preset(void) | ||
610 | { | ||
611 | int fd, i; | ||
612 | char filename[MAX_PATH]; | ||
613 | int *setting; | ||
614 | |||
615 | create_numbered_filename(filename, EQS_DIR, "eq", ".cfg", 2); | ||
616 | |||
617 | /* allow user to modify filename */ | ||
618 | while (true) { | ||
619 | if (!kbd_input(filename, sizeof filename)) { | ||
620 | fd = creat(filename,0); | ||
621 | if (fd < 0) | ||
622 | gui_syncsplash(HZ, true, str(LANG_FAILED)); | ||
623 | else | ||
624 | break; | ||
625 | } | ||
626 | else { | ||
627 | gui_syncsplash(HZ, true, str(LANG_RESET_DONE_CANCEL)); | ||
628 | return false; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | /* TODO: Should we really do this? */ | ||
633 | fdprintf(fd, "eq enabled: yes\r\n"); | ||
634 | |||
635 | setting = &global_settings.eq_band0_cutoff; | ||
636 | |||
637 | for(i = 0; i < 5; ++i) { | ||
638 | fdprintf(fd, "eq band %d cutoff: %d\r\n", i, *setting++); | ||
639 | fdprintf(fd, "eq band %d q: %d\r\n", i, *setting++); | ||
640 | fdprintf(fd, "eq band %d gain: %d\r\n", i, *setting++); | ||
641 | } | ||
642 | |||
643 | close(fd); | ||
644 | |||
645 | gui_syncsplash(HZ, true, (unsigned char *)"%s %s", str(LANG_SETTINGS_SAVED1), | ||
646 | str(LANG_SETTINGS_SAVED2)); | ||
647 | |||
648 | return true; | ||
649 | } | ||
650 | |||
651 | /* Allows browsing of preset files */ | ||
652 | bool eq_browse_presets(void) | ||
653 | { | ||
654 | return rockbox_browse(EQS_DIR, SHOW_CFG); | ||
655 | } | ||
656 | |||
657 | /* Full equalizer menu */ | ||
658 | bool eq_menu(void) | ||
659 | { | ||
660 | int m; | ||
661 | bool result; | ||
662 | static const struct menu_item items[] = { | ||
663 | { ID2P(LANG_EQUALIZER_ENABLED), eq_enabled }, | ||
664 | { ID2P(LANG_EQUALIZER_GRAPHICAL), eq_menu_graphical }, | ||
665 | { ID2P(LANG_EQUALIZER_GAIN), eq_gain_menu }, | ||
666 | { ID2P(LANG_EQUALIZER_ADVANCED), eq_advanced_menu }, | ||
667 | { ID2P(LANG_EQUALIZER_SAVE), eq_save_preset }, | ||
668 | { ID2P(LANG_EQUALIZER_BROWSE), eq_browse_presets }, | ||
669 | }; | ||
670 | |||
671 | m=menu_init( items, sizeof(items) / sizeof(*items), NULL, | ||
672 | NULL, NULL, NULL); | ||
673 | result = menu_run(m); | ||
674 | menu_exit(m); | ||
675 | |||
676 | return result; | ||
677 | } | ||
678 | |||