1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Robert Hak <rhak at ramapo.edu>
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "lib/helper.h"
26 static const struct plugin_api
* rb
;
28 static const char* const credits
[] = {
29 #include "credits.raw" /* generated list of names from docs/CREDITS */
32 #ifdef HAVE_LCD_CHARCELLS
34 static void roll_credits(void)
36 int numnames
= sizeof(credits
)/sizeof(char*);
38 int curr_len
= rb
->utf8length(credits
[0]);
41 int name
, len
, new_len
, line
, x
;
45 rb
->lcd_clear_display();
58 credits
[name
] + rb
->utf8seek(credits
[name
], -x
));
60 rb
->lcd_puts(x
, line
, credits
[name
]);
62 if (++name
>= numnames
)
68 if ((unsigned)x2
< 11)
69 rb
->lcd_putc(x2
, line
, '*');
71 new_len
= rb
->utf8length(credits
[name
]);
72 x
+= MAX(len
/2 + 2, len
- new_len
/2 + 1);
77 /* abort on keypress */
78 if(rb
->action_userabort(HZ
/8))
81 if (++curr_index
>= curr_len
)
83 if (++curr_name
>= numnames
)
85 new_len
= rb
->utf8length(credits
[curr_name
]);
86 curr_index
-= MAX(curr_len
/2 + 2, curr_len
- new_len
/2 + 1);
95 static bool stop_autoscroll(int action
)
99 case ACTION_STD_CANCEL
:
101 case ACTION_STD_NEXT
:
102 case ACTION_STD_NEXTREPEAT
:
103 case ACTION_STD_PREV
:
104 case ACTION_STD_PREVREPEAT
:
112 static int update_rowpos(int action
, int cur_pos
, int rows_per_screen
, int tot_rows
)
116 case ACTION_STD_PREV
:
117 case ACTION_STD_PREVREPEAT
:
120 case ACTION_STD_NEXT
:
121 case ACTION_STD_NEXTREPEAT
:
126 if(cur_pos
> tot_rows
- rows_per_screen
)
129 cur_pos
= tot_rows
- rows_per_screen
;
134 static void roll_credits(void)
136 /* to do: use target defines iso keypads to set animation timings */
137 #if (CONFIG_KEYPAD == RECORDER_PAD)
138 #define PAUSE_TIME 1.2
139 #define ANIM_SPEED 35
140 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
141 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
143 #define ANIM_SPEED 100
144 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
146 #define ANIM_SPEED 35
147 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
149 #define ANIM_SPEED 100
152 #define ANIM_SPEED 40
155 #define NUM_VISIBLE_LINES (LCD_HEIGHT/font_h - 1)
156 #define CREDITS_TARGETPOS ((LCD_WIDTH/2)-(credits_w/2))
158 int i
=0, j
=0, namepos
=0, offset_dummy
;
159 int name_w
, name_h
, name_targetpos
=1, font_h
;
160 int credits_w
, credits_pos
;
161 int numnames
= (sizeof(credits
)/sizeof(char*));
162 char name
[40], elapsednames
[32];
163 int action
= ACTION_NONE
;
165 /* control if scrolling is automatic (with animation) or manual */
166 bool manual_scroll
= false;
168 rb
->lcd_setfont(FONT_UI
);
169 rb
->lcd_clear_display();
172 rb
->lcd_getstringsize("A", NULL
, &font_h
);
174 /* snprintf "credits" text, and save the width and height */
175 rb
->snprintf(elapsednames
, sizeof(elapsednames
), "[Credits] %d/%d",
177 rb
->lcd_getstringsize(elapsednames
, &credits_w
, NULL
);
179 /* fly in "credits" text from the left */
180 for(credits_pos
= 0 - credits_w
; credits_pos
<= CREDITS_TARGETPOS
;
181 credits_pos
+= (CREDITS_TARGETPOS
-credits_pos
+ 14) / 7)
183 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
184 rb
->lcd_fillrect(0, 0, LCD_WIDTH
, font_h
);
185 rb
->lcd_set_drawmode(DRMODE_SOLID
);
186 rb
->lcd_putsxy(credits_pos
, 0, elapsednames
);
187 rb
->lcd_update_rect(0, 0, LCD_WIDTH
, font_h
);
188 rb
->sleep(HZ
/ANIM_SPEED
);
191 /* first screen's worth of lines fly in */
192 for(i
=0; i
<NUM_VISIBLE_LINES
; i
++)
194 rb
->snprintf(name
, sizeof(name
), "%s", credits
[i
]);
195 rb
->lcd_getstringsize(name
, &name_w
, &name_h
);
197 rb
->snprintf(elapsednames
, sizeof(elapsednames
), "[Credits] %d/%d",
199 rb
->lcd_getstringsize(elapsednames
, &credits_w
, NULL
);
200 rb
->lcd_putsxy(CREDITS_TARGETPOS
, 0, elapsednames
);
201 rb
->lcd_update_rect(CREDITS_TARGETPOS
, 0, credits_w
, font_h
);
203 for(namepos
= 0-name_w
; namepos
<= name_targetpos
;
204 namepos
+= (name_targetpos
- namepos
+ 14) / 7)
206 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
207 /* clear any trails left behind */
208 rb
->lcd_fillrect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
209 rb
->lcd_set_drawmode(DRMODE_SOLID
);
210 rb
->lcd_putsxy(namepos
, font_h
*(i
+1), name
);
211 rb
->lcd_update_rect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
213 /* exit on abort, switch to manual on up/down */
214 action
= rb
->get_action(CONTEXT_LIST
, HZ
/ANIM_SPEED
);
215 if(stop_autoscroll(action
))
218 if(stop_autoscroll(action
))
222 /* process user actions (if any) */
223 if(ACTION_STD_CANCEL
== action
)
225 if(stop_autoscroll(action
))
226 manual_scroll
= true; /* up/down - abort was catched above */
232 /* pause for a bit if needed */
233 action
= rb
->get_action(CONTEXT_LIST
, HZ
*PAUSE_TIME
);
234 if(ACTION_STD_CANCEL
== action
)
236 if(stop_autoscroll(action
))
237 manual_scroll
= true;
244 /* just a screen's worth at a time */
245 for(i
=0; i
<NUM_VISIBLE_LINES
; i
++)
251 rb
->snprintf(name
, sizeof(name
), "%s",
252 credits
[j
+i
-NUM_VISIBLE_LINES
]);
253 rb
->lcd_getstringsize(name
, &name_w
, &name_h
);
255 /* fly out an existing line.. */
256 while(namepos
<LCD_WIDTH
+offset_dummy
)
258 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
260 rb
->lcd_fillrect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
261 rb
->lcd_set_drawmode(DRMODE_SOLID
);
262 rb
->lcd_putsxy(namepos
, font_h
*(i
+1), name
);
263 rb
->lcd_update_rect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
265 /* exit on keypress, react to scrolling */
266 action
= rb
->get_action(CONTEXT_LIST
, HZ
/ANIM_SPEED
);
267 if(stop_autoscroll(action
))
270 namepos
+= offset_dummy
;
272 } /* while(namepos<LCD_WIDTH+offset_dummy) */
273 if(stop_autoscroll(action
))
276 rb
->snprintf(name
, sizeof(name
), "%s", credits
[j
+i
]);
277 rb
->lcd_getstringsize(name
, &name_w
, &name_h
);
279 rb
->snprintf(elapsednames
, sizeof(elapsednames
),
280 "[Credits] %d/%d", j
+i
+1, numnames
);
281 rb
->lcd_getstringsize(elapsednames
, &credits_w
, NULL
);
282 rb
->lcd_putsxy(CREDITS_TARGETPOS
, 0, elapsednames
);
283 if (j
+i
< NUM_VISIBLE_LINES
) /* takes care of trail on loop */
284 rb
->lcd_update_rect(0, 0, LCD_WIDTH
, font_h
);
286 for(namepos
= 0-name_w
; namepos
<= name_targetpos
;
287 namepos
+= (name_targetpos
- namepos
+ 14) / 7)
289 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
290 rb
->lcd_fillrect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
291 rb
->lcd_set_drawmode(DRMODE_SOLID
);
292 rb
->lcd_putsxy(namepos
, font_h
*(i
+1), name
);
293 rb
->lcd_update_rect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
294 rb
->lcd_update_rect(CREDITS_TARGETPOS
, 0, credits_w
,font_h
);
296 /* stop on keypress */
297 action
= rb
->get_action(CONTEXT_LIST
, HZ
/ANIM_SPEED
);
298 if(stop_autoscroll(action
))
301 if(stop_autoscroll(action
))
303 namepos
= name_targetpos
;
304 } /* for(i=0; i<NUM_VISIBLE_LINES; i++) */
305 if(stop_autoscroll(action
))
308 action
= rb
->get_action(CONTEXT_LIST
, HZ
*PAUSE_TIME
);
309 if(stop_autoscroll(action
))
312 j
+=i
; /* no user intervention, draw the next screen-full */
313 } /* while(j < numnames) */
315 /* handle the keypress that we intercepted during autoscroll */
316 if(ACTION_STD_CANCEL
== action
)
318 if(stop_autoscroll(action
))
319 manual_scroll
= true;
320 } /* if(!manual_scroll) */
324 /* user went into manual scrolling, handle it here */
325 rb
->lcd_set_drawmode(DRMODE_SOLID
);
326 while(ACTION_STD_CANCEL
!= action
)
328 rb
->lcd_clear_display();
329 rb
->snprintf(elapsednames
, sizeof(elapsednames
),
330 "[Credits] %d-%d/%d", j
+1,
331 j
+NUM_VISIBLE_LINES
, numnames
);
332 rb
->lcd_getstringsize(elapsednames
, &credits_w
, NULL
);
333 rb
->lcd_putsxy(CREDITS_TARGETPOS
, 0, elapsednames
);
335 for(i
=0; i
<NUM_VISIBLE_LINES
; i
++)
337 rb
->snprintf(name
, sizeof(name
), "%s", credits
[j
+i
]);
338 rb
->lcd_putsxy(0, font_h
*(i
+1), name
);
344 /* wait for user action */
345 action
= rb
->get_action(CONTEXT_LIST
, TIMEOUT_BLOCK
);
346 if(ACTION_STD_CANCEL
== action
)
348 j
= update_rowpos(action
, j
, NUM_VISIBLE_LINES
, numnames
);
350 return; /* exit without animation */
353 action
= rb
->get_action(CONTEXT_LIST
, HZ
*3);
354 if(ACTION_STD_CANCEL
== action
)
359 /* now make the text exit to the right */
360 for(credits_pos
= (LCD_WIDTH
/2)-(credits_w
/2);
361 credits_pos
<= LCD_WIDTH
+offset_dummy
;
362 credits_pos
+= offset_dummy
, offset_dummy
++)
364 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
365 rb
->lcd_fillrect(0, 0, LCD_WIDTH
, font_h
);
366 rb
->lcd_set_drawmode(DRMODE_SOLID
);
367 rb
->lcd_putsxy(credits_pos
, 0, elapsednames
);
374 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
379 /* Turn off backlight timeout */
380 backlight_force_on(rb
); /* backlight control in lib/helper.c */
383 #ifdef HAVE_LCD_CHARCELLS
384 rb
->lcd_double_height(false);
387 /* Show the logo for about 3 secs allowing the user to stop */
388 if(!rb
->action_userabort(3*HZ
))
391 /* Turn on backlight timeout (revert to settings) */
392 backlight_use_settings(rb
); /* backlight control in lib/helper.c */