rockbox/apps/plugins/credits.c
Andrew Mahone 23d9812273 loader-initialized global plugin API:
struct plugin_api *rb is declared in PLUGIN_HEADER, and pointed to by
__header.api

the loader uses this pointer to initialize rb before calling entry_point

entry_point is no longer passed a pointer to the plugin API

all plugins, and pluginlib functions, are modified to refer to the
global rb

pluginlib functions which only served to copy the API pointer are
removed

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19776 a1c6a512-1295-4272-9138-f99709370657
2009-01-16 10:34:40 +00:00

392 lines
13 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Robert Hak <rhak at ramapo.edu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "plugin.h"
#include "lib/helper.h"
PLUGIN_HEADER
static const char* const credits[] = {
#include "credits.raw" /* generated list of names from docs/CREDITS */
};
#ifdef HAVE_LCD_CHARCELLS
static void roll_credits(void)
{
int numnames = sizeof(credits)/sizeof(char*);
int curr_name = 0;
int curr_len = rb->utf8length(credits[0]);
int curr_index = 0;
int curr_line = 0;
int name, len, new_len, line, x;
while (1)
{
rb->lcd_clear_display();
name = curr_name;
x = -curr_index;
len = curr_len;
line = curr_line;
while (x < 11)
{
int x2;
if (x < 0)
rb->lcd_puts(0, line,
credits[name] + rb->utf8seek(credits[name], -x));
else
rb->lcd_puts(x, line, credits[name]);
if (++name >= numnames)
break;
line ^= 1;
x2 = x + len/2;
if ((unsigned)x2 < 11)
rb->lcd_putc(x2, line, '*');
new_len = rb->utf8length(credits[name]);
x += MAX(len/2 + 2, len - new_len/2 + 1);
len = new_len;
}
rb->lcd_update();
/* abort on keypress */
if(rb->action_userabort(HZ/8))
return;
if (++curr_index >= curr_len)
{
if (++curr_name >= numnames)
break;
new_len = rb->utf8length(credits[curr_name]);
curr_index -= MAX(curr_len/2 + 2, curr_len - new_len/2 + 1);
curr_len = new_len;
curr_line ^= 1;
}
}
}
#else
static bool stop_autoscroll(int action)
{
switch (action)
{
case ACTION_STD_CANCEL:
case ACTION_STD_OK:
case ACTION_STD_NEXT:
case ACTION_STD_NEXTREPEAT:
case ACTION_STD_PREV:
case ACTION_STD_PREVREPEAT:
return true;
default:
return false;
}
return false;
}
static int update_rowpos(int action, int cur_pos, int rows_per_screen, int tot_rows)
{
switch(action)
{
case ACTION_STD_PREV:
case ACTION_STD_PREVREPEAT:
cur_pos--;
break;
case ACTION_STD_NEXT:
case ACTION_STD_NEXTREPEAT:
cur_pos++;
break;
}
if(cur_pos > tot_rows - rows_per_screen)
cur_pos = 0;
if(cur_pos < 0)
cur_pos = tot_rows - rows_per_screen;
return cur_pos;
}
static void roll_credits(void)
{
/* to do: use target defines iso keypads to set animation timings */
#if (CONFIG_KEYPAD == RECORDER_PAD)
#define PAUSE_TIME 1.2
#define ANIM_SPEED 35
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
(CONFIG_KEYPAD == IPOD_1G2G_PAD)
#define PAUSE_TIME 0
#define ANIM_SPEED 100
#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
#define PAUSE_TIME 0
#define ANIM_SPEED 35
#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
#define PAUSE_TIME 0
#define ANIM_SPEED 100
#else
#define PAUSE_TIME 1
#define ANIM_SPEED 40
#endif
#define NUM_VISIBLE_LINES (LCD_HEIGHT/font_h - 1)
#define CREDITS_TARGETPOS ((LCD_WIDTH/2)-(credits_w/2))
int i=0, j=0, namepos=0, offset_dummy;
int name_w, name_h, name_targetpos=1, font_h;
int credits_w, credits_pos;
int numnames = (sizeof(credits)/sizeof(char*));
char name[40], elapsednames[32];
int action = ACTION_NONE;
/* control if scrolling is automatic (with animation) or manual */
bool manual_scroll = false;
rb->lcd_setfont(FONT_UI);
rb->lcd_clear_display();
rb->lcd_update();
rb->lcd_getstringsize("A", NULL, &font_h);
/* snprintf "credits" text, and save the width and height */
rb->snprintf(elapsednames, sizeof(elapsednames), "[Credits] %d/%d",
j+1, numnames);
rb->lcd_getstringsize(elapsednames, &credits_w, NULL);
/* fly in "credits" text from the left */
for(credits_pos = 0 - credits_w; credits_pos <= CREDITS_TARGETPOS;
credits_pos += (CREDITS_TARGETPOS-credits_pos + 14) / 7)
{
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
rb->lcd_fillrect(0, 0, LCD_WIDTH, font_h);
rb->lcd_set_drawmode(DRMODE_SOLID);
rb->lcd_putsxy(credits_pos, 0, elapsednames);
rb->lcd_update_rect(0, 0, LCD_WIDTH, font_h);
rb->sleep(HZ/ANIM_SPEED);
}
/* first screen's worth of lines fly in */
for(i=0; i<NUM_VISIBLE_LINES; i++)
{
rb->snprintf(name, sizeof(name), "%s", credits[i]);
rb->lcd_getstringsize(name, &name_w, &name_h);
rb->snprintf(elapsednames, sizeof(elapsednames), "[Credits] %d/%d",
i+1, numnames);
rb->lcd_getstringsize(elapsednames, &credits_w, NULL);
rb->lcd_putsxy(CREDITS_TARGETPOS, 0, elapsednames);
rb->lcd_update_rect(CREDITS_TARGETPOS, 0, credits_w, font_h);
for(namepos = 0-name_w; namepos <= name_targetpos;
namepos += (name_targetpos - namepos + 14) / 7)
{
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
/* clear any trails left behind */
rb->lcd_fillrect(0, font_h*(i+1), LCD_WIDTH, font_h);
rb->lcd_set_drawmode(DRMODE_SOLID);
rb->lcd_putsxy(namepos, font_h*(i+1), name);
rb->lcd_update_rect(0, font_h*(i+1), LCD_WIDTH, font_h);
/* exit on abort, switch to manual on up/down */
action = rb->get_action(CONTEXT_LIST, HZ/ANIM_SPEED);
if(stop_autoscroll(action))
break;
}
if(stop_autoscroll(action))
break;
}
/* process user actions (if any) */
if(ACTION_STD_CANCEL == action)
return;
if(stop_autoscroll(action))
manual_scroll = true; /* up/down - abort was catched above */
if(!manual_scroll)
{
j+= i;
/* pause for a bit if needed */
action = rb->get_action(CONTEXT_LIST, HZ*PAUSE_TIME);
if(ACTION_STD_CANCEL == action)
return;
if(stop_autoscroll(action))
manual_scroll = true;
}
if(!manual_scroll)
{
while(j < numnames)
{
/* just a screen's worth at a time */
for(i=0; i<NUM_VISIBLE_LINES; i++)
{
if(j+i >= numnames)
break;
offset_dummy=1;
rb->snprintf(name, sizeof(name), "%s",
credits[j+i-NUM_VISIBLE_LINES]);
rb->lcd_getstringsize(name, &name_w, &name_h);
/* fly out an existing line.. */
while(namepos<LCD_WIDTH+offset_dummy)
{
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
/* clear trails */
rb->lcd_fillrect(0, font_h*(i+1), LCD_WIDTH, font_h);
rb->lcd_set_drawmode(DRMODE_SOLID);
rb->lcd_putsxy(namepos, font_h*(i+1), name);
rb->lcd_update_rect(0, font_h*(i+1), LCD_WIDTH, font_h);
/* exit on keypress, react to scrolling */
action = rb->get_action(CONTEXT_LIST, HZ/ANIM_SPEED);
if(stop_autoscroll(action))
break;
namepos += offset_dummy;
offset_dummy++;
} /* while(namepos<LCD_WIDTH+offset_dummy) */
if(stop_autoscroll(action))
break;
rb->snprintf(name, sizeof(name), "%s", credits[j+i]);
rb->lcd_getstringsize(name, &name_w, &name_h);
rb->snprintf(elapsednames, sizeof(elapsednames),
"[Credits] %d/%d", j+i+1, numnames);
rb->lcd_getstringsize(elapsednames, &credits_w, NULL);
rb->lcd_putsxy(CREDITS_TARGETPOS, 0, elapsednames);
if (j+i < NUM_VISIBLE_LINES) /* takes care of trail on loop */
rb->lcd_update_rect(0, 0, LCD_WIDTH, font_h);
for(namepos = 0-name_w; namepos <= name_targetpos;
namepos += (name_targetpos - namepos + 14) / 7)
{
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
rb->lcd_fillrect(0, font_h*(i+1), LCD_WIDTH, font_h);
rb->lcd_set_drawmode(DRMODE_SOLID);
rb->lcd_putsxy(namepos, font_h*(i+1), name);
rb->lcd_update_rect(0, font_h*(i+1), LCD_WIDTH, font_h);
rb->lcd_update_rect(CREDITS_TARGETPOS, 0, credits_w,font_h);
/* stop on keypress */
action = rb->get_action(CONTEXT_LIST, HZ/ANIM_SPEED);
if(stop_autoscroll(action))
break;
}
if(stop_autoscroll(action))
break;
namepos = name_targetpos;
} /* for(i=0; i<NUM_VISIBLE_LINES; i++) */
if(stop_autoscroll(action))
break;
action = rb->get_action(CONTEXT_LIST, HZ*PAUSE_TIME);
if(stop_autoscroll(action))
break;
j+=i; /* no user intervention, draw the next screen-full */
} /* while(j < numnames) */
/* handle the keypress that we intercepted during autoscroll */
if(ACTION_STD_CANCEL == action)
return;
if(stop_autoscroll(action))
manual_scroll = true;
} /* if(!manual_scroll) */
if(manual_scroll)
{
/* user went into manual scrolling, handle it here */
rb->lcd_set_drawmode(DRMODE_SOLID);
while(ACTION_STD_CANCEL != action)
{
rb->lcd_clear_display();
rb->snprintf(elapsednames, sizeof(elapsednames),
"[Credits] %d-%d/%d", j+1,
j+NUM_VISIBLE_LINES, numnames);
rb->lcd_getstringsize(elapsednames, &credits_w, NULL);
rb->lcd_putsxy(CREDITS_TARGETPOS, 0, elapsednames);
for(i=0; i<NUM_VISIBLE_LINES; i++)
{
rb->snprintf(name, sizeof(name), "%s", credits[j+i]);
rb->lcd_putsxy(0, font_h*(i+1), name);
}
rb->lcd_update();
rb->yield();
/* wait for user action */
action = rb->get_action(CONTEXT_LIST, TIMEOUT_BLOCK);
if(ACTION_STD_CANCEL == action)
return;
j = update_rowpos(action, j, NUM_VISIBLE_LINES, numnames);
}
return; /* exit without animation */
}
action = rb->get_action(CONTEXT_LIST, HZ*3);
if(ACTION_STD_CANCEL == action)
return;
offset_dummy = 1;
/* now make the text exit to the right */
for(credits_pos = (LCD_WIDTH/2)-(credits_w/2);
credits_pos <= LCD_WIDTH+offset_dummy;
credits_pos += offset_dummy, offset_dummy++)
{
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
rb->lcd_fillrect(0, 0, LCD_WIDTH, font_h);
rb->lcd_set_drawmode(DRMODE_SOLID);
rb->lcd_putsxy(credits_pos, 0, elapsednames);
rb->lcd_update();
}
}
#endif
enum plugin_status plugin_start(const void* parameter)
{
(void)parameter;
/* Turn off backlight timeout */
backlight_force_on(); /* backlight control in lib/helper.c */
rb->show_logo();
#ifdef HAVE_LCD_CHARCELLS
rb->lcd_double_height(false);
#endif
/* Show the logo for about 3 secs allowing the user to stop */
if(!rb->action_userabort(3*HZ))
roll_credits();
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings(); /* backlight control in lib/helper.c */
return PLUGIN_OK;
}