A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Dan Everton
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include <stdio.h>
24#include <stdbool.h>
25#include <string.h>
26#include "eq_menu.h"
27#include "system.h"
28#include "kernel.h"
29#include "lcd.h"
30#include "list.h"
31#include "menu.h"
32#include "action.h"
33#include "settings.h"
34#include "rbpaths.h"
35#include "screens.h"
36#include "icons.h"
37#include "font.h"
38#include "lang.h"
39#include "talk.h"
40#include "misc.h"
41#include "sound.h"
42#include "dsp_proc_settings.h"
43#include "tree.h"
44#include "screen_access.h"
45#include "keyboard.h"
46#include "gui/scrollbar.h"
47#include "menu_common.h"
48#include "viewport.h"
49#include "exported_menus.h"
50#include "pcmbuf.h"
51#include "option_select.h"
52#include "string-extra.h"
53
54static void eq_apply(void);
55
56/*
57 * Utility functions
58 */
59
60const char* eq_q_format(char* buffer, size_t buffer_size, int value, const char* unit)
61{
62 snprintf(buffer, buffer_size, "%d.%d %s", value / EQ_USER_DIVISOR,
63 value % EQ_USER_DIVISOR, unit);
64 return buffer;
65}
66
67const char* eq_precut_format(char* buffer, size_t buffer_size, int value, const char* unit)
68{
69 snprintf(buffer, buffer_size, "%s%d.%d %s", value == 0 ? " " : "-",
70 value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit);
71 return buffer;
72}
73
74void eq_enabled_option_callback(bool enabled)
75{
76 (void)enabled;
77 eq_apply();
78}
79
80/*
81 * Settings functions
82 */
83static void eq_apply(void)
84{
85 dsp_eq_enable(global_settings.eq_enabled);
86 dsp_set_eq_precut(global_settings.eq_precut);
87 /* Update all bands */
88 for(int i = 0; i < EQ_NUM_BANDS; i++) {
89 dsp_set_eq_coefs(i, &global_settings.eq_band_settings[i]);
90 }
91}
92
93static int eq_setting_callback(int action,
94 const struct menu_item_ex *this_item,
95 struct gui_synclist *this_list)
96{
97 (void)this_list;
98 switch (action)
99 {
100 case ACTION_ENTER_MENUITEM:
101 action = lowlatency_callback(action, this_item, NULL);
102 break;
103 case ACTION_EXIT_MENUITEM:
104 eq_apply();
105 action = lowlatency_callback(action, this_item, NULL);
106 break;
107 }
108
109 return action;
110}
111MENUITEM_SETTING(eq_enable, &global_settings.eq_enabled, eq_setting_callback);
112MENUITEM_SETTING(eq_precut, &global_settings.eq_precut, eq_setting_callback);
113
114static char* gainitem_get_name(int selected_item, void *data, char *buffer, size_t len)
115{
116 (void)data;
117 snprintf(buffer, len, str(LANG_EQUALIZER_GAIN_ITEM),
118 global_settings.eq_band_settings[selected_item].cutoff);
119
120 return buffer;
121}
122
123static int gainitem_speak_item(int selected_item, void *data)
124{
125 (void)data;
126 talk_number(global_settings.eq_band_settings[selected_item].cutoff, false);
127 talk_id(LANG_EQUALIZER_GAIN_ITEM, true);
128 return 0;
129}
130
131static enum themable_icons gainitem_get_icon(int selected_item, void * data)
132{
133 (void)selected_item;
134 (void)data;
135
136 return Icon_Menu_functioncall;
137}
138
139static const char* db_format(char* buffer, size_t buffer_size, int value,
140 const char* unit)
141{
142 int v = abs(value);
143
144 snprintf(buffer, buffer_size, "%s%d.%d %s", value < 0 ? "-" : "",
145 v / 10, v % 10, unit);
146 return buffer;
147}
148
149static int32_t get_dec_talkid(int value, int unit)
150{
151 return TALK_ID_DECIMAL(value, 1, unit);
152}
153
154static const struct int_setting gain_int_setting = {
155 .option_callback = NULL,
156 .unit = UNIT_DB,
157 .step = EQ_GAIN_STEP,
158 .min = EQ_GAIN_MIN,
159 .max = EQ_GAIN_MAX,
160 .formatter = db_format,
161 .get_talk_id = get_dec_talkid,
162};
163
164static const struct int_setting q_int_setting = {
165 .option_callback = NULL,
166 .unit = UNIT_INT,
167 .step = EQ_Q_STEP,
168 .min = EQ_Q_MIN,
169 .max = EQ_Q_MAX,
170 .formatter = eq_q_format,
171 .get_talk_id = get_dec_talkid,
172};
173
174static const struct int_setting cutoff_int_setting = {
175 .option_callback = NULL,
176 .unit = UNIT_HERTZ,
177 .step = EQ_CUTOFF_STEP,
178 .min = EQ_CUTOFF_MIN,
179 .max = EQ_CUTOFF_MAX,
180 .formatter = NULL,
181 .get_talk_id = NULL,
182};
183
184static int simplelist_action_callback(int action, struct gui_synclist *lists)
185{
186 (void)lists;
187 if (action == ACTION_STD_OK)
188 return ACTION_STD_CANCEL;
189 return action;
190}
191
192static int eq_do_simple_menu(void * param)
193{
194 (void)param;
195 struct simplelist_info info;
196 struct settings_list setting;
197 char title[MAX_PATH];
198
199 simplelist_info_init(&info, str(LANG_EQUALIZER_GAIN), EQ_NUM_BANDS, NULL);
200 info.get_name = (list_get_name*)gainitem_get_name;
201 info.get_talk = gainitem_speak_item;
202 info.get_icon = gainitem_get_icon;
203 info.action_callback = simplelist_action_callback;
204 info.selection = -1;
205 info.title_icon = Icon_Submenu;
206 setting.flags = F_BANFROMQS|F_INT_SETTING|F_T_INT|F_NO_WRAP;
207 setting.lang_id = LANG_GAIN;
208 setting.default_val.int_ = 0;
209 setting.int_setting = &gain_int_setting;
210
211 while (true)
212 {
213 simplelist_show_list(&info);
214 if (info.selection < 0)
215 break;
216 pcmbuf_set_low_latency(true);
217 setting.setting = &global_settings.eq_band_settings[info.selection].gain;
218 option_screen(&setting, NULL, false,
219 gainitem_get_name(info.selection, NULL, title, MAX_PATH));
220 eq_apply();
221 pcmbuf_set_low_latency(false);
222 }
223 return 0;
224}
225MENUITEM_FUNCTION(gain_menu, 0, ID2P(LANG_EQUALIZER_GAIN),
226 eq_do_simple_menu, NULL, Icon_Submenu);
227
228static void selection_to_banditem(int selection, int expanded_band, int *band, int *item)
229{
230 int diff = selection - expanded_band;
231
232 if (expanded_band < 0 || diff < 0)
233 {
234 *item = 0;
235 *band = selection;
236 }
237 else if (diff < 4)
238 {
239 *item = selection - expanded_band;
240 *band = expanded_band;
241 }
242 else
243 {
244 *item = 0;
245 *band = expanded_band + diff - 3;
246 }
247}
248
249static char *advancedmenu_item_get_name(int selected_item, void *data, char *buffer, size_t len)
250{
251 int band;
252 int item;
253 int lang = -1;
254
255 selection_to_banditem(selected_item, *(intptr_t*)data, &band, &item);
256
257 switch (item)
258 {
259 case 0: /* Band title */
260 if (band == 0)
261 return str(LANG_EQUALIZER_BAND_LOW_SHELF);
262 else if (band == EQ_NUM_BANDS - 1)
263 return str(LANG_EQUALIZER_BAND_HIGH_SHELF);
264 else
265 {
266 snprintf(buffer, len, str(LANG_EQUALIZER_BAND_PEAK), band);
267 return buffer;
268 }
269 break;
270 case 1: /* cutoff */
271 if (band == 0)
272 lang = LANG_EQUALIZER_BAND_CUTOFF;
273 else if (band == EQ_NUM_BANDS - 1)
274 lang = LANG_EQUALIZER_BAND_CUTOFF;
275 else
276 lang = LANG_EQUALIZER_BAND_CENTER;
277 break;
278 case 2: /* Q */
279 lang = LANG_EQUALIZER_BAND_Q;
280 break;
281 case 3: /* Gain */
282 lang = LANG_GAIN;
283 break;
284 }
285
286 if(lang < 0)
287 buffer[0] = 0;
288 else {
289 buffer[0] = '\t';
290 strmemccpy(&buffer[1], str(lang), len - 1);
291 }
292
293 return buffer;
294}
295
296static int advancedmenu_speak_item(int selected_item, void *data)
297{
298 (void)data;
299 int band;
300 int item;
301 int lang = -1;
302
303 selection_to_banditem(selected_item, *(intptr_t*)data, &band, &item);
304
305 switch (item)
306 {
307 case 0: /* Band title */
308 if (band == 0)
309 lang = LANG_EQUALIZER_BAND_LOW_SHELF;
310 else if (band == EQ_NUM_BANDS - 1)
311 lang = LANG_EQUALIZER_BAND_HIGH_SHELF;
312 else
313 {
314 talk_id(LANG_EQUALIZER_BAND_PEAK, false);
315 talk_number(band, true);
316 return -1;
317 }
318 break;
319 case 1: /* cutoff */
320 if (band == 0)
321 lang = LANG_EQUALIZER_BAND_CUTOFF;
322 else if (band == EQ_NUM_BANDS - 1)
323 lang = LANG_EQUALIZER_BAND_CUTOFF;
324 else
325 lang = LANG_EQUALIZER_BAND_CENTER;
326 break;
327 case 2: /* Q */
328 lang = LANG_EQUALIZER_BAND_Q;
329 break;
330 case 3: /* Gain */
331 lang = LANG_GAIN;
332 break;
333 }
334 talk_id(lang, true);
335 return -1;
336}
337
338static enum themable_icons advancedmenu_get_icon(int selected_item, void * data)
339{
340 (void)data;
341 int band;
342 int item;
343
344 selection_to_banditem(selected_item, *(intptr_t*)data, &band, &item);
345
346 if (item == 0)
347 return Icon_Submenu;
348 else
349 return Icon_Menu_setting;
350}
351extern struct eq_band_setting eq_defaults[EQ_NUM_BANDS];
352
353static int eq_do_advanced_menu(void * param)
354{
355 (void)param;
356 struct simplelist_info info;
357 struct settings_list setting;
358 char title[MAX_PATH];
359 int band, item;
360 intptr_t selected_band = -1;
361
362 simplelist_info_init(&info, str(LANG_EQUALIZER_ADVANCED),
363 EQ_NUM_BANDS, &selected_band);
364 info.get_name = (list_get_name*)advancedmenu_item_get_name;
365 info.get_talk = advancedmenu_speak_item;
366 info.get_icon = advancedmenu_get_icon;
367 info.action_callback = simplelist_action_callback;
368 info.selection = -1;
369 info.title_icon = Icon_EQ;
370 setting.flags = F_BANFROMQS|F_INT_SETTING|F_T_INT|F_NO_WRAP;
371
372 while (true)
373 {
374 simplelist_show_list(&info);
375 if (info.selection < 0)
376 break;
377 selection_to_banditem(info.selection, selected_band, &band, &item);
378 switch (item)
379 {
380 case 0: /* title, do nothing */
381 {
382 int extra;
383 if (selected_band == band)
384 {
385 extra = 0;
386 selected_band = -1;
387 }
388 else
389 {
390 extra = 3;
391 selected_band = band;
392 }
393 info.selection = band;
394 info.count = EQ_NUM_BANDS + extra;
395 continue;
396 }
397 case 1: /* cutoff */
398 if (band == 0 || band == EQ_NUM_BANDS - 1)
399 setting.lang_id = LANG_EQUALIZER_BAND_CUTOFF;
400 else
401 setting.lang_id = LANG_EQUALIZER_BAND_CENTER;
402 setting.default_val.int_ = eq_defaults[band].cutoff;
403 setting.int_setting = &cutoff_int_setting;
404 setting.setting = &global_settings.eq_band_settings[band].cutoff;
405 break;
406 case 2: /* Q */
407 setting.lang_id = LANG_EQUALIZER_BAND_Q;
408 setting.default_val.int_ = eq_defaults[band].q;
409 setting.int_setting = &q_int_setting;
410 setting.setting = &global_settings.eq_band_settings[band].q;
411 break;
412 case 3: /* Gain */
413 setting.lang_id = LANG_GAIN;
414 setting.default_val.int_ = eq_defaults[band].gain;
415 setting.int_setting = &gain_int_setting;
416 setting.setting = &global_settings.eq_band_settings[band].gain;
417 break;
418 }
419 pcmbuf_set_low_latency(true);
420 advancedmenu_item_get_name(info.selection, &selected_band, title, MAX_PATH);
421
422 option_screen(&setting, NULL, false, title[0] == '\t' ? &title[1] : title);
423 eq_apply();
424 pcmbuf_set_low_latency(false);
425 }
426 return 0;
427}
428MENUITEM_FUNCTION(advanced_menu, 0, ID2P(LANG_EQUALIZER_ADVANCED),
429 eq_do_advanced_menu, NULL, Icon_EQ);
430
431enum eq_slider_mode {
432 GAIN,
433 CUTOFF,
434 Q,
435};
436
437enum eq_type {
438 LOW_SHELF,
439 PEAK,
440 HIGH_SHELF
441};
442
443/* Size of just the slider/srollbar */
444#define SCROLLBAR_SIZE 6
445
446/* Draw the UI for a whole EQ band */
447static int draw_eq_slider(struct screen * screen, int x, int y,
448 int width, int cutoff, int q, int gain, bool selected,
449 enum eq_slider_mode mode, int band)
450{
451 char buf[26];
452 int steps, min_item, max_item;
453 int abs_gain = abs(gain);
454 int x1, x2, y1, total_height;
455 int w, h;
456
457 switch(mode) {
458 case Q:
459 steps = EQ_Q_MAX - EQ_Q_MIN;
460 min_item = q - EQ_Q_STEP - EQ_Q_MIN;
461 max_item = q + EQ_Q_STEP - EQ_Q_MIN;
462 break;
463 case CUTOFF:
464 steps = EQ_CUTOFF_MAX - EQ_CUTOFF_MIN;
465 min_item = cutoff - EQ_CUTOFF_FAST_STEP * 2;
466 max_item = cutoff + EQ_CUTOFF_FAST_STEP * 2;
467 break;
468 case GAIN:
469 default:
470 steps = EQ_GAIN_MAX - EQ_GAIN_MIN;
471 min_item = abs(EQ_GAIN_MIN) + gain - EQ_GAIN_STEP * 5;
472 max_item = abs(EQ_GAIN_MIN) + gain + EQ_GAIN_STEP * 5;
473 break;
474 }
475
476 /* Start two pixels in, one for border, one for margin */
477 x1 = x + 2;
478 y1 = y + 2;
479
480 /* Print out the band label */
481 if (band == 0) {
482 screen->putsxy(x1, y1, "LS: ");
483 /*screen->getstringsize("LS:", &w, &h); UNUSED*/
484 } else if (band == EQ_NUM_BANDS - 1) {
485 screen->putsxy(x1, y1, "HS: ");
486 /*screen->getstringsize("HS:", &w, &h); UNUSED*/
487 } else {
488 snprintf(buf, sizeof(buf), "PK%d:", band);
489 screen->putsxy(x1, y1, buf);
490 /*screen->getstringsize(buf, &w, &h); UNUSED*/
491 }
492
493 w = screen->getstringsize("A", NULL, &h);
494
495 x1 += 5*w; /* 4 chars for label + 1 space = 5 */
496
497 /* Print out gain part of status line (left justify after label) */
498 if (mode == GAIN && selected)
499 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
500 else
501 screen->set_drawmode(DRMODE_SOLID);
502
503 snprintf(buf, sizeof(buf), "%s%2d.%d%s", gain < 0 ? "-" : " ",
504 abs_gain / EQ_USER_DIVISOR, abs_gain % EQ_USER_DIVISOR,
505 screen->lcdwidth >= 160 ? "dB" : "");
506 screen->putsxy(x1, y1, buf);
507 w = screen->getstringsize(buf, NULL, NULL);
508 x1 += w;
509
510 /* Print out Q part of status line (right justify) */
511 if (mode == Q && selected)
512 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
513 else
514 screen->set_drawmode(DRMODE_SOLID);
515
516 snprintf(buf, sizeof(buf), "%d.%d%s", q / EQ_USER_DIVISOR,
517 q % EQ_USER_DIVISOR, screen->lcdwidth >= 160 ? " Q" : "");
518 w = screen->getstringsize(buf, NULL, NULL);
519 x2 = x + width - w - 2;
520 screen->putsxy(x2, y1, buf);
521
522 /* Print out cutoff part of status line (center between gain & Q) */
523 if (mode == CUTOFF && selected)
524 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
525 else
526 screen->set_drawmode(DRMODE_SOLID);
527
528 snprintf(buf, sizeof(buf), "%5d%s", cutoff,
529 screen->lcdwidth >= 160 ? "Hz" : "");
530 w = screen->getstringsize(buf, NULL, NULL);
531 x1 = x1 + (x2 - x1 - w)/2;
532 screen->putsxy(x1, y1, buf);
533
534 /* Draw selection box */
535 total_height = 3 + h + 1 + SCROLLBAR_SIZE + 3;
536 screen->set_drawmode(DRMODE_SOLID);
537 if (selected) {
538 screen->drawrect(x, y, width, total_height);
539 }
540
541 /* Draw horizontal slider. Reuse scrollbar for this */
542 gui_scrollbar_draw(screen, x + 3, y1 + h + 1, width - 6, SCROLLBAR_SIZE,
543 steps, min_item, max_item, HORIZONTAL);
544
545 return total_height;
546}
547
548/* Draw's all the EQ sliders. Returns the total height of the sliders drawn */
549static void draw_eq_sliders(struct screen * screen, int x, int y,
550 int nb_eq_sliders, int start_item,
551 int current_band, enum eq_slider_mode mode)
552{
553 int height = y;
554
555 start_item = MIN(start_item, EQ_NUM_BANDS - nb_eq_sliders);
556
557 for (int i = 0; i < EQ_NUM_BANDS; i++) {
558 struct eq_band_setting *setting = &global_settings.eq_band_settings[i];
559 int cutoff = setting->cutoff;
560 int q = setting->q;
561 int gain = setting->gain;
562
563 if (i == start_item + nb_eq_sliders)
564 break;
565
566 if (i >= start_item) {
567 height += draw_eq_slider(screen, x, height, screen->lcdwidth - x - 1,
568 cutoff, q, gain, i == current_band, mode,
569 i);
570 /* add a margin */
571 height++;
572 }
573 }
574
575 if (nb_eq_sliders != EQ_NUM_BANDS)
576 gui_scrollbar_draw(screen, 0, y, SCROLLBAR_SIZE - 1,
577 screen->lcdheight - y, EQ_NUM_BANDS,
578 start_item, start_item + nb_eq_sliders,
579 VERTICAL);
580 return;
581}
582
583/* Provides a graphical means of editing the EQ settings */
584int eq_menu_graphical(void)
585{
586 bool exit_request = false;
587 bool result = true;
588 bool has_changed = false;
589 int button;
590 int *setting;
591 int current_band, x, y, step, fast_step, min, max;
592 enum eq_slider_mode mode;
593 int h, height, start_item, nb_eq_sliders[NB_SCREENS];
594 FOR_NB_SCREENS(i)
595 viewportmanager_theme_enable(i, false, NULL);
596
597
598 FOR_NB_SCREENS(i) {
599 screens[i].set_viewport(NULL);
600 screens[i].setfont(FONT_SYSFIXED);
601 screens[i].clear_display();
602
603 /* Figure out how many sliders can be drawn on the screen */
604 h = screens[i].getcharheight();
605
606 /* Total height includes margins (1), text, slider, and line selector (1) */
607 height = 3 + h + 1 + SCROLLBAR_SIZE + 3;
608 nb_eq_sliders[i] = screens[i].lcdheight / height;
609
610 /* Make sure the "Edit Mode" text fits too */
611 height = nb_eq_sliders[i]*height + h + 2;
612 if (height > screens[i].lcdheight)
613 nb_eq_sliders[i]--;
614
615 if (nb_eq_sliders[i] > EQ_NUM_BANDS)
616 nb_eq_sliders[i] = EQ_NUM_BANDS;
617 }
618
619 y = h + 1;
620
621 /* Start off editing gain on the first band */
622 mode = GAIN;
623 current_band = 0;
624
625 while (!exit_request) {
626 FOR_NB_SCREENS(i)
627 {
628 screens[i].clear_display();
629
630 /* Set pointer to the band data currently editable */
631 if (mode == GAIN) {
632 /* gain */
633 setting = &global_settings.eq_band_settings[current_band].gain;
634
635 step = EQ_GAIN_STEP;
636 fast_step = EQ_GAIN_FAST_STEP;
637 min = EQ_GAIN_MIN;
638 max = EQ_GAIN_MAX;
639
640 screens[i].putsxyf(0, 0, str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
641 str(LANG_GAIN), "(dB)");
642 } else if (mode == CUTOFF) {
643 /* cutoff */
644 setting = &global_settings.eq_band_settings[current_band].cutoff;
645
646 step = EQ_CUTOFF_STEP;
647 fast_step = EQ_CUTOFF_FAST_STEP;
648 min = EQ_CUTOFF_MIN;
649 max = EQ_CUTOFF_MAX;
650
651 screens[i].putsxyf(0, 0, str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
652 str(LANG_SYSFONT_EQUALIZER_BAND_CUTOFF), "(Hz)");
653 } else {
654 /* Q */
655 setting = &global_settings.eq_band_settings[current_band].q;
656
657 step = EQ_Q_STEP;
658 fast_step = EQ_Q_FAST_STEP;
659 min = EQ_Q_MIN;
660 max = EQ_Q_MAX;
661
662 screens[i].putsxyf(0, 0, str(LANG_SYSFONT_EQUALIZER_EDIT_MODE),
663 str(LANG_EQUALIZER_BAND_Q), "");
664 }
665
666 /* Draw scrollbar if needed */
667 if (nb_eq_sliders[i] != EQ_NUM_BANDS)
668 {
669 if (current_band == 0) {
670 start_item = 0;
671 } else if (current_band == EQ_NUM_BANDS - 1) {
672 start_item = EQ_NUM_BANDS - nb_eq_sliders[i];
673 } else {
674 start_item = current_band - 1;
675 }
676 x = SCROLLBAR_SIZE;
677 } else {
678 x = 1;
679 start_item = 0;
680 }
681 /* Draw equalizer band details */
682 draw_eq_sliders(&screens[i], x, y, nb_eq_sliders[i], start_item,
683 current_band, mode);
684
685 screens[i].update();
686 }
687
688 button = get_action(CONTEXT_SETTINGS_EQ,TIMEOUT_BLOCK);
689
690 switch (button) {
691 case ACTION_SETTINGS_DEC:
692 case ACTION_SETTINGS_DECREPEAT:
693 *(setting) -= step;
694 has_changed = true;
695 if (*(setting) < min)
696 *(setting) = min;
697 break;
698
699 case ACTION_SETTINGS_INC:
700 case ACTION_SETTINGS_INCREPEAT:
701 *(setting) += step;
702 has_changed = true;
703 if (*(setting) > max)
704 *(setting) = max;
705 break;
706
707 case ACTION_SETTINGS_INCBIGSTEP:
708 *(setting) += fast_step;
709 has_changed = true;
710 if (*(setting) > max)
711 *(setting) = max;
712 break;
713
714 case ACTION_SETTINGS_DECBIGSTEP:
715 *(setting) -= fast_step;
716 has_changed = true;
717 if (*(setting) < min)
718 *(setting) = min;
719 break;
720
721 case ACTION_STD_PREV:
722 case ACTION_STD_PREVREPEAT:
723 current_band--;
724 if (current_band < 0)
725 current_band = EQ_NUM_BANDS - 1; /* wrap around */
726 break;
727
728 case ACTION_STD_NEXT:
729 case ACTION_STD_NEXTREPEAT:
730 current_band = (current_band + 1) % EQ_NUM_BANDS;
731 break;
732
733 case ACTION_STD_OK:
734 mode++;
735 if (mode > Q)
736 mode = GAIN; /* wrap around */
737 break;
738
739 case ACTION_STD_CANCEL:
740 exit_request = true;
741 result = false;
742 break;
743 default:
744 if(default_event_handler(button) == SYS_USB_CONNECTED) {
745 exit_request = true;
746 result = true;
747 }
748 break;
749 }
750
751 /* Update the filter if the user changed something */
752 if (has_changed) {
753 dsp_set_eq_coefs(current_band,
754 &global_settings.eq_band_settings[current_band]);
755 has_changed = false;
756 }
757 }
758
759 /* Reset screen settings */
760 FOR_NB_SCREENS(i)
761 {
762 screens[i].setfont(FONT_UI);
763 screens[i].clear_display();
764 screens[i].set_viewport(NULL);
765 viewportmanager_theme_undo(i, false);
766 }
767 return (result) ? 1 : 0;
768}
769
770static int eq_save_preset(void)
771{
772 /* make sure that the eq is enabled for setting saving */
773 bool enabled = global_settings.eq_enabled;
774 global_settings.eq_enabled = true;
775
776 bool result = settings_save_config(SETTINGS_SAVE_EQPRESET);
777
778 global_settings.eq_enabled = enabled;
779
780 return (result) ? 1 : 0;
781}
782/* Allows browsing of preset files */
783static struct browse_folder_info eqs = { EQS_DIR, SHOW_CFG };
784
785static void eq_reset_defaults(void)
786{
787 for (int i = 0; i < EQ_NUM_BANDS; i++) {
788 global_settings.eq_band_settings[i].cutoff = eq_defaults[i].cutoff;
789 global_settings.eq_band_settings[i].q = eq_defaults[i].q;
790 global_settings.eq_band_settings[i].gain = eq_defaults[i].gain;
791 }
792 eq_apply();
793}
794
795MENUITEM_FUNCTION(eq_graphical, 0, ID2P(LANG_EQUALIZER_GRAPHICAL),
796 eq_menu_graphical, lowlatency_callback, Icon_EQ);
797MENUITEM_FUNCTION(eq_save, 0, ID2P(LANG_EQUALIZER_SAVE),
798 eq_save_preset, NULL, Icon_NOICON);
799MENUITEM_FUNCTION(eq_reset, 0, ID2P(LANG_RESET_EQUALIZER),
800 eq_reset_defaults, NULL, Icon_NOICON);
801MENUITEM_FUNCTION_W_PARAM(eq_browse, 0, ID2P(LANG_EQUALIZER_BROWSE),
802 browse_folder, (void*)&eqs,
803 lowlatency_callback, Icon_NOICON);
804
805MAKE_MENU(equalizer_menu, ID2P(LANG_EQUALIZER), NULL, Icon_EQ,
806 &eq_enable, &eq_graphical, &eq_precut, &gain_menu,
807 &advanced_menu, &eq_save, &eq_browse, &eq_reset);