Index: apps/menus/eq_menu.h =================================================================== --- apps/menus/eq_menu.h (Revision 23110) +++ apps/menus/eq_menu.h (Arbeitskopie) @@ -24,8 +24,8 @@ #include "menu.h" #include "config.h" /* Various user interface limits and sizes */ -#define EQ_CUTOFF_MIN 20 -#define EQ_CUTOFF_MAX 22040 +#define EQ_CUTOFF_MIN(a) cutoff_lim[0][a] +#define EQ_CUTOFF_MAX(b) cutoff_lim[1][b] #define EQ_CUTOFF_STEP 10 #define EQ_CUTOFF_FAST_STEP 100 #define EQ_GAIN_MIN (-240) Index: apps/menus/eq_menu.c =================================================================== --- apps/menus/eq_menu.c (Revision 23110) +++ apps/menus/eq_menu.c (Arbeitskopie) @@ -46,6 +46,7 @@ #include "gui/scrollbar.h" #include "menu_common.h" #include "viewport.h" +#include "stdlib.h" /* * Utility functions @@ -172,6 +173,36 @@ { &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 }, +}; + +#ifdef HAVE_TOUCHSCREEN +typedef struct { + int x[3]; + int y[5]; + int width[3]; + int height; +}eq_setting_item_data; + +typedef struct { + int x; + int y[5]; + int height; + int length; +}eq_slider_data; + +/* used to identify touched objects */ +struct eq{ + eq_setting_item_data setting_item; + eq_slider_data slider; +}eq; +#endif + static char* centerband_get_name(int selected_item, void * data, char *buffer) { (void)selected_item; @@ -240,36 +271,147 @@ HIGH_SHELF }; -/* Size of just the slider/srollbar */ #define SCROLLBAR_SIZE 6 +#define EQ_INNER_MARGIN 3 +#ifdef HAVE_TOUCHSCREEN + /* left and right border for better control on touchscreen */ + #define EQ_OUTER_MARGIN_L 6 + #define EQ_OUTER_MARGIN_R 6 + /* to let reach the max setting shortly before slider end */ + #define SLIDER_TOUCH_MARGIN 3 +#else + #define EQ_OUTER_MARGIN_L 1 + #define EQ_OUTER_MARGIN_R 1 +#endif + +static void draw_slider_bar(struct screen * screen, int x, int y, + int width, int height, int value, + int min, int max) +{ + int inner_x, inner_y, inner_wd, inner_ht; + int start, size; + short edge_reached = 0; +#ifdef HAVE_LCD_COLOR + int infill; +#endif + +#define SLIDER_SIZE 20 +#define LEFT_EDGE 1 +#define RIGHT_EDGE 2 + + inner_x = x + 1; + inner_y = y + 1; + inner_wd = width - 2; + inner_ht = height - 2; + + size = SLIDER_SIZE; + start = inner_x + ((value - min) * inner_wd / (max - min)) - SLIDER_SIZE / 2; + + if (start <= inner_x) + { + size = start + SLIDER_SIZE - inner_x; + start = inner_x; + edge_reached = LEFT_EDGE; + } + + if (start > 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 the UI for a whole EQ band */ -static int draw_eq_slider(struct screen * screen, int x, int y, +static int draw_eq_slider(struct screen * screen, int x, int y, int slider_height, int width, int cutoff, int q, int gain, bool selected, enum eq_slider_mode mode, int band) { char buf[26]; - int steps, min_item, max_item; + int value, min_item, max_item; int abs_gain = abs(gain); int x1, x2, y1, total_height; int w, h; switch(mode) { case Q: - steps = EQ_Q_MAX - EQ_Q_MIN; - min_item = q - EQ_Q_STEP - EQ_Q_MIN; - max_item = q + EQ_Q_STEP - EQ_Q_MIN; + value = q; + min_item = EQ_Q_MIN; + max_item = EQ_Q_MAX; break; case CUTOFF: - steps = EQ_CUTOFF_MAX - EQ_CUTOFF_MIN; - min_item = cutoff - EQ_CUTOFF_FAST_STEP * 2; - max_item = cutoff + EQ_CUTOFF_FAST_STEP * 2; + value = cutoff; + min_item = EQ_CUTOFF_MIN(band); + max_item = EQ_CUTOFF_MAX(band); break; case GAIN: default: - steps = EQ_GAIN_MAX - EQ_GAIN_MIN; - min_item = abs(EQ_GAIN_MIN) + gain - EQ_GAIN_STEP * 5; - max_item = abs(EQ_GAIN_MIN) + gain + EQ_GAIN_STEP * 5; + value = gain; + min_item = EQ_GAIN_MIN; + max_item = EQ_GAIN_MAX; break; } @@ -304,6 +446,17 @@ screen->lcdwidth >= 160 ? "dB" : ""); screen->putsxy(x1, y1, buf); screen->getstringsize(buf, &w, &h); + +#ifdef HAVE_TOUCHSCREEN + eq.setting_item.y[band] = y1 - 1; + if (!eq.setting_item.x[0]) + { /* we need this once only */ + eq.setting_item.x[0] = x1; + eq.setting_item.height = h + 2; + eq.setting_item.width[0] = w; + } +#endif + x1 += w; /* Print out Q part of status line (right justify) */ @@ -318,6 +471,14 @@ x2 = x + width - w - 2; screen->putsxy(x2, y1, buf); +#ifdef HAVE_TOUCHSCREEN + if (!eq.setting_item.x[2]) + { /* we need this once only */ + eq.setting_item.x[2] = x2; + eq.setting_item.width[2] = w; + } +#endif + /* Print out cutoff part of status line (center between gain & Q) */ if (mode == CUTOFF && selected) screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); @@ -330,29 +491,54 @@ x1 = x1 + (x2 - x1 - w)/2; screen->putsxy(x1, y1, buf); +#ifdef HAVE_TOUCHSCREEN + if (!eq.setting_item.x[1]) + { /* we need this once only */ + eq.setting_item.x[1] = x1; + eq.setting_item.width[1] = w; + } +#endif + /* Draw selection box */ - total_height = 3 + h + 1 + SCROLLBAR_SIZE + 3; + total_height = 3 + h + 1 + slider_height + 3; screen->set_drawmode(DRMODE_SOLID); if (selected) { screen->drawrect(x, y, width, total_height); } - /* Draw horizontal slider. Reuse scrollbar for this */ - gui_scrollbar_draw(screen, x + 3, y1 + h + 1, width - 6, SCROLLBAR_SIZE, - steps, min_item, max_item, HORIZONTAL); - + /* Draw horizontal slider */ + draw_slider_bar(screen, x + EQ_INNER_MARGIN, y1 + h + 1, + width - 2 * EQ_INNER_MARGIN, slider_height, value, + min_item, max_item); return total_height; } /* Draw's all the EQ sliders. Returns the total height of the sliders drawn */ static void draw_eq_sliders(struct screen * screen, int x, int y, - int nb_eq_sliders, int start_item, + int nb_eq_sliders, int slider_height, int start_item, int current_band, enum eq_slider_mode mode) { int i, gain, q, cutoff; int height = y; int *setting = &global_settings.eq_band0_cutoff; +#ifdef HAVE_TOUCHSCREEN + eq.setting_item.height = 0; + eq.slider.height = 0; + eq.slider.length = 0; + eq.slider.x = 0; + for (i = 0; i <= 2; i++) + { + eq.setting_item.x[i] = 0; + eq.setting_item.width[i] = 0; + } + for (i = 0; i <= 5; i++) + { + eq.setting_item.y[i] = 0; + eq.slider.y[i] = 0; + } +#endif + start_item = MIN(start_item, 5-nb_eq_sliders); for (i=0; i<5; i++) { cutoff = *setting++; @@ -363,12 +549,21 @@ break; if (i >= start_item) { - height += draw_eq_slider(screen, x, height, screen->lcdwidth - x - 1, - cutoff, q, gain, i == current_band, mode, - i); + height += draw_eq_slider(screen, x, height, slider_height, + screen->lcdwidth - x - EQ_OUTER_MARGIN_R, + cutoff, q, gain, i == current_band, mode, i); +#ifdef HAVE_TOUCHSCREEN + eq.slider.y[i] = height - slider_height; +#endif /* add a margin */ height++; } +#ifdef HAVE_TOUCHSCREEN + eq.slider.x = x + EQ_INNER_MARGIN + SLIDER_TOUCH_MARGIN; + eq.slider.length = screen->lcdwidth - eq.slider.x - SLIDER_TOUCH_MARGIN - + EQ_INNER_MARGIN - EQ_OUTER_MARGIN_R; + eq.slider.height = slider_height; +#endif } if (nb_eq_sliders != 5) gui_scrollbar_draw(screen, 0, y, SCROLLBAR_SIZE - 1, @@ -392,18 +587,43 @@ char buf[24]; int i, w, h, height, start_item, nb_eq_sliders[NB_SCREENS]; int barsenabled = viewportmanager_set_statusbar(VP_SB_HIDE_ALL); + int slider_height[NB_SCREENS]; +#ifdef HAVE_TOUCHSCREEN + touchscreen_set_mode(TOUCHSCREEN_POINT); +#endif FOR_NB_SCREENS(i) { screens[i].set_viewport(NULL); - screens[i].setfont(FONT_SYSFIXED); - screens[i].clear_display(); - /* Figure out how many sliders can be drawn on the screen */ + /* Select the font and figure out how many sliders can be drawn on */ + /* the screen. Use the theme font if possible */ + + screens[i].setfont(FONT_UI); screens[i].getstringsize("A", &w, &h); + if (w * 20 > screens[i].lcdwidth) + { /* 3 x 5 characters for setting items, 2 x 3 spaces, 1 x 4 for band label */ + screens[i].setfont(FONT_SYSFIXED); + screens[i].getstringsize("A", &w, &h); + } + slider_height[i] = (screens[i].lcdheight - h - 2 - 5 * + (3 + h + 1 + 3) - screens[i].lcdheight * 0.05) / 5; + /* calculate slider height so that the screen is filled out and 5% */ + /* free space is left at the buttom */ + if (slider_height[i] > 25) + { + slider_height[i] = 25; + } + else if (slider_height[i] < 6) + { + slider_height[i] = 6; + screens[i].setfont(FONT_SYSFIXED); + screens[i].getstringsize("A", &w, &h); + } + screens[i].clear_display(); /* Total height includes margins (1), text, slider, and line selector (1) */ - height = 3 + h + 1 + SCROLLBAR_SIZE + 3; + height = 3 + h + 1 + slider_height[i] + 3; nb_eq_sliders[i] = screens[i].lcdheight / height; /* Make sure the "Edit Mode" text fits too */ @@ -450,8 +670,8 @@ step = EQ_CUTOFF_STEP; fast_step = EQ_CUTOFF_FAST_STEP; - min = EQ_CUTOFF_MIN; - max = EQ_CUTOFF_MAX; + min = EQ_CUTOFF_MIN(current_band); + max = EQ_CUTOFF_MAX(current_band); voice_unit = UNIT_HERTZ; snprintf(buf, sizeof(buf), str(LANG_SYSFONT_EQUALIZER_EDIT_MODE), @@ -485,20 +705,190 @@ } else { start_item = current_band - 1; } - x = SCROLLBAR_SIZE; + x = SCROLLBAR_SIZE + EQ_OUTER_MARGIN_L; } else { - x = 1; + x = EQ_OUTER_MARGIN_L; start_item = 0; } /* Draw equalizer band details */ - draw_eq_sliders(&screens[i], x, y, nb_eq_sliders[i], start_item, - current_band, mode); + draw_eq_sliders(&screens[i], x, y, nb_eq_sliders[i], slider_height[i], + start_item, current_band, mode); screens[i].update(); } button = get_action(CONTEXT_SETTINGS_EQ,TIMEOUT_BLOCK); +#ifdef HAVE_TOUCHSCREEN + +#define EQ_ITEM 1 +#define SLIDER 2 +#define EQ_SLIDER_TCONST 2 + + static bool slider_change = false; + static bool band_changed = false; + + if ((button == ACTION_TOUCHSCREEN && + touchscreen_get_mode() == TOUCHSCREEN_POINT) || + slider_change || band_changed) + { + short touched_item = 0; + 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 < eq.setting_item.y[0] && touch_x > eq.slider.x) + { + button = ACTION_STD_CANCEL; + slider_change = false; + band_changed = false; + /* leave the menue when "Edit Mode" line is touched */ + } + else + { + button = BUTTON_NONE; + selected_band = 0; + if (touch_x >= eq.slider.x && !band_changed) + { + do { /* find out which item and band has been touched */ + if ( touch_y >= eq.setting_item.y[selected_band] && + (touch_y <= (eq.slider.y[selected_band] + + eq.slider.height))) + { + if (touch_y <= eq.setting_item.y[selected_band] + + eq.setting_item.height) + { + touched_item = EQ_ITEM; + } + else + { + touched_item = SLIDER; + } + } + else + { + selected_band++; + } + } while (selected_band <= 5 && !touched_item); + } + } + + if (touched_item || slider_change) + { + if (!slider_change) + { + if (current_band != selected_band) { + band_changed = true; + current_band = selected_band; + } + else if (touched_item == SLIDER) { + slider_change = true; + } + } + + if (!(band_changed || slider_change)) + { + if (touched_item == EQ_ITEM) + { + if (touch_x >= eq.setting_item.x[0] && + (touch_x <= eq.setting_item.x[0] + + eq.setting_item.width[0])) + { + mode = GAIN; + } + else if (touch_x >= eq.setting_item.x[1] && + (touch_x <= eq.setting_item.x[1] + + eq.setting_item.width[1])) + { + mode = CUTOFF; + } + else if (touch_x >= eq.setting_item.x[2] && + (touch_x <= eq.setting_item.x[2] + + eq.setting_item.width[2])) + { + mode = Q; + } + } + + if (current_band != selected_band) { + band_changed = true; + current_band = selected_band; + } + else if (touched_item == SLIDER) { + slider_change = true; + } + } + + if (slider_change && !band_changed) + { + if (mode == GAIN) { + target_value = max * 2 * (touch_x - eq.slider.x - + eq.slider.length/2) / eq.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.slider.x) / eq.slider.length); + } + else if (mode == Q) { + target_value = min + ((max-min) * (touch_x - + eq.slider.x) / eq.slider.length); + } + + target_value = (target_value / step) * step; + + 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; + } + + if (band_changed && (button_touchscreen & BUTTON_REL)) { + band_changed = false; + } + } +#endif + switch (button) { case ACTION_SETTINGS_DEC: case ACTION_SETTINGS_DECREPEAT: @@ -553,6 +943,9 @@ case ACTION_STD_CANCEL: exit_request = true; result = false; +#ifdef HAVE_TOUCHSCREEN + touchscreen_set_mode(global_settings.touch_mode); +#endif break; default: if(default_event_handler(button) == SYS_USB_CONNECTED) { Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (Revision 23110) +++ apps/settings_list.c (Arbeitskopie) @@ -1229,20 +1229,20 @@ get_precut_talkid, dsp_set_eq_precut), /* 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, - EQ_CUTOFF_MAX, EQ_CUTOFF_STEP, NULL, NULL, NULL), + 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, EQ_CUTOFF_MIN, - EQ_CUTOFF_MAX, EQ_CUTOFF_STEP, NULL, NULL, NULL), + 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, EQ_CUTOFF_MIN, - EQ_CUTOFF_MAX, EQ_CUTOFF_STEP, NULL, NULL, NULL), + 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, EQ_CUTOFF_MIN, - EQ_CUTOFF_MAX, EQ_CUTOFF_STEP, NULL, NULL, NULL), + 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, EQ_CUTOFF_MIN, - EQ_CUTOFF_MAX, EQ_CUTOFF_STEP, NULL, NULL, NULL), + 12000, "eq band 4 cutoff", UNIT_HERTZ, 2000, + 22040, EQ_CUTOFF_STEP, NULL, NULL, NULL), /* 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,