4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/)
33 * \brief Generic editor for (volume/gain/contrast/...) setting.
36 * \author Stefano Fedrigo <aleph@develer.com>
39 #include "leveledit.h"
41 #include <appconfig.h>
42 #include <cfg/macros.h> /* MAX() */
45 #include <drv/timer.h>
47 #include <gui/levelbar.h>
49 #include <mware/pgm.h>
54 #if CONFIG_MENU_MENUBAR
55 #include <gui/menubar.h>
58 // BEGIN project_grl LOCAL
59 #include <drv/lcd_gfx.h>
60 #include <gui/guiman.h>
61 // END project_grl LOCAL
63 #warning FIXME: Revise me!
65 #define LBAR_HEIGHT 16
68 * Allow user to change level.
70 void level_edit(struct LevelEdit *lev)
72 #if CONFIG_MENU_MENUBAR
73 /* Labels for menubars */
74 enum LabelId ch_labels[] = { LABEL_C1PLUS2, LABEL_CH_1, LABEL_CH_2 };
75 const_iptr_t labels[] =
77 (const_iptr_t)LABEL_BACK,
78 (const_iptr_t)LABEL_MINUS,
79 (const_iptr_t)LABEL_PLUS,
80 (const_iptr_t)LABEL_EMPTY
83 #endif /* CONFIG_MENU_MENUBAR */
85 struct LevelBar bar1, bar2;
86 keymask_t keys, old_rpt_mask;
89 rep_step = MAX(lev->step, ((lev->max - lev->min) / 200));
92 // Allow keys repetition.
93 old_rpt_mask = kbd_setRepeatMask(K_UP | K_DOWN);
95 text_clear(lev->bitmap);
96 //text_style(STYLEF_UNDERLINE, STYLEF_UNDERLINE);
97 text_puts(lev->title, lev->bitmap);
98 //text_style(0, STYLEF_UNDERLINE);
100 if (lev->type & LEVELEDIT_DOUBLE)
102 int chn = 0; /* edit both channels */
105 lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
106 lev->min, lev->max, *lev->ch1_val, 0, 16, lev->bitmap->width / 2 - 1, 23);
107 lbar_init(&bar2, lev->bitmap, LBAR_HORIZONTAL,
108 lev->min, lev->max, *lev->ch2_val, lev->bitmap->width / 2 + 1, 16, lev->bitmap->width, 23);
110 #if CONFIG_MENU_MENUBAR
111 labels[3] = (const_iptr_t)ch_labels[chn];
112 mbar_init(&mb, lev->bitmap, labels, countof(labels));
114 #endif /* CONFIG_MENU_MENUBAR */
116 /* Input loop for double level setting */
119 #if CONFIG_LEVELEDIT_TIMEOUT != 0
120 ticks_t idle_timeout = timer_clock();
124 if (lev->display_hook)
125 lev->display_hook(lev);
128 text_xprintf(lev->bitmap, 1, 0, TEXT_CENTER | TEXT_FILL, lev->unit);
129 PGM_FUNC(text_xprintf)(lev->bitmap, 1, 3, 0, PGM_STR("%d"), *lev->ch1_val);
130 PGM_FUNC(text_xprintf)(lev->bitmap, 1, 14, 0, PGM_STR("%d"), *lev->ch2_val);
132 lbar_setLevel(&bar1, *lev->ch1_val);
133 lbar_setLevel(&bar2, *lev->ch2_val);
138 #if CONFIG_LEVELEDIT_TIMEOUT != 0
139 if (timer_clock() - idle_timeout > ms_to_ticks(CONFIG_LEVELEDIT_TIMEOUT))
141 /* Accept input implicitly */
147 while (!(keys = kbd_peek()));
156 #if CONFIG_MENU_MENUBAR
157 labels[3] = (const_iptr_t)ch_labels[chn];
159 #endif /* CONFIG_MENU_MENUBAR */
162 /* Increment step to achieve greater accelerations on larger values */
164 step = MIN(rep_step, step + 1);
168 if (keys & (K_UP | K_DOWN))
172 /* If changing both channels (chn == 0), don't change
173 * level if one of two is at min or max */
175 (*lev->ch1_val + step <= lev->max
176 && *lev->ch2_val + step <= lev->max))
178 /* If chn == 0 change both channels */
181 *lev->ch1_val += step;
182 if (*lev->ch1_val > lev->max)
183 *lev->ch1_val = lev->max;
187 *lev->ch2_val += step;
188 if (*lev->ch2_val > lev->max)
189 *lev->ch2_val = lev->max;
196 (*lev->ch1_val - step >= lev->min
197 && *lev->ch2_val - step >= lev->min))
201 *lev->ch1_val -= step;
202 if (*lev->ch1_val < lev->min)
203 *lev->ch1_val = lev->min;
207 *lev->ch2_val -= step;
208 if (*lev->ch2_val < lev->min)
209 *lev->ch2_val = lev->min;
221 const PGM_ATTR char *fmt = lev->unit ? PGM_STR("%d %s") : PGM_STR("%d");
224 const int textw = MAX(PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->max, lev->unit),
225 PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->min, lev->unit));
227 const coord_t barlen = lev->bitmap->width - 6 - textw;
229 const coord_t barlen = lev->bitmap->width;
230 const coord_t barvtop = lev->bitmap->height / 2 - LBAR_HEIGHT/2 + lev->bitmap->font->height;
231 lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
232 lev->min, lev->max, *lev->ch1_val,
233 0, barvtop, barlen, barvtop + LBAR_HEIGHT);
235 #if CONFIG_MENU_MENUBAR
236 mbar_init(&mb, lev->bitmap, labels, countof(labels));
238 #endif /* CONFIG_MENU_MENUBAR */
240 /* Input loop for single level setting */
243 #if CONFIG_LEVELEDIT_TIMEOUT != 0
244 ticks_t idle_timeout = timer_clock();
248 if (lev->display_hook)
249 lev->display_hook(lev);
252 if (lev->type != LEVELEDIT_NOBAR)
254 lbar_setLevel(&bar1, *lev->ch1_val);
257 PGM_FUNC(text_xyprintf)(lev->bitmap, 0, bar1.y1 - lev->bitmap->font->height,
258 TEXT_CENTER | TEXT_FILL, fmt, *lev->ch1_val, lev->unit);
261 #if CONFIG_LEVELEDIT_TIMEOUT != 0
262 if (timer_clock() - idle_timeout > CONFIG_LEVELEDIT_TIMEOUT)
264 /* Accept input implicitly */
270 // BEGIN project_grl LOCAL
272 //FIXME: must to this only when needed
273 lcd_blitBitmap(&lcd_bitmap);
275 while (!(keys = GuiMan_KbdPeek()));
278 while (!(keys = kbd_peek()));
280 // END project_grl LOCAL
285 /* Increment step to achieve greater accelerations on larger values */
287 step = MIN(rep_step, step + 1);
293 *lev->ch1_val += step;
294 if (*lev->ch1_val > lev->max)
295 *lev->ch1_val = lev->max;
300 *lev->ch1_val -= step;
301 if (*lev->ch1_val < lev->min)
302 *lev->ch1_val = lev->min;
310 kbd_setRepeatMask(old_rpt_mask);
314 * LevelEdit structure initialization.
315 * Init data structure and init LevelEdit widgets.
317 void level_init(struct LevelEdit *lev,
319 struct Bitmap *bmp, const char *title, const char *unit,
320 int min, int max, int step,
321 int *ch1_val, int *ch2_val,
322 level_set_callback *set_hook, display_callback *display_hook)
332 lev->ch1_val = ch1_val;
333 lev->ch2_val = ch2_val;
334 lev->set_hook = set_hook;
335 lev->display_hook = display_hook;