blob: f0c793a78029a75281954ff9dca74f9006fb51ae [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"
Markus Braun000c2db2002-08-30 13:49:32 +000029
Daniel Stenbergbf603f92002-06-14 08:47:44 +000030#ifdef HAVE_LCD_BITMAP
31#include "icons.h"
Markus Braun000c2db2002-08-30 13:49:32 +000032#include "widgets.h"
Daniel Stenbergbf603f92002-06-14 08:47:44 +000033#endif
Markus Braun000c2db2002-08-30 13:49:32 +000034
Björn Stenbergcd225732002-08-11 09:17:47 +000035#ifdef LOADABLE_FONTS
36#include "ajf.h"
37#endif
Markus Braun5e4c1d22002-08-20 19:37:00 +000038
Björn Stenberg2ac05722002-05-26 17:03:17 +000039struct menu {
Björn Stenbergf76cee72002-05-28 15:35:33 +000040 int top;
Björn Stenberg2ac05722002-05-26 17:03:17 +000041 int cursor;
42 struct menu_items* items;
43 int itemcount;
44};
45
46#define MAX_MENUS 4
47
Björn Stenbergf76cee72002-05-28 15:35:33 +000048#ifdef HAVE_LCD_BITMAP
Markus Braun000c2db2002-08-30 13:49:32 +000049
50#define MARGIN_X (global_settings.scrollbar ? SCROLLBAR_WIDTH : 0) + CURSOR_WIDTH /* X pixel margin */
51#define MARGIN_Y (global_settings.statusbar ? STATUSBAR_HEIGHT : 0) /* Y pixel margin */
52
53#define LINE_X 0 /* X position the entry-list starts at */
Markus Braun5e4c1d22002-08-20 19:37:00 +000054#define LINE_Y (global_settings.statusbar ? 1 : 0) /* Y position the entry-list starts at */
55#define LINE_HEIGTH 8 /* pixels for each text line */
Markus Braun000c2db2002-08-30 13:49:32 +000056
Markus Braun5e4c1d22002-08-20 19:37:00 +000057#define MENU_LINES (LCD_HEIGHT / LINE_HEIGTH - LINE_Y)
Markus Braun000c2db2002-08-30 13:49:32 +000058
59#define CURSOR_X (global_settings.scrollbar ? 1 : 0)
60#define CURSOR_Y 0 /* the cursor is not positioned in regard to
61 the margins, so this is the amount of lines
62 we add to the cursor Y position to position
63 it on a line */
64#define CURSOR_WIDTH 4
65
66#define SCROLLBAR_X 0
67#define SCROLLBAR_Y lcd_getymargin()
68#define SCROLLBAR_WIDTH 6
69
70#else /* HAVE_LCD_BITMAP */
71
72#define LINE_X 0 /* X position the entry-list starts at */
73
Björn Stenbergf76cee72002-05-28 15:35:33 +000074#define MENU_LINES 2
Markus Braun000c2db2002-08-30 13:49:32 +000075
76#define CURSOR_X 0
77#define CURSOR_Y 0 /* not really used for players */
78
79#endif /* HAVE_LCD_BITMAP */
Björn Stenbergf76cee72002-05-28 15:35:33 +000080
Björn Stenberg9314a682002-05-31 09:04:51 +000081#ifdef HAVE_NEW_CHARCELL_LCD
82#define CURSOR_CHAR "\x7e"
83#else
84#define CURSOR_CHAR "\x89"
85#endif
Björn Stenberg9314a682002-05-31 09:04:51 +000086
Björn Stenberg2ac05722002-05-26 17:03:17 +000087static struct menu menus[MAX_MENUS];
88static bool inuse[MAX_MENUS] = { false };
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000089
Daniel Stenbergbf603f92002-06-14 08:47:44 +000090/* count in letter posistions, NOT pixels */
91void put_cursorxy(int x, int y, bool on)
92{
Björn Stenberg71f71ef2002-08-11 09:20:53 +000093#ifdef HAVE_LCD_BITMAP
Björn Stenbergcd225732002-08-11 09:17:47 +000094#ifdef LOADABLE_FONTS
95 int fh;
96 unsigned char* font = lcd_getcurrentldfont();
97 fh = ajf_get_fontheight(font);
98#else
99 int fh = 8;
100#endif
Björn Stenberg71f71ef2002-08-11 09:20:53 +0000101#endif
Björn Stenbergcd225732002-08-11 09:17:47 +0000102
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000103 /* place the cursor */
104 if(on) {
105#ifdef HAVE_LCD_BITMAP
106 lcd_bitmap ( bitmap_icons_6x8[Cursor],
Markus Braun5e4c1d22002-08-20 19:37:00 +0000107 x*6, y*fh + lcd_getymargin(), 4, 8, true);
Daniel Stenberge35f8eb2002-06-15 11:39:36 +0000108#elif defined(SIMULATOR)
Daniel Stenbergc4be1ee2002-06-19 13:00:14 +0000109 /* player simulator */
Daniel Stenberge35f8eb2002-06-15 11:39:36 +0000110 unsigned char cursor[] = { 0x7f, 0x3e, 0x1c, 0x08 };
Daniel Stenberg7cdf5c82002-08-09 09:13:00 +0000111 lcd_bitmap ( cursor, x*6, 12+y*16, 4, 8, true);
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000112#else
113 lcd_puts(x, y, CURSOR_CHAR);
114#endif
115 }
116 else {
Daniel Stenbergc4be1ee2002-06-19 13:00:14 +0000117#if defined(HAVE_LCD_BITMAP)
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000118 /* I use xy here since it needs to disregard the margins */
Markus Braun5e4c1d22002-08-20 19:37:00 +0000119 lcd_clearrect (x*6, y*fh + lcd_getymargin(), 4, 8);
Daniel Stenbergc4be1ee2002-06-19 13:00:14 +0000120#elif defined(SIMULATOR)
121 /* player simulator in action */
Daniel Stenberg7cdf5c82002-08-09 09:13:00 +0000122 lcd_clearrect (x*6, 12+y*16, 4, 8);
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000123#else
124 lcd_puts(x, y, " ");
125#endif
126 }
127}
128
Björn Stenbergf76cee72002-05-28 15:35:33 +0000129static void menu_draw(int m)
130{
131 int i = 0;
Björn Stenbergcd225732002-08-11 09:17:47 +0000132#ifdef LOADABLE_FONTS
133 int menu_lines;
134 int fh;
135 unsigned char* font = lcd_getcurrentldfont();
136 fh = ajf_get_fontheight(font);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000137 if (global_settings.statusbar)
138 menu_lines = (LCD_HEIGHT - STATUSBAR_HEIGHT) / fh;
139 else
140 menu_lines = LCD_HEIGHT/fh;
Björn Stenbergcd225732002-08-11 09:17:47 +0000141#else
142 int menu_lines = MENU_LINES;
143#endif
Björn Stenbergf76cee72002-05-28 15:35:33 +0000144
Daniel Stenberga8e89fd2002-08-22 21:45:22 +0000145 lcd_scroll_pause(); /* halt scroll first... */
146 lcd_clear_display(); /* ...then clean the screen */
Björn Stenbergf76cee72002-05-28 15:35:33 +0000147#ifdef HAVE_LCD_BITMAP
Markus Braun000c2db2002-08-30 13:49:32 +0000148 lcd_setmargins(MARGIN_X,MARGIN_Y); /* leave room for cursor and icon */
Björn Stenbergf76cee72002-05-28 15:35:33 +0000149 lcd_setfont(0);
150#endif
Markus Braun5e4c1d22002-08-20 19:37:00 +0000151 /* correct cursor pos if out of screen */
152 if (menus[m].cursor - menus[m].top >= menu_lines)
153 menus[m].top++;
154
Björn Stenbergf76cee72002-05-28 15:35:33 +0000155 for (i = menus[m].top;
Björn Stenbergcd225732002-08-11 09:17:47 +0000156 (i < menus[m].itemcount) && (i<menus[m].top+menu_lines);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000157 i++) {
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000158 if((menus[m].cursor - menus[m].top)==(i-menus[m].top))
Markus Braun000c2db2002-08-30 13:49:32 +0000159 lcd_puts_scroll(LINE_X, i-menus[m].top, menus[m].items[i].desc);
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000160 else
Markus Braun000c2db2002-08-30 13:49:32 +0000161 lcd_puts(LINE_X, i-menus[m].top, menus[m].items[i].desc);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000162 }
Robert Hakc501ac72002-05-30 08:06:42 +0000163
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000164 /* place the cursor */
Markus Braun000c2db2002-08-30 13:49:32 +0000165 put_cursorxy(CURSOR_X, menus[m].cursor - menus[m].top, true);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000166#ifdef HAVE_LCD_BITMAP
Markus Braun000c2db2002-08-30 13:49:32 +0000167 if (global_settings.scrollbar)
168 scrollbar(SCROLLBAR_X, SCROLLBAR_Y, SCROLLBAR_WIDTH - 1,
169 LCD_HEIGHT - SCROLLBAR_Y, menus[m].itemcount, menus[m].top,
170 menus[m].top + menu_lines, VERTICAL);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000171#endif
Markus Braun000c2db2002-08-30 13:49:32 +0000172 status_draw();
Björn Stenbergf76cee72002-05-28 15:35:33 +0000173 lcd_update();
174}
175
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000176/*
177 * Move the cursor to a particular id,
178 * target: where you want it to be
179 */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000180static void put_cursor(int m, int target)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000181{
Robert Hakc501ac72002-05-30 08:06:42 +0000182 bool do_update = true;
Björn Stenbergcd225732002-08-11 09:17:47 +0000183#ifdef LOADABLE_FONTS
184 int menu_lines;
185 int fh;
186 unsigned char* font = lcd_getcurrentldfont();
187 fh = ajf_get_fontheight(font);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000188 if (global_settings.statusbar)
189 menu_lines = (LCD_HEIGHT-STATUSBAR_HEIGHT)/fh;
190 else
191 menu_lines = LCD_HEIGHT/fh;
Björn Stenbergcd225732002-08-11 09:17:47 +0000192#else
193 int menu_lines = MENU_LINES;
194#endif
Markus Braun000c2db2002-08-30 13:49:32 +0000195 put_cursorxy(CURSOR_X, menus[m].cursor - menus[m].top, false);
Robert Hakc501ac72002-05-30 08:06:42 +0000196 menus[m].cursor = target;
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000197 menu_draw(m);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000198
199 if ( target < menus[m].top ) {
200 menus[m].top--;
201 menu_draw(m);
Robert Hakc501ac72002-05-30 08:06:42 +0000202 do_update = false;
Björn Stenbergf76cee72002-05-28 15:35:33 +0000203 }
Björn Stenbergcd225732002-08-11 09:17:47 +0000204 else if ( target-menus[m].top > menu_lines-1 ) {
Björn Stenbergf76cee72002-05-28 15:35:33 +0000205 menus[m].top++;
206 menu_draw(m);
Robert Hakc501ac72002-05-30 08:06:42 +0000207 do_update = false;
Björn Stenbergf76cee72002-05-28 15:35:33 +0000208 }
Robert Hakc501ac72002-05-30 08:06:42 +0000209
210 if (do_update) {
Markus Braun000c2db2002-08-30 13:49:32 +0000211 put_cursorxy(CURSOR_X, menus[m].cursor - menus[m].top, true);
Robert Hakc501ac72002-05-30 08:06:42 +0000212 lcd_update();
213 }
214
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000215}
216
Björn Stenberg2ac05722002-05-26 17:03:17 +0000217int menu_init(struct menu_items* mitems, int count)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000218{
Björn Stenberg2ac05722002-05-26 17:03:17 +0000219 int i;
220
221 for ( i=0; i<MAX_MENUS; i++ ) {
222 if ( !inuse[i] ) {
223 inuse[i] = true;
224 break;
225 }
226 }
227 if ( i == MAX_MENUS ) {
228 DEBUGF("Out of menus!\n");
229 return -1;
230 }
231 menus[i].items = mitems;
232 menus[i].itemcount = count;
Björn Stenbergf76cee72002-05-28 15:35:33 +0000233 menus[i].top = 0;
Björn Stenberg2ac05722002-05-26 17:03:17 +0000234 menus[i].cursor = 0;
235
236 return i;
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000237}
238
Björn Stenberg2ac05722002-05-26 17:03:17 +0000239void menu_exit(int m)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000240{
Björn Stenberg2ac05722002-05-26 17:03:17 +0000241 inuse[m] = false;
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000242}
243
Daniel Stenbergb2850762002-08-23 12:32:52 +0000244Menu menu_run(int m)
Robert Hak7ec9aa32002-05-18 11:41:37 +0000245{
Justin Heiner0a3589d2002-08-23 02:45:39 +0000246#ifndef SIMULATOR
Justin Heineredf6b802002-08-23 02:26:22 +0000247#ifdef HAVE_LCD_BITMAP
Justin Heiner26302452002-08-23 02:17:00 +0000248 bool laststate;
Justin Heineredf6b802002-08-23 02:26:22 +0000249#endif
Justin Heiner0a3589d2002-08-23 02:45:39 +0000250#endif
Daniel Stenbergb2850762002-08-23 12:32:52 +0000251 Menu result = MENU_OK;
Justin Heiner26302452002-08-23 02:17:00 +0000252
Björn Stenberg2ac05722002-05-26 17:03:17 +0000253 menu_draw(m);
Justin Heiner26302452002-08-23 02:17:00 +0000254
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000255 while(1) {
Markus Braun5e4c1d22002-08-20 19:37:00 +0000256 switch( button_get_w_tmo(HZ/2) ) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000257#ifdef HAVE_RECORDER_KEYPAD
258 case BUTTON_UP:
Björn Stenbergcbc71792002-08-10 09:04:55 +0000259 case BUTTON_UP | BUTTON_REPEAT:
Robert Hak7ec9aa32002-05-18 11:41:37 +0000260#else
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000261 case BUTTON_LEFT:
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000262 case BUTTON_LEFT | BUTTON_REPEAT:
Robert Hak7ec9aa32002-05-18 11:41:37 +0000263#endif
Björn Stenberg4caebab2002-05-29 14:25:06 +0000264 if (menus[m].cursor) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000265 /* move up */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000266 put_cursor(m, menus[m].cursor-1);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000267 }
268 break;
Robert Hakdfba2102002-05-21 08:47:34 +0000269
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000270#ifdef HAVE_RECORDER_KEYPAD
271 case BUTTON_DOWN:
Björn Stenbergcbc71792002-08-10 09:04:55 +0000272 case BUTTON_DOWN | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000273#else
274 case BUTTON_RIGHT:
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000275 case BUTTON_RIGHT | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000276#endif
Björn Stenberg4caebab2002-05-29 14:25:06 +0000277 if (menus[m].cursor < menus[m].itemcount-1) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000278 /* move down */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000279 put_cursor(m, menus[m].cursor+1);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000280 }
281 break;
282
283#ifdef HAVE_RECORDER_KEYPAD
284 case BUTTON_RIGHT:
285#endif
286 case BUTTON_PLAY:
287 /* Erase current display state */
Daniel Stenberga8e89fd2002-08-22 21:45:22 +0000288 lcd_scroll_pause(); /* pause is better than stop when
289 are gonna clear the screen anyway */
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000290 lcd_clear_display();
291
Daniel Stenberg49984fa2002-08-23 12:57:00 +0000292 /* if a child returns that the contents is changed, we
293 must remember this, even if we perhaps invoke other
294 children too before returning back */
295 if(MENU_DISK_CHANGED ==
296 menus[m].items[menus[m].cursor].function())
297 result = MENU_DISK_CHANGED;
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000298
299 /* Return to previous display state */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000300 menu_draw(m);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000301 break;
302
303#ifdef HAVE_RECORDER_KEYPAD
304 case BUTTON_LEFT:
Linus Nielsen Feltzinga552f4c2002-07-27 19:53:26 +0000305 case BUTTON_F1:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000306#else
307 case BUTTON_STOP:
Björn Stenberg60fad542002-05-29 12:28:08 +0000308 case BUTTON_MENU:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000309#endif
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000310 lcd_stop_scroll();
Daniel Stenbergb2850762002-08-23 12:32:52 +0000311 return result;
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000312
Markus Braun5e4c1d22002-08-20 19:37:00 +0000313#ifdef HAVE_RECORDER_KEYPAD
Markus Braun000c2db2002-08-30 13:49:32 +0000314 case BUTTON_F3: {
Markus Braun5e4c1d22002-08-20 19:37:00 +0000315#ifdef HAVE_LCD_BITMAP
Markus Braun000c2db2002-08-30 13:49:32 +0000316 unsigned char state;
317 state = global_settings.statusbar << 1 | global_settings.scrollbar;
318 state = (state + 1) % 4;
319 global_settings.statusbar = state >> 1;
320 global_settings.scrollbar = state & 0x1;
321 settings_save();
322
323 menu_draw(m);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000324#endif
Markus Braun000c2db2002-08-30 13:49:32 +0000325 }
Markus Braun5e4c1d22002-08-20 19:37:00 +0000326 break;
327#endif
328
Justin Heiner26302452002-08-23 02:17:00 +0000329#ifndef SIMULATOR
330 case SYS_USB_CONNECTED:
331#ifdef HAVE_LCD_BITMAP
332 laststate = statusbar(false);
333#endif
334 usb_acknowledge(SYS_USB_CONNECTED_ACK);
335 usb_wait_for_disconnect(&button_queue);
Justin Heiner26302452002-08-23 02:17:00 +0000336#ifdef HAVE_LCD_BITMAP
337 statusbar(laststate);
338#else
339 lcd_icon(ICON_PARAM, true);
340#endif
Daniel Stenberg49984fa2002-08-23 12:57:00 +0000341 menu_draw(m);
Daniel Stenbergaa458aa2002-08-23 12:41:25 +0000342 result = MENU_DISK_CHANGED;
Justin Heiner26302452002-08-23 02:17:00 +0000343 break;
344#endif
345
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000346 default:
347 break;
348 }
349
Markus Braun5e4c1d22002-08-20 19:37:00 +0000350 status_draw();
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000351 lcd_update();
352 }
Daniel Stenbergb2850762002-08-23 12:32:52 +0000353
354 return result;
Robert Hak7ec9aa32002-05-18 11:41:37 +0000355}