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,999 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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;
+
+ if (w * 10 > 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