1
0
Fork 0
forked from len0rd/rockbox

Added resume. Works in dirs and playlists, shuffled or not. Resumes mid-song, but press pause on players before you shutdown so they get a chance to store the position on disk. Recorders use RTC ram. Todo: Time display is wrong after mid-track resume and ffd/rew is not handled.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@1787 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Björn Stenberg 2002-08-16 14:41:47 +00:00
parent 085e774675
commit 6224cdb166
12 changed files with 379 additions and 144 deletions

View file

@ -66,7 +66,7 @@ int playlist_add(char *filename)
return 0;
}
char* playlist_next(int steps)
char* playlist_next(int steps, int* index)
{
int seek;
int max;
@ -103,7 +103,9 @@ char* playlist_next(int steps)
else
return NULL;
}
if (index)
*index = playlist.index;
/* Zero-terminate the file name */
seek=0;
@ -165,7 +167,11 @@ char* playlist_next(int steps)
}
}
void play_list(char *dir, char *file, int start_index)
void play_list(char *dir,
char *file,
int start_index,
int start_offset,
int random_seed )
{
char *sep="";
int dirlen;
@ -211,7 +217,7 @@ void play_list(char *dir, char *file, int start_index)
status_draw();
lcd_update();
}
randomise_playlist( current_tick );
randomise_playlist( random_seed );
}
if(!playlist.in_ram) {
@ -220,7 +226,7 @@ void play_list(char *dir, char *file, int start_index)
lcd_update();
}
/* also make the first song get playing */
mpeg_play(playlist_next(0));
mpeg_play(start_offset);
}
/*

View file

@ -40,8 +40,9 @@ typedef struct
extern playlist_info_t playlist;
extern bool playlist_shuffle;
void play_list(char *dir, char *file, int start_index);
char* playlist_next(int steps);
void play_list(char *dir, char *file, int start_index,
int start_offset, int random_seed );
char* playlist_next(int steps, int* id);
void randomise_playlist( unsigned int seed );
void sort_playlist(void);
void empty_playlist(void);

View file

@ -37,10 +37,9 @@
struct user_settings global_settings;
static unsigned short last_checksum = 0;
#define CONFIG_BLOCK_VERSION 1
#define CONFIG_BLOCK_SIZE 44
#define CONFIG_BLOCK_SIZE 512
#define RTC_BLOCK_SIZE 44
/********************************************
@ -64,6 +63,8 @@ offset abs
0x0f 0x23 <scroll speed & WPS display byte>
0x10 0x24 <playlist options byte>
0x11 0x25 <AVC byte>
0x12 0x26 <(int) Resume playlist index, or -1 if no playlist resume>
0x16 0x2b <(int) Byte offset into resume file>
<all unused space filled with 0xff>
@ -81,24 +82,30 @@ location used, and reset the setting in question with a factory default if
needed. Memory locations not used by a given version should not be
modified unless the header & checksum test fails.
Rest of config block, only saved to disk:
0xF8 (int) Playlist shuffle seed
0xFC (char[260]) Resume playlist (path/to/dir or path/to/playlist.m3u)
*************************************/
#include "rtc.h"
static unsigned char rtc_config_block[CONFIG_BLOCK_SIZE];
static unsigned char config_block[CONFIG_BLOCK_SIZE];
/*
* Calculates the checksum for the config block and places it in the given 2-byte buffer
* Calculates the checksum for the config block and returns it
*/
static unsigned short calculate_config_checksum(void)
static unsigned short calculate_config_checksum(unsigned char* buf)
{
unsigned int i;
unsigned char cksum[2];
cksum[0] = cksum[1] = 0;
for (i=0; i < CONFIG_BLOCK_SIZE - 2; i+=2 ) {
cksum[0] ^= rtc_config_block[i];
cksum[1] ^= rtc_config_block[i+1];
for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) {
cksum[0] ^= buf[i];
cksum[1] ^= buf[i+1];
}
return (cksum[0] << 8) | cksum[1];
@ -112,12 +119,12 @@ static void init_config_buffer( void )
DEBUGF( "init_config_buffer()\n" );
/* reset to 0xff - all unused */
memset(rtc_config_block, 0xff, CONFIG_BLOCK_SIZE);
memset(config_block, 0xff, CONFIG_BLOCK_SIZE);
/* insert header */
rtc_config_block[0] = 'R';
rtc_config_block[1] = 'o';
rtc_config_block[2] = 'c';
rtc_config_block[3] = CONFIG_BLOCK_VERSION;
config_block[0] = 'R';
config_block[1] = 'o';
config_block[2] = 'c';
config_block[3] = CONFIG_BLOCK_VERSION;
}
/*
@ -126,7 +133,6 @@ static void init_config_buffer( void )
static int save_config_buffer( void )
{
unsigned short chksum;
#ifdef HAVE_RTC
unsigned int i;
#endif
@ -134,36 +140,29 @@ static int save_config_buffer( void )
DEBUGF( "save_config_buffer()\n" );
/* update the checksum in the end of the block before saving */
chksum = calculate_config_checksum();
rtc_config_block[ CONFIG_BLOCK_SIZE - 2 ] = chksum >> 8;
rtc_config_block[ CONFIG_BLOCK_SIZE - 1 ] = chksum & 0xff;
/* don't save if no changes were made */
if ( chksum == last_checksum )
return 0;
last_checksum = chksum;
chksum = calculate_config_checksum(config_block);
config_block[ RTC_BLOCK_SIZE - 2 ] = chksum >> 8;
config_block[ RTC_BLOCK_SIZE - 1 ] = chksum & 0xff;
#ifdef HAVE_RTC
/* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
that it would write a number of bytes at a time since the RTC chip
supports that, but this will have to do for now 8-) */
for (i=0; i < CONFIG_BLOCK_SIZE; i++ ) {
int r = rtc_write(0x14+i, rtc_config_block[i]);
for (i=0; i < RTC_BLOCK_SIZE; i++ ) {
int r = rtc_write(0x14+i, config_block[i]);
if (r) {
DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n", 14+i, r );
return r;
}
}
#else
#endif
if(battery_level_safe() && (fat_startsector()!=0))
ata_delayed_write( 61, rtc_config_block);
if (fat_startsector() != 0)
ata_delayed_write( 61, config_block);
else
return -1;
#endif
return 0;
}
@ -173,40 +172,61 @@ static int save_config_buffer( void )
static int load_config_buffer( void )
{
unsigned short chksum;
bool correct = false;
#ifdef HAVE_RTC
unsigned int i;
unsigned char rtc_block[RTC_BLOCK_SIZE];
#endif
DEBUGF( "load_config_buffer()\n" );
if (fat_startsector() != 0) {
ata_read_sectors( 61, 1, config_block);
/* calculate the checksum, check it and the header */
chksum = calculate_config_checksum(config_block);
if (config_block[0] == 'R' &&
config_block[1] == 'o' &&
config_block[2] == 'c' &&
config_block[3] == CONFIG_BLOCK_VERSION &&
(chksum >> 8) == config_block[RTC_BLOCK_SIZE - 2] &&
(chksum & 0xff) == config_block[RTC_BLOCK_SIZE - 1])
{
DEBUGF( "load_config_buffer: header & checksum test ok\n" );
correct = true;
}
}
#ifdef HAVE_RTC
/* FIXME: the same comment applies here as for rtc_write */
for (i=0; i < CONFIG_BLOCK_SIZE; i++ )
rtc_config_block[i] = rtc_read(0x14+i);
#else
ata_read_sectors( 61, 1, rtc_config_block);
/* read rtc block */
for (i=0; i < RTC_BLOCK_SIZE; i++ )
rtc_block[i] = rtc_read(0x14+i);
chksum = calculate_config_checksum(rtc_block);
/* if rtc block is ok, use that */
if (rtc_block[0] == 'R' &&
rtc_block[1] == 'o' &&
rtc_block[2] == 'c' &&
rtc_block[3] == CONFIG_BLOCK_VERSION &&
(chksum >> 8) == rtc_block[RTC_BLOCK_SIZE - 2] &&
(chksum & 0xff) == rtc_block[RTC_BLOCK_SIZE - 1])
{
memcpy(config_block, rtc_block, RTC_BLOCK_SIZE);
correct = true;
}
#endif
/* calculate the checksum, check it and the header */
chksum = calculate_config_checksum();
if (rtc_config_block[0] == 'R' &&
rtc_config_block[1] == 'o' &&
rtc_config_block[2] == 'c' &&
rtc_config_block[3] == CONFIG_BLOCK_VERSION &&
(chksum >> 8) == rtc_config_block[CONFIG_BLOCK_SIZE - 2] &&
(chksum & 0xff) == rtc_config_block[CONFIG_BLOCK_SIZE - 1])
{
DEBUGF( "load_config_buffer: header & checksum test ok\n" );
last_checksum = chksum;
return 0; /* header and checksum is valid */
if ( !correct ) {
/* if checksum is not valid, clear the config buffer */
DEBUGF( "load_config_buffer: header & checksum test failed\n" );
init_config_buffer();
return -1;
}
/* if checksum is not valid, initialize the config buffer to all-unused */
DEBUGF( "load_config_buffer: header & checksum test failed\n" );
init_config_buffer();
return 1;
return 0;
}
/*
@ -218,33 +238,47 @@ int settings_save( void )
/* update the config block buffer with current
settings and save the block in the RTC */
rtc_config_block[0x4] = (unsigned char)global_settings.volume;
rtc_config_block[0x5] = (unsigned char)global_settings.balance;
rtc_config_block[0x6] = (unsigned char)global_settings.bass;
rtc_config_block[0x7] = (unsigned char)global_settings.treble;
rtc_config_block[0x8] = (unsigned char)global_settings.loudness;
rtc_config_block[0x9] = (unsigned char)global_settings.bass_boost;
config_block[0x4] = (unsigned char)global_settings.volume;
config_block[0x5] = (unsigned char)global_settings.balance;
config_block[0x6] = (unsigned char)global_settings.bass;
config_block[0x7] = (unsigned char)global_settings.treble;
config_block[0x8] = (unsigned char)global_settings.loudness;
config_block[0x9] = (unsigned char)global_settings.bass_boost;
rtc_config_block[0xa] = (unsigned char)global_settings.contrast;
rtc_config_block[0xb] = (unsigned char)global_settings.backlight;
rtc_config_block[0xc] = (unsigned char)global_settings.poweroff;
rtc_config_block[0xd] = (unsigned char)global_settings.resume;
config_block[0xa] = (unsigned char)global_settings.contrast;
config_block[0xb] = (unsigned char)global_settings.backlight;
config_block[0xc] = (unsigned char)global_settings.poweroff;
config_block[0xd] = (unsigned char)global_settings.resume;
rtc_config_block[0xe] = (unsigned char)
config_block[0xe] = (unsigned char)
((global_settings.playlist_shuffle & 1) |
((global_settings.mp3filter & 1) << 1) |
((global_settings.sort_case & 1) << 2) |
((global_settings.discharge & 1) << 3) |
((global_settings.statusbar & 1) << 4));
rtc_config_block[0xf] = (unsigned char)
config_block[0xf] = (unsigned char)
((global_settings.scroll_speed << 3) |
(global_settings.wps_display & 7));
rtc_config_block[0x11] = (unsigned char)global_settings.avc;
config_block[0x10] = (unsigned char)global_settings.ff_rewind;
config_block[0x11] = (unsigned char)global_settings.avc;
memcpy(&rtc_config_block[0x24], &global_settings.total_uptime, 4);
memcpy(&config_block[0x12], &global_settings.resume_index, 4);
memcpy(&config_block[0x16], &global_settings.resume_offset, 4);
memcpy(&config_block[0xF8], &global_settings.resume_seed, 4);
memcpy(&config_block[0x24], &global_settings.total_uptime, 4);
strncpy(&config_block[0xFC], global_settings.resume_file, MAX_PATH);
DEBUGF("+Resume file %s\n",global_settings.resume_file);
DEBUGF("+Resume index %X offset %X\n",
global_settings.resume_index,
global_settings.resume_offset);
DEBUGF("+Resume shuffle %s seed %X\n",
global_settings.playlist_shuffle?"on":"off",
global_settings.resume_seed);
if(save_config_buffer())
{
lcd_clear_display();
@ -277,51 +311,65 @@ void settings_load(void)
/* load the buffer from the RTC (resets it to all-unused if the block
is invalid) and decode the settings which are set in the block */
if (!load_config_buffer()) {
if (rtc_config_block[0x4] != 0xFF)
global_settings.volume = rtc_config_block[0x4];
if (rtc_config_block[0x5] != 0xFF)
global_settings.balance = rtc_config_block[0x5];
if (rtc_config_block[0x6] != 0xFF)
global_settings.bass = rtc_config_block[0x6];
if (rtc_config_block[0x7] != 0xFF)
global_settings.treble = rtc_config_block[0x7];
if (rtc_config_block[0x8] != 0xFF)
global_settings.loudness = rtc_config_block[0x8];
if (rtc_config_block[0x9] != 0xFF)
global_settings.bass_boost = rtc_config_block[0x9];
if (config_block[0x4] != 0xFF)
global_settings.volume = config_block[0x4];
if (config_block[0x5] != 0xFF)
global_settings.balance = config_block[0x5];
if (config_block[0x6] != 0xFF)
global_settings.bass = config_block[0x6];
if (config_block[0x7] != 0xFF)
global_settings.treble = config_block[0x7];
if (config_block[0x8] != 0xFF)
global_settings.loudness = config_block[0x8];
if (config_block[0x9] != 0xFF)
global_settings.bass_boost = config_block[0x9];
if (rtc_config_block[0xa] != 0xFF) {
global_settings.contrast = rtc_config_block[0xa];
if (config_block[0xa] != 0xFF) {
global_settings.contrast = config_block[0xa];
if ( global_settings.contrast < MIN_CONTRAST_SETTING )
global_settings.contrast = DEFAULT_CONTRAST_SETTING;
}
if (rtc_config_block[0xb] != 0xFF)
global_settings.backlight = rtc_config_block[0xb];
if (rtc_config_block[0xc] != 0xFF)
global_settings.poweroff = rtc_config_block[0xc];
if (rtc_config_block[0xd] != 0xFF)
global_settings.resume = rtc_config_block[0xd];
if (rtc_config_block[0xe] != 0xFF) {
global_settings.playlist_shuffle = rtc_config_block[0xe] & 1;
global_settings.mp3filter = (rtc_config_block[0xe] >> 1) & 1;
global_settings.sort_case = (rtc_config_block[0xe] >> 2) & 1;
global_settings.discharge = (rtc_config_block[0xe] >> 3) & 1;
global_settings.statusbar = (rtc_config_block[0xe] >> 4) & 1;
if (config_block[0xb] != 0xFF)
global_settings.backlight = config_block[0xb];
if (config_block[0xc] != 0xFF)
global_settings.poweroff = config_block[0xc];
if (config_block[0xd] != 0xFF)
global_settings.resume = config_block[0xd];
if (config_block[0xe] != 0xFF) {
global_settings.playlist_shuffle = config_block[0xe] & 1;
global_settings.mp3filter = (config_block[0xe] >> 1) & 1;
global_settings.sort_case = (config_block[0xe] >> 2) & 1;
global_settings.discharge = (config_block[0xe] >> 3) & 1;
global_settings.statusbar = (config_block[0xe] >> 4) & 1;
}
c = rtc_config_block[0xf] >> 3;
c = config_block[0xf] >> 3;
if (c != 31)
global_settings.scroll_speed = c;
c = rtc_config_block[0xf] & 7;
c = config_block[0xf] & 7;
if (c != 7)
global_settings.wps_display = c;
if (rtc_config_block[0x11] != 0xFF)
global_settings.avc = rtc_config_block[0x11];
if (config_block[0x10] != 0xFF)
global_settings.ff_rewind = config_block[0x10];
if (rtc_config_block[0x24] != 0xFF)
memcpy(&global_settings.total_uptime, &rtc_config_block[0x24], 4);
if (config_block[0x11] != 0xFF)
global_settings.avc = config_block[0x11];
if (config_block[0x12] != 0xFF)
memcpy(&global_settings.resume_index, &config_block[0x12], 4);
if (config_block[0x16] != 0xFF)
memcpy(&global_settings.resume_offset, &config_block[0x16], 4);
memcpy(&global_settings.resume_seed, &config_block[0xF8], 4);
if (config_block[0x24] != 0xFF)
memcpy(&global_settings.total_uptime, &config_block[0x24], 4);
strncpy(global_settings.resume_file, &config_block[0xFC], MAX_PATH);
global_settings.resume_file[MAX_PATH]=0;
}
lcd_set_contrast(global_settings.contrast);
lcd_scroll_speed(global_settings.scroll_speed);
@ -345,6 +393,7 @@ void settings_reset(void) {
global_settings.loudness = mpeg_sound_default(SOUND_LOUDNESS);
global_settings.bass_boost = mpeg_sound_default(SOUND_SUPERBASS);
global_settings.avc = mpeg_sound_default(SOUND_AVC);
global_settings.resume = true;
global_settings.contrast = DEFAULT_CONTRAST_SETTING;
global_settings.poweroff = DEFAULT_POWEROFF_SETTING;
global_settings.backlight = DEFAULT_BACKLIGHT_SETTING;
@ -358,6 +407,8 @@ void settings_reset(void) {
global_settings.total_uptime = 0;
global_settings.scroll_speed = 8;
global_settings.ff_rewind = DEFAULT_FF_REWIND_SETTING;
global_settings.resume_index = -1;
global_settings.resume_offset = -1;
}

View file

@ -21,6 +21,7 @@
#define __SETTINGS_H__
#include <stdbool.h>
#include "file.h"
/* data structures */
@ -49,8 +50,11 @@ struct user_settings
/* resume settings */
int resume; /* power-on song resume: 0=no. 1=yes song. 2=yes pl */
int track_time; /* number of seconds into the track to resume */
bool resume; /* resume option on/off */
int resume_index; /* index in playlist (-1 for no active resume) */
int resume_offset; /* byte offset in mp3 file */
int resume_seed; /* random seed for playlist shuffle */
unsigned char resume_file[MAX_PATH+1]; /* playlist name (or dir) */
/* misc options */

View file

@ -57,6 +57,11 @@ static void sort_case(void)
set_bool( "[Sort case sensitive]", &global_settings.sort_case );
}
static void resume(void)
{
set_bool( "[Resume]", &global_settings.resume );
}
static void backlight_timer(void)
{
char* names[] = { "off", "on ",
@ -153,13 +158,13 @@ void settings_menu(void)
{ "Time/Date", timedate_set },
#endif
{ "FF/Rewind", ff_rewind },
{ "Resume", resume },
};
bool old_shuffle = global_settings.playlist_shuffle;
m=menu_init( items, sizeof items / sizeof(struct menu_items) );
menu_run(m);
menu_exit(m);
settings_save();
if (old_shuffle != global_settings.playlist_shuffle)
{

View file

@ -102,12 +102,14 @@ extern unsigned char bitmap_icons_6x8[LastIcon][6];
#define TREE_EXIT BUTTON_LEFT
#define TREE_ENTER BUTTON_RIGHT
#define TREE_MENU BUTTON_F1
#define RELEASE_MASK (BUTTON_OFF)
#else
#define TREE_NEXT BUTTON_RIGHT
#define TREE_PREV BUTTON_LEFT
#define TREE_EXIT BUTTON_STOP
#define TREE_ENTER BUTTON_PLAY
#define TREE_MENU BUTTON_MENU
#define RELEASE_MASK (BUTTON_STOP)
#endif /* HAVE_RECORDER_KEYPAD */
#define TREE_ATTR_M3U 0x80 /* unused by FAT attributes */
@ -292,6 +294,98 @@ static int showdir(char *path, int start)
return filesindir;
}
bool ask_resume(void)
{
lcd_clear_display();
lcd_puts(0,0,"Resume?");
#ifdef HAVE_LCD_CHARCELLS
lcd_puts(0,1,"(Play/Stop)");
#else
lcd_puts(0,1,"Play = Yes");
lcd_puts(0,2,"Any other = No");
#endif
lcd_update();
if (button_get(true) == BUTTON_PLAY)
return true;
return false;
}
void start_resume(void)
{
if ( global_settings.resume &&
global_settings.resume_index != -1 ) {
int len = strlen(global_settings.resume_file);
DEBUGF("Resume file %s\n",global_settings.resume_file);
DEBUGF("Resume index %X offset %X\n",
global_settings.resume_index,
global_settings.resume_offset);
DEBUGF("Resume shuffle %s seed %X\n",
global_settings.playlist_shuffle?"on":"off",
global_settings.resume_seed);
/* playlist? */
if (!strcasecmp(&global_settings.resume_file[len-4], ".m3u")) {
char* slash;
/* check that the file exists */
int fd = open(global_settings.resume_file, O_RDONLY);
if(fd<0)
return;
close(fd);
if (!ask_resume())
return;
slash = strrchr(global_settings.resume_file,'/');
if (slash) {
*slash=0;
play_list(global_settings.resume_file,
slash+1,
global_settings.resume_index,
global_settings.resume_offset,
global_settings.resume_seed );
*slash='/';
}
else {
/* check that the dir exists */
DIR* dir = opendir(global_settings.resume_file);
if(!dir)
return;
closedir(dir);
if (!ask_resume())
return;
play_list("/",
global_settings.resume_file,
global_settings.resume_index,
global_settings.resume_offset,
global_settings.resume_seed );
}
}
else {
int start_index;
if (!ask_resume())
return;
if (showdir(global_settings.resume_file, 0) < 0 )
return;
start_index = build_playlist(global_settings.resume_index);
play_list(global_settings.resume_file,
NULL,
start_index,
global_settings.resume_offset,
global_settings.resume_seed);
}
status_set_playmode(STATUS_PLAY);
status_draw();
wps_show();
}
}
bool dirbrowse(char *root)
{
int numentries=0;
@ -317,6 +411,9 @@ bool dirbrowse(char *root)
tree_max_on_screen = TREE_MAX_ON_SCREEN;
#endif
start_resume();
button_set_release(RELEASE_MASK);
memcpy(currdir,root,sizeof(currdir));
numentries = showdir(root, start);
if (numentries == -1)
@ -350,6 +447,7 @@ bool dirbrowse(char *root)
restore = true;
}
break;
#ifdef HAVE_RECORDER_KEYPAD
case BUTTON_OFF:
mpeg_stop();
@ -357,7 +455,15 @@ bool dirbrowse(char *root)
status_draw();
restore = true;
break;
case BUTTON_OFF | BUTTON_REL:
#else
case BUTTON_STOP | BUTTON_REL:
#endif
global_settings.resume_index = -1;
settings_save();
break;
case TREE_ENTER:
#ifdef HAVE_RECORDER_KEYPAD
@ -383,16 +489,34 @@ bool dirbrowse(char *root)
dircursor=0;
start=0;
} else {
int seed = current_tick;
lcd_stop_scroll();
if(dircache[dircursor+start].attr & TREE_ATTR_M3U )
{
if ( global_settings.resume )
snprintf(global_settings.resume_file,
MAX_PATH, "%s/%s",
currdir,
dircache[dircursor+start].name);
play_list(currdir,
dircache[dircursor+start].name, 0);
dircache[dircursor+start].name,
0, 0, seed );
}
else {
if ( global_settings.resume )
strncpy(global_settings.resume_file,
currdir, MAX_PATH);
start_index = build_playlist(dircursor+start);
play_list(currdir, NULL, start_index);
play_list(currdir, NULL, start_index, 0, seed);
}
if ( global_settings.resume ) {
global_settings.resume_index = 0;
global_settings.resume_offset = 0;
global_settings.resume_seed = seed;
settings_save();
}
status_set_playmode(STATUS_PLAY);
status_draw();
lcd_stop_scroll();
@ -405,6 +529,7 @@ bool dirbrowse(char *root)
dirlevel = 0;
dircursor = 0;
start = 0;
global_settings.resume_index = -1;
}
}
restore = true;

View file

@ -34,6 +34,7 @@
#include "powermgmt.h"
#include "status.h"
#include "main_menu.h"
#include "ata.h"
#ifdef HAVE_LCD_BITMAP
#include "icons.h"
#include "widgets.h"
@ -462,6 +463,13 @@ int wps_show(void)
{
mpeg_pause();
status_set_playmode(STATUS_PAUSE);
if (global_settings.resume) {
status_draw();
settings_save();
#ifndef HAVE_RTC
ata_flush();
#endif
}
}
else
{
@ -577,7 +585,6 @@ int wps_show(void)
mpeg_ff_rewind(ff_rewind_count);
ff_rewind_count = 0;
ff_rewind = false;
status_set_playmode(STATUS_PLAY);
#ifdef HAVE_LCD_CHARCELLS
draw_screen(id3);
#endif
@ -589,7 +596,6 @@ int wps_show(void)
#endif
{
mpeg_prev();
status_set_playmode(STATUS_PLAY);
}
}
#ifdef HAVE_PLAYER_KEYPAD
@ -612,7 +618,6 @@ int wps_show(void)
mpeg_ff_rewind(ff_rewind_count);
ff_rewind_count = 0;
ff_rewind = false;
status_set_playmode(STATUS_PLAY);
#ifdef HAVE_LCD_CHARCELLS
draw_screen(id3);
#endif
@ -624,7 +629,6 @@ int wps_show(void)
#endif
{
mpeg_next();
status_set_playmode(STATUS_PLAY);
}
}
#ifdef HAVE_PLAYER_KEYPAD
@ -862,6 +866,16 @@ int wps_show(void)
if (mpeg_is_playing() && id3)
display_file_time(id3->elapsed, id3->length);
/* save resume data */
if ( id3 &&
global_settings.resume &&
global_settings.resume_offset != id3->offset ) {
DEBUGF("R%X,%X (%X)\n",global_settings.resume_offset,id3->offset,id3);
global_settings.resume_index = id3->index;
global_settings.resume_offset = id3->offset;
settings_save();
}
status_draw();
break;
}

View file

@ -304,6 +304,7 @@ extern void ata_delayed_write(unsigned long sector, void* buf)
extern void ata_flush(void)
{
if ( delayed_write ) {
DEBUGF("ata_flush()\n");
delayed_write = false;
ata_write_sectors(delayed_sector_num, 1, delayed_sector);
}

View file

@ -47,6 +47,10 @@ struct mp3entry {
/* these following two fields are used for local buffering */
char id3v2buf[300];
char id3v1buf[3][32];
/* resume related */
int offset; /* bytes played */
int index; /* playlist index */
};
#define VBR_FRAMES_FLAG 0x01

View file

@ -52,7 +52,8 @@
#define MPEG_SWAP_DATA 101
#define MPEG_TRACK_CHANGE 102
extern char* playlist_next(int steps);
extern char* playlist_next(int steps, int* id);
extern void update_file_pos( int id, int pos );
static char *units[] =
{
@ -243,6 +244,7 @@ static void remove_all_tags(void)
}
#endif
static bool paused; /* playback is paused */
#ifdef SIMULATOR
static bool playing = false;
static bool play_pending = false;
@ -502,7 +504,7 @@ static void stop_dma(void)
static void dma_tick(void)
{
if(playing)
if(playing && !paused)
{
/* Start DMA if it is disabled and the DEMAND pin is high */
if(!dma_on && (PBDR & 0x4000))
@ -594,6 +596,7 @@ void DEI3(void)
DTCR3 = last_dma_chunk_size & 0xffff;
SAR3 = (unsigned int)mp3buf + mp3buf_read;
id3tags[tag_read_idx]->id3.offset += last_dma_chunk_size;
}
else
{
@ -646,10 +649,11 @@ static void add_track_to_tag_list(char *filename)
/* If next_track is true, opens the next track, if false, opens prev track */
static int new_file(int steps)
{
char *trackname;
do {
trackname = playlist_next( steps );
char *trackname;
int index;
trackname = playlist_next( steps, &index );
if ( !trackname )
return -1;
@ -666,6 +670,8 @@ static int new_file(int steps)
lseek(mpeg_file,
id3tags[tag_read_idx]->id3.id3v2len & ~1,
SEEK_SET);
id3tags[tag_read_idx]->id3.index = index;
id3tags[tag_read_idx]->id3.offset = 0;
}
} while ( mpeg_file < 0 );
@ -706,6 +712,7 @@ static void mpeg_thread(void)
int amount_to_read;
int amount_to_swap;
int t1, t2;
int start_offset;
play_pending = false;
playing = false;
@ -720,7 +727,7 @@ static void mpeg_thread(void)
switch(ev.id)
{
case MPEG_PLAY:
DEBUGF("MPEG_PLAY %s\n",ev.data);
DEBUGF("MPEG_PLAY\n");
/* Stop the current stream */
play_pending = false;
playing = false;
@ -732,18 +739,21 @@ static void mpeg_thread(void)
if(mpeg_file >= 0)
close(mpeg_file);
mpeg_file = open((char*)ev.data, O_RDONLY);
while (mpeg_file < 0) {
DEBUGF("Couldn't open file: %s\n",ev.data);
if ( new_file(1) == -1 )
return;
}
if ( new_file(0) == -1 )
return;
add_track_to_tag_list((char *)ev.data);
/* skip past id3v2 tag (to an even byte) */
lseek(mpeg_file,
id3tags[tag_read_idx]->id3.id3v2len & ~1,
SEEK_SET);
start_offset = (int)ev.data;
if (start_offset) {
lseek(mpeg_file, start_offset, SEEK_SET);
id3tags[tag_read_idx]->id3.offset = start_offset;
}
else {
/* skip past id3v2 tag (to an even byte) */
lseek(mpeg_file,
id3tags[tag_read_idx]->id3.id3v2len & ~1,
SEEK_SET);
}
/* Make it read more data */
filling = true;
@ -752,6 +762,7 @@ static void mpeg_thread(void)
/* Tell the file loading code that we want to start playing
as soon as we have some data */
play_pending = true;
paused = false;
current_track_counter++;
break;
@ -764,6 +775,7 @@ static void mpeg_thread(void)
case MPEG_PAUSE:
DEBUGF("MPEG_PAUSE\n");
/* Stop the current stream */
paused = true;
playing = false;
pause_tick = current_tick;
stop_dma();
@ -775,6 +787,7 @@ static void mpeg_thread(void)
playing = true;
last_dma_tick += current_tick - pause_tick;
pause_tick = 0;
paused = false;
start_dma();
break;
@ -799,7 +812,8 @@ static void mpeg_thread(void)
play_pending = true;
} else {
playing = true;
start_dma();
if (!paused)
start_dma();
}
track_change();
@ -931,7 +945,8 @@ static void mpeg_thread(void)
playing = true;
last_dma_tick = current_tick;
init_dma();
start_dma();
if (!paused)
start_dma();
}
else
{
@ -1016,7 +1031,8 @@ static void mpeg_thread(void)
last_dma_tick = current_tick;
init_dma();
start_dma();
if (!paused)
start_dma();
/* Tell ourselves that we need more data */
queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
@ -1188,7 +1204,7 @@ static void setup_sci0(void)
static struct mp3entry taginfo;
#endif
struct mp3entry* mpeg_current_track(void)
struct mp3entry* mpeg_current_track()
{
#ifdef SIMULATOR
return &taginfo;
@ -1210,13 +1226,17 @@ bool mpeg_has_changed_track(void)
return false;
}
void mpeg_play(char* trackname)
void mpeg_play(int offset)
{
#ifdef SIMULATOR
mp3info(&taginfo, trackname);
playing = true;
char* trackname = playlist_next( 0, NULL );
if ( trackname ) {
mp3info(&taginfo, trackname);
playing = true;
}
(void)offset;
#else
queue_post(&mpeg_queue, MPEG_PLAY, trackname);
queue_post(&mpeg_queue, MPEG_PLAY, (void*)offset);
#endif
}
@ -1252,7 +1272,7 @@ void mpeg_next(void)
#ifndef SIMULATOR
queue_post(&mpeg_queue, MPEG_NEXT, NULL);
#else
char* file = playlist_next(1);
char* file = playlist_next(1,NULL);
mp3info(&taginfo, file);
current_track_counter++;
playing = true;
@ -1264,7 +1284,7 @@ void mpeg_prev(void)
#ifndef SIMULATOR
queue_post(&mpeg_queue, MPEG_PREV, NULL);
#else
char* file = playlist_next(-1);
char* file = playlist_next(-1,NULL);
mp3info(&taginfo, file);
current_track_counter--;
playing = true;
@ -1282,7 +1302,7 @@ void mpeg_ff_rewind(int change)
bool mpeg_is_playing(void)
{
return playing || play_pending;
return (playing || play_pending) && (!paused) ;
}
#ifndef SIMULATOR

View file

@ -22,7 +22,7 @@
#include <stdbool.h>
void mpeg_init(int volume, int bass, int treble, int balance, int loudness, int bass_boost, int avc);
void mpeg_play(char* trackname);
void mpeg_play(int offset);
void mpeg_stop(void);
void mpeg_pause(void);
void mpeg_resume(void);

View file

@ -80,3 +80,7 @@ void ata_delayed_write(unsigned long sector, void* buf)
{
ata_write_sectors(sector,1,buf);
}
void ata_flush(void)
{
}