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 char* const credits
[] = {
27 #include "credits.raw" /* generated list of names from docs/CREDITS */
30 #ifdef HAVE_LCD_CHARCELLS
32 static void roll_credits(void)
34 int numnames
= sizeof(credits
)/sizeof(char*);
36 int curr_len
= rb
->utf8length(credits
[0]);
39 int name
, len
, new_len
, line
, x
;
43 rb
->lcd_clear_display();
56 credits
[name
] + rb
->utf8seek(credits
[name
], -x
));
58 rb
->lcd_puts(x
, line
, credits
[name
]);
60 if (++name
>= numnames
)
66 if ((unsigned)x2
< 11)
67 rb
->lcd_putc(x2
, line
, '*');
69 new_len
= rb
->utf8length(credits
[name
]);
70 x
+= MAX(len
/2 + 2, len
- new_len
/2 + 1);
75 /* abort on keypress */
76 if(rb
->action_userabort(HZ
/8))
79 if (++curr_index
>= curr_len
)
81 if (++curr_name
>= numnames
)
83 new_len
= rb
->utf8length(credits
[curr_name
]);
84 curr_index
-= MAX(curr_len
/2 + 2, curr_len
- new_len
/2 + 1);
93 static bool stop_autoscroll(int action
)
97 case ACTION_STD_CANCEL
:
100 case ACTION_STD_NEXTREPEAT
:
101 case ACTION_STD_PREV
:
102 case ACTION_STD_PREVREPEAT
:
110 static int update_rowpos(int action
, int cur_pos
, int rows_per_screen
, int tot_rows
)
114 case ACTION_STD_PREV
:
115 case ACTION_STD_PREVREPEAT
:
118 case ACTION_STD_NEXT
:
119 case ACTION_STD_NEXTREPEAT
:
124 if(cur_pos
> tot_rows
- rows_per_screen
)
127 cur_pos
= tot_rows
- rows_per_screen
;
132 static void roll_credits(void)
134 /* to do: use target defines iso keypads to set animation timings */
135 #if (CONFIG_KEYPAD == RECORDER_PAD)
136 #define PAUSE_TIME 1.2
137 #define ANIM_SPEED 35
138 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
139 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
141 #define ANIM_SPEED 100
142 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
144 #define ANIM_SPEED 35
145 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
147 #define ANIM_SPEED 100
150 #define ANIM_SPEED 40
153 #define NUM_VISIBLE_LINES (LCD_HEIGHT/font_h - 1)
154 #define CREDITS_TARGETPOS ((LCD_WIDTH/2)-(credits_w/2))
156 int i
=0, j
=0, namepos
=0, offset_dummy
;
157 int name_w
, name_h
, name_targetpos
=1, font_h
;
158 int credits_w
, credits_pos
;
159 int numnames
= (sizeof(credits
)/sizeof(char*));
160 char name
[40], elapsednames
[32];
161 int action
= ACTION_NONE
;
163 /* control if scrolling is automatic (with animation) or manual */
164 bool manual_scroll
= false;
166 rb
->lcd_setfont(FONT_UI
);
167 rb
->lcd_clear_display();
170 rb
->lcd_getstringsize("A", NULL
, &font_h
);
172 /* snprintf "credits" text, and save the width and height */
173 rb
->snprintf(elapsednames
, sizeof(elapsednames
), "[Credits] %d/%d",
175 rb
->lcd_getstringsize(elapsednames
, &credits_w
, NULL
);
177 /* fly in "credits" text from the left */
178 for(credits_pos
= 0 - credits_w
; credits_pos
<= CREDITS_TARGETPOS
;
179 credits_pos
+= (CREDITS_TARGETPOS
-credits_pos
+ 14) / 7)
181 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
182 rb
->lcd_fillrect(0, 0, LCD_WIDTH
, font_h
);
183 rb
->lcd_set_drawmode(DRMODE_SOLID
);
184 rb
->lcd_putsxy(credits_pos
, 0, elapsednames
);
185 rb
->lcd_update_rect(0, 0, LCD_WIDTH
, font_h
);
186 rb
->sleep(HZ
/ANIM_SPEED
);
189 /* first screen's worth of lines fly in */
190 for(i
=0; i
<NUM_VISIBLE_LINES
; i
++)
192 rb
->snprintf(name
, sizeof(name
), "%s", credits
[i
]);
193 rb
->lcd_getstringsize(name
, &name_w
, &name_h
);
195 rb
->snprintf(elapsednames
, sizeof(elapsednames
), "[Credits] %d/%d",
197 rb
->lcd_getstringsize(elapsednames
, &credits_w
, NULL
);
198 rb
->lcd_putsxy(CREDITS_TARGETPOS
, 0, elapsednames
);
199 rb
->lcd_update_rect(CREDITS_TARGETPOS
, 0, credits_w
, font_h
);
201 for(namepos
= 0-name_w
; namepos
<= name_targetpos
;
202 namepos
+= (name_targetpos
- namepos
+ 14) / 7)
204 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
205 /* clear any trails left behind */
206 rb
->lcd_fillrect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
207 rb
->lcd_set_drawmode(DRMODE_SOLID
);
208 rb
->lcd_putsxy(namepos
, font_h
*(i
+1), name
);
209 rb
->lcd_update_rect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
211 /* exit on abort, switch to manual on up/down */
212 action
= rb
->get_action(CONTEXT_LIST
, HZ
/ANIM_SPEED
);
213 if(stop_autoscroll(action
))
216 if(stop_autoscroll(action
))
220 /* process user actions (if any) */
221 if(ACTION_STD_CANCEL
== action
)
223 if(stop_autoscroll(action
))
224 manual_scroll
= true; /* up/down - abort was catched above */
230 /* pause for a bit if needed */
231 action
= rb
->get_action(CONTEXT_LIST
, HZ
*PAUSE_TIME
);
232 if(ACTION_STD_CANCEL
== action
)
234 if(stop_autoscroll(action
))
235 manual_scroll
= true;
242 /* just a screen's worth at a time */
243 for(i
=0; i
<NUM_VISIBLE_LINES
; i
++)
249 rb
->snprintf(name
, sizeof(name
), "%s",
250 credits
[j
+i
-NUM_VISIBLE_LINES
]);
251 rb
->lcd_getstringsize(name
, &name_w
, &name_h
);
253 /* fly out an existing line.. */
254 while(namepos
<LCD_WIDTH
+offset_dummy
)
256 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
258 rb
->lcd_fillrect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
259 rb
->lcd_set_drawmode(DRMODE_SOLID
);
260 rb
->lcd_putsxy(namepos
, font_h
*(i
+1), name
);
261 rb
->lcd_update_rect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
263 /* exit on keypress, react to scrolling */
264 action
= rb
->get_action(CONTEXT_LIST
, HZ
/ANIM_SPEED
);
265 if(stop_autoscroll(action
))
268 namepos
+= offset_dummy
;
270 } /* while(namepos<LCD_WIDTH+offset_dummy) */
271 if(stop_autoscroll(action
))
274 rb
->snprintf(name
, sizeof(name
), "%s", credits
[j
+i
]);
275 rb
->lcd_getstringsize(name
, &name_w
, &name_h
);
277 rb
->snprintf(elapsednames
, sizeof(elapsednames
),
278 "[Credits] %d/%d", j
+i
+1, numnames
);
279 rb
->lcd_getstringsize(elapsednames
, &credits_w
, NULL
);
280 rb
->lcd_putsxy(CREDITS_TARGETPOS
, 0, elapsednames
);
281 if (j
+i
< NUM_VISIBLE_LINES
) /* takes care of trail on loop */
282 rb
->lcd_update_rect(0, 0, LCD_WIDTH
, font_h
);
284 for(namepos
= 0-name_w
; namepos
<= name_targetpos
;
285 namepos
+= (name_targetpos
- namepos
+ 14) / 7)
287 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
288 rb
->lcd_fillrect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
289 rb
->lcd_set_drawmode(DRMODE_SOLID
);
290 rb
->lcd_putsxy(namepos
, font_h
*(i
+1), name
);
291 rb
->lcd_update_rect(0, font_h
*(i
+1), LCD_WIDTH
, font_h
);
292 rb
->lcd_update_rect(CREDITS_TARGETPOS
, 0, credits_w
,font_h
);
294 /* stop on keypress */
295 action
= rb
->get_action(CONTEXT_LIST
, HZ
/ANIM_SPEED
);
296 if(stop_autoscroll(action
))
299 if(stop_autoscroll(action
))
301 namepos
= name_targetpos
;
302 } /* for(i=0; i<NUM_VISIBLE_LINES; i++) */
303 if(stop_autoscroll(action
))
306 action
= rb
->get_action(CONTEXT_LIST
, HZ
*PAUSE_TIME
);
307 if(stop_autoscroll(action
))
310 j
+=i
; /* no user intervention, draw the next screen-full */
311 } /* while(j < numnames) */
313 /* handle the keypress that we intercepted during autoscroll */
314 if(ACTION_STD_CANCEL
== action
)
316 if(stop_autoscroll(action
))
317 manual_scroll
= true;
318 } /* if(!manual_scroll) */
322 /* user went into manual scrolling, handle it here */
323 rb
->lcd_set_drawmode(DRMODE_SOLID
);
324 while(ACTION_STD_CANCEL
!= action
)
326 rb
->lcd_clear_display();
327 rb
->snprintf(elapsednames
, sizeof(elapsednames
),
328 "[Credits] %d-%d/%d", j
+1,
329 j
+NUM_VISIBLE_LINES
, numnames
);
330 rb
->lcd_getstringsize(elapsednames
, &credits_w
, NULL
);
331 rb
->lcd_putsxy(CREDITS_TARGETPOS
, 0, elapsednames
);
333 for(i
=0; i
<NUM_VISIBLE_LINES
; i
++)
335 rb
->snprintf(name
, sizeof(name
), "%s", credits
[j
+i
]);
336 rb
->lcd_putsxy(0, font_h
*(i
+1), name
);
342 /* wait for user action */
343 action
= rb
->get_action(CONTEXT_LIST
, TIMEOUT_BLOCK
);
344 if(ACTION_STD_CANCEL
== action
)
346 j
= update_rowpos(action
, j
, NUM_VISIBLE_LINES
, numnames
);
348 return; /* exit without animation */
351 action
= rb
->get_action(CONTEXT_LIST
, HZ
*3);
352 if(ACTION_STD_CANCEL
== action
)
357 /* now make the text exit to the right */
358 for(credits_pos
= (LCD_WIDTH
/2)-(credits_w
/2);
359 credits_pos
<= LCD_WIDTH
+offset_dummy
;
360 credits_pos
+= offset_dummy
, offset_dummy
++)
362 rb
->lcd_set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
363 rb
->lcd_fillrect(0, 0, LCD_WIDTH
, font_h
);
364 rb
->lcd_set_drawmode(DRMODE_SOLID
);
365 rb
->lcd_putsxy(credits_pos
, 0, elapsednames
);
372 enum plugin_status
plugin_start(const void* parameter
)
376 /* Turn off backlight timeout */
377 backlight_force_on(); /* backlight control in lib/helper.c */
380 #ifdef HAVE_LCD_CHARCELLS
381 rb
->lcd_double_height(false);
384 /* Show the logo for about 3 secs allowing the user to stop */
385 if(!rb
->action_userabort(3*HZ
))
388 /* Turn on backlight timeout (revert to settings) */
389 backlight_use_settings(); /* backlight control in lib/helper.c */