rockbox/apps/plugins/credits.c
William Wilgus 18ec1a2aa6 [Bug Fix] Credits Plugin don't set the back/foreground on greyscale displays
Change-Id: I2e5a37111dd055932b84962b70ff6c3eace945c7
2022-12-20 02:40:14 -05:00

388 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"
#ifdef HAVE_REMOTE_LCD
#define REMOTE_WIDTH LCD_REMOTE_WIDTH
#define REMOTE_HEIGHT LCD_REMOTE_HEIGHT
#include "pluginbitmaps/remote_rockboxlogo.h"
#define REMOTE_LOGO_WIDTH BMPWIDTH_remote_rockboxlogo
#define REMOTE_LOGO_HEIGHT BMPHEIGHT_remote_rockboxlogo
#define REMOTE_LOGO (const fb_remote_data*)remote_rockboxlogo
#endif /* HAVE_REMOTE_LCD */
#define LOGO (const fb_data*)rockboxlogo
#include "pluginbitmaps/rockboxlogo.h"
#define LOGO_WIDTH BMPWIDTH_rockboxlogo
#define LOGO_HEIGHT BMPHEIGHT_rockboxlogo
static const char* const credits[] = {
#include "credits.raw" /* generated list of names from docs/CREDITS */
};
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 == 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->lcd_putsxyf(0, font_h*(i+1), "%s", credits[j+i]);
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();
}
}
int show_logo(void)
{
unsigned char version[32];
int font_h, ver_w;
rb->snprintf(version, sizeof(version), "Ver. %s", rb->rbversion);
ver_w = rb->font_getstringsize(version, NULL, &font_h, FONT_SYSFIXED);
rb->lcd_clear_display();
rb->lcd_setfont(FONT_SYSFIXED);
#if defined(SANSA_CLIP) || defined(SANSA_CLIPV2) || defined(SANSA_CLIPPLUS)
/* display the logo in the blue area of the screen (bottom 48 pixels) */
if (ver_w > LCD_WIDTH)
rb->lcd_puts_scroll(0, 0, version);
else
rb->lcd_putsxy((LCD_WIDTH/2) - (ver_w/2), 0, version);
rb->lcd_bitmap(LOGO, (LCD_WIDTH - LOGO_WIDTH) / 2, 16,
LOGO_WIDTH, LOGO_HEIGHT);
#else
rb->lcd_bitmap(LOGO, (LCD_WIDTH - LOGO_WIDTH) / 2, 10,
LOGO_WIDTH, LOGO_HEIGHT);
if (ver_w > LCD_WIDTH)
rb->lcd_puts_scroll(0, (LCD_HEIGHT-font_h) / font_h, version);
else
rb->lcd_putsxy((LCD_WIDTH/2) - (ver_w/2), LCD_HEIGHT-font_h, version);
#endif
rb->lcd_setfont(FONT_UI);
rb->lcd_update();
#ifdef HAVE_REMOTE_LCD
rb->lcd_remote_clear_display();
rb->lcd_remote_bitmap(REMOTE_LOGO, 0, 10,
REMOTE_LOGO_WIDTH, REMOTE_LOGO_HEIGHT);
rb->lcd_remote_setfont(FONT_SYSFIXED);
if (ver_w > LCD_REMOTE_WIDTH)
rb->lcd_remote_puts_scroll(0, (LCD_REMOTE_HEIGHT-font_h) / font_h, version);
else
rb->lcd_remote_putsxy((LCD_REMOTE_WIDTH/2) - (ver_w/2),
LCD_REMOTE_HEIGHT-font_h, version);
rb->lcd_remote_setfont(FONT_UI);
rb->lcd_remote_update();
#endif
return 0;
}
enum plugin_status plugin_start(const void* parameter)
{
(void)parameter;
/* Turn off backlight timeout */
backlight_ignore_timeout();
#if LCD_DEPTH >= 16
rb->lcd_set_foreground (LCD_WHITE);
rb->lcd_set_background (LCD_BLACK);
#endif
show_logo();
/* Show the logo for about 5 secs allowing the user to stop */
if(!rb->action_userabort(5*HZ))
{
rb->lcd_scroll_stop();
roll_credits();
}
#ifdef HAVE_REMOTE_LCD
rb->lcd_remote_scroll_stop();
#endif
/* Turn on backlight timeout (revert to settings) */
backlight_use_settings();
return PLUGIN_OK;
}