4 * Copyright 2004, 2006 Develer S.r.l. (http://www.develer.com/)
5 * This file is part of DevLib - See README.devlib for information.
8 * \brief Generic editor for (volume/gain/contrast/...) setting.
11 * \author Stefano Fedrigo <aleph@develer.com>
14 #include "leveledit.h"
16 #include <cfg/macros.h> /* MAX() */
18 #include <drv/timer.h>
19 #include <gui/levelbar.h>
20 #include <mware/pgm.h>
23 #include <appconfig.h>
25 #if CONFIG_MENU_MENUBAR
26 #include <gui/menubar.h>
29 // BEGIN project_grl LOCAL
30 #include <drv/lcd_gfx.h>
31 #include <gui/guiman.h>
32 // END project_grl LOCAL
34 #define LBAR_HEIGHT 16
37 * Allow user to change level.
39 void level_edit(struct LevelEdit *lev)
41 #if CONFIG_MENU_MENUBAR
42 /* Labels for menubars */
43 enum LabelId ch_labels[] = { LABEL_C1PLUS2, LABEL_CH_1, LABEL_CH_2 };
44 const_iptr_t labels[] =
46 (const_iptr_t)LABEL_BACK,
47 (const_iptr_t)LABEL_MINUS,
48 (const_iptr_t)LABEL_PLUS,
49 (const_iptr_t)LABEL_EMPTY
52 #endif /* CONFIG_MENU_MENUBAR */
54 struct LevelBar bar1, bar2;
55 keymask_t keys, old_rpt_mask;
58 rep_step = MAX(lev->step, ((lev->max - lev->min) / 200));
61 // Allow keys repetition.
62 old_rpt_mask = kbd_setRepeatMask(K_UP | K_DOWN);
64 text_clear(lev->bitmap);
65 //text_style(STYLEF_UNDERLINE, STYLEF_UNDERLINE);
66 text_puts(lev->title, lev->bitmap);
67 //text_style(0, STYLEF_UNDERLINE);
69 if (lev->type & LEVELEDIT_DOUBLE)
71 int chn = 0; /* edit both channels */
74 lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
75 lev->min, lev->max, *lev->ch1_val, 0, 16, lev->bitmap->width / 2 - 1, 23);
76 lbar_init(&bar2, lev->bitmap, LBAR_HORIZONTAL,
77 lev->min, lev->max, *lev->ch2_val, lev->bitmap->width / 2 + 1, 16, lev->bitmap->width, 23);
79 #if CONFIG_MENU_MENUBAR
80 labels[3] = (const_iptr_t)ch_labels[chn];
81 mbar_init(&mb, lev->bitmap, labels, countof(labels));
83 #endif /* CONFIG_MENU_MENUBAR */
85 /* Input loop for double level setting */
88 #if CONFIG_LEVELEDIT_TIMEOUT != 0
89 ticks_t idle_timeout = timer_clock();
93 if (lev->display_hook)
94 lev->display_hook(lev);
97 text_xprintf(lev->bitmap, 1, 0, TEXT_CENTER | TEXT_FILL, lev->unit);
98 PGM_FUNC(text_xprintf)(lev->bitmap, 1, 3, 0, PGM_STR("%d"), *lev->ch1_val);
99 PGM_FUNC(text_xprintf)(lev->bitmap, 1, 14, 0, PGM_STR("%d"), *lev->ch2_val);
101 lbar_setLevel(&bar1, *lev->ch1_val);
102 lbar_setLevel(&bar2, *lev->ch2_val);
107 #if CONFIG_LEVELEDIT_TIMEOUT != 0
108 if (timer_clock() - idle_timeout > ms_to_ticks(CONFIG_LEVELEDIT_TIMEOUT))
110 /* Accept input implicitly */
116 while (!(keys = kbd_peek()));
125 #if CONFIG_MENU_MENUBAR
126 labels[3] = (const_iptr_t)ch_labels[chn];
128 #endif /* CONFIG_MENU_MENUBAR */
131 /* Increment step to achieve greater accelerations on larger values */
133 step = MIN(rep_step, step + 1);
137 if (keys & (K_UP | K_DOWN))
141 /* If changing both channels (chn == 0), don't change
142 * level if one of two is at min or max */
144 (*lev->ch1_val + step <= lev->max
145 && *lev->ch2_val + step <= lev->max))
147 /* If chn == 0 change both channels */
150 *lev->ch1_val += step;
151 if (*lev->ch1_val > lev->max)
152 *lev->ch1_val = lev->max;
156 *lev->ch2_val += step;
157 if (*lev->ch2_val > lev->max)
158 *lev->ch2_val = lev->max;
165 (*lev->ch1_val - step >= lev->min
166 && *lev->ch2_val - step >= lev->min))
170 *lev->ch1_val -= step;
171 if (*lev->ch1_val < lev->min)
172 *lev->ch1_val = lev->min;
176 *lev->ch2_val -= step;
177 if (*lev->ch2_val < lev->min)
178 *lev->ch2_val = lev->min;
190 const PGM_ATTR char *fmt = lev->unit ? PGM_STR("%d %s") : PGM_STR("%d");
193 const int textw = MAX(PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->max, lev->unit),
194 PGM_FUNC(text_widthf)(lev->bitmap, fmt, lev->min, lev->unit));
196 const coord_t barlen = lev->bitmap->width - 6 - textw;
198 const coord_t barlen = lev->bitmap->width;
199 const coord_t barvtop = lev->bitmap->height / 2 - LBAR_HEIGHT/2 + lev->bitmap->font->height;
200 lbar_init(&bar1, lev->bitmap, LBAR_HORIZONTAL,
201 lev->min, lev->max, *lev->ch1_val,
202 0, barvtop, barlen, barvtop + LBAR_HEIGHT);
204 #if CONFIG_MENU_MENUBAR
205 mbar_init(&mb, lev->bitmap, labels, countof(labels));
207 #endif /* CONFIG_MENU_MENUBAR */
209 /* Input loop for single level setting */
212 #if CONFIG_LEVELEDIT_TIMEOUT != 0
213 ticks_t idle_timeout = timer_clock();
217 if (lev->display_hook)
218 lev->display_hook(lev);
221 if (lev->type != LEVELEDIT_NOBAR)
223 lbar_setLevel(&bar1, *lev->ch1_val);
226 PGM_FUNC(text_xyprintf)(lev->bitmap, 0, bar1.y1 - lev->bitmap->font->height,
227 TEXT_CENTER | TEXT_FILL, fmt, *lev->ch1_val, lev->unit);
230 #if CONFIG_LEVELEDIT_TIMEOUT != 0
231 if (timer_clock() - idle_timeout > CONFIG_LEVELEDIT_TIMEOUT)
233 /* Accept input implicitly */
239 // BEGIN project_grl LOCAL
241 //FIXME: must to this only when needed
242 lcd_blitBitmap(&lcd_bitmap);
244 while (!(keys = GuiMan_KbdPeek()));
247 while (!(keys = kbd_peek()));
249 // END project_grl LOCAL
254 /* Increment step to achieve greater accelerations on larger values */
256 step = MIN(rep_step, step + 1);
262 *lev->ch1_val += step;
263 if (*lev->ch1_val > lev->max)
264 *lev->ch1_val = lev->max;
269 *lev->ch1_val -= step;
270 if (*lev->ch1_val < lev->min)
271 *lev->ch1_val = lev->min;
279 kbd_setRepeatMask(old_rpt_mask);
283 * LevelEdit structure initialization.
284 * Init data structure and init LevelEdit widgets.
286 void level_init(struct LevelEdit *lev,
288 struct Bitmap *bmp, const char *title, const char *unit,
289 int min, int max, int step,
290 int *ch1_val, int *ch2_val,
291 level_set_callback *set_hook, display_callback *display_hook)
301 lev->ch1_val = ch1_val;
302 lev->ch2_val = ch2_val;
303 lev->set_hook = set_hook;
304 lev->display_hook = display_hook;