blob: 1f04ef22492f70d6e846cb7a7253be19f7053684 [file] [log] [blame]
Daniel Stenberg1c0c8612002-05-17 12:22:24 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Robert E. Hak
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
Björn Stenberg2ac05722002-05-26 17:03:17 +000019#include <stdbool.h>
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000020#include "lcd.h"
21#include "menu.h"
Björn Stenbergb21a3bd2002-05-21 14:25:45 +000022#include "button.h"
23#include "kernel.h"
24#include "debug.h"
Justin Heiner26302452002-08-23 02:17:00 +000025#include "usb.h"
Björn Stenbergcd225732002-08-11 09:17:47 +000026#include "panic.h"
Markus Braun5e4c1d22002-08-20 19:37:00 +000027#include "settings.h"
28#include "status.h"
Daniel Stenbergbf603f92002-06-14 08:47:44 +000029#ifdef HAVE_LCD_BITMAP
30#include "icons.h"
31#endif
Björn Stenbergcd225732002-08-11 09:17:47 +000032#ifdef LOADABLE_FONTS
33#include "ajf.h"
34#endif
Markus Braun5e4c1d22002-08-20 19:37:00 +000035
Björn Stenberg2ac05722002-05-26 17:03:17 +000036struct menu {
Björn Stenbergf76cee72002-05-28 15:35:33 +000037 int top;
Björn Stenberg2ac05722002-05-26 17:03:17 +000038 int cursor;
39 struct menu_items* items;
40 int itemcount;
41};
42
43#define MAX_MENUS 4
44
Björn Stenbergf76cee72002-05-28 15:35:33 +000045#ifdef HAVE_LCD_BITMAP
Markus Braun5e4c1d22002-08-20 19:37:00 +000046#define LINE_Y (global_settings.statusbar ? 1 : 0) /* Y position the entry-list starts at */
47#define LINE_HEIGTH 8 /* pixels for each text line */
48#define MENU_LINES (LCD_HEIGHT / LINE_HEIGTH - LINE_Y)
Björn Stenbergf76cee72002-05-28 15:35:33 +000049#else
50#define MENU_LINES 2
51#endif
52
Björn Stenberg9314a682002-05-31 09:04:51 +000053#ifdef HAVE_NEW_CHARCELL_LCD
54#define CURSOR_CHAR "\x7e"
55#else
56#define CURSOR_CHAR "\x89"
57#endif
Björn Stenberg9314a682002-05-31 09:04:51 +000058
Björn Stenberg2ac05722002-05-26 17:03:17 +000059static struct menu menus[MAX_MENUS];
60static bool inuse[MAX_MENUS] = { false };
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000061
Daniel Stenbergbf603f92002-06-14 08:47:44 +000062/* count in letter posistions, NOT pixels */
63void put_cursorxy(int x, int y, bool on)
64{
Björn Stenberg71f71ef2002-08-11 09:20:53 +000065#ifdef HAVE_LCD_BITMAP
Björn Stenbergcd225732002-08-11 09:17:47 +000066#ifdef LOADABLE_FONTS
67 int fh;
68 unsigned char* font = lcd_getcurrentldfont();
69 fh = ajf_get_fontheight(font);
70#else
71 int fh = 8;
72#endif
Björn Stenberg71f71ef2002-08-11 09:20:53 +000073#endif
Björn Stenbergcd225732002-08-11 09:17:47 +000074
Daniel Stenbergbf603f92002-06-14 08:47:44 +000075 /* place the cursor */
76 if(on) {
77#ifdef HAVE_LCD_BITMAP
78 lcd_bitmap ( bitmap_icons_6x8[Cursor],
Markus Braun5e4c1d22002-08-20 19:37:00 +000079 x*6, y*fh + lcd_getymargin(), 4, 8, true);
Daniel Stenberge35f8eb2002-06-15 11:39:36 +000080#elif defined(SIMULATOR)
Daniel Stenbergc4be1ee2002-06-19 13:00:14 +000081 /* player simulator */
Daniel Stenberge35f8eb2002-06-15 11:39:36 +000082 unsigned char cursor[] = { 0x7f, 0x3e, 0x1c, 0x08 };
Daniel Stenberg7cdf5c82002-08-09 09:13:00 +000083 lcd_bitmap ( cursor, x*6, 12+y*16, 4, 8, true);
Daniel Stenbergbf603f92002-06-14 08:47:44 +000084#else
85 lcd_puts(x, y, CURSOR_CHAR);
86#endif
87 }
88 else {
Daniel Stenbergc4be1ee2002-06-19 13:00:14 +000089#if defined(HAVE_LCD_BITMAP)
Daniel Stenbergbf603f92002-06-14 08:47:44 +000090 /* I use xy here since it needs to disregard the margins */
Markus Braun5e4c1d22002-08-20 19:37:00 +000091 lcd_clearrect (x*6, y*fh + lcd_getymargin(), 4, 8);
Daniel Stenbergc4be1ee2002-06-19 13:00:14 +000092#elif defined(SIMULATOR)
93 /* player simulator in action */
Daniel Stenberg7cdf5c82002-08-09 09:13:00 +000094 lcd_clearrect (x*6, 12+y*16, 4, 8);
Daniel Stenbergbf603f92002-06-14 08:47:44 +000095#else
96 lcd_puts(x, y, " ");
97#endif
98 }
99}
100
Björn Stenbergf76cee72002-05-28 15:35:33 +0000101static void menu_draw(int m)
102{
103 int i = 0;
Björn Stenbergcd225732002-08-11 09:17:47 +0000104#ifdef LOADABLE_FONTS
105 int menu_lines;
106 int fh;
107 unsigned char* font = lcd_getcurrentldfont();
108 fh = ajf_get_fontheight(font);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000109 if (global_settings.statusbar)
110 menu_lines = (LCD_HEIGHT - STATUSBAR_HEIGHT) / fh;
111 else
112 menu_lines = LCD_HEIGHT/fh;
Björn Stenbergcd225732002-08-11 09:17:47 +0000113#else
114 int menu_lines = MENU_LINES;
115#endif
Björn Stenbergf76cee72002-05-28 15:35:33 +0000116
Daniel Stenberga8e89fd2002-08-22 21:45:22 +0000117 lcd_scroll_pause(); /* halt scroll first... */
118 lcd_clear_display(); /* ...then clean the screen */
Björn Stenbergf76cee72002-05-28 15:35:33 +0000119#ifdef HAVE_LCD_BITMAP
Markus Braun5e4c1d22002-08-20 19:37:00 +0000120 if(global_settings.statusbar)
121 lcd_setmargins(0, STATUSBAR_HEIGHT);
122 else
123 lcd_setmargins(0, 0);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000124 lcd_setfont(0);
125#endif
Markus Braun5e4c1d22002-08-20 19:37:00 +0000126 /* correct cursor pos if out of screen */
127 if (menus[m].cursor - menus[m].top >= menu_lines)
128 menus[m].top++;
129
Björn Stenbergf76cee72002-05-28 15:35:33 +0000130 for (i = menus[m].top;
Björn Stenbergcd225732002-08-11 09:17:47 +0000131 (i < menus[m].itemcount) && (i<menus[m].top+menu_lines);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000132 i++) {
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000133 if((menus[m].cursor - menus[m].top)==(i-menus[m].top))
134 lcd_puts_scroll(1, i-menus[m].top, menus[m].items[i].desc);
135 else
136 lcd_puts(1, i-menus[m].top, menus[m].items[i].desc);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000137 }
Robert Hakc501ac72002-05-30 08:06:42 +0000138
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000139 /* place the cursor */
140 put_cursorxy(0, menus[m].cursor - menus[m].top, true);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000141#ifdef HAVE_LCD_BITMAP
142 status_draw();
143#endif
Björn Stenbergf76cee72002-05-28 15:35:33 +0000144 lcd_update();
145}
146
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000147/*
148 * Move the cursor to a particular id,
149 * target: where you want it to be
150 */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000151static void put_cursor(int m, int target)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000152{
Robert Hakc501ac72002-05-30 08:06:42 +0000153 bool do_update = true;
Björn Stenbergcd225732002-08-11 09:17:47 +0000154#ifdef LOADABLE_FONTS
155 int menu_lines;
156 int fh;
157 unsigned char* font = lcd_getcurrentldfont();
158 fh = ajf_get_fontheight(font);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000159 if (global_settings.statusbar)
160 menu_lines = (LCD_HEIGHT-STATUSBAR_HEIGHT)/fh;
161 else
162 menu_lines = LCD_HEIGHT/fh;
Björn Stenbergcd225732002-08-11 09:17:47 +0000163#else
164 int menu_lines = MENU_LINES;
165#endif
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000166 put_cursorxy(0, menus[m].cursor - menus[m].top, false);
Robert Hakc501ac72002-05-30 08:06:42 +0000167 menus[m].cursor = target;
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000168 menu_draw(m);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000169
170 if ( target < menus[m].top ) {
171 menus[m].top--;
172 menu_draw(m);
Robert Hakc501ac72002-05-30 08:06:42 +0000173 do_update = false;
Björn Stenbergf76cee72002-05-28 15:35:33 +0000174 }
Björn Stenbergcd225732002-08-11 09:17:47 +0000175 else if ( target-menus[m].top > menu_lines-1 ) {
Björn Stenbergf76cee72002-05-28 15:35:33 +0000176 menus[m].top++;
177 menu_draw(m);
Robert Hakc501ac72002-05-30 08:06:42 +0000178 do_update = false;
Björn Stenbergf76cee72002-05-28 15:35:33 +0000179 }
Robert Hakc501ac72002-05-30 08:06:42 +0000180
181 if (do_update) {
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000182 put_cursorxy(0, menus[m].cursor - menus[m].top, true);
Robert Hakc501ac72002-05-30 08:06:42 +0000183 lcd_update();
184 }
185
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000186}
187
Björn Stenberg2ac05722002-05-26 17:03:17 +0000188int menu_init(struct menu_items* mitems, int count)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000189{
Björn Stenberg2ac05722002-05-26 17:03:17 +0000190 int i;
191
192 for ( i=0; i<MAX_MENUS; i++ ) {
193 if ( !inuse[i] ) {
194 inuse[i] = true;
195 break;
196 }
197 }
198 if ( i == MAX_MENUS ) {
199 DEBUGF("Out of menus!\n");
200 return -1;
201 }
202 menus[i].items = mitems;
203 menus[i].itemcount = count;
Björn Stenbergf76cee72002-05-28 15:35:33 +0000204 menus[i].top = 0;
Björn Stenberg2ac05722002-05-26 17:03:17 +0000205 menus[i].cursor = 0;
206
207 return i;
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000208}
209
Björn Stenberg2ac05722002-05-26 17:03:17 +0000210void menu_exit(int m)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000211{
Björn Stenberg2ac05722002-05-26 17:03:17 +0000212 inuse[m] = false;
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000213}
214
Björn Stenberg2ac05722002-05-26 17:03:17 +0000215void menu_run(int m)
Robert Hak7ec9aa32002-05-18 11:41:37 +0000216{
Justin Heiner26302452002-08-23 02:17:00 +0000217 bool laststate;
218
Björn Stenberg2ac05722002-05-26 17:03:17 +0000219 menu_draw(m);
Justin Heiner26302452002-08-23 02:17:00 +0000220
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000221 while(1) {
Markus Braun5e4c1d22002-08-20 19:37:00 +0000222 switch( button_get_w_tmo(HZ/2) ) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000223#ifdef HAVE_RECORDER_KEYPAD
224 case BUTTON_UP:
Björn Stenbergcbc71792002-08-10 09:04:55 +0000225 case BUTTON_UP | BUTTON_REPEAT:
Robert Hak7ec9aa32002-05-18 11:41:37 +0000226#else
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000227 case BUTTON_LEFT:
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000228 case BUTTON_LEFT | BUTTON_REPEAT:
Robert Hak7ec9aa32002-05-18 11:41:37 +0000229#endif
Björn Stenberg4caebab2002-05-29 14:25:06 +0000230 if (menus[m].cursor) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000231 /* move up */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000232 put_cursor(m, menus[m].cursor-1);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000233 }
234 break;
Robert Hakdfba2102002-05-21 08:47:34 +0000235
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000236#ifdef HAVE_RECORDER_KEYPAD
237 case BUTTON_DOWN:
Björn Stenbergcbc71792002-08-10 09:04:55 +0000238 case BUTTON_DOWN | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000239#else
240 case BUTTON_RIGHT:
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000241 case BUTTON_RIGHT | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000242#endif
Björn Stenberg4caebab2002-05-29 14:25:06 +0000243 if (menus[m].cursor < menus[m].itemcount-1) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000244 /* move down */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000245 put_cursor(m, menus[m].cursor+1);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000246 }
247 break;
248
249#ifdef HAVE_RECORDER_KEYPAD
250 case BUTTON_RIGHT:
251#endif
252 case BUTTON_PLAY:
253 /* Erase current display state */
Daniel Stenberga8e89fd2002-08-22 21:45:22 +0000254 lcd_scroll_pause(); /* pause is better than stop when
255 are gonna clear the screen anyway */
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000256 lcd_clear_display();
257
Björn Stenberg2ac05722002-05-26 17:03:17 +0000258 menus[m].items[menus[m].cursor].function();
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000259
260 /* Return to previous display state */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000261 menu_draw(m);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000262 break;
263
264#ifdef HAVE_RECORDER_KEYPAD
265 case BUTTON_LEFT:
Linus Nielsen Feltzinga552f4c2002-07-27 19:53:26 +0000266 case BUTTON_F1:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000267#else
268 case BUTTON_STOP:
Björn Stenberg60fad542002-05-29 12:28:08 +0000269 case BUTTON_MENU:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000270#endif
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000271 lcd_stop_scroll();
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000272 return;
273
Markus Braun5e4c1d22002-08-20 19:37:00 +0000274#ifdef HAVE_RECORDER_KEYPAD
275 case BUTTON_F3:
276#ifdef HAVE_LCD_BITMAP
277 global_settings.statusbar = !global_settings.statusbar;
278 settings_save();
279 menu_draw(m);
280#endif
281 break;
282#endif
283
Justin Heiner26302452002-08-23 02:17:00 +0000284#ifndef SIMULATOR
285 case SYS_USB_CONNECTED:
286#ifdef HAVE_LCD_BITMAP
287 laststate = statusbar(false);
288#endif
289 usb_acknowledge(SYS_USB_CONNECTED_ACK);
290 usb_wait_for_disconnect(&button_queue);
291 menu_draw(m);
292#ifdef HAVE_LCD_BITMAP
293 statusbar(laststate);
294#else
295 lcd_icon(ICON_PARAM, true);
296#endif
297 break;
298#endif
299
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000300 default:
301 break;
302 }
303
Markus Braun5e4c1d22002-08-20 19:37:00 +0000304 status_draw();
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000305 lcd_update();
306 }
Robert Hak7ec9aa32002-05-18 11:41:37 +0000307}