Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (Revision 23566) +++ 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/gui/viewport.c =================================================================== --- apps/gui/viewport.c (Revision 23566) +++ apps/gui/viewport.c (Arbeitskopie) @@ -307,6 +307,7 @@ bool is_y = (y >= vp->y && y < (vp->y + vp->height)); return (is_x && is_y); } + #endif /* HAVE_TOUCHSCREEN */ #endif /* HAVE_LCD_BITMAP */ #endif /* __PCTOOL__ */ Index: apps/menus/eq_menu.h =================================================================== --- apps/menus/eq_menu.h (Revision 23566) +++ 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,1079 @@ +/*************************************************************************** + * __________ __ ___. + * 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 }, +}; + +/* variables used to store buttonbar, band and slider position */ +struct button_data{ + int x; + int width; +}; + +struct button_bar{ + struct button_data ok; + struct button_data cancel; + struct button_data edit_mode; + short height; + short y; +}; + +struct eq_screen_data{ + struct eq_slider_data{ + short x; + short y; + short height; + short length; + }slider; + struct eq_txt_data{ + short x; + short y[5]; + short height; + short width; + }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_WIDTH) + { + 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 viewport *vp, + 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; + + screen->set_viewport(vp); + + 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,"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, " 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, "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; +} + +/* draws a rectangle around a button */ +static void draw_button (struct screen *screen, char *buf, + int x, int y, int width, int height) +{ + int txt_w, txt_h; + + /* draw button */ + 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); + + /* draw button text */ + screen->getstringsize(buf, &txt_w, &txt_h); + screen->putsxy(x + (width - txt_w)/2 , (height - txt_h)/2, buf); + +} + +/* draws the button bar at the top of the screen */ +static void draw_button_bar(struct screen *screen, + struct viewport *vp, + enum eq_slider_mode mode, + struct button_bar *btn_bar) +{ + + char buf[24]; + + screen->set_viewport(vp); + screen->set_drawmode(DRMODE_SOLID); + + /* Edit mode button */ + if (mode == CUTOFF) { + /* cutoff */ + snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_MODE), + str(LANG_SYSFONT_EQUALIZER_BAND_CUTOFF), "(Hz)"); + } + else if (mode == GAIN) { + /* gain */ + snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_MODE), + str(LANG_SYSFONT_GAIN), "(dB)"); + } + else { + /* Q */ + snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_MODE), + str(LANG_EQUALIZER_BAND_Q), ""); + } + draw_button(screen, buf, btn_bar->edit_mode.x, 0, + btn_bar->edit_mode.width, btn_bar->height); + + /* Cancel button */ + snprintf(buf, sizeof(buf), str(LANG_GRAPHIC_EQ_CANCEL), NULL, NULL); + draw_button(screen, buf, btn_bar->cancel.x, 0, + btn_bar->cancel.width, btn_bar->height); + + /* Ok button */ + snprintf(buf, sizeof(buf), str(LANG_GRAPHIC_EQ_OK), NULL, NULL); + draw_button(screen, buf, btn_bar->ok.x, 0, + btn_bar->ok.width, btn_bar->height); + + return; +} + +#ifdef HAVE_REMOTE_LCD +void draw_remote_screen(struct screen * screen, + struct viewport *vp, + int current_band, + enum eq_slider_mode mode, + int setting) +{ + int x, h, y; + char buf[10]; + + screen->set_viewport(vp); + + screen->getstringsize("PK ", &x, &h); + y = (vp->height - h) / 2; + + if (current_band == 0) { + screen->putsxy(2, y, "LS "); + } else if (current_band == 4) { + screen->putsxy(2, y, "HS "); + } else { + snprintf(buf, sizeof(buf), "PK%d", current_band); + screen->putsxy(2, y, buf); + } + + switch(mode) { + case Q: + snprintf (buf, sizeof(buf), "-Q: %d.%d", setting / EQ_USER_DIVISOR, + setting % EQ_USER_DIVISOR); + break; + case CUTOFF: + snprintf (buf, sizeof(buf), "-C: %5d", setting); + break; + case GAIN: + default: + snprintf (buf, sizeof(buf), "-G: %s%2d.%d", setting < 0 ? "-" : " ", + abs(setting) / EQ_USER_DIVISOR, abs(setting) % EQ_USER_DIVISOR); + break; + } + screen->putsxy(x, y, buf); +} +#endif + +/* calculates buttonbar, band and slider postionions and sizes */ +static bool init_eq_screen(struct screen * screen, + struct viewport *vp, + struct button_bar *btn_bar, + struct eq_screen_data *eq_data) +{ + int w, w1, h, i; + char buf[24]; + + btn_bar->y = 0; + /* check if the button bar fits in the viewport*/ + + /* Edit 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; + } + btn_bar->edit_mode.width = w + 10; + btn_bar->edit_mode.x = vp->width - btn_bar->edit_mode.width; + + /* 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 = btn_bar->cancel.width + 5; + + /* Ok button */ + snprintf(buf, sizeof(buf), str(LANG_GRAPHIC_EQ_OK), NULL, NULL); + screen->getstringsize(buf, &w, &h); + btn_bar->ok.x = 0; + btn_bar->ok.width = btn_bar->cancel.width; + + screen->getstringsize("A", &w, &h); + if (w * 20 > vp->width || + (btn_bar->cancel.width + btn_bar->ok.width + + btn_bar->edit_mode.width + 10 ) > vp->width) + { + return false; /* buttonbar or 3 settings do not fit on the screen */ + } + + /* determine the height of the button bar */ + if (h <= 16) { + btn_bar->height = 20; + } + else { + btn_bar->height = h + 4; + } + + /* calculate band postion and size */ + eq_data->band.x = 0; + eq_data->band.width = vp->width; + eq_data->band.height = (vp->height - 1 - btn_bar->height - + BUTTON_BAR_MARGIN_BOTTOM) / 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 = SLIDER_TOUCH_MARGIN; + eq_data->slider.length = vp->width - 2 * SLIDER_TOUCH_MARGIN; + 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; + struct viewport vp [NB_SCREENS]; + + touchscreen_set_mode(TOUCHSCREEN_POINT); + save_eq_settings(eq_settings); + + FOR_NB_SCREENS(i) { + screens[i].set_viewport(NULL); + screens[i].stop_scroll(); + viewport_set_defaults(&vp[i], i); + screens[i].set_viewport(&vp[i]); + screens[i].clear_viewport(); + screens[i].update_viewport(); + } + + vp[SCREEN_MAIN].x = EQ_OUTER_MARGIN; + vp[SCREEN_MAIN].width -= 2 * EQ_OUTER_MARGIN; + vp[SCREEN_MAIN].y += EQ_OUTER_MARGIN; + vp[SCREEN_MAIN].height -= EQ_OUTER_MARGIN; + vp[SCREEN_MAIN].font = FONT_UI; + +#ifdef HAVE_REMOTE_LCD + vp[SCREEN_REMOTE].font = FONT_SYSFIXED; +#endif + + /* Select the font. Use the theme font if possible, use Sysfont if the */ + /* buttonbar or EQ do not fit on the screen. Additionally buttonbar */ + /* band and slider coordinates are calculated once. */ + if (!init_eq_screen(&screens[SCREEN_MAIN], &vp[SCREEN_MAIN], &btn_bar, &eq_data)) + { + vp[SCREEN_MAIN].font = FONT_SYSFIXED; + init_eq_screen(&screens[SCREEN_MAIN], &vp[SCREEN_MAIN], &btn_bar, &eq_data); + } + + while (!exit_request) { + + FOR_NB_SCREENS(i) { + screens[i].clear_viewport(); + } + + /* 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[SCREEN_MAIN], &vp[SCREEN_MAIN], mode, &btn_bar); + draw_eq_sliders(&screens[SCREEN_MAIN], &vp[SCREEN_MAIN], + &eq_data, current_band, mode); +#ifdef HAVE_REMOTE_LCD + draw_remote_screen(&screens[SCREEN_REMOTE], &vp[SCREEN_REMOTE], + current_band, mode, *setting); +#endif + FOR_NB_SCREENS(i) { + screens[i].set_viewport(&vp[i]); + screens[i].update_viewport(); + } + + /* wait here until a button or the touchscreen is pressed. no need to */ + /* to redraw if there is no action */ + 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 (viewport_point_within_vp(&vp[SCREEN_MAIN], + (int)touch_x, (int)touch_y)) + { /* convert touch into VP coordinates */ + touch_x -= vp[SCREEN_MAIN].x; + touch_y -= vp[SCREEN_MAIN].y; + + if (touch_y >= btn_bar.y && + touch_y <= btn_bar.y + btn_bar.height && + touch_x >= eq_data.slider.x && + touch_x <= eq_data.slider.x + eq_data.slider.length && + !slider_change) + { + if (touch_x >= btn_bar.ok.x && + touch_x <= btn_bar.ok.x + btn_bar.ok.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 && + touch_x <= btn_bar.edit_mode.x + btn_bar.edit_mode.width && + (button_touchscreen & BUTTON_REL)) + { + button = ACTION_STD_OK; + /* change Edit Mode */ + } + else + { + button = BUTTON_NONE; + } + } + else + { + button = BUTTON_NONE; + selected_band = 0; + if (touch_x >= eq_data.band.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; + } + } + else { + button = BUTTON_NONE; + } + } + + 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 23566) +++ apps/settings_list.c (Arbeitskopie) @@ -1215,6 +1215,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, @@ -1231,6 +1250,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 23566) +++ 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