Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (Revision 23328) +++ apps/lang/english.lang (Arbeitskopie) @@ -13076,6 +13076,57 @@ + id: LANG_GRAPHIC_EQ_OK + desc: in graphic EQ screen + user: core + + *: none + swcodec: "Ok" + + + *: none + swcodec: "Ok" + + + *: none + rswcodec: "" + + + + id: LANG_GRAPHIC_EQ_CANCEL + desc: in graphic EQ screen + user: core + + *: none + swcodec: "Cancel" + + + *: none + swcodec: "Cancel" + + + *: none + rswcodec: "" + + + + id: LANG_SYSFONT_EQUALIZER_MODE + desc: in the equalizer settings menu + user: core + + *: none + swcodec: "Mode: %s %s" + + + *: none + swcodec: "Mode: %s %s" + + + *: none + swcodec: "" + + + id: LANG_SKIP_OUTRO desc: skipping to the 5 seconds before the end of a track user: core Index: apps/menus/eq_menu.h =================================================================== --- apps/menus/eq_menu.h (Revision 23328) +++ apps/menus/eq_menu.h (Arbeitskopie) @@ -24,8 +24,15 @@ #include "menu.h" #include "config.h" /* Various user interface limits and sizes */ + +#ifdef HAVE_TOUCHSCREEN +#define EQ_CUTOFF_MIN(a) cutoff_lim[0][a] +#define EQ_CUTOFF_MAX(b) cutoff_lim[1][b] +#else #define EQ_CUTOFF_MIN 20 #define EQ_CUTOFF_MAX 22040 +#endif + #define EQ_CUTOFF_STEP 10 #define EQ_CUTOFF_FAST_STEP 100 #define EQ_GAIN_MIN (-240) Index: apps/menus/eq_menu-touchscreen.c =================================================================== --- apps/menus/eq_menu-touchscreen.c (Revision 0) +++ apps/menus/eq_menu-touchscreen.c (Revision 0) @@ -0,0 +1,1000 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: eq_menu.c 12179 2007-02-01 23:08:15Z amiconn $ + * + * Copyright (C) 2006 Dan Everton, 2009 Carsten Schreiter + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "config.h" +#include +#include +#include +#include "eq_menu.h" +#include "system.h" +#include "kernel.h" +#include "lcd.h" +#include "menu.h" +#include "action.h" +#include "mp3_playback.h" +#include "settings.h" +#include "screens.h" +#include "icons.h" +#include "font.h" +#include "lang.h" +#include "sprintf.h" +#include "talk.h" +#include "misc.h" +#include "sound.h" +#include "dsp.h" +#include "tree.h" +#include "screen_access.h" +#include "keyboard.h" +#include "gui/scrollbar.h" +#include "menu_common.h" +#include "viewport.h" +#include "stdlib.h" + +/* + * Utility functions + */ + +const char* eq_q_format(char* buffer, size_t buffer_size, int value, const char* unit) +{ + snprintf(buffer, buffer_size, "%d.%d %s", value / EQ_USER_DIVISOR, + value % EQ_USER_DIVISOR, unit); + return buffer; +} + +const char* eq_precut_format(char* buffer, size_t buffer_size, int value, const char* unit) +{ + snprintf(buffer, buffer_size, "%s%d.%d %s", value == 0 ? " " : "-", + value / EQ_USER_DIVISOR, value % EQ_USER_DIVISOR, unit); + return buffer; +} + +/* + * Settings functions + */ +static void eq_apply(void) +{ + int i; + dsp_set_eq(global_settings.eq_enabled); + dsp_set_eq_precut(global_settings.eq_precut); + /* Update all bands */ + for(i = 0; i < 5; i++) { + dsp_set_eq_coefs(i); + } +} + +static int eq_setting_callback(int action, const struct menu_item_ex *this_item) +{ + switch (action) + { + case ACTION_ENTER_MENUITEM: + action = lowlatency_callback(action, this_item); + break; + case ACTION_EXIT_MENUITEM: + eq_apply(); + action = lowlatency_callback(action, this_item); + break; + } + + return action; +} +MENUITEM_SETTING(eq_enable, &global_settings.eq_enabled, eq_setting_callback); +MENUITEM_SETTING(eq_precut, &global_settings.eq_precut, eq_setting_callback); + +MENUITEM_SETTING(cutoff_0, &global_settings.eq_band0_cutoff, eq_setting_callback); +MENUITEM_SETTING(cutoff_1, &global_settings.eq_band1_cutoff, eq_setting_callback); +MENUITEM_SETTING(cutoff_2, &global_settings.eq_band2_cutoff, eq_setting_callback); +MENUITEM_SETTING(cutoff_3, &global_settings.eq_band3_cutoff, eq_setting_callback); +MENUITEM_SETTING(cutoff_4, &global_settings.eq_band4_cutoff, eq_setting_callback); + +MENUITEM_SETTING(q_0, &global_settings.eq_band0_q, eq_setting_callback); +MENUITEM_SETTING(q_1, &global_settings.eq_band1_q, eq_setting_callback); +MENUITEM_SETTING(q_2, &global_settings.eq_band2_q, eq_setting_callback); +MENUITEM_SETTING(q_3, &global_settings.eq_band3_q, eq_setting_callback); +MENUITEM_SETTING(q_4, &global_settings.eq_band4_q, eq_setting_callback); + +MENUITEM_SETTING(gain_0, &global_settings.eq_band0_gain, eq_setting_callback); +MENUITEM_SETTING(gain_1, &global_settings.eq_band1_gain, eq_setting_callback); +MENUITEM_SETTING(gain_2, &global_settings.eq_band2_gain, eq_setting_callback); +MENUITEM_SETTING(gain_3, &global_settings.eq_band3_gain, eq_setting_callback); +MENUITEM_SETTING(gain_4, &global_settings.eq_band4_gain, eq_setting_callback); + +static char* gainitem_get_name(int selected_item, void * data, char *buffer) +{ + (void)selected_item; + int *setting = (int*)data; + snprintf(buffer, MAX_PATH, str(LANG_EQUALIZER_GAIN_ITEM), *setting); + return buffer; +} + +static int gainitem_speak_item(int selected_item, void * data) +{ + (void)selected_item; + int *setting = (int*)data; + talk_number(*setting, false); + talk_id(LANG_EQUALIZER_GAIN_ITEM, true); + return 0; +} + +static int do_option(void * param) +{ + const struct menu_item_ex *setting = (const struct menu_item_ex*)param; + lowlatency_callback(ACTION_ENTER_MENUITEM, setting); + do_setting_from_menu(setting, NULL); + eq_apply(); + lowlatency_callback(ACTION_EXIT_MENUITEM, setting); + return 0; +} + +MENUITEM_FUNCTION_DYNTEXT(gain_item_0, MENU_FUNC_USEPARAM, + do_option, (void*)&gain_0, + gainitem_get_name, gainitem_speak_item, + &global_settings.eq_band0_cutoff, NULL, Icon_NOICON); +MENUITEM_FUNCTION_DYNTEXT(gain_item_1, MENU_FUNC_USEPARAM, + do_option, (void*)&gain_1, + gainitem_get_name, gainitem_speak_item, + &global_settings.eq_band1_cutoff, NULL, Icon_NOICON); +MENUITEM_FUNCTION_DYNTEXT(gain_item_2, MENU_FUNC_USEPARAM, + do_option, (void*)&gain_2, + gainitem_get_name, gainitem_speak_item, + &global_settings.eq_band2_cutoff, NULL, Icon_NOICON); +MENUITEM_FUNCTION_DYNTEXT(gain_item_3, MENU_FUNC_USEPARAM, + do_option, (void*)&gain_3, + gainitem_get_name, gainitem_speak_item, + &global_settings.eq_band3_cutoff, NULL, Icon_NOICON); +MENUITEM_FUNCTION_DYNTEXT(gain_item_4, MENU_FUNC_USEPARAM, + do_option, (void*)&gain_4, + gainitem_get_name, gainitem_speak_item, + &global_settings.eq_band4_cutoff, NULL, Icon_NOICON); + +MAKE_MENU(gain_menu, ID2P(LANG_EQUALIZER_GAIN), NULL, Icon_NOICON, &gain_item_0, + &gain_item_1, &gain_item_2, &gain_item_3, &gain_item_4); + +static const struct menu_item_ex *band_items[3][3] = { + { &cutoff_1, &q_1, &gain_1 }, + { &cutoff_2, &q_2, &gain_2 }, + { &cutoff_3, &q_3, &gain_3 } +}; + +/* cutoff limits min and max for each eq band */ +/* required for better setting resolution on a touchscreen */ + +const int cutoff_lim[2][5] = { + { 20, 20, 500, 1000, 5000 }, + { 500, 2000, 5000, 15000, 22040 }, +}; + +struct button_data{ + int x; + int width; +}; + +struct button_bar{ + struct button_data ok; + struct button_data cancel; + struct button_data edit_mode; + int height; + int y; +}; + +struct eq_slider_data{ + int x; + int y; + int height; + int length; +}; + +struct eq_txt_data{ + int x; + int y[5]; + int height; + int width; +}; + +struct eq_screen_data{ + struct eq_slider_data slider; + struct eq_txt_data band; +}; + +static char* centerband_get_name(int selected_item, void * data, char *buffer) +{ + (void)selected_item; + int band = (intptr_t)data; + snprintf(buffer, MAX_PATH, str(LANG_EQUALIZER_BAND_PEAK), band); + return buffer; +} + +static int centerband_speak_item(int selected_item, void * data) +{ + (void)selected_item; + int band = (intptr_t)data; + talk_id(LANG_EQUALIZER_BAND_PEAK, false); + talk_number(band, true); + return 0; +} + +static int do_center_band_menu(void* param) +{ + int band = (intptr_t)param; + struct menu_item_ex menu; + struct menu_callback_with_desc cb_and_desc; + char desc[MAX_PATH]; + + cb_and_desc.menu_callback = NULL; + snprintf(desc, MAX_PATH, str(LANG_EQUALIZER_BAND_PEAK), band); + cb_and_desc.desc = desc; + cb_and_desc.icon_id = Icon_EQ; + menu.flags = MT_MENU|(3< inner_x + inner_wd - SLIDER_SIZE) + { + size = inner_x + inner_wd - start; + edge_reached = RIGHT_EDGE; + } + + /* draw box */ +#ifdef HAVE_LCD_COLOR + /* must avoid corners if case of (flags & FOREGROUND) */ + screen->hline(inner_x, x + inner_wd, y); + screen->hline(inner_x, x + inner_wd, y + height - 1); + screen->vline(x, inner_y, y + inner_ht); + screen->vline(x + width - 1, inner_y, y + inner_ht); +#else + screen->drawrect(x, y, width, height); +#endif + + screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); + +#ifdef HAVE_LCD_COLOR + infill = (screen->depth > 1 ? INNER_FILL_MASK : INNER_FILL); + +#endif + /* clear corner pixels */ + screen->drawpixel(x, y); + screen->drawpixel(x + width - 1, y); + screen->drawpixel(x, y + height - 1); + screen->drawpixel(x + width - 1, y + height - 1); + +#ifdef HAVE_LCD_COLOR + if (infill != INNER_BGFILL) + infill = INNER_FILL; + + if (infill == INNER_FILL) +#endif + { + /* clear pixels in progress bar */ + screen->fillrect(inner_x, inner_y, inner_wd, inner_ht); + } + + screen->set_drawmode(DRMODE_SOLID); + +#ifdef HAVE_LCD_COLOR + if (infill == INNER_BGFILL) + { + /* fill inner area with current background color */ + unsigned fg = screen->get_foreground(); + screen->set_foreground(screen->get_background()); + screen->fillrect(inner_x, inner_y, inner_wd, inner_ht); + screen->set_foreground(fg); + } +#endif + /* draw slider */ + screen->fillrect(start, inner_y, size, inner_ht); + + /* clear corner pixels of slider */ + screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); + if (edge_reached != LEFT_EDGE) + { + screen->drawpixel(start, inner_y); + screen->drawpixel(start, inner_y + inner_ht - 1); + } + if (edge_reached != RIGHT_EDGE) + { + screen->drawpixel(start + size - 1, inner_y); + screen->drawpixel(start + size - 1, inner_y + inner_ht - 1); + } + screen->set_drawmode(DRMODE_SOLID); +} + +/* Draw's all the EQ sliders. */ +static void draw_eq_sliders(struct screen * screen, struct eq_screen_data *eq_data, + int current_band, enum eq_slider_mode mode) +{ + int band, w, h, gain, q, cutoff; + int *setting = &global_settings.eq_band0_cutoff; + char buf[26]; + int value, min_item, max_item; + int x1, x2, y1; + + for (band = 0; band < 5; band ++) { + cutoff = *setting++; + q = *setting++; + gain = *setting++; + + switch(mode) { + case Q: + value = q; + min_item = EQ_Q_MIN; + max_item = EQ_Q_MAX; + break; + case CUTOFF: + value = cutoff; + min_item = EQ_CUTOFF_MIN(band); + max_item = EQ_CUTOFF_MAX(band); + break; + case GAIN: + default: + value = gain; + min_item = EQ_GAIN_MIN; + max_item = EQ_GAIN_MAX; + break; + } + + /* Start two pixels in, one for border, one for margin */ + x1 = (int)eq_data->band.x + 2; + y1 = (int)eq_data->band.y[band] + 2; + + /* Print out the band label */ + if (band == 0) { + screen->putsxy(x1, y1, "LS: "); + screen->getstringsize("LS:", &w, &h); + } else if (band == 4) { + screen->putsxy(x1, y1, "HS: "); + screen->getstringsize("HS:", &w, &h); + } else { + snprintf(buf, sizeof(buf), "PK%d:", band); + screen->putsxy(x1, y1, buf); + screen->getstringsize(buf, &w, &h); + } + + screen->getstringsize("A", &w, &h); + x1 += 5*w; /* 4 chars for label + 1 space = 5 */ + + /* Print out gain part of status line (left justify after label) */ + if (mode == GAIN && band == current_band) + screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); + else + screen->set_drawmode(DRMODE_SOLID); + + snprintf(buf, sizeof(buf), "%s%2d.%d%s", gain < 0 ? "-" : " ", + abs(gain) / EQ_USER_DIVISOR, abs(gain) % EQ_USER_DIVISOR, + screen->lcdwidth >= 160 ? "dB" : ""); + screen->putsxy(x1, y1, buf); + screen->getstringsize(buf, &w, &h); + + x1 += w; + + /* Print out Q part of status line (right justify) */ + if (mode == Q && band == current_band) + screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); + else + screen->set_drawmode(DRMODE_SOLID); + + snprintf(buf, sizeof(buf), "%d.%d%s", q / EQ_USER_DIVISOR, + q % EQ_USER_DIVISOR, screen->lcdwidth >= 160 ? " Q" : ""); + screen->getstringsize(buf, &w, &h); + x2 = eq_data->band.x + eq_data->band.width - w - 2; + screen->putsxy(x2, y1, buf); + + /* Print out cutoff part of status line (center between gain & Q) */ + if (mode == CUTOFF && band == current_band) + screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); + else + screen->set_drawmode(DRMODE_SOLID); + + snprintf(buf, sizeof(buf), "%5d%s", cutoff, + screen->lcdwidth >= 160 ? "Hz" : ""); + screen->getstringsize(buf, &w, &h); + x1 = x1 + (x2 - x1 - w)/2; + screen->putsxy(x1, y1, buf); + + screen->set_drawmode(DRMODE_SOLID); + + /* Draw horizontal slider */ + draw_slider_bar(screen, eq_data->band.x, eq_data->band.y[band] + eq_data->slider.y, + eq_data->band.width, eq_data->slider.height, value, + min_item, max_item); + } + return; +} + +static void save_eq_settings(int *eq_settings) +{ + int i; + int *setting = &global_settings.eq_band0_cutoff; + + for (i = 0; i < 15; i ++) + { + eq_settings[i] = setting[i]; + } + return; +} + +static void restore_eq_settings(int *eq_settings) +{ + int i; + int *setting = &global_settings.eq_band0_cutoff; + + for (i = 0; i < 15; i++) + { + setting[i] = eq_settings[i]; + } + for (i = 0; i < 5; i++) + { + dsp_set_eq_coefs(i); + } + return; +} + +/* draws a rectangle around a button */ +static void draw_button (struct screen *screen, int x, int y, + int width, int height) +{ + screen->drawrect(x, y, width, height); + /* clear corner pixels of button */ + screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); + screen->drawpixel(x, y); + screen->drawpixel(x + width - 1, y); + screen->drawpixel(x, y + height - 1); + screen->drawpixel(x + width -1, y + height -1); + screen->set_drawmode(DRMODE_SOLID); + +} + +/* draws the button bar at the top of the screen */ +static void draw_button_bar(struct screen *screen, enum eq_slider_mode mode, + struct button_bar *btn_bar) +{ + int w, h, btn_txt_y; + char buf[24]; + + screen->set_drawmode(DRMODE_SOLID); + + /* get size of the edit mode button */ + snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_MODE), + str(LANG_SYSFONT_EQUALIZER_BAND_CUTOFF), "(Hz)"); + screen->getstringsize(buf, &w, &h); + btn_bar->edit_mode.width = w + 10; + btn_bar->edit_mode.x = screen->lcdwidth - btn_bar->edit_mode.width - + EQ_OUTER_MARGIN; + btn_bar->y = 1; + + btn_txt_y = btn_bar->y + btn_bar->height / 2 - h / 2 - 1; + + if (mode == CUTOFF) { + /* cutoff */ + screen->putsxy(btn_bar->edit_mode.x + 5 , btn_txt_y, buf); + } + else if (mode == GAIN) { + /* gain */ + snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_MODE), + str(LANG_SYSFONT_GAIN), "(dB)"); + screen->putsxy(btn_bar->edit_mode.x + 5, btn_txt_y, buf); + } + else { + /* Q */ + snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_MODE), + str(LANG_EQUALIZER_BAND_Q), ""); + screen->putsxy(btn_bar->edit_mode.x + 5, btn_txt_y, buf); + } + + /* get size of the Cancel button */ + snprintf(buf, sizeof(buf), str(LANG_GRAPHIC_EQ_CANCEL), NULL, NULL); + screen->getstringsize(buf, &w, &h); + btn_bar->cancel.width = w + 10; + btn_bar->cancel.x = 15 + w + EQ_OUTER_MARGIN; + screen->putsxy(btn_bar->cancel.x + (btn_bar->cancel.width - w )/2, + btn_txt_y, buf); + draw_button(screen, btn_bar->cancel.x, btn_bar->y -1, + btn_bar->cancel.width, btn_bar->height); + + /* get size of the Ok button */ + btn_bar->ok.width = btn_bar->cancel.width; + snprintf(buf, sizeof(buf), str(LANG_GRAPHIC_EQ_OK), NULL, NULL); + screen->getstringsize(buf, &w, &h); + btn_bar->ok.x = EQ_OUTER_MARGIN; + screen->putsxy(btn_bar->ok.x + (btn_bar->ok.width - w)/2, btn_txt_y, buf); + draw_button(screen, btn_bar->ok.x, btn_bar->y -1, + btn_bar->ok.width, btn_bar->height); + + draw_button(screen, btn_bar->edit_mode.x, btn_bar->y -1, + btn_bar->edit_mode.width, btn_bar->height); + + return; +} + +/* calculates band and slider postioniona and size */ +static bool init_eq_screen(struct screen * screen, + struct button_bar *btn_bar, + struct eq_screen_data *eq_data) +{ + int w, w1, h, total_width, i; + char buf[24]; + + /* check if the button bar fits in */ + + /* get the max size of the mode button */ + /* don't know which setting is the longest in each language, therefore */ + /* check all 3 settings*/ + snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_MODE), + str(LANG_SYSFONT_EQUALIZER_BAND_CUTOFF), "(Hz)"); + screen->getstringsize(buf, &w1, &h); + w = w1; + + snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_MODE), + str(LANG_SYSFONT_GAIN), "(dB)"); + screen->getstringsize(buf, &w1, &h); + if (w1 > w) { + w = w1; + } + + snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_MODE), + str(LANG_EQUALIZER_BAND_Q), ""); + screen->getstringsize(buf, &w1, &h); + if (w1 > w) { + w = w1; + } + + total_width = w + 10; + + /* get size of the Cancel button */ + snprintf(buf, sizeof(buf), str(LANG_GRAPHIC_EQ_CANCEL), + NULL, NULL); + screen->getstringsize(buf, &w, &h); + total_width = total_width + w + 10; + + /* get size of the Ok button */ + snprintf(buf, sizeof(buf), str(LANG_GRAPHIC_EQ_OK), + NULL, NULL); + screen->getstringsize(buf, &w, &h); + total_width = total_width + w; + + /* 3 x 5 characters for setting items, 2 x 3 spaces, 1 x 4 for band label */ + if (w * 20 > screen->lcdwidth || + ( 2 * EQ_OUTER_MARGIN + total_width ) > screen->lcdwidth) + { + return false; /* buttonbar does not fit on the screen */ + } + + /* determine the size of the button bar */ + if (h < 20) { + btn_bar->height = 20; + } + else { + btn_bar->height = h + 4; + } + + /* calculate band postion and size */ + eq_data->band.x = EQ_OUTER_MARGIN; + eq_data->band.width = screen->lcdwidth - 2 * EQ_OUTER_MARGIN; + eq_data->band.height = (screen->lcdheight - btn_bar->height - + BUTTON_BAR_MARGIN_BOTTOM - screens->lcdheight * 0.02) / 5; + for (i=0; i < 5; i++) + { + eq_data->band.y[i] = btn_bar->height + BUTTON_BAR_MARGIN_BOTTOM + i * + eq_data->band.height; + } + + /* calculate slider postion within a band and size */ + eq_data->slider.x = EQ_OUTER_MARGIN + SLIDER_TOUCH_MARGIN; + eq_data->slider.length = screen->lcdwidth - 2 * eq_data->slider.x; + eq_data->slider.y = h + 3 + 1; + eq_data->slider.height = eq_data->band.height - eq_data->slider.y; + + if (eq_data->slider.height > 30) + { + eq_data->slider.height = 30; + } + else if (eq_data->slider.height < 15) + { + return false; /*sliders are too small */ + } + return true; +} + +/* Provides a graphical means of editing the EQ settings */ +bool eq_menu_graphical(void) +{ + bool exit_request = false; + bool result = true; + bool has_changed = false; + int button; + int *setting; + int current_band = 0; + int i, step, min, max, voice_unit; + enum eq_slider_mode mode = GAIN; + int barsenabled = viewportmanager_set_statusbar(VP_SB_HIDE_ALL); + int eq_settings[15]; + struct button_bar btn_bar; + struct eq_screen_data eq_data; + + touchscreen_set_mode(TOUCHSCREEN_POINT); + save_eq_settings(eq_settings); + + FOR_NB_SCREENS(i) { + screens[i].setfont(FONT_UI); + screens[i].set_viewport(NULL); + } + + /* Select the font. Use the theme font if possible, use Sysfont if the */ + /* stuff does not fit on the screen */ + if (!init_eq_screen(&screens[0], &btn_bar, &eq_data)) + { + screens[0].setfont(FONT_SYSFIXED); + init_eq_screen(&screens[0], &btn_bar, &eq_data); + } + + while (!exit_request) { + + FOR_NB_SCREENS(i) { + screens[i].clear_display(); + } + + /* Set pointer to the band data currently editable */ + if (mode == GAIN) { + /* gain */ + setting = &global_settings.eq_band0_gain; + setting += current_band * 3; + + step = EQ_GAIN_STEP; + min = EQ_GAIN_MIN; + max = EQ_GAIN_MAX; + voice_unit = UNIT_DB; + + } else if (mode == CUTOFF) { + /* cutoff */ + setting = &global_settings.eq_band0_cutoff; + setting += current_band * 3; + + step = EQ_CUTOFF_STEP; + min = EQ_CUTOFF_MIN(current_band); + max = EQ_CUTOFF_MAX(current_band); + voice_unit = UNIT_HERTZ; + + } else { + /* Q */ + setting = &global_settings.eq_band0_q; + setting += current_band * 3; + + step = EQ_Q_STEP; + min = EQ_Q_MIN; + max = EQ_Q_MAX; + voice_unit = UNIT_INT; + } + + /* Draw button bar and equalizer bands */ + draw_button_bar(&screens[0], mode, &btn_bar); + draw_eq_sliders(&screens[0], &eq_data, current_band, mode); + + FOR_NB_SCREENS(i) { + screens[i].update(); + } + + /* wait here until a button or the touchscreen is pressed */ + do + { + button = get_action(CONTEXT_SETTINGS_EQ,TIMEOUT_BLOCK); + } + while (button == BUTTON_NONE); + +#define EQ_SLIDER_TCONST 2 + + static bool slider_change = false; + + if ((button == ACTION_TOUCHSCREEN && + touchscreen_get_mode() == TOUCHSCREEN_POINT) || + slider_change) + { + bool slider_touched = false; + short selected_band = current_band; + int button_touchscreen; + short touch_x = 0, touch_y = 0; + int target_value = 0; + + button_touchscreen = action_get_touchscreen_press(&touch_x, &touch_y); + + if (touch_y < btn_bar.height + 3 && touch_x > eq_data.slider.x && !slider_change) + { + if (touch_x < eq_data.slider.x + btn_bar.cancel.width) + { + button = ACTION_STD_CANCEL; + slider_change = false; + } + else if (touch_x > btn_bar.cancel.x && + touch_x < btn_bar.cancel.x + btn_bar.cancel.width && + (button_touchscreen & BUTTON_REL)) + { + restore_eq_settings(eq_settings); + button = ACTION_STD_CANCEL; + slider_change = false; + } + else if (touch_x > btn_bar.edit_mode.x && + (button_touchscreen & BUTTON_REL)) + { + button = ACTION_STD_OK; + /* change Edit Mode */ + } + } + else + { + button = BUTTON_NONE; + selected_band = 0; + if (touch_x >= eq_data.slider.x && touch_y >= eq_data.band.y[0] + eq_data.slider.y) + { + do { /* find out which item and band has been touched */ + if ( touch_y >= eq_data.band.y[selected_band] + eq_data.slider.y && + (touch_y <= (eq_data.band.y[selected_band] + eq_data.slider.y + + eq_data.slider.height))) + { + slider_touched = true; + } + else + { + selected_band++; + } + } while (selected_band <= 5 && !slider_touched); + } + } + + if (slider_touched || slider_change) + { + if (!(slider_change)) + { + if (current_band != selected_band) + { + current_band = selected_band; + } + else if (slider_touched) { + slider_change = true; + } + } + + if (slider_change) + { + if (mode == GAIN) { + target_value = max * 2 * (touch_x - eq_data.slider.x - + eq_data.slider.length/2) / eq_data.slider.length; + } + else if (mode == CUTOFF) { + if (current_band == 1) + { + step = step * 2; + } + else if (current_band > 1 && current_band < 4) + { + step = step * 5; + } + else if (current_band == 4) + { + step = step * 10; + } + target_value = min + ((max-min) * (touch_x - + eq_data.slider.x) / eq_data.slider.length); + } + else if (mode == Q) { + target_value = min + ((max-min) * (touch_x - + eq_data.slider.x) / eq_data.slider.length); + } + + target_value = (target_value / step) * step; + + if (mode != Q) + { + if (abs(target_value) % step >= step / 2) + { + if (target_value >= 0) + { + target_value += step; + } + else + { + target_value -= step; + } + } + } + + if (target_value < min) { + target_value = min; + } + else if (target_value > max) { + target_value = max; + } + + /* make the slider movement a little smoother */ + *(setting) = (*(setting) + (target_value - *(setting)) / + EQ_SLIDER_TCONST + (target_value - *(setting)) % + EQ_SLIDER_TCONST); + has_changed = true; + } + } + + if (slider_change && (button_touchscreen & BUTTON_REL)) { + slider_change = false; + *(setting) = target_value; + } + } + + switch (button) { + case ACTION_SETTINGS_DEC: + case ACTION_SETTINGS_DECREPEAT: + *(setting) -= step; + has_changed = true; + if (*(setting) < min) + *(setting) = min; + break; + + case ACTION_SETTINGS_INC: + case ACTION_SETTINGS_INCREPEAT: + *(setting) += step; + has_changed = true; + if (*(setting) > max) + *(setting) = max; + break; + + case ACTION_STD_PREV: + case ACTION_STD_PREVREPEAT: + current_band--; + if (current_band < 0) + current_band = 4; /* wrap around */ + break; + + case ACTION_STD_NEXT: + case ACTION_STD_NEXTREPEAT: + current_band++; + if (current_band > 4) + current_band = 0; /* wrap around */ + break; + + case ACTION_STD_OK: + mode++; + if (mode > Q) + mode = GAIN; /* wrap around */ + break; + + case ACTION_STD_CANCEL: + exit_request = true; + result = false; + touchscreen_set_mode(global_settings.touch_mode); + break; + default: + if(default_event_handler(button) == SYS_USB_CONNECTED) { + exit_request = true; + result = true; + } + break; + } + + /* Update the filter if the user changed something */ + if (has_changed) { + dsp_set_eq_coefs(current_band); + has_changed = false; + } + } + + /* Reset screen settings */ + FOR_NB_SCREENS(i) { + screens[i].setfont(FONT_UI); + screens[i].clear_display(); + screens[i].set_viewport(NULL); + } + viewportmanager_set_statusbar(barsenabled); + return result; +} + +static bool eq_save_preset(void) +{ + /* make sure that the eq is enabled for setting saving */ + bool enabled = global_settings.eq_enabled; + global_settings.eq_enabled = true; + + bool result = settings_save_config(SETTINGS_SAVE_EQPRESET); + + global_settings.eq_enabled = enabled; + + return result; +} + +/* Allows browsing of preset files */ +bool eq_browse_presets(void) +{ + return rockbox_browse(EQS_DIR, SHOW_CFG); +} + +MENUITEM_FUNCTION(eq_graphical, 0, ID2P(LANG_EQUALIZER_GRAPHICAL), + (int(*)(void))eq_menu_graphical, NULL, lowlatency_callback, + Icon_EQ); +MENUITEM_FUNCTION(eq_save, 0, ID2P(LANG_EQUALIZER_SAVE), + (int(*)(void))eq_save_preset, NULL, NULL, Icon_NOICON); +MENUITEM_FUNCTION(eq_browse, 0, ID2P(LANG_EQUALIZER_BROWSE), + (int(*)(void))eq_browse_presets, NULL, lowlatency_callback, + Icon_NOICON); + +MAKE_MENU(equalizer_menu, ID2P(LANG_EQUALIZER), NULL, Icon_EQ, + &eq_enable, &eq_graphical, &eq_precut, &gain_menu, + &advanced_eq_menu_, &eq_save, &eq_browse); + Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (Revision 23328) +++ apps/settings_list.c (Arbeitskopie) @@ -1231,6 +1231,25 @@ INT_SETTING_NOWRAP(F_EQSETTING, eq_precut, LANG_EQUALIZER_PRECUT, 0, "eq precut", UNIT_DB, 0, 240, 5, eq_precut_format, get_precut_talkid, dsp_set_eq_precut), + +#ifdef HAVE_TOUCHSCREEN + INT_SETTING_NOWRAP(F_EQSETTING, eq_band0_cutoff, LANG_EQUALIZER_BAND_CUTOFF, + 60, "eq band 0 cutoff", UNIT_HERTZ, 20, + 400, EQ_CUTOFF_STEP, NULL, NULL, NULL), + INT_SETTING_NOWRAP(F_EQSETTING, eq_band1_cutoff, LANG_EQUALIZER_BAND_CENTER, + 200, "eq band 1 cutoff", UNIT_HERTZ, 20, + 2000, EQ_CUTOFF_STEP, NULL, NULL, NULL), + INT_SETTING_NOWRAP(F_EQSETTING, eq_band2_cutoff, LANG_EQUALIZER_BAND_CENTER, + 800, "eq band 2 cutoff", UNIT_HERTZ, 500, + 5000, EQ_CUTOFF_STEP, NULL, NULL, NULL), + INT_SETTING_NOWRAP(F_EQSETTING, eq_band3_cutoff, LANG_EQUALIZER_BAND_CENTER, + 4000, "eq band 3 cutoff", UNIT_HERTZ, 2000, + 15000, EQ_CUTOFF_STEP, NULL, NULL, NULL), + INT_SETTING_NOWRAP(F_EQSETTING, eq_band4_cutoff, LANG_EQUALIZER_BAND_CUTOFF, + 12000, "eq band 4 cutoff", UNIT_HERTZ, 2000, + 22040, EQ_CUTOFF_STEP, NULL, NULL, NULL), +#else + /* 0..32768 Hz */ INT_SETTING_NOWRAP(F_EQSETTING, eq_band0_cutoff, LANG_EQUALIZER_BAND_CUTOFF, 60, "eq band 0 cutoff", UNIT_HERTZ, EQ_CUTOFF_MIN, @@ -1247,6 +1266,7 @@ INT_SETTING_NOWRAP(F_EQSETTING, eq_band4_cutoff, LANG_EQUALIZER_BAND_CUTOFF, 12000, "eq band 4 cutoff", UNIT_HERTZ, EQ_CUTOFF_MIN, EQ_CUTOFF_MAX, EQ_CUTOFF_STEP, NULL, NULL, NULL), +#endif /* 0..64 (or 0.0 to 6.4) */ INT_SETTING_NOWRAP(F_EQSETTING, eq_band0_q, LANG_EQUALIZER_BAND_Q, 7, "eq band 0 q", UNIT_INT, EQ_Q_MIN, EQ_Q_MAX, EQ_Q_STEP, Index: apps/SOURCES =================================================================== --- apps/SOURCES (Revision 23328) +++ apps/SOURCES (Arbeitskopie) @@ -14,7 +14,11 @@ menus/display_menu.c menus/theme_menu.c #if CONFIG_CODEC == SWCODEC +#ifdef HAVE_TOUCHSCREEN +menus/eq_menu-touchscreen.c +#else menus/eq_menu.c +#endif buffering.c voice_thread.c replaygain.c