b311367481
1) Introduces apps/features.txt that controls which strings are included for each target based on defines. 2) .lng and .voice files are now target specific and the format versions of both these file types have been bumped, which means that new voice files are needed. 3) Use the 'features' mechanism to exclude strings for targets that didn't use them. 4) Delete unused and deprecated and duplicated strings, sort strings in english.lang Some string IDs were changed so translations will be slightly worse than before. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14198 a1c6a512-1295-4272-9138-f99709370657
1357 lines
41 KiB
C
1357 lines
41 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2002 Björn Stenberg
|
|
*
|
|
* 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 <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include "backlight.h"
|
|
#include "action.h"
|
|
#include "lcd.h"
|
|
#ifdef HAVE_REMOTE_LCD
|
|
#include "lcd-remote.h"
|
|
#endif
|
|
#include "lang.h"
|
|
#include "icons.h"
|
|
#include "font.h"
|
|
#include "audio.h"
|
|
#include "mp3_playback.h"
|
|
#include "usb.h"
|
|
#include "settings.h"
|
|
#include "status.h"
|
|
#include "playlist.h"
|
|
#include "sprintf.h"
|
|
#include "kernel.h"
|
|
#include "power.h"
|
|
#include "system.h"
|
|
#include "powermgmt.h"
|
|
#include "adc.h"
|
|
#include "action.h"
|
|
#include "talk.h"
|
|
#include "misc.h"
|
|
#include "id3.h"
|
|
#include "screens.h"
|
|
#include "debug.h"
|
|
#include "led.h"
|
|
#include "sound.h"
|
|
#include "splash.h"
|
|
#include "statusbar.h"
|
|
#include "screen_access.h"
|
|
#include "quickscreen.h"
|
|
#include "pcmbuf.h"
|
|
#include "list.h"
|
|
#include "yesno.h"
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
#include <bitmaps/usblogo.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_REMOTE_LCD
|
|
#include <bitmaps/remote_usblogo.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_MMC
|
|
#include "ata_mmc.h"
|
|
#endif
|
|
#if CONFIG_CODEC == SWCODEC
|
|
#include "dsp.h"
|
|
#endif
|
|
|
|
#if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1))
|
|
#include "backdrop.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
#define SCROLLBAR_WIDTH 6
|
|
#endif
|
|
|
|
void usb_screen(void)
|
|
{
|
|
#ifdef USB_NONE
|
|
/* nothing here! */
|
|
#else
|
|
int i;
|
|
bool statusbar = global_settings.statusbar; /* force the statusbar */
|
|
global_settings.statusbar = true;
|
|
#if LCD_DEPTH > 1
|
|
show_main_backdrop();
|
|
#endif
|
|
#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
|
|
show_remote_main_backdrop();
|
|
#endif
|
|
FOR_NB_SCREENS(i)
|
|
{
|
|
screens[i].backlight_on();
|
|
screens[i].clear_display();
|
|
#if NB_SCREENS > 1
|
|
if (i == SCREEN_REMOTE)
|
|
{
|
|
screens[i].bitmap(remote_usblogo,
|
|
(LCD_REMOTE_WIDTH-BMPWIDTH_remote_usblogo),
|
|
(LCD_REMOTE_HEIGHT-BMPHEIGHT_remote_usblogo)/2,
|
|
BMPWIDTH_remote_usblogo, BMPHEIGHT_remote_usblogo);
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
#ifdef HAVE_LCD_BITMAP
|
|
screens[i].transparent_bitmap(usblogo,
|
|
(LCD_WIDTH-BMPWIDTH_usblogo),
|
|
(LCD_HEIGHT-BMPHEIGHT_usblogo)/2,
|
|
BMPWIDTH_usblogo, BMPHEIGHT_usblogo);
|
|
#else
|
|
screens[i].puts_scroll(0, 0, "[USB Mode]");
|
|
status_set_param(false);
|
|
status_set_audio(false);
|
|
status_set_usb(true);
|
|
#endif /* HAVE_LCD_BITMAP */
|
|
#if NB_SCREENS > 1
|
|
}
|
|
#endif
|
|
screens[i].update();
|
|
}
|
|
|
|
gui_syncstatusbar_draw(&statusbars, true);
|
|
#ifdef SIMULATOR
|
|
while (button_get(true) & BUTTON_REL);
|
|
#else
|
|
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
|
while(usb_wait_for_disconnect_w_tmo(&button_queue, HZ)) {
|
|
if(usb_inserted()) {
|
|
#ifdef HAVE_MMC /* USB-MMC bridge can report activity */
|
|
led(mmc_usb_active(HZ));
|
|
#endif /* HAVE_MMC */
|
|
gui_syncstatusbar_draw(&statusbars, false);
|
|
}
|
|
}
|
|
#endif /* SIMULATOR */
|
|
#ifdef HAVE_LCD_CHARCELLS
|
|
status_set_usb(false);
|
|
#endif /* HAVE_LCD_CHARCELLS */
|
|
FOR_NB_SCREENS(i)
|
|
screens[i].backlight_on();
|
|
global_settings.statusbar = statusbar;
|
|
#endif /* USB_NONE */
|
|
}
|
|
|
|
#ifdef HAVE_MMC
|
|
int mmc_remove_request(void)
|
|
{
|
|
struct event ev;
|
|
int i;
|
|
FOR_NB_SCREENS(i)
|
|
screens[i].clear_display();
|
|
gui_syncsplash(1, str(LANG_REMOVE_MMC));
|
|
if (talk_menus_enabled())
|
|
talk_id(LANG_REMOVE_MMC, false);
|
|
|
|
while (1)
|
|
{
|
|
queue_wait_w_tmo(&button_queue, &ev, HZ/2);
|
|
switch (ev.id)
|
|
{
|
|
case SYS_HOTSWAP_EXTRACTED:
|
|
return SYS_HOTSWAP_EXTRACTED;
|
|
|
|
case SYS_USB_DISCONNECTED:
|
|
return SYS_USB_DISCONNECTED;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* the charging screen is only used for archos targets */
|
|
#if CONFIG_CHARGING && !defined(HAVE_POWEROFF_WHILE_CHARGING) && defined(CPU_SH)
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
static void charging_display_info(bool animate)
|
|
{
|
|
unsigned char charging_logo[36];
|
|
const int pox_x = (LCD_WIDTH - sizeof(charging_logo)) / 2;
|
|
const int pox_y = 32;
|
|
static unsigned phase = 3;
|
|
unsigned i;
|
|
char buf[32];
|
|
(void)buf;
|
|
|
|
#ifdef NEED_ATA_POWER_BATT_MEASURE
|
|
if (ide_powered()) /* FM and V2 can only measure when ATA power is on */
|
|
#endif
|
|
{
|
|
int battv = battery_voltage();
|
|
snprintf(buf, 32, " Batt: %d.%02dV %d%% ", battv / 100,
|
|
battv % 100, battery_level());
|
|
lcd_puts(0, 7, buf);
|
|
}
|
|
|
|
#if CONFIG_CHARGING == CHARGING_CONTROL
|
|
|
|
snprintf(buf, 32, "Charge mode:");
|
|
lcd_puts(0, 2, buf);
|
|
|
|
if (charge_state == CHARGING)
|
|
snprintf(buf, 32, str(LANG_BATTERY_CHARGE));
|
|
else if (charge_state == TOPOFF)
|
|
snprintf(buf, 32, str(LANG_BATTERY_TOPOFF_CHARGE));
|
|
else if (charge_state == TRICKLE)
|
|
snprintf(buf, 32, str(LANG_BATTERY_TRICKLE_CHARGE));
|
|
else
|
|
snprintf(buf, 32, "not charging");
|
|
|
|
lcd_puts(0, 3, buf);
|
|
if (!charger_enabled)
|
|
animate = false;
|
|
#endif /* CONFIG_CHARGING == CHARGING_CONTROL */
|
|
|
|
|
|
/* middle part */
|
|
memset(charging_logo+3, 0x00, 32);
|
|
charging_logo[0] = 0x3C;
|
|
charging_logo[1] = 0x24;
|
|
charging_logo[2] = charging_logo[35] = 0xFF;
|
|
|
|
if (!animate)
|
|
{ /* draw the outline */
|
|
/* middle part */
|
|
lcd_mono_bitmap(charging_logo, pox_x, pox_y + 8, sizeof(charging_logo), 8);
|
|
lcd_set_drawmode(DRMODE_FG);
|
|
/* upper line */
|
|
charging_logo[0] = charging_logo[1] = 0x00;
|
|
memset(charging_logo+2, 0x80, 34);
|
|
lcd_mono_bitmap(charging_logo, pox_x, pox_y, sizeof(charging_logo), 8);
|
|
/* lower line */
|
|
memset(charging_logo+2, 0x01, 34);
|
|
lcd_mono_bitmap(charging_logo, pox_x, pox_y + 16, sizeof(charging_logo), 8);
|
|
lcd_set_drawmode(DRMODE_SOLID);
|
|
}
|
|
else
|
|
{ /* animate the middle part */
|
|
for (i = 3; i<MIN(sizeof(charging_logo)-1, phase); i++)
|
|
{
|
|
if ((i-phase) % 8 == 0)
|
|
{ /* draw a "bubble" here */
|
|
unsigned bitpos;
|
|
bitpos = (phase + i/8) % 15; /* "bounce" effect */
|
|
if (bitpos > 7)
|
|
bitpos = 14 - bitpos;
|
|
charging_logo[i] = 0x01 << bitpos;
|
|
}
|
|
}
|
|
lcd_mono_bitmap(charging_logo, pox_x, pox_y + 8, sizeof(charging_logo), 8);
|
|
phase++;
|
|
}
|
|
lcd_update();
|
|
}
|
|
#else /* not HAVE_LCD_BITMAP */
|
|
|
|
static unsigned long logo_chars[4];
|
|
static const unsigned char logo_pattern[] = {
|
|
0x07, 0x04, 0x1c, 0x14, 0x1c, 0x04, 0x07, 0, /* char 1 */
|
|
0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0, /* char 2 */
|
|
0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0, /* char 3 */
|
|
0x1f, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f, 0, /* char 4 */
|
|
};
|
|
|
|
static void logo_lock_patterns(bool on)
|
|
{
|
|
int i;
|
|
|
|
if (on)
|
|
{
|
|
for (i = 0; i < 4; i++)
|
|
logo_chars[i] = lcd_get_locked_pattern();
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < 4; i++)
|
|
lcd_unlock_pattern(logo_chars[i]);
|
|
}
|
|
}
|
|
|
|
static void charging_display_info(bool animate)
|
|
{
|
|
int battv;
|
|
unsigned i, ypos;
|
|
static unsigned phase = 3;
|
|
char buf[32];
|
|
|
|
battv = battery_voltage();
|
|
snprintf(buf, sizeof(buf), " %d.%02dV", battv / 100, battv % 100);
|
|
lcd_puts(4, 1, buf);
|
|
|
|
memcpy(buf, logo_pattern, 32); /* copy logo patterns */
|
|
|
|
if (!animate) /* build the screen */
|
|
{
|
|
lcd_double_height(false);
|
|
lcd_puts(0, 0, "[Charging]");
|
|
for (i = 0; i < 4; i++)
|
|
lcd_putc(i, 1, logo_chars[i]);
|
|
}
|
|
else /* animate the logo */
|
|
{
|
|
for (i = 3; i < MIN(19, phase); i++)
|
|
{
|
|
if ((i - phase) % 5 == 0)
|
|
{ /* draw a "bubble" here */
|
|
ypos = (phase + i/5) % 9; /* "bounce" effect */
|
|
if (ypos > 4)
|
|
ypos = 8 - ypos;
|
|
buf[5 - ypos + 8 * (i/5)] |= 0x10 >> (i%5);
|
|
}
|
|
}
|
|
phase++;
|
|
}
|
|
|
|
for (i = 0; i < 4; i++)
|
|
lcd_define_pattern(logo_chars[i], buf + 8 * i);
|
|
|
|
lcd_update();
|
|
}
|
|
#endif /* (not) HAVE_LCD_BITMAP */
|
|
|
|
/* blocks while charging, returns on event:
|
|
1 if charger cable was removed
|
|
2 if Off/Stop key was pressed
|
|
3 if On key was pressed
|
|
4 if USB was connected */
|
|
|
|
int charging_screen(void)
|
|
{
|
|
unsigned int button;
|
|
int rc = 0;
|
|
|
|
ide_power_enable(false); /* power down the disk, else would be spinning */
|
|
|
|
lcd_clear_display();
|
|
backlight_set_timeout(global_settings.backlight_timeout);
|
|
#ifdef HAVE_REMOTE_LCD
|
|
remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
|
|
#endif
|
|
backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged);
|
|
gui_syncstatusbar_draw(&statusbars, true);
|
|
|
|
#ifdef HAVE_LCD_CHARCELLS
|
|
logo_lock_patterns(true);
|
|
#endif
|
|
charging_display_info(false);
|
|
|
|
do
|
|
{
|
|
gui_syncstatusbar_draw(&statusbars, false);
|
|
charging_display_info(true);
|
|
button = get_action(CONTEXT_STD,HZ/3);
|
|
if (button == ACTION_STD_OK)
|
|
rc = 2;
|
|
else if (usb_detect())
|
|
rc = 3;
|
|
else if (!charger_inserted())
|
|
rc = 1;
|
|
} while (!rc);
|
|
|
|
#ifdef HAVE_LCD_CHARCELLS
|
|
logo_lock_patterns(false);
|
|
#endif
|
|
return rc;
|
|
}
|
|
#endif /* CONFIG_CHARGING && !HAVE_POWEROFF_WHILE_CHARGING && defined(CPU_SH) */
|
|
|
|
#ifdef HAVE_PITCHSCREEN
|
|
|
|
#define PITCH_MAX 2000
|
|
#define PITCH_MIN 500
|
|
#define PITCH_SMALL_DELTA 1
|
|
#define PITCH_BIG_DELTA 10
|
|
#define PITCH_NUDGE_DELTA 20
|
|
|
|
#define PITCH_MODE_ABSOLUTE 1
|
|
#define PITCH_MODE_SEMITONE -PITCH_MODE_ABSOLUTE
|
|
|
|
static int pitch_mode = PITCH_MODE_ABSOLUTE; /* 1 - absolute, -1 - semitone */
|
|
|
|
/* returns:
|
|
0 if no key was pressed
|
|
1 if USB was connected */
|
|
|
|
static void pitch_screen_draw(struct screen *display, int pitch, int pitch_mode)
|
|
{
|
|
unsigned char* ptr;
|
|
unsigned char buf[32];
|
|
int w, h;
|
|
|
|
display->clear_display();
|
|
|
|
if (display->nb_lines < 4) /* very small screen, just show the pitch value */
|
|
{
|
|
w = snprintf((char *)buf, sizeof(buf), "%s: %d.%d%%",str(LANG_PITCH),
|
|
pitch / 10, pitch % 10 );
|
|
display->putsxy((display->width-(w*display->char_width))/2,
|
|
display->nb_lines/2,buf);
|
|
}
|
|
else /* bigger screen, show everything... */
|
|
{
|
|
|
|
/* UP: Pitch Up */
|
|
if (pitch_mode == PITCH_MODE_ABSOLUTE) {
|
|
ptr = str(LANG_PITCH_UP);
|
|
} else {
|
|
ptr = str(LANG_PITCH_UP_SEMITONE);
|
|
}
|
|
display->getstringsize(ptr,&w,&h);
|
|
display->putsxy((display->width-w)/2, 0, ptr);
|
|
display->mono_bitmap(bitmap_icons_7x8[Icon_UpArrow],
|
|
display->width/2 - 3, h, 7, 8);
|
|
|
|
/* DOWN: Pitch Down */
|
|
if (pitch_mode == PITCH_MODE_ABSOLUTE) {
|
|
ptr = str(LANG_PITCH_DOWN);
|
|
} else {
|
|
ptr = str(LANG_PITCH_DOWN_SEMITONE);
|
|
}
|
|
display->getstringsize(ptr,&w,&h);
|
|
display->putsxy((display->width-w)/2, display->height - h, ptr);
|
|
display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow],
|
|
display->width/2 - 3, display->height - h*2, 7, 8);
|
|
|
|
/* RIGHT: +2% */
|
|
ptr = "+2%";
|
|
display->getstringsize(ptr,&w,&h);
|
|
display->putsxy(display->width-w, (display->height-h)/2, ptr);
|
|
display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward],
|
|
display->width-w-8, (display->height-h)/2, 7, 8);
|
|
|
|
/* LEFT: -2% */
|
|
ptr = "-2%";
|
|
display->getstringsize(ptr,&w,&h);
|
|
display->putsxy(0, (display->height-h)/2, ptr);
|
|
display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward],
|
|
w+1, (display->height-h)/2, 7, 8);
|
|
|
|
/* "Pitch" */
|
|
snprintf((char *)buf, sizeof(buf), str(LANG_PITCH));
|
|
display->getstringsize(buf,&w,&h);
|
|
display->putsxy((display->width-w)/2, (display->height/2)-h, buf);
|
|
/* "XX.X%" */
|
|
snprintf((char *)buf, sizeof(buf), "%d.%d%%",
|
|
pitch / 10, pitch % 10 );
|
|
display->getstringsize(buf,&w,&h);
|
|
display->putsxy((display->width-w)/2, display->height/2, buf);
|
|
}
|
|
|
|
display->update();
|
|
}
|
|
|
|
static int pitch_increase(int pitch, int delta,
|
|
bool allow_cutoff, bool redraw_screens) {
|
|
int new_pitch;
|
|
int i;
|
|
|
|
if (delta < 0) {
|
|
if (pitch + delta >= PITCH_MIN) {
|
|
new_pitch = pitch + delta;
|
|
} else {
|
|
if (!allow_cutoff) {
|
|
return pitch;
|
|
}
|
|
new_pitch = PITCH_MIN;
|
|
}
|
|
} else if (delta > 0) {
|
|
if (pitch + delta <= PITCH_MAX) {
|
|
new_pitch = pitch + delta;
|
|
} else {
|
|
if (!allow_cutoff) {
|
|
return pitch;
|
|
}
|
|
new_pitch = PITCH_MAX;
|
|
}
|
|
} else {
|
|
/* delta == 0 -> no real change */
|
|
return pitch;
|
|
}
|
|
sound_set_pitch(new_pitch);
|
|
|
|
if (redraw_screens) {
|
|
FOR_NB_SCREENS(i)
|
|
pitch_screen_draw(&screens[i], pitch, pitch_mode);
|
|
}
|
|
|
|
return new_pitch;
|
|
}
|
|
|
|
/* Factor for changing the pitch one half tone up.
|
|
The exact value is 2^(1/12) = 1.05946309436
|
|
But we use only integer arithmetics, so take
|
|
rounded factor multiplied by 10^5=100,000. This is
|
|
enough to get the same promille values as if we
|
|
had used floating point (checked with a spread
|
|
sheet).
|
|
*/
|
|
#define PITCH_SEMITONE_FACTOR 105946L
|
|
|
|
/* Some helpful constants. K is the scaling factor for SEMITONE.
|
|
N is for more accurate rounding
|
|
KN is K * N
|
|
*/
|
|
#define PITCH_K_FCT 100000UL
|
|
#define PITCH_N_FCT 10
|
|
#define PITCH_KN_FCT 1000000UL
|
|
|
|
static int pitch_increase_semitone(int pitch, bool up) {
|
|
uint32_t tmp;
|
|
uint32_t round_fct; /* How much to scale down at the end */
|
|
tmp = pitch;
|
|
if (up) {
|
|
tmp = tmp * PITCH_SEMITONE_FACTOR;
|
|
round_fct = PITCH_K_FCT;
|
|
} else {
|
|
tmp = (tmp * PITCH_KN_FCT) / PITCH_SEMITONE_FACTOR;
|
|
round_fct = PITCH_N_FCT;
|
|
}
|
|
/* Scaling down with rounding */
|
|
tmp = (tmp + round_fct / 2) / round_fct;
|
|
return pitch_increase(pitch, tmp - pitch, false, false);
|
|
}
|
|
|
|
bool pitch_screen(void)
|
|
{
|
|
int button;
|
|
int pitch = sound_get_pitch();
|
|
int new_pitch;
|
|
bool nudged = false;
|
|
bool exit = false;
|
|
int i;
|
|
|
|
#if CONFIG_CODEC == SWCODEC
|
|
pcmbuf_set_low_latency(true);
|
|
#endif
|
|
|
|
while (!exit)
|
|
{
|
|
FOR_NB_SCREENS(i)
|
|
pitch_screen_draw(&screens[i], pitch, pitch_mode);
|
|
|
|
button = get_action(CONTEXT_PITCHSCREEN,TIMEOUT_BLOCK);
|
|
switch (button) {
|
|
case ACTION_PS_INC_SMALL:
|
|
if (pitch_mode == PITCH_MODE_ABSOLUTE) {
|
|
pitch = pitch_increase(pitch, PITCH_SMALL_DELTA, true, false);
|
|
} else {
|
|
pitch = pitch_increase_semitone(pitch, true);
|
|
}
|
|
break;
|
|
|
|
case ACTION_PS_INC_BIG:
|
|
if (pitch_mode == PITCH_MODE_ABSOLUTE) {
|
|
pitch = pitch_increase(pitch, PITCH_BIG_DELTA, true, false);
|
|
}
|
|
break;
|
|
|
|
case ACTION_PS_DEC_SMALL:
|
|
if (pitch_mode == PITCH_MODE_ABSOLUTE) {
|
|
pitch = pitch_increase(pitch, -PITCH_SMALL_DELTA, true, false);
|
|
} else {
|
|
pitch = pitch_increase_semitone(pitch, false);
|
|
}
|
|
break;
|
|
|
|
case ACTION_PS_DEC_BIG:
|
|
if (pitch_mode == PITCH_MODE_ABSOLUTE) {
|
|
pitch = pitch_increase(pitch, -PITCH_BIG_DELTA, true, false);
|
|
}
|
|
break;
|
|
|
|
case ACTION_PS_NUDGE_RIGHT:
|
|
new_pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false, true);
|
|
nudged = (new_pitch != pitch);
|
|
pitch = new_pitch;
|
|
break;
|
|
case ACTION_PS_NUDGE_RIGHTOFF:
|
|
if (nudged) {
|
|
pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false, false);
|
|
}
|
|
nudged = false;
|
|
break;
|
|
|
|
case ACTION_PS_NUDGE_LEFT:
|
|
new_pitch = pitch_increase(pitch, -PITCH_NUDGE_DELTA, false, true);
|
|
nudged = (new_pitch != pitch);
|
|
pitch = new_pitch;
|
|
break;
|
|
|
|
case ACTION_PS_NUDGE_LEFTOFF:
|
|
if (nudged) {
|
|
pitch = pitch_increase(pitch, PITCH_NUDGE_DELTA, false, false);
|
|
}
|
|
nudged = false;
|
|
break;
|
|
|
|
case ACTION_PS_RESET:
|
|
pitch = 1000;
|
|
sound_set_pitch( pitch );
|
|
break;
|
|
|
|
case ACTION_PS_TOGGLE_MODE:
|
|
pitch_mode = -pitch_mode;
|
|
break;
|
|
|
|
case ACTION_PS_EXIT:
|
|
exit = true;
|
|
break;
|
|
|
|
default:
|
|
if(default_event_handler(button) == SYS_USB_CONNECTED)
|
|
return 1;
|
|
break;
|
|
}
|
|
}
|
|
#if CONFIG_CODEC == SWCODEC
|
|
pcmbuf_set_low_latency(false);
|
|
#endif
|
|
lcd_setfont(FONT_UI);
|
|
return 0;
|
|
}
|
|
#endif /* HAVE_PITCHSCREEN */
|
|
|
|
#ifdef HAVE_QUICKSCREEN
|
|
|
|
#define bool_to_int(b)\
|
|
b?1:0
|
|
#define int_to_bool(i)\
|
|
i==0?false:true
|
|
|
|
static void quick_screen_quick_apply(struct gui_quickscreen *qs)
|
|
{
|
|
global_settings.playlist_shuffle=int_to_bool(qs->left_option->option);
|
|
global_settings.dirfilter=qs->bottom_option->option;
|
|
global_settings.repeat_mode=qs->right_option->option;
|
|
}
|
|
|
|
bool quick_screen_quick(int button_enter)
|
|
{
|
|
bool res, oldshuffle;
|
|
struct option_select left_option;
|
|
struct option_select bottom_option;
|
|
struct option_select right_option;
|
|
int oldrepeat, old_x_margin, old_y_margin;
|
|
|
|
static const struct opt_items left_items[] = {
|
|
[0]={ STR(LANG_SYSFONT_OFF) },
|
|
[1]={ STR(LANG_SYSFONT_ON) }
|
|
};
|
|
static const struct opt_items bottom_items[] = {
|
|
[SHOW_ALL]={ STR(LANG_SYSFONT_ALL) },
|
|
[SHOW_SUPPORTED]={ STR(LANG_SYSFONT_FILTER_SUPPORTED) },
|
|
[SHOW_MUSIC]={ STR(LANG_SYSFONT_FILTER_MUSIC) },
|
|
[SHOW_PLAYLIST]={ STR(LANG_SYSFONT_FILTER_PLAYLIST) },
|
|
};
|
|
static const struct opt_items right_items[] = {
|
|
[REPEAT_OFF]={ STR(LANG_SYSFONT_OFF) },
|
|
[REPEAT_ALL]={ STR(LANG_SYSFONT_ALL) },
|
|
[REPEAT_ONE]={ STR(LANG_SYSFONT_REPEAT_ONE) },
|
|
[REPEAT_SHUFFLE]={ STR(LANG_SYSFONT_SHUFFLE) },
|
|
#ifdef AB_REPEAT_ENABLE
|
|
[REPEAT_AB]={ STR(LANG_SYSFONT_REPEAT_AB) }
|
|
#endif
|
|
};
|
|
struct gui_quickscreen qs;
|
|
|
|
old_x_margin = lcd_getxmargin();
|
|
old_y_margin = lcd_getymargin();
|
|
lcd_setmargins(0, 0);
|
|
|
|
option_select_init_items(&left_option,
|
|
(char *)str(LANG_SYSFONT_SHUFFLE),
|
|
bool_to_int(global_settings.playlist_shuffle),
|
|
left_items,
|
|
2);
|
|
option_select_init_items(&bottom_option,
|
|
(char *)str(LANG_SYSFONT_FILTER),
|
|
global_settings.dirfilter,
|
|
bottom_items,
|
|
sizeof(bottom_items)/sizeof(struct opt_items));
|
|
option_select_init_items(&right_option,
|
|
(char *)str(LANG_SYSFONT_REPEAT),
|
|
global_settings.repeat_mode,
|
|
right_items,
|
|
sizeof(right_items)/sizeof(struct opt_items));
|
|
|
|
gui_quickscreen_init(&qs, &left_option, &bottom_option, &right_option,
|
|
&quick_screen_quick_apply);
|
|
oldrepeat=global_settings.repeat_mode;
|
|
oldshuffle=global_settings.playlist_shuffle;
|
|
res=gui_syncquickscreen_run(&qs, button_enter);
|
|
if(!res)
|
|
{
|
|
if ( oldrepeat != global_settings.repeat_mode &&
|
|
(audio_status() & AUDIO_STATUS_PLAY) )
|
|
audio_flush_and_reload_tracks();
|
|
if(oldshuffle != global_settings.playlist_shuffle
|
|
&& audio_status() & AUDIO_STATUS_PLAY)
|
|
{
|
|
#if CONFIG_CODEC == SWCODEC
|
|
dsp_set_replaygain();
|
|
#endif
|
|
if (global_settings.playlist_shuffle)
|
|
playlist_randomise(NULL, current_tick, true);
|
|
else
|
|
playlist_sort(NULL, true);
|
|
}
|
|
settings_save();
|
|
}
|
|
lcd_setmargins(old_x_margin, old_y_margin);
|
|
return(res);
|
|
}
|
|
|
|
#ifdef BUTTON_F3
|
|
static void quick_screen_f3_apply(struct gui_quickscreen *qs)
|
|
{
|
|
global_settings.scrollbar=int_to_bool(qs->left_option->option);
|
|
|
|
global_settings.flip_display=int_to_bool(qs->bottom_option->option);
|
|
button_set_flip(global_settings.flip_display);
|
|
lcd_set_flip(global_settings.flip_display);
|
|
|
|
global_settings.statusbar=int_to_bool(qs->right_option->option);
|
|
gui_syncstatusbar_draw(&statusbars, true);
|
|
}
|
|
|
|
bool quick_screen_f3(int button_enter)
|
|
{
|
|
bool res;
|
|
struct option_select left_option;
|
|
struct option_select bottom_option;
|
|
struct option_select right_option;
|
|
int old_x_margin, old_y_margin;
|
|
|
|
static const struct opt_items onoff_items[] = {
|
|
[0]={ STR(LANG_SYSFONT_OFF) },
|
|
[1]={ STR(LANG_SYSFONT_ON) }
|
|
};
|
|
static const struct opt_items yesno_items[] = {
|
|
[0]={ STR(LANG_SYSFONT_SET_BOOL_NO) },
|
|
[1]={ STR(LANG_SYSFONT_SET_BOOL_YES) }
|
|
};
|
|
|
|
struct gui_quickscreen qs;
|
|
|
|
old_x_margin = lcd_getxmargin();
|
|
old_y_margin = lcd_getymargin();
|
|
lcd_setmargins(0, 0);
|
|
|
|
option_select_init_items(&left_option,
|
|
str(LANG_SYSFONT_SCROLL_BAR),
|
|
bool_to_int(global_settings.scrollbar),
|
|
onoff_items,
|
|
2);
|
|
option_select_init_items(&bottom_option,
|
|
str(LANG_SYSFONT_FLIP_DISPLAY),
|
|
bool_to_int(global_settings.flip_display),
|
|
yesno_items,
|
|
2);
|
|
option_select_init_items(&right_option,
|
|
str(LANG_SYSFONT_STATUS_BAR),
|
|
bool_to_int(global_settings.statusbar),
|
|
onoff_items,
|
|
2);
|
|
gui_quickscreen_init(&qs, &left_option, &bottom_option, &right_option,
|
|
&quick_screen_f3_apply);
|
|
res=gui_syncquickscreen_run(&qs, button_enter);
|
|
if(!res)
|
|
settings_save();
|
|
lcd_setmargins(old_x_margin, old_y_margin);
|
|
return(res);
|
|
}
|
|
#endif /* BUTTON_F3 */
|
|
#endif /* CONFIG_KEYPAD in (RECORDER_PAD |IRIVER_H100_PAD | IRIVER_H300_PAD) */
|
|
|
|
#if CONFIG_CHARGING || defined(SIMULATOR)
|
|
void charging_splash(void)
|
|
{
|
|
gui_syncsplash(2*HZ, (unsigned char *)str(LANG_BATTERY_CHARGE));
|
|
button_clear_queue();
|
|
}
|
|
#endif
|
|
|
|
|
|
#if defined(HAVE_LCD_BITMAP) && (CONFIG_RTC != 0)
|
|
|
|
const int dayname[] = {
|
|
LANG_WEEKDAY_SUNDAY,
|
|
LANG_WEEKDAY_MONDAY,
|
|
LANG_WEEKDAY_TUESDAY,
|
|
LANG_WEEKDAY_WEDNESDAY,
|
|
LANG_WEEKDAY_THURSDAY,
|
|
LANG_WEEKDAY_FRIDAY,
|
|
LANG_WEEKDAY_SATURDAY
|
|
};
|
|
|
|
const int monthname[] = {
|
|
LANG_MONTH_JANUARY,
|
|
LANG_MONTH_FEBRUARY,
|
|
LANG_MONTH_MARCH,
|
|
LANG_MONTH_APRIL,
|
|
LANG_MONTH_MAY,
|
|
LANG_MONTH_JUNE,
|
|
LANG_MONTH_JULY,
|
|
LANG_MONTH_AUGUST,
|
|
LANG_MONTH_SEPTEMBER,
|
|
LANG_MONTH_OCTOBER,
|
|
LANG_MONTH_NOVEMBER,
|
|
LANG_MONTH_DECEMBER
|
|
};
|
|
|
|
/* little helper function for voice output */
|
|
static void say_time(int cursorpos, const struct tm *tm)
|
|
{
|
|
static const int unit[] = { UNIT_HOUR, UNIT_MIN, UNIT_SEC, 0, 0, 0 };
|
|
int value = 0;
|
|
|
|
if (!talk_menus_enabled())
|
|
return;
|
|
|
|
switch(cursorpos)
|
|
{
|
|
case 0:
|
|
value = tm->tm_hour;
|
|
break;
|
|
case 1:
|
|
value = tm->tm_min;
|
|
break;
|
|
case 2:
|
|
value = tm->tm_sec;
|
|
break;
|
|
case 3:
|
|
value = tm->tm_year + 1900;
|
|
break;
|
|
case 5:
|
|
value = tm->tm_mday;
|
|
break;
|
|
}
|
|
|
|
if (cursorpos == 4) /* month */
|
|
talk_id(LANG_MONTH_JANUARY + tm->tm_mon, false);
|
|
else
|
|
talk_value(value, unit[cursorpos], false);
|
|
}
|
|
|
|
|
|
#define INDEX_X 0
|
|
#define INDEX_Y 1
|
|
#define INDEX_WIDTH 2
|
|
|
|
#define SEPARATOR ":"
|
|
bool set_time_screen(const char* title, struct tm *tm)
|
|
{
|
|
bool done = false;
|
|
int button;
|
|
unsigned int i, s;
|
|
unsigned int cursorpos = 0;
|
|
unsigned int lastcursorpos = 1;
|
|
unsigned int julianday;
|
|
unsigned int realyear;
|
|
unsigned int width;
|
|
unsigned int min = 0, steps = 0;
|
|
unsigned int statusbar_height = 0;
|
|
unsigned int separator_width, weekday_width;
|
|
unsigned int line_height, prev_line_height;
|
|
unsigned char daysinmonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
|
unsigned char buffer[20];
|
|
|
|
/* 6 possible cursor possitions, 3 values stored for each: x, y, width */
|
|
unsigned char cursor[6][3];
|
|
memset(cursor, 0, sizeof(cursor));
|
|
|
|
int *valptr = NULL;
|
|
unsigned char *ptr[6];
|
|
|
|
if(global_settings.statusbar)
|
|
statusbar_height = STATUSBAR_HEIGHT;
|
|
|
|
while ( !done ) {
|
|
/* for easy acess in the drawing loop */
|
|
ptr[0] = buffer; /* hours */
|
|
ptr[1] = buffer + 3; /* minutes */
|
|
ptr[2] = buffer + 6; /* seconds */
|
|
ptr[3] = buffer + 9; /* year */
|
|
ptr[4] = str(monthname[tm->tm_mon]); /* monthname */
|
|
ptr[5] = buffer + 14; /* day of month */
|
|
|
|
/* calculate the number of days in febuary */
|
|
realyear = tm->tm_year + 1900;
|
|
if((realyear % 4 == 0 && !(realyear % 100 == 0)) || realyear % 400 == 0)
|
|
daysinmonth[1] = 29;
|
|
else
|
|
daysinmonth[1] = 28;
|
|
|
|
/* fix day if month or year changed */
|
|
if (tm->tm_mday > daysinmonth[tm->tm_mon])
|
|
tm->tm_mday = daysinmonth[tm->tm_mon];
|
|
|
|
/* calculate day of week */
|
|
julianday = 0;
|
|
for(i = 0; (int)i < tm->tm_mon; i++) {
|
|
julianday += daysinmonth[i];
|
|
}
|
|
julianday += tm->tm_mday;
|
|
tm->tm_wday = (realyear + julianday + (realyear - 1) / 4 -
|
|
(realyear - 1) / 100 + (realyear - 1) / 400 + 7 - 1) % 7;
|
|
|
|
/* put all the numbers we want from the tm struct into
|
|
an easily printable buffer */
|
|
snprintf(buffer, sizeof(buffer),
|
|
"%02d " "%02d " "%02d " "%04d " "%02d",
|
|
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
|
tm->tm_year+1900, tm->tm_mday);
|
|
|
|
/* convert spaces in the buffer to '\0' to make it possible to work
|
|
directly on the buffer */
|
|
for(i=0; i < sizeof(buffer); i++)
|
|
{
|
|
if(buffer[i] == ' ')
|
|
buffer[i] = '\0';
|
|
}
|
|
|
|
FOR_NB_SCREENS(s)
|
|
{
|
|
/* minimum lines needed is 2 + title line */
|
|
gui_textarea_update_nblines(&screens[s]);
|
|
if (screens[s].nb_lines < 4)
|
|
{
|
|
screens[s].setfont(FONT_SYSFIXED);
|
|
gui_textarea_update_nblines(&screens[s]);
|
|
}
|
|
|
|
/* recalculate the positions and offsets */
|
|
if (screens[s].nb_lines >= 3)
|
|
screens[s].getstringsize(title, NULL, &prev_line_height);
|
|
else
|
|
prev_line_height = 0;
|
|
screens[s].getstringsize(buffer, NULL, &line_height);
|
|
screens[s].getstringsize(SEPARATOR, &separator_width, NULL);
|
|
|
|
|
|
/* get width for each string except the last one and put them
|
|
in the cursor array */
|
|
for(i=0; i < 5; i++)
|
|
{
|
|
screens[s].getstringsize(ptr[i], &width, NULL);
|
|
cursor[i][INDEX_WIDTH] = width;
|
|
}
|
|
|
|
/* hour */
|
|
/* cursor[0][INDEX_X] is already 0 because of the memset */
|
|
cursor[0][INDEX_Y] = prev_line_height + statusbar_height;
|
|
|
|
/* minute */
|
|
cursor[1][INDEX_X] = cursor[0][INDEX_WIDTH] + separator_width;
|
|
cursor[1][INDEX_Y] = prev_line_height + statusbar_height;
|
|
|
|
/* second */
|
|
cursor[2][INDEX_X] = cursor[0][INDEX_WIDTH] + separator_width +
|
|
cursor[1][INDEX_WIDTH] + separator_width;
|
|
cursor[2][INDEX_Y] = prev_line_height + statusbar_height;
|
|
|
|
/* weekday */
|
|
screens[s].getstringsize(str(dayname[tm->tm_wday]), &weekday_width, NULL);
|
|
screens[s].getstringsize(" ", &separator_width, NULL);
|
|
|
|
/* year */
|
|
cursor[3][INDEX_X] = weekday_width + separator_width;
|
|
cursor[3][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height;
|
|
|
|
/* month */
|
|
cursor[4][INDEX_X] = weekday_width + 2 * separator_width +
|
|
cursor[3][INDEX_WIDTH];
|
|
cursor[4][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height;
|
|
|
|
/* day */
|
|
cursor[5][INDEX_X] = weekday_width + 3 * separator_width +
|
|
cursor[3][INDEX_WIDTH] +
|
|
cursor[4][INDEX_WIDTH];
|
|
cursor[5][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height;
|
|
|
|
/* draw the screen */
|
|
screens[s].set_drawmode(DRMODE_SOLID);
|
|
gui_textarea_clear(&screens[s]);
|
|
/* display the screen title */
|
|
screens[s].puts_scroll(0, 0, title);
|
|
|
|
/* these are not selectable, so we draw them outside the loop */
|
|
screens[s].putsxy(0, cursor[3][INDEX_Y], str(dayname[tm->tm_wday])); /* name of the week day */
|
|
screens[s].putsxy(cursor[1][INDEX_X] - separator_width,
|
|
cursor[0][INDEX_Y], SEPARATOR);
|
|
screens[s].putsxy(cursor[2][INDEX_X] - separator_width,
|
|
cursor[0][INDEX_Y], SEPARATOR);
|
|
|
|
/* draw the selected item with drawmode set to
|
|
DRMODE_SOLID|DRMODE_INVERSEVID, all other selectable
|
|
items with drawmode DRMODE_SOLID */
|
|
for(i=0; i<6; i++)
|
|
{
|
|
if (cursorpos == i)
|
|
screens[s].set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
else
|
|
screens[s].set_drawmode(DRMODE_SOLID);
|
|
|
|
screens[s].putsxy(cursor[i][INDEX_X],
|
|
cursor[i][INDEX_Y], ptr[i]);
|
|
}
|
|
|
|
/* print help text */
|
|
if (screens[s].nb_lines > 4)
|
|
screens[s].puts(0, 4, str(LANG_TIME_SET_BUTTON));
|
|
if (screens[s].nb_lines > 5)
|
|
screens[s].puts(0, 5, str(LANG_TIME_REVERT));
|
|
screens[s].update();
|
|
}
|
|
gui_syncstatusbar_draw(&statusbars, true);
|
|
|
|
/* calculate the minimum and maximum for the number under cursor */
|
|
if(cursorpos!=lastcursorpos) {
|
|
lastcursorpos=cursorpos;
|
|
switch(cursorpos) {
|
|
case 0: /* hour */
|
|
min = 0;
|
|
steps = 24;
|
|
valptr = &tm->tm_hour;
|
|
break;
|
|
case 1: /* minute */
|
|
min = 0;
|
|
steps = 60;
|
|
valptr = &tm->tm_min;
|
|
break;
|
|
case 2: /* second */
|
|
min = 0;
|
|
steps = 60;
|
|
valptr = &tm->tm_sec;
|
|
break;
|
|
case 3: /* year */
|
|
min = 1;
|
|
steps = 200;
|
|
valptr = &tm->tm_year;
|
|
break;
|
|
case 4: /* month */
|
|
min = 0;
|
|
steps = 12;
|
|
valptr = &tm->tm_mon;
|
|
break;
|
|
case 5: /* day */
|
|
min = 1;
|
|
steps = daysinmonth[tm->tm_mon];
|
|
valptr = &tm->tm_mday;
|
|
break;
|
|
}
|
|
say_time(cursorpos, tm);
|
|
}
|
|
|
|
button = get_action(CONTEXT_SETTINGS_TIME, TIMEOUT_BLOCK);
|
|
switch ( button ) {
|
|
case ACTION_STD_PREV:
|
|
cursorpos = (cursorpos + 6 - 1) % 6;
|
|
break;
|
|
case ACTION_STD_NEXT:
|
|
cursorpos = (cursorpos + 6 + 1) % 6;
|
|
break;
|
|
case ACTION_SETTINGS_INC:
|
|
case ACTION_SETTINGS_INCREPEAT:
|
|
*valptr = (*valptr + steps - min + 1) %
|
|
steps + min;
|
|
if(*valptr == 0)
|
|
*valptr = min;
|
|
say_time(cursorpos, tm);
|
|
break;
|
|
case ACTION_SETTINGS_DEC:
|
|
case ACTION_SETTINGS_DECREPEAT:
|
|
*valptr = (*valptr + steps - min - 1) %
|
|
steps + min;
|
|
if(*valptr == 0)
|
|
*valptr = min;
|
|
say_time(cursorpos, tm);
|
|
break;
|
|
|
|
case ACTION_STD_OK:
|
|
done = true;
|
|
break;
|
|
|
|
case ACTION_STD_CANCEL:
|
|
done = true;
|
|
tm->tm_year = -1;
|
|
break;
|
|
|
|
default:
|
|
if (default_event_handler(button) == SYS_USB_CONNECTED)
|
|
return true;
|
|
break;
|
|
}
|
|
}
|
|
FOR_NB_SCREENS(i)
|
|
{
|
|
screens[i].setfont(FONT_UI);
|
|
gui_textarea_update_nblines(&screens[i]);
|
|
}
|
|
return false;
|
|
}
|
|
#endif /* defined(HAVE_LCD_BITMAP) && (CONFIG_RTC != 0) */
|
|
|
|
#if (CONFIG_KEYPAD == RECORDER_PAD) && !defined(HAVE_SW_POWEROFF)
|
|
bool shutdown_screen(void)
|
|
{
|
|
int button;
|
|
bool done = false;
|
|
long time_entered = current_tick;
|
|
|
|
lcd_stop_scroll();
|
|
|
|
gui_syncsplash(0, str(LANG_CONFIRM_SHUTDOWN));
|
|
|
|
while(!done && TIME_BEFORE(current_tick,time_entered+HZ*2))
|
|
{
|
|
button = get_action(CONTEXT_STD,HZ);
|
|
switch(button)
|
|
{
|
|
case ACTION_STD_CANCEL:
|
|
sys_poweroff();
|
|
break;
|
|
|
|
/* do nothing here, because ACTION_NONE might be caused
|
|
* by timeout or button release. In case of timeout the loop
|
|
* is terminated by TIME_BEFORE */
|
|
case ACTION_NONE:
|
|
break;
|
|
|
|
default:
|
|
if(default_event_handler(button) == SYS_USB_CONNECTED)
|
|
return true;
|
|
done = true;
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
static const int id3_headers[]=
|
|
{
|
|
LANG_ID3_TITLE,
|
|
LANG_ID3_ARTIST,
|
|
LANG_ID3_ALBUM,
|
|
LANG_ID3_ALBUMARTIST,
|
|
LANG_ID3_DISCNUM,
|
|
LANG_ID3_TRACKNUM,
|
|
LANG_ID3_COMMENT,
|
|
LANG_ID3_GENRE,
|
|
LANG_ID3_YEAR,
|
|
LANG_ID3_LENGTH,
|
|
LANG_ID3_PLAYLIST,
|
|
LANG_ID3_BITRATE,
|
|
LANG_ID3_FREQUENCY,
|
|
#if CONFIG_CODEC == SWCODEC
|
|
LANG_ID3_TRACK_GAIN,
|
|
LANG_ID3_ALBUM_GAIN,
|
|
#endif
|
|
LANG_ID3_PATH,
|
|
};
|
|
|
|
static char * id3_get_info(int selected_item, void* data, char *buffer)
|
|
{
|
|
struct mp3entry* id3 =(struct mp3entry*)data;
|
|
int info_no=selected_item/2;
|
|
if(!(selected_item%2))
|
|
{/* header */
|
|
return( str(id3_headers[info_no]));
|
|
}
|
|
else
|
|
{/* data */
|
|
|
|
char * info=NULL;
|
|
switch(info_no)
|
|
{
|
|
case 0:/*LANG_ID3_TITLE*/
|
|
info=id3->title;
|
|
break;
|
|
case 1:/*LANG_ID3_ARTIST*/
|
|
info=id3->artist;
|
|
break;
|
|
case 2:/*LANG_ID3_ALBUM*/
|
|
info=id3->album;
|
|
break;
|
|
case 3:/*LANG_ID3_ALBUMARTIST*/
|
|
info=id3->albumartist;
|
|
break;
|
|
case 4:/*LANG_ID3_DISCNUM*/
|
|
if (id3->disc_string)
|
|
info = id3->disc_string;
|
|
else if (id3->discnum)
|
|
{
|
|
snprintf(buffer, MAX_PATH, "%d", id3->discnum);
|
|
info = buffer;
|
|
}
|
|
break;
|
|
case 5:/*LANG_ID3_TRACKNUM*/
|
|
if (id3->track_string)
|
|
info = id3->track_string;
|
|
else if (id3->tracknum)
|
|
{
|
|
snprintf(buffer, MAX_PATH, "%d", id3->tracknum);
|
|
info = buffer;
|
|
}
|
|
break;
|
|
case 6:/*LANG_ID3_COMMENT*/
|
|
info=id3->comment;
|
|
break;
|
|
case 7:/*LANG_ID3_GENRE*/
|
|
info = id3->genre_string;
|
|
break;
|
|
case 8:/*LANG_ID3_YEAR*/
|
|
if (id3->year_string)
|
|
info = id3->year_string;
|
|
else if (id3->year)
|
|
{
|
|
snprintf(buffer, MAX_PATH, "%d", id3->year);
|
|
info = buffer;
|
|
}
|
|
break;
|
|
case 9:/*LANG_ID3_LENGTH*/
|
|
format_time(buffer, MAX_PATH, id3->length);
|
|
info=buffer;
|
|
break;
|
|
case 10:/*LANG_ID3_PLAYLIST*/
|
|
snprintf(buffer, MAX_PATH, "%d/%d", playlist_get_display_index(),
|
|
playlist_amount());
|
|
info=buffer;
|
|
break;
|
|
case 11:/*LANG_ID3_BITRATE*/
|
|
snprintf(buffer, MAX_PATH, "%d kbps%s", id3->bitrate,
|
|
id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) "");
|
|
info=buffer;
|
|
break;
|
|
case 12:/*LANG_ID3_FREQUENCY*/
|
|
snprintf(buffer, MAX_PATH, "%ld Hz", id3->frequency);
|
|
info=buffer;
|
|
break;
|
|
#if CONFIG_CODEC == SWCODEC
|
|
case 13:/*LANG_ID3_TRACK_GAIN*/
|
|
info=id3->track_gain_string;
|
|
break;
|
|
case 14:/*LANG_ID3_ALBUM_GAIN*/
|
|
info=id3->album_gain_string;
|
|
break;
|
|
case 15:/*LANG_ID3_PATH*/
|
|
#else
|
|
case 13:/*LANG_ID3_PATH*/
|
|
#endif
|
|
info=id3->path;
|
|
break;
|
|
}
|
|
return info && *info ? info : (char*) str(LANG_ID3_NO_INFO);
|
|
}
|
|
}
|
|
|
|
bool browse_id3(void)
|
|
{
|
|
struct gui_synclist id3_lists;
|
|
struct mp3entry* id3 = audio_current_track();
|
|
int key;
|
|
|
|
gui_synclist_init(&id3_lists, &id3_get_info, id3, true, 2);
|
|
gui_synclist_set_nb_items(&id3_lists,
|
|
sizeof(id3_headers)/sizeof(id3_headers[0])*2);
|
|
gui_synclist_draw(&id3_lists);
|
|
gui_syncstatusbar_draw(&statusbars, true);
|
|
while (true) {
|
|
gui_syncstatusbar_draw(&statusbars, false);
|
|
key = get_action(CONTEXT_LIST,HZ/2);
|
|
if(key!=ACTION_NONE && key!=ACTION_UNKNOWN
|
|
&& !gui_synclist_do_button(&id3_lists, key,LIST_WRAP_UNLESS_HELD))
|
|
{
|
|
return(default_event_handler(key) == SYS_USB_CONNECTED);
|
|
}
|
|
}
|
|
}
|
|
|
|
static char* runtime_get_data(int selected_item, void* data, char* buffer)
|
|
{
|
|
(void) data;
|
|
unsigned char *headers[] = {str(LANG_RUNNING_TIME), str(LANG_TOP_TIME) };
|
|
int t;
|
|
if(!(selected_item%2))
|
|
return headers[selected_item/2];
|
|
|
|
if(selected_item/2) t = global_status.topruntime;
|
|
else t = global_status.runtime;
|
|
|
|
snprintf(buffer, 16, "%dh %dm %ds",
|
|
t / 3600, (t % 3600) / 60, t % 60);
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
bool view_runtime(void)
|
|
{
|
|
unsigned char *lines[]={str(LANG_CLEAR_TIME)};
|
|
struct text_message message={(char **)lines, 1};
|
|
|
|
struct gui_synclist lists;
|
|
int action;
|
|
gui_synclist_init(&lists, runtime_get_data, NULL, false, 2);
|
|
#if !defined(HAVE_LCD_CHARCELLS)
|
|
gui_synclist_set_title(&lists, str(LANG_RUNNING_TIME), NOICON);
|
|
#else
|
|
gui_synclist_set_title(&lists, NULL, NOICON);
|
|
#endif
|
|
gui_synclist_set_icon_callback(&lists, NULL);
|
|
gui_synclist_set_nb_items(&lists, 4);
|
|
while(1)
|
|
{
|
|
#if CONFIG_CHARGING
|
|
if (charger_inserted()
|
|
#ifdef HAVE_USB_POWER
|
|
|| usb_powered()
|
|
#endif
|
|
)
|
|
{
|
|
global_status.runtime = 0;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
global_status.runtime += ((current_tick - lasttime) / HZ);
|
|
}
|
|
lasttime = current_tick;
|
|
gui_synclist_draw(&lists);
|
|
gui_syncstatusbar_draw(&statusbars, true);
|
|
action = get_action(CONTEXT_STD, HZ);
|
|
gui_synclist_do_button(&lists, action, LIST_WRAP_UNLESS_HELD);
|
|
if(action == ACTION_STD_CANCEL)
|
|
break;
|
|
if(action == ACTION_STD_OK) {
|
|
if(gui_syncyesno_run(&message, NULL, NULL)==YESNO_YES)
|
|
{
|
|
if (!(gui_synclist_get_sel_pos(&lists)/2))
|
|
global_status.runtime = 0;
|
|
else
|
|
global_status.topruntime = 0;
|
|
}
|
|
}
|
|
if(default_event_handler(action) == SYS_USB_CONNECTED)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|