blob: 5e8a51200a552da4afa5dcdceac1ef6e40f7a209 [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>
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +000020#include <stdlib.h>
Justin Heinerb5025a82002-08-31 04:58:35 +000021
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +000022#include "hwcompat.h"
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000023#include "lcd.h"
Daniel Stenberg93b231c2002-09-12 13:33:59 +000024#include "font.h"
Justin Heinerb5025a82002-08-31 04:58:35 +000025#include "backlight.h"
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000026#include "menu.h"
Björn Stenbergb21a3bd2002-05-21 14:25:45 +000027#include "button.h"
28#include "kernel.h"
29#include "debug.h"
Justin Heiner26302452002-08-23 02:17:00 +000030#include "usb.h"
Björn Stenbergcd225732002-08-11 09:17:47 +000031#include "panic.h"
Markus Braun5e4c1d22002-08-20 19:37:00 +000032#include "settings.h"
33#include "status.h"
Björn Stenberga4c3b032002-09-24 18:04:15 +000034#include "screens.h"
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +000035#include "talk.h"
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +000036#include "lang.h"
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +000037#include "misc.h"
Markus Braun000c2db2002-08-30 13:49:32 +000038
Daniel Stenbergbf603f92002-06-14 08:47:44 +000039#ifdef HAVE_LCD_BITMAP
40#include "icons.h"
Markus Braun000c2db2002-08-30 13:49:32 +000041#include "widgets.h"
Daniel Stenbergbf603f92002-06-14 08:47:44 +000042#endif
Markus Braun000c2db2002-08-30 13:49:32 +000043
Björn Stenberg2ac05722002-05-26 17:03:17 +000044struct menu {
Björn Stenbergf76cee72002-05-28 15:35:33 +000045 int top;
Björn Stenberg2ac05722002-05-26 17:03:17 +000046 int cursor;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +000047 struct menu_item* items;
Björn Stenberg2ac05722002-05-26 17:03:17 +000048 int itemcount;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +000049 int (*callback)(int, int);
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +000050#ifdef HAVE_LCD_BITMAP
51 bool use_buttonbar; /* true if a buttonbar is defined */
52 char *buttonbar[3];
53#endif
Björn Stenberg2ac05722002-05-26 17:03:17 +000054};
55
Hardeep Sidhu107ebc52004-01-26 17:05:21 +000056#define MAX_MENUS 5
Björn Stenberg2ac05722002-05-26 17:03:17 +000057
Björn Stenbergf76cee72002-05-28 15:35:33 +000058#ifdef HAVE_LCD_BITMAP
Markus Braun000c2db2002-08-30 13:49:32 +000059
Björn Stenberg8fb73122002-09-24 19:41:23 +000060/* pixel margins */
61#define MARGIN_X (global_settings.scrollbar && \
62 menu_lines < menus[m].itemcount ? SCROLLBAR_WIDTH : 0) +\
63 CURSOR_WIDTH
64#define MARGIN_Y (global_settings.statusbar ? STATUSBAR_HEIGHT : 0)
Markus Braun000c2db2002-08-30 13:49:32 +000065
Björn Stenberg8fb73122002-09-24 19:41:23 +000066/* position the entry-list starts at */
67#define LINE_X 0
68#define LINE_Y (global_settings.statusbar ? 1 : 0)
Markus Braun000c2db2002-08-30 13:49:32 +000069
Björn Stenberg8fb73122002-09-24 19:41:23 +000070#define CURSOR_X (global_settings.scrollbar && \
71 menu_lines < menus[m].itemcount ? 1 : 0)
72#define CURSOR_Y 0 /* the cursor is not positioned in regard to
73 the margins, so this is the amount of lines
74 we add to the cursor Y position to position
75 it on a line */
Linus Nielsen Feltzinge43b78a2003-04-16 00:12:31 +000076#define CURSOR_WIDTH (global_settings.invert_cursor ? 0 : 4)
Markus Braun000c2db2002-08-30 13:49:32 +000077
78#define SCROLLBAR_X 0
79#define SCROLLBAR_Y lcd_getymargin()
80#define SCROLLBAR_WIDTH 6
81
82#else /* HAVE_LCD_BITMAP */
83
Justin Heinerb5025a82002-08-31 04:58:35 +000084#define LINE_X 1 /* X position the entry-list starts at */
Markus Braun000c2db2002-08-30 13:49:32 +000085
Björn Stenbergf76cee72002-05-28 15:35:33 +000086#define MENU_LINES 2
Markus Braun000c2db2002-08-30 13:49:32 +000087
88#define CURSOR_X 0
89#define CURSOR_Y 0 /* not really used for players */
90
91#endif /* HAVE_LCD_BITMAP */
Björn Stenbergf76cee72002-05-28 15:35:33 +000092
Kjell Ericsonc11b90f2003-01-10 09:55:50 +000093#define CURSOR_CHAR 0x92
Björn Stenberg9314a682002-05-31 09:04:51 +000094
Björn Stenberg2ac05722002-05-26 17:03:17 +000095static struct menu menus[MAX_MENUS];
96static bool inuse[MAX_MENUS] = { false };
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000097
Daniel Stenberg93b231c2002-09-12 13:33:59 +000098/* count in letter positions, NOT pixels */
Daniel Stenbergbf603f92002-06-14 08:47:44 +000099void put_cursorxy(int x, int y, bool on)
100{
Björn Stenberg71f71ef2002-08-11 09:20:53 +0000101#ifdef HAVE_LCD_BITMAP
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000102 int fh, fw;
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000103 int xpos, ypos;
Björn Stenbergd1a6fa12003-06-05 09:38:26 +0000104
105 /* check here instead of at every call (ugly, but cheap) */
Linus Nielsen Feltzinge43b78a2003-04-16 00:12:31 +0000106 if (global_settings.invert_cursor)
107 return;
Björn Stenbergd1a6fa12003-06-05 09:38:26 +0000108
Björn Stenberga4c3b032002-09-24 18:04:15 +0000109 lcd_getstringsize("A", &fw, &fh);
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000110 xpos = x*6;
111 ypos = y*fh + lcd_getymargin();
112 if ( fh > 8 )
113 ypos += (fh - 8) / 2;
Björn Stenberg71f71ef2002-08-11 09:20:53 +0000114#endif
Björn Stenbergcd225732002-08-11 09:17:47 +0000115
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000116 /* place the cursor */
117 if(on) {
118#ifdef HAVE_LCD_BITMAP
119 lcd_bitmap ( bitmap_icons_6x8[Cursor],
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000120 xpos, ypos, 4, 8, true);
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000121#else
Kjell Ericsonc11b90f2003-01-10 09:55:50 +0000122 lcd_putc(x, y, CURSOR_CHAR);
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000123#endif
124 }
125 else {
Daniel Stenbergc4be1ee2002-06-19 13:00:14 +0000126#if defined(HAVE_LCD_BITMAP)
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000127 /* I use xy here since it needs to disregard the margins */
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000128 lcd_clearrect (xpos, ypos, 4, 8);
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000129#else
Björn Stenberg3b974742002-09-09 23:57:00 +0000130 lcd_putc(x, y, ' ');
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000131#endif
132 }
133}
134
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000135void menu_draw(int m)
Björn Stenbergf76cee72002-05-28 15:35:33 +0000136{
137 int i = 0;
Eric Linenberg038df5c2002-09-16 03:18:49 +0000138#ifdef HAVE_LCD_BITMAP
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000139 int fw, fh;
Björn Stenbergcd225732002-08-11 09:17:47 +0000140 int menu_lines;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000141 int height = LCD_HEIGHT;
142
Björn Stenberga4c3b032002-09-24 18:04:15 +0000143 lcd_setfont(FONT_UI);
144 lcd_getstringsize("A", &fw, &fh);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000145 if (global_settings.statusbar)
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000146 height -= STATUSBAR_HEIGHT;
147
148 if(global_settings.buttonbar && menus[m].use_buttonbar) {
149 buttonbar_set(menus[m].buttonbar[0],
150 menus[m].buttonbar[1],
151 menus[m].buttonbar[2]);
152 height -= BUTTONBAR_HEIGHT;
153 }
154
155 menu_lines = height / fh;
156
Björn Stenbergcd225732002-08-11 09:17:47 +0000157#else
158 int menu_lines = MENU_LINES;
159#endif
Björn Stenbergf76cee72002-05-28 15:35:33 +0000160
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000161 lcd_clear_display();
Björn Stenbergf76cee72002-05-28 15:35:33 +0000162#ifdef HAVE_LCD_BITMAP
Markus Braun000c2db2002-08-30 13:49:32 +0000163 lcd_setmargins(MARGIN_X,MARGIN_Y); /* leave room for cursor and icon */
Björn Stenbergf76cee72002-05-28 15:35:33 +0000164#endif
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000165 /* Adjust cursor pos if it's below the screen */
Markus Braun5e4c1d22002-08-20 19:37:00 +0000166 if (menus[m].cursor - menus[m].top >= menu_lines)
167 menus[m].top++;
168
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000169 /* Adjust cursor pos if it's above the screen */
170 if(menus[m].cursor < menus[m].top)
171 menus[m].top = menus[m].cursor;
172
Björn Stenbergf76cee72002-05-28 15:35:33 +0000173 for (i = menus[m].top;
Björn Stenbergcd225732002-08-11 09:17:47 +0000174 (i < menus[m].itemcount) && (i<menus[m].top+menu_lines);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000175 i++) {
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000176
177 /* We want to scroll the line where the cursor is */
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000178 if((menus[m].cursor - menus[m].top)==(i-menus[m].top))
Linus Nielsen Feltzinge43b78a2003-04-16 00:12:31 +0000179#ifdef HAVE_LCD_BITMAP
180 if (global_settings.invert_cursor)
181 lcd_puts_scroll_style(LINE_X, i-menus[m].top,
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000182 P2STR(menus[m].items[i].desc), STYLE_INVERT);
Linus Nielsen Feltzinge43b78a2003-04-16 00:12:31 +0000183 else
184#endif
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000185 lcd_puts_scroll(LINE_X, i-menus[m].top, P2STR(menus[m].items[i].desc));
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000186 else
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000187 lcd_puts(LINE_X, i-menus[m].top, P2STR(menus[m].items[i].desc));
Björn Stenbergf76cee72002-05-28 15:35:33 +0000188 }
Robert Hakc501ac72002-05-30 08:06:42 +0000189
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000190 /* place the cursor */
Markus Braun000c2db2002-08-30 13:49:32 +0000191 put_cursorxy(CURSOR_X, menus[m].cursor - menus[m].top, true);
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000192
Markus Braun5e4c1d22002-08-20 19:37:00 +0000193#ifdef HAVE_LCD_BITMAP
Björn Stenberg8fb73122002-09-24 19:41:23 +0000194 if (global_settings.scrollbar && menus[m].itemcount > menu_lines)
Markus Braun000c2db2002-08-30 13:49:32 +0000195 scrollbar(SCROLLBAR_X, SCROLLBAR_Y, SCROLLBAR_WIDTH - 1,
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000196 height, menus[m].itemcount, menus[m].top,
Markus Braun000c2db2002-08-30 13:49:32 +0000197 menus[m].top + menu_lines, VERTICAL);
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000198
199 if(global_settings.buttonbar && menus[m].use_buttonbar)
200 buttonbar_draw();
Markus Braun5e4c1d22002-08-20 19:37:00 +0000201#endif
Björn Stenberg942bc942003-04-23 11:26:25 +0000202 status_draw(true);
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000203
Björn Stenbergf76cee72002-05-28 15:35:33 +0000204 lcd_update();
205}
206
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000207/*
208 * Move the cursor to a particular id,
209 * target: where you want it to be
210 */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000211static void put_cursor(int m, int target)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000212{
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000213 int voice_id;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000214
Robert Hakc501ac72002-05-30 08:06:42 +0000215 menus[m].cursor = target;
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000216 menu_draw(m);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000217
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000218 /* "say" the entry under the cursor */
219 if(global_settings.talk_menu)
220 {
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000221 voice_id = P2ID(menus[m].items[menus[m].cursor].desc);
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000222 if (voice_id >= 0) /* valid ID given? */
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +0000223 talk_id(voice_id, false); /* say it */
224 }
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000225}
226
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000227int menu_init(const struct menu_item* mitems, int count, int (*callback)(int, int),
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000228 char *button1, char *button2, char *button3)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000229{
Björn Stenberg2ac05722002-05-26 17:03:17 +0000230 int i;
231
232 for ( i=0; i<MAX_MENUS; i++ ) {
233 if ( !inuse[i] ) {
234 inuse[i] = true;
235 break;
236 }
237 }
238 if ( i == MAX_MENUS ) {
239 DEBUGF("Out of menus!\n");
240 return -1;
241 }
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000242 menus[i].items = (struct menu_item*)mitems; /* de-const */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000243 menus[i].itemcount = count;
Björn Stenbergf76cee72002-05-28 15:35:33 +0000244 menus[i].top = 0;
Björn Stenberg2ac05722002-05-26 17:03:17 +0000245 menus[i].cursor = 0;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000246 menus[i].callback = callback;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000247#ifdef HAVE_LCD_BITMAP
248 menus[i].buttonbar[0] = button1;
249 menus[i].buttonbar[1] = button2;
250 menus[i].buttonbar[2] = button3;
Björn Stenberg2ac05722002-05-26 17:03:17 +0000251
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000252 if(button1 || button2 || button3)
253 menus[i].use_buttonbar = true;
254 else
255 menus[i].use_buttonbar = false;
256#else
257 (void)button1;
258 (void)button2;
259 (void)button3;
260#endif
Björn Stenberg2ac05722002-05-26 17:03:17 +0000261 return i;
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000262}
263
Björn Stenberg2ac05722002-05-26 17:03:17 +0000264void menu_exit(int m)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000265{
Björn Stenberg2ac05722002-05-26 17:03:17 +0000266 inuse[m] = false;
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000267}
268
Kjell Ericson5cd393c2003-01-29 08:26:11 +0000269int menu_show(int m)
Robert Hak7ec9aa32002-05-18 11:41:37 +0000270{
Björn Stenbergb1b8bd42002-09-24 17:22:12 +0000271 bool exit = false;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000272 int key;
Linus Nielsen Feltzingf1659a32003-11-20 01:51:15 +0000273#ifdef HAVE_LCD_BITMAP
274 int fw, fh;
275 int menu_lines;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000276 int height = LCD_HEIGHT;
277
Linus Nielsen Feltzingf1659a32003-11-20 01:51:15 +0000278 lcd_setfont(FONT_UI);
279 lcd_getstringsize("A", &fw, &fh);
280 if (global_settings.statusbar)
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000281 height -= STATUSBAR_HEIGHT;
282
283 if(global_settings.buttonbar && menus[m].use_buttonbar) {
284 buttonbar_set(menus[m].buttonbar[0],
285 menus[m].buttonbar[1],
286 menus[m].buttonbar[2]);
287 height -= BUTTONBAR_HEIGHT;
288 }
289
290 menu_lines = height / fh;
Linus Nielsen Feltzingf1659a32003-11-20 01:51:15 +0000291#endif
Justin Heiner26302452002-08-23 02:17:00 +0000292
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000293 /* Put the cursor on the first line and draw the menu */
Linus Nielsen Feltzing49ea16e2004-04-14 06:04:38 +0000294 put_cursor(m, menus[m].cursor);
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +0000295
Björn Stenbergb1b8bd42002-09-24 17:22:12 +0000296 while (!exit) {
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000297 key = button_get_w_tmo(HZ/2);
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +0000298
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000299 /*
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000300 * "short-circuit" the default keypresses by running the
301 * callback function
302 * The callback may return a new key value, often this will be
303 * BUTTON_NONE or the same key value, but it's perfectly legal
304 * to "simulate" key presses by returning another value.
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000305 */
306
307 if( menus[m].callback != NULL )
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000308 key = menus[m].callback(key, m);
309
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000310 switch( key ) {
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +0000311
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000312#ifdef HAVE_RECORDER_KEYPAD
313 case BUTTON_UP:
Björn Stenbergcbc71792002-08-10 09:04:55 +0000314 case BUTTON_UP | BUTTON_REPEAT:
Robert Hak7ec9aa32002-05-18 11:41:37 +0000315#else
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000316 case BUTTON_LEFT:
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000317 case BUTTON_LEFT | BUTTON_REPEAT:
Robert Hak7ec9aa32002-05-18 11:41:37 +0000318#endif
Björn Stenberg4caebab2002-05-29 14:25:06 +0000319 if (menus[m].cursor) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000320 /* move up */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000321 put_cursor(m, menus[m].cursor-1);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000322 }
Eric Linenbergc076b272002-09-04 04:21:10 +0000323 else {
324 /* move to bottom */
325#ifdef HAVE_RECORDER_KEYPAD
Linus Nielsen Feltzingf1659a32003-11-20 01:51:15 +0000326 menus[m].top = menus[m].itemcount-(menu_lines+1);
Eric Linenbergc076b272002-09-04 04:21:10 +0000327#else
328 menus[m].top = menus[m].itemcount-3;
329#endif
330 if (menus[m].top < 0)
331 menus[m].top = 0;
332 menus[m].cursor = menus[m].itemcount-1;
333 put_cursor(m, menus[m].itemcount-1);
334 }
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000335 break;
Robert Hakdfba2102002-05-21 08:47:34 +0000336
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000337#ifdef HAVE_RECORDER_KEYPAD
338 case BUTTON_DOWN:
Björn Stenbergcbc71792002-08-10 09:04:55 +0000339 case BUTTON_DOWN | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000340#else
341 case BUTTON_RIGHT:
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000342 case BUTTON_RIGHT | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000343#endif
Björn Stenberg4caebab2002-05-29 14:25:06 +0000344 if (menus[m].cursor < menus[m].itemcount-1) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000345 /* move down */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000346 put_cursor(m, menus[m].cursor+1);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000347 }
Eric Linenbergc076b272002-09-04 04:21:10 +0000348 else {
349 /* move to top */
350 menus[m].top = 0;
351 menus[m].cursor = 0;
352 put_cursor(m, 0);
353 }
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000354 break;
355
356#ifdef HAVE_RECORDER_KEYPAD
357 case BUTTON_RIGHT:
358#endif
359 case BUTTON_PLAY:
360 /* Erase current display state */
361 lcd_clear_display();
Kjell Ericson5cd393c2003-01-29 08:26:11 +0000362 return menus[m].cursor;
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000363
364#ifdef HAVE_RECORDER_KEYPAD
365 case BUTTON_LEFT:
Linus Nielsen Feltzinga552f4c2002-07-27 19:53:26 +0000366 case BUTTON_F1:
Björn Stenberg461d6e32003-12-04 00:08:25 +0000367 case BUTTON_OFF | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000368#else
369 case BUTTON_STOP:
Björn Stenberg60fad542002-05-29 12:28:08 +0000370 case BUTTON_MENU:
Björn Stenberg461d6e32003-12-04 00:08:25 +0000371 case BUTTON_STOP | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000372#endif
Kjell Ericson767d6042003-01-23 14:28:16 +0000373 lcd_stop_scroll();
Björn Stenbergb1b8bd42002-09-24 17:22:12 +0000374 exit = true;
375 break;
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000376
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +0000377 default:
378 if(default_event_handler(key) == SYS_USB_CONNECTED)
379 return MENU_ATTACHED_USB;
380 break;
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000381 }
382
Björn Stenberg942bc942003-04-23 11:26:25 +0000383 status_draw(false);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000384 }
Kjell Ericson5cd393c2003-01-29 08:26:11 +0000385 return MENU_SELECTED_EXIT;
386}
Daniel Stenbergb2850762002-08-23 12:32:52 +0000387
Kjell Ericson5cd393c2003-01-29 08:26:11 +0000388
389bool menu_run(int m)
390{
391 bool stop=false;
392 while (!stop) {
393 int result=menu_show(m);
394 if (result == MENU_SELECTED_EXIT)
395 return false;
396 else if (result == MENU_ATTACHED_USB)
397 return true;
398 if (menus[m].items[menus[m].cursor].function()) {
399 return true;
400 }
401 }
402 return false;
Robert Hak7ec9aa32002-05-18 11:41:37 +0000403}
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000404
405/*
406 * Property function - return the current cursor for "menu"
407 */
408
409int menu_cursor(int menu)
410{
411 return menus[menu].cursor;
412}
413
414/*
415 * Property function - return the "menu" description at "position"
416 */
417
418char* menu_description(int menu, int position)
419{
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000420 return P2STR(menus[menu].items[position].desc);
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000421}
422
423/*
424 * Delete the element "position" from the menu items in "menu"
425 */
426
427void menu_delete(int menu, int position)
428{
429 int i;
430
431 /* copy the menu item from the one below */
432 for( i = position; i < (menus[menu].itemcount - 1); i++)
433 menus[menu].items[i] = menus[menu].items[i + 1];
434
435 /* reduce the count */
436 menus[menu].itemcount--;
437
438 /* adjust if this was the last menu item and the cursor was on it */
439 if( menus[menu].itemcount <= menus[menu].cursor)
440 menus[menu].cursor = menus[menu].itemcount - 1;
441}
442
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000443void menu_insert(int menu, int position, char *desc, bool (*function) (void))
Linus Nielsen Feltzing82586a62004-07-05 14:26:58 +0000444{
445 int i;
446
447 if(position < 0)
448 position = menus[menu].itemcount;
449
450 /* Move the items below one position forward */
451 for( i = menus[menu].itemcount; i > position; i--)
452 menus[menu].items[i] = menus[menu].items[i - 1];
453
454 /* Increase the count */
455 menus[menu].itemcount++;
456
457 /* Update the current item */
458 menus[menu].items[position].desc = desc;
Linus Nielsen Feltzing82586a62004-07-05 14:26:58 +0000459 menus[menu].items[position].function = function;
460}
461
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000462/*
463 * Property function - return the "count" of menu items in "menu"
464 */
465
466int menu_count(int menu)
467{
468 return menus[menu].itemcount;
469}
470
471/*
472 * Allows a menu item at the current cursor position in "menu" to be moved up the list
473 */
474
475bool menu_moveup(int menu)
476{
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000477 struct menu_item swap;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000478
479 /* can't be the first item ! */
480 if( menus[menu].cursor == 0)
481 return false;
482
483 /* use a temporary variable to do the swap */
484 swap = menus[menu].items[menus[menu].cursor - 1];
485 menus[menu].items[menus[menu].cursor - 1] = menus[menu].items[menus[menu].cursor];
486 menus[menu].items[menus[menu].cursor] = swap;
487 menus[menu].cursor--;
488
489 return true;
490}
491
492/*
493 * Allows a menu item at the current cursor position in "menu" to be moved down the list
494 */
495
496bool menu_movedown(int menu)
497{
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000498 struct menu_item swap;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000499
500 /* can't be the last item ! */
501 if( menus[menu].cursor == menus[menu].itemcount - 1)
502 return false;
503
504 /* use a temporary variable to do the swap */
505 swap = menus[menu].items[menus[menu].cursor + 1];
506 menus[menu].items[menus[menu].cursor + 1] = menus[menu].items[menus[menu].cursor];
507 menus[menu].items[menus[menu].cursor] = swap;
508 menus[menu].cursor++;
509
510 return true;
511}