d6c054575b
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7416 a1c6a512-1295-4272-9138-f99709370657
405 lines
11 KiB
C
405 lines
11 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2002 by Linus Nielsen Feltzing
|
|
*
|
|
* All files in this archive are subject to the GNU General Public License.
|
|
* See the file COPYING in the source tree root for full license agreement.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
#include "string.h"
|
|
#include "lcd.h"
|
|
#include "debug.h"
|
|
#include "kernel.h"
|
|
#include "power.h"
|
|
#include "thread.h"
|
|
#include "settings.h"
|
|
#include "status.h"
|
|
#include "mp3_playback.h"
|
|
#include "audio.h"
|
|
#include "wps.h"
|
|
#include "abrepeat.h"
|
|
#ifdef HAVE_RTC
|
|
#include "timefuncs.h"
|
|
#endif
|
|
#ifdef HAVE_LCD_BITMAP
|
|
#include "icons.h"
|
|
#include "font.h"
|
|
#endif
|
|
#include "powermgmt.h"
|
|
#include "led.h"
|
|
#include "sound.h"
|
|
#if CONFIG_KEYPAD == IRIVER_H100_PAD
|
|
#include "button.h"
|
|
#endif
|
|
#include "usb.h"
|
|
|
|
static enum playmode ff_mode;
|
|
|
|
static long switch_tick;
|
|
static bool battery_state = true;
|
|
#ifdef HAVE_CHARGING
|
|
static int battery_charge_step = 0;
|
|
#endif
|
|
|
|
struct status_info {
|
|
int battlevel;
|
|
int volume;
|
|
int hour;
|
|
int minute;
|
|
int playmode;
|
|
int repeat;
|
|
bool inserted;
|
|
bool shuffle;
|
|
bool keylock;
|
|
bool battery_safe;
|
|
bool redraw_volume; /* true if the volume gauge needs updating */
|
|
#if CONFIG_LED == LED_VIRTUAL
|
|
bool led; /* disk LED simulation in the status bar */
|
|
#endif
|
|
#ifdef HAVE_USB_POWER
|
|
bool usb_power;
|
|
#endif
|
|
|
|
};
|
|
|
|
void status_init(void)
|
|
{
|
|
ff_mode = 0;
|
|
}
|
|
|
|
void status_set_ffmode(enum playmode mode)
|
|
{
|
|
ff_mode = mode; /* Either STATUS_FASTFORWARD or STATUS_FASTBACKWARD */
|
|
status_draw(false);
|
|
}
|
|
|
|
enum playmode status_get_ffmode(void)
|
|
{
|
|
/* only use this function for STATUS_FASTFORWARD or STATUS_FASTBACKWARD */
|
|
/* use audio_status() for other modes */
|
|
return ff_mode;
|
|
}
|
|
|
|
int current_playmode(void)
|
|
{
|
|
int audio_stat = audio_status();
|
|
|
|
/* ff_mode can be either STATUS_FASTFORWARD or STATUS_FASTBACKWARD
|
|
and that supercedes the other modes */
|
|
if(ff_mode)
|
|
return ff_mode;
|
|
|
|
if(audio_stat & AUDIO_STATUS_PLAY)
|
|
{
|
|
if(audio_stat & AUDIO_STATUS_PAUSE)
|
|
return STATUS_PAUSE;
|
|
else
|
|
return STATUS_PLAY;
|
|
}
|
|
#if CONFIG_CODEC == MAS3587F
|
|
else
|
|
{
|
|
if(audio_stat & AUDIO_STATUS_RECORD)
|
|
{
|
|
if(audio_stat & AUDIO_STATUS_PAUSE)
|
|
return STATUS_RECORD_PAUSE;
|
|
else
|
|
return STATUS_RECORD;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return STATUS_STOP;
|
|
}
|
|
|
|
#if defined(HAVE_LCD_CHARCELLS)
|
|
static bool record = false;
|
|
static bool audio = false;
|
|
static bool param = false;
|
|
static bool usb = false;
|
|
|
|
void status_set_record(bool b)
|
|
{
|
|
record = b;
|
|
}
|
|
|
|
void status_set_audio(bool b)
|
|
{
|
|
audio = b;
|
|
}
|
|
|
|
void status_set_param(bool b)
|
|
{
|
|
param = b;
|
|
}
|
|
|
|
void status_set_usb(bool b)
|
|
{
|
|
usb = b;
|
|
}
|
|
|
|
#endif /* HAVE_LCD_CHARCELLS */
|
|
|
|
void status_draw(bool force_redraw)
|
|
{
|
|
/* This is static because we use memcmp() below to check for changes, and
|
|
the unused bytes (due to struct member alignment) might change if
|
|
the struct is allocated on the stack. */
|
|
static struct status_info info;
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
static struct status_info lastinfo;
|
|
struct tm* tm;
|
|
|
|
if ( !global_settings.statusbar )
|
|
return;
|
|
#else
|
|
(void)force_redraw; /* players always "redraw" */
|
|
#endif
|
|
|
|
info.volume = sound_val2phys(SOUND_VOLUME, global_settings.volume);
|
|
info.inserted = charger_inserted();
|
|
info.battlevel = battery_level();
|
|
info.battery_safe = battery_level_safe();
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
tm = get_time();
|
|
info.hour = tm->tm_hour;
|
|
info.minute = tm->tm_min;
|
|
info.shuffle = global_settings.playlist_shuffle;
|
|
#if CONFIG_KEYPAD == IRIVER_H100_PAD
|
|
info.keylock = button_hold();
|
|
#else
|
|
info.keylock = keys_locked;
|
|
#endif
|
|
info.repeat = global_settings.repeat_mode;
|
|
info.playmode = current_playmode();
|
|
#if CONFIG_LED == LED_VIRTUAL
|
|
info.led = led_read(HZ/2); /* delay should match polling interval */
|
|
#endif
|
|
#ifdef HAVE_USB_POWER
|
|
info.usb_power = usb_powered();
|
|
#endif
|
|
|
|
/* only redraw if forced to, or info has changed */
|
|
if (force_redraw ||
|
|
info.inserted ||
|
|
!info.battery_safe ||
|
|
info.redraw_volume ||
|
|
memcmp(&info, &lastinfo, sizeof(struct status_info)))
|
|
{
|
|
lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
lcd_fillrect(0,0,LCD_WIDTH,8);
|
|
lcd_set_drawmode(DRMODE_SOLID);
|
|
#else
|
|
/* players always "redraw" */
|
|
{
|
|
#endif
|
|
|
|
#ifdef HAVE_CHARGING
|
|
if (info.inserted) {
|
|
battery_state = true;
|
|
#if defined(HAVE_CHARGE_CTRL) || CONFIG_BATTERY == BATT_LIION2200
|
|
/* zero battery run time if charging */
|
|
if (charge_state > 0) {
|
|
global_settings.runtime = 0;
|
|
lasttime = current_tick;
|
|
}
|
|
|
|
/* animate battery if charging */
|
|
if ((charge_state == 1) ||
|
|
(charge_state == 2)) {
|
|
#else
|
|
global_settings.runtime = 0;
|
|
lasttime = current_tick;
|
|
{
|
|
#endif
|
|
/* animate in three steps (34% per step for a better look) */
|
|
info.battlevel = battery_charge_step * 34;
|
|
if (info.battlevel > 100)
|
|
info.battlevel = 100;
|
|
if(TIME_AFTER(current_tick, switch_tick)) {
|
|
battery_charge_step=(battery_charge_step+1)%4;
|
|
switch_tick = current_tick + HZ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif /* HAVE_CHARGING */
|
|
{
|
|
if (info.battery_safe)
|
|
battery_state = true;
|
|
else {
|
|
/* blink battery if level is low */
|
|
if(TIME_AFTER(current_tick, switch_tick) &&
|
|
(info.battlevel > -1)) {
|
|
switch_tick = current_tick+HZ;
|
|
battery_state =! battery_state;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
if (battery_state)
|
|
statusbar_icon_battery(info.battlevel);
|
|
|
|
/* draw power plug if charging */
|
|
if (info.inserted)
|
|
lcd_mono_bitmap(bitmap_icons_7x8[Icon_Plug], ICON_PLUG_X_POS,
|
|
STATUSBAR_Y_POS, ICON_PLUG_WIDTH, STATUSBAR_HEIGHT);
|
|
#ifdef HAVE_USB_POWER
|
|
else if (info.usb_power)
|
|
lcd_mono_bitmap(bitmap_icons_7x8[Icon_USBPlug], ICON_PLUG_X_POS,
|
|
STATUSBAR_Y_POS, ICON_PLUG_WIDTH, STATUSBAR_HEIGHT);
|
|
#endif
|
|
|
|
info.redraw_volume = statusbar_icon_volume(info.volume);
|
|
statusbar_icon_play_state(current_playmode() + Icon_Play);
|
|
switch (info.repeat) {
|
|
#ifdef AB_REPEAT_ENABLE
|
|
case REPEAT_AB:
|
|
statusbar_icon_play_mode(Icon_RepeatAB);
|
|
break;
|
|
#endif
|
|
|
|
case REPEAT_ONE:
|
|
statusbar_icon_play_mode(Icon_RepeatOne);
|
|
break;
|
|
|
|
case REPEAT_ALL:
|
|
case REPEAT_SHUFFLE:
|
|
statusbar_icon_play_mode(Icon_Repeat);
|
|
break;
|
|
}
|
|
if (info.shuffle)
|
|
statusbar_icon_shuffle();
|
|
if (info.keylock)
|
|
statusbar_icon_lock();
|
|
#ifdef HAVE_RTC
|
|
statusbar_time(info.hour, info.minute);
|
|
#endif
|
|
#if CONFIG_LED == LED_VIRTUAL
|
|
if (info.led)
|
|
statusbar_led();
|
|
#endif
|
|
lcd_update_rect(0, 0, LCD_WIDTH, STATUSBAR_HEIGHT);
|
|
lastinfo = info;
|
|
#endif
|
|
}
|
|
|
|
|
|
#if defined(HAVE_LCD_CHARCELLS)
|
|
if (info.battlevel > -1)
|
|
lcd_icon(ICON_BATTERY, battery_state);
|
|
lcd_icon(ICON_BATTERY_1, info.battlevel > 25);
|
|
lcd_icon(ICON_BATTERY_2, info.battlevel > 50);
|
|
lcd_icon(ICON_BATTERY_3, info.battlevel > 75);
|
|
|
|
lcd_icon(ICON_VOLUME, true);
|
|
lcd_icon(ICON_VOLUME_1, info.volume > 10);
|
|
lcd_icon(ICON_VOLUME_2, info.volume > 30);
|
|
lcd_icon(ICON_VOLUME_3, info.volume > 50);
|
|
lcd_icon(ICON_VOLUME_4, info.volume > 70);
|
|
lcd_icon(ICON_VOLUME_5, info.volume > 90);
|
|
|
|
lcd_icon(ICON_PLAY, current_playmode() == STATUS_PLAY);
|
|
lcd_icon(ICON_PAUSE, current_playmode() == STATUS_PAUSE);
|
|
|
|
lcd_icon(ICON_REPEAT, global_settings.repeat_mode != REPEAT_OFF);
|
|
lcd_icon(ICON_1, global_settings.repeat_mode == REPEAT_ONE);
|
|
|
|
lcd_icon(ICON_RECORD, record);
|
|
lcd_icon(ICON_AUDIO, audio);
|
|
lcd_icon(ICON_PARAM, param);
|
|
lcd_icon(ICON_USB, usb);
|
|
#endif
|
|
|
|
}
|
|
|
|
#if defined(HAVE_LCD_BITMAP) && (CONFIG_KEYPAD == RECORDER_PAD)
|
|
static void draw_buttonbar_btn(int num, const char* caption)
|
|
{
|
|
int xpos, ypos, button_width, text_width;
|
|
int fw, fh;
|
|
|
|
lcd_setfont(FONT_SYSFIXED);
|
|
lcd_getstringsize("M", &fw, &fh);
|
|
|
|
button_width = LCD_WIDTH/3;
|
|
xpos = num * button_width;
|
|
ypos = LCD_HEIGHT - fh;
|
|
|
|
if(caption)
|
|
{
|
|
/* center the text */
|
|
text_width = fw * strlen(caption);
|
|
lcd_putsxy(xpos + (button_width - text_width)/2, ypos, caption);
|
|
}
|
|
|
|
lcd_set_drawmode(DRMODE_COMPLEMENT);
|
|
lcd_fillrect(xpos, ypos, button_width - 1, fh);
|
|
lcd_set_drawmode(DRMODE_SOLID);
|
|
}
|
|
|
|
static char stored_caption1[8];
|
|
static char stored_caption2[8];
|
|
static char stored_caption3[8];
|
|
|
|
void buttonbar_set(const char* caption1, const char *caption2,
|
|
const char *caption3)
|
|
{
|
|
buttonbar_unset();
|
|
if(caption1)
|
|
{
|
|
strncpy(stored_caption1, caption1, 7);
|
|
stored_caption1[7] = 0;
|
|
}
|
|
if(caption2)
|
|
{
|
|
strncpy(stored_caption2, caption2, 7);
|
|
stored_caption2[7] = 0;
|
|
}
|
|
if(caption3)
|
|
{
|
|
strncpy(stored_caption3, caption3, 7);
|
|
stored_caption3[7] = 0;
|
|
}
|
|
}
|
|
|
|
void buttonbar_unset(void)
|
|
{
|
|
stored_caption1[0] = 0;
|
|
stored_caption2[0] = 0;
|
|
stored_caption3[0] = 0;
|
|
}
|
|
|
|
void buttonbar_draw(void)
|
|
{
|
|
lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
lcd_fillrect(0, LCD_HEIGHT-8, LCD_WIDTH, 8);
|
|
lcd_set_drawmode(DRMODE_SOLID);
|
|
draw_buttonbar_btn(0, stored_caption1);
|
|
draw_buttonbar_btn(1, stored_caption2);
|
|
draw_buttonbar_btn(2, stored_caption3);
|
|
}
|
|
|
|
bool buttonbar_isset(void)
|
|
{
|
|
/* If all buttons are unset, the button bar is considered disabled */
|
|
return (global_settings.buttonbar &&
|
|
((stored_caption1[0] != 0) ||
|
|
(stored_caption2[0] != 0) ||
|
|
(stored_caption3[0] != 0)));
|
|
}
|
|
|
|
#endif
|