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:
parent
085e774675
commit
6224cdb166
12 changed files with 379 additions and 144 deletions
|
@ -66,7 +66,7 @@ int playlist_add(char *filename)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* playlist_next(int steps)
|
char* playlist_next(int steps, int* index)
|
||||||
{
|
{
|
||||||
int seek;
|
int seek;
|
||||||
int max;
|
int max;
|
||||||
|
@ -103,7 +103,9 @@ char* playlist_next(int steps)
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index)
|
||||||
|
*index = playlist.index;
|
||||||
|
|
||||||
/* Zero-terminate the file name */
|
/* Zero-terminate the file name */
|
||||||
seek=0;
|
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="";
|
char *sep="";
|
||||||
int dirlen;
|
int dirlen;
|
||||||
|
@ -211,7 +217,7 @@ void play_list(char *dir, char *file, int start_index)
|
||||||
status_draw();
|
status_draw();
|
||||||
lcd_update();
|
lcd_update();
|
||||||
}
|
}
|
||||||
randomise_playlist( current_tick );
|
randomise_playlist( random_seed );
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!playlist.in_ram) {
|
if(!playlist.in_ram) {
|
||||||
|
@ -220,7 +226,7 @@ void play_list(char *dir, char *file, int start_index)
|
||||||
lcd_update();
|
lcd_update();
|
||||||
}
|
}
|
||||||
/* also make the first song get playing */
|
/* also make the first song get playing */
|
||||||
mpeg_play(playlist_next(0));
|
mpeg_play(start_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -40,8 +40,9 @@ typedef struct
|
||||||
extern playlist_info_t playlist;
|
extern playlist_info_t playlist;
|
||||||
extern bool playlist_shuffle;
|
extern bool playlist_shuffle;
|
||||||
|
|
||||||
void play_list(char *dir, char *file, int start_index);
|
void play_list(char *dir, char *file, int start_index,
|
||||||
char* playlist_next(int steps);
|
int start_offset, int random_seed );
|
||||||
|
char* playlist_next(int steps, int* id);
|
||||||
void randomise_playlist( unsigned int seed );
|
void randomise_playlist( unsigned int seed );
|
||||||
void sort_playlist(void);
|
void sort_playlist(void);
|
||||||
void empty_playlist(void);
|
void empty_playlist(void);
|
||||||
|
|
249
apps/settings.c
249
apps/settings.c
|
@ -37,10 +37,9 @@
|
||||||
|
|
||||||
struct user_settings global_settings;
|
struct user_settings global_settings;
|
||||||
|
|
||||||
static unsigned short last_checksum = 0;
|
|
||||||
|
|
||||||
#define CONFIG_BLOCK_VERSION 1
|
#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>
|
0x0f 0x23 <scroll speed & WPS display byte>
|
||||||
0x10 0x24 <playlist options byte>
|
0x10 0x24 <playlist options byte>
|
||||||
0x11 0x25 <AVC 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>
|
<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
|
needed. Memory locations not used by a given version should not be
|
||||||
modified unless the header & checksum test fails.
|
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"
|
#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 int i;
|
||||||
unsigned char cksum[2];
|
unsigned char cksum[2];
|
||||||
cksum[0] = cksum[1] = 0;
|
cksum[0] = cksum[1] = 0;
|
||||||
|
|
||||||
for (i=0; i < CONFIG_BLOCK_SIZE - 2; i+=2 ) {
|
for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) {
|
||||||
cksum[0] ^= rtc_config_block[i];
|
cksum[0] ^= buf[i];
|
||||||
cksum[1] ^= rtc_config_block[i+1];
|
cksum[1] ^= buf[i+1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (cksum[0] << 8) | cksum[1];
|
return (cksum[0] << 8) | cksum[1];
|
||||||
|
@ -112,12 +119,12 @@ static void init_config_buffer( void )
|
||||||
DEBUGF( "init_config_buffer()\n" );
|
DEBUGF( "init_config_buffer()\n" );
|
||||||
|
|
||||||
/* reset to 0xff - all unused */
|
/* reset to 0xff - all unused */
|
||||||
memset(rtc_config_block, 0xff, CONFIG_BLOCK_SIZE);
|
memset(config_block, 0xff, CONFIG_BLOCK_SIZE);
|
||||||
/* insert header */
|
/* insert header */
|
||||||
rtc_config_block[0] = 'R';
|
config_block[0] = 'R';
|
||||||
rtc_config_block[1] = 'o';
|
config_block[1] = 'o';
|
||||||
rtc_config_block[2] = 'c';
|
config_block[2] = 'c';
|
||||||
rtc_config_block[3] = CONFIG_BLOCK_VERSION;
|
config_block[3] = CONFIG_BLOCK_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -126,7 +133,6 @@ static void init_config_buffer( void )
|
||||||
static int save_config_buffer( void )
|
static int save_config_buffer( void )
|
||||||
{
|
{
|
||||||
unsigned short chksum;
|
unsigned short chksum;
|
||||||
|
|
||||||
#ifdef HAVE_RTC
|
#ifdef HAVE_RTC
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
#endif
|
#endif
|
||||||
|
@ -134,36 +140,29 @@ static int save_config_buffer( void )
|
||||||
DEBUGF( "save_config_buffer()\n" );
|
DEBUGF( "save_config_buffer()\n" );
|
||||||
|
|
||||||
/* update the checksum in the end of the block before saving */
|
/* update the checksum in the end of the block before saving */
|
||||||
chksum = calculate_config_checksum();
|
chksum = calculate_config_checksum(config_block);
|
||||||
rtc_config_block[ CONFIG_BLOCK_SIZE - 2 ] = chksum >> 8;
|
config_block[ RTC_BLOCK_SIZE - 2 ] = chksum >> 8;
|
||||||
rtc_config_block[ CONFIG_BLOCK_SIZE - 1 ] = chksum & 0xff;
|
config_block[ RTC_BLOCK_SIZE - 1 ] = chksum & 0xff;
|
||||||
|
|
||||||
/* don't save if no changes were made */
|
|
||||||
if ( chksum == last_checksum )
|
|
||||||
return 0;
|
|
||||||
last_checksum = chksum;
|
|
||||||
|
|
||||||
#ifdef HAVE_RTC
|
#ifdef HAVE_RTC
|
||||||
/* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
|
/* 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
|
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-) */
|
supports that, but this will have to do for now 8-) */
|
||||||
for (i=0; i < CONFIG_BLOCK_SIZE; i++ ) {
|
for (i=0; i < RTC_BLOCK_SIZE; i++ ) {
|
||||||
int r = rtc_write(0x14+i, rtc_config_block[i]);
|
int r = rtc_write(0x14+i, config_block[i]);
|
||||||
if (r) {
|
if (r) {
|
||||||
DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n", 14+i, r );
|
DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n", 14+i, r );
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
if(battery_level_safe() && (fat_startsector()!=0))
|
if (fat_startsector() != 0)
|
||||||
ata_delayed_write( 61, rtc_config_block);
|
ata_delayed_write( 61, config_block);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,40 +172,61 @@ static int save_config_buffer( void )
|
||||||
static int load_config_buffer( void )
|
static int load_config_buffer( void )
|
||||||
{
|
{
|
||||||
unsigned short chksum;
|
unsigned short chksum;
|
||||||
|
bool correct = false;
|
||||||
|
|
||||||
#ifdef HAVE_RTC
|
#ifdef HAVE_RTC
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
unsigned char rtc_block[RTC_BLOCK_SIZE];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUGF( "load_config_buffer()\n" );
|
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
|
#ifdef HAVE_RTC
|
||||||
/* FIXME: the same comment applies here as for rtc_write */
|
/* read rtc block */
|
||||||
for (i=0; i < CONFIG_BLOCK_SIZE; i++ )
|
for (i=0; i < RTC_BLOCK_SIZE; i++ )
|
||||||
rtc_config_block[i] = rtc_read(0x14+i);
|
rtc_block[i] = rtc_read(0x14+i);
|
||||||
#else
|
|
||||||
ata_read_sectors( 61, 1, rtc_config_block);
|
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
|
#endif
|
||||||
|
|
||||||
/* calculate the checksum, check it and the header */
|
if ( !correct ) {
|
||||||
chksum = calculate_config_checksum();
|
/* if checksum is not valid, clear the config buffer */
|
||||||
|
DEBUGF( "load_config_buffer: header & checksum test failed\n" );
|
||||||
if (rtc_config_block[0] == 'R' &&
|
init_config_buffer();
|
||||||
rtc_config_block[1] == 'o' &&
|
return -1;
|
||||||
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 checksum is not valid, initialize the config buffer to all-unused */
|
return 0;
|
||||||
DEBUGF( "load_config_buffer: header & checksum test failed\n" );
|
|
||||||
init_config_buffer();
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -218,33 +238,47 @@ int settings_save( void )
|
||||||
|
|
||||||
/* update the config block buffer with current
|
/* update the config block buffer with current
|
||||||
settings and save the block in the RTC */
|
settings and save the block in the RTC */
|
||||||
rtc_config_block[0x4] = (unsigned char)global_settings.volume;
|
config_block[0x4] = (unsigned char)global_settings.volume;
|
||||||
rtc_config_block[0x5] = (unsigned char)global_settings.balance;
|
config_block[0x5] = (unsigned char)global_settings.balance;
|
||||||
rtc_config_block[0x6] = (unsigned char)global_settings.bass;
|
config_block[0x6] = (unsigned char)global_settings.bass;
|
||||||
rtc_config_block[0x7] = (unsigned char)global_settings.treble;
|
config_block[0x7] = (unsigned char)global_settings.treble;
|
||||||
rtc_config_block[0x8] = (unsigned char)global_settings.loudness;
|
config_block[0x8] = (unsigned char)global_settings.loudness;
|
||||||
rtc_config_block[0x9] = (unsigned char)global_settings.bass_boost;
|
config_block[0x9] = (unsigned char)global_settings.bass_boost;
|
||||||
|
|
||||||
rtc_config_block[0xa] = (unsigned char)global_settings.contrast;
|
config_block[0xa] = (unsigned char)global_settings.contrast;
|
||||||
rtc_config_block[0xb] = (unsigned char)global_settings.backlight;
|
config_block[0xb] = (unsigned char)global_settings.backlight;
|
||||||
rtc_config_block[0xc] = (unsigned char)global_settings.poweroff;
|
config_block[0xc] = (unsigned char)global_settings.poweroff;
|
||||||
rtc_config_block[0xd] = (unsigned char)global_settings.resume;
|
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.playlist_shuffle & 1) |
|
||||||
((global_settings.mp3filter & 1) << 1) |
|
((global_settings.mp3filter & 1) << 1) |
|
||||||
((global_settings.sort_case & 1) << 2) |
|
((global_settings.sort_case & 1) << 2) |
|
||||||
((global_settings.discharge & 1) << 3) |
|
((global_settings.discharge & 1) << 3) |
|
||||||
((global_settings.statusbar & 1) << 4));
|
((global_settings.statusbar & 1) << 4));
|
||||||
|
|
||||||
rtc_config_block[0xf] = (unsigned char)
|
config_block[0xf] = (unsigned char)
|
||||||
((global_settings.scroll_speed << 3) |
|
((global_settings.scroll_speed << 3) |
|
||||||
(global_settings.wps_display & 7));
|
(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())
|
if(save_config_buffer())
|
||||||
{
|
{
|
||||||
lcd_clear_display();
|
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
|
/* 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 */
|
is invalid) and decode the settings which are set in the block */
|
||||||
if (!load_config_buffer()) {
|
if (!load_config_buffer()) {
|
||||||
if (rtc_config_block[0x4] != 0xFF)
|
if (config_block[0x4] != 0xFF)
|
||||||
global_settings.volume = rtc_config_block[0x4];
|
global_settings.volume = config_block[0x4];
|
||||||
if (rtc_config_block[0x5] != 0xFF)
|
if (config_block[0x5] != 0xFF)
|
||||||
global_settings.balance = rtc_config_block[0x5];
|
global_settings.balance = config_block[0x5];
|
||||||
if (rtc_config_block[0x6] != 0xFF)
|
if (config_block[0x6] != 0xFF)
|
||||||
global_settings.bass = rtc_config_block[0x6];
|
global_settings.bass = config_block[0x6];
|
||||||
if (rtc_config_block[0x7] != 0xFF)
|
if (config_block[0x7] != 0xFF)
|
||||||
global_settings.treble = rtc_config_block[0x7];
|
global_settings.treble = config_block[0x7];
|
||||||
if (rtc_config_block[0x8] != 0xFF)
|
if (config_block[0x8] != 0xFF)
|
||||||
global_settings.loudness = rtc_config_block[0x8];
|
global_settings.loudness = config_block[0x8];
|
||||||
if (rtc_config_block[0x9] != 0xFF)
|
if (config_block[0x9] != 0xFF)
|
||||||
global_settings.bass_boost = rtc_config_block[0x9];
|
global_settings.bass_boost = config_block[0x9];
|
||||||
|
|
||||||
if (rtc_config_block[0xa] != 0xFF) {
|
if (config_block[0xa] != 0xFF) {
|
||||||
global_settings.contrast = rtc_config_block[0xa];
|
global_settings.contrast = config_block[0xa];
|
||||||
if ( global_settings.contrast < MIN_CONTRAST_SETTING )
|
if ( global_settings.contrast < MIN_CONTRAST_SETTING )
|
||||||
global_settings.contrast = DEFAULT_CONTRAST_SETTING;
|
global_settings.contrast = DEFAULT_CONTRAST_SETTING;
|
||||||
}
|
}
|
||||||
if (rtc_config_block[0xb] != 0xFF)
|
if (config_block[0xb] != 0xFF)
|
||||||
global_settings.backlight = rtc_config_block[0xb];
|
global_settings.backlight = config_block[0xb];
|
||||||
if (rtc_config_block[0xc] != 0xFF)
|
if (config_block[0xc] != 0xFF)
|
||||||
global_settings.poweroff = rtc_config_block[0xc];
|
global_settings.poweroff = config_block[0xc];
|
||||||
if (rtc_config_block[0xd] != 0xFF)
|
if (config_block[0xd] != 0xFF)
|
||||||
global_settings.resume = rtc_config_block[0xd];
|
global_settings.resume = config_block[0xd];
|
||||||
if (rtc_config_block[0xe] != 0xFF) {
|
if (config_block[0xe] != 0xFF) {
|
||||||
global_settings.playlist_shuffle = rtc_config_block[0xe] & 1;
|
global_settings.playlist_shuffle = config_block[0xe] & 1;
|
||||||
global_settings.mp3filter = (rtc_config_block[0xe] >> 1) & 1;
|
global_settings.mp3filter = (config_block[0xe] >> 1) & 1;
|
||||||
global_settings.sort_case = (rtc_config_block[0xe] >> 2) & 1;
|
global_settings.sort_case = (config_block[0xe] >> 2) & 1;
|
||||||
global_settings.discharge = (rtc_config_block[0xe] >> 3) & 1;
|
global_settings.discharge = (config_block[0xe] >> 3) & 1;
|
||||||
global_settings.statusbar = (rtc_config_block[0xe] >> 4) & 1;
|
global_settings.statusbar = (config_block[0xe] >> 4) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = rtc_config_block[0xf] >> 3;
|
c = config_block[0xf] >> 3;
|
||||||
if (c != 31)
|
if (c != 31)
|
||||||
global_settings.scroll_speed = c;
|
global_settings.scroll_speed = c;
|
||||||
|
|
||||||
c = rtc_config_block[0xf] & 7;
|
c = config_block[0xf] & 7;
|
||||||
if (c != 7)
|
if (c != 7)
|
||||||
global_settings.wps_display = c;
|
global_settings.wps_display = c;
|
||||||
|
|
||||||
if (rtc_config_block[0x11] != 0xFF)
|
if (config_block[0x10] != 0xFF)
|
||||||
global_settings.avc = rtc_config_block[0x11];
|
global_settings.ff_rewind = config_block[0x10];
|
||||||
|
|
||||||
if (rtc_config_block[0x24] != 0xFF)
|
if (config_block[0x11] != 0xFF)
|
||||||
memcpy(&global_settings.total_uptime, &rtc_config_block[0x24], 4);
|
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_set_contrast(global_settings.contrast);
|
||||||
lcd_scroll_speed(global_settings.scroll_speed);
|
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.loudness = mpeg_sound_default(SOUND_LOUDNESS);
|
||||||
global_settings.bass_boost = mpeg_sound_default(SOUND_SUPERBASS);
|
global_settings.bass_boost = mpeg_sound_default(SOUND_SUPERBASS);
|
||||||
global_settings.avc = mpeg_sound_default(SOUND_AVC);
|
global_settings.avc = mpeg_sound_default(SOUND_AVC);
|
||||||
|
global_settings.resume = true;
|
||||||
global_settings.contrast = DEFAULT_CONTRAST_SETTING;
|
global_settings.contrast = DEFAULT_CONTRAST_SETTING;
|
||||||
global_settings.poweroff = DEFAULT_POWEROFF_SETTING;
|
global_settings.poweroff = DEFAULT_POWEROFF_SETTING;
|
||||||
global_settings.backlight = DEFAULT_BACKLIGHT_SETTING;
|
global_settings.backlight = DEFAULT_BACKLIGHT_SETTING;
|
||||||
|
@ -358,6 +407,8 @@ void settings_reset(void) {
|
||||||
global_settings.total_uptime = 0;
|
global_settings.total_uptime = 0;
|
||||||
global_settings.scroll_speed = 8;
|
global_settings.scroll_speed = 8;
|
||||||
global_settings.ff_rewind = DEFAULT_FF_REWIND_SETTING;
|
global_settings.ff_rewind = DEFAULT_FF_REWIND_SETTING;
|
||||||
|
global_settings.resume_index = -1;
|
||||||
|
global_settings.resume_offset = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define __SETTINGS_H__
|
#define __SETTINGS_H__
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
/* data structures */
|
/* data structures */
|
||||||
|
|
||||||
|
@ -49,8 +50,11 @@ struct user_settings
|
||||||
|
|
||||||
/* resume settings */
|
/* resume settings */
|
||||||
|
|
||||||
int resume; /* power-on song resume: 0=no. 1=yes song. 2=yes pl */
|
bool resume; /* resume option on/off */
|
||||||
int track_time; /* number of seconds into the track to resume */
|
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 */
|
/* misc options */
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,11 @@ static void sort_case(void)
|
||||||
set_bool( "[Sort case sensitive]", &global_settings.sort_case );
|
set_bool( "[Sort case sensitive]", &global_settings.sort_case );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void resume(void)
|
||||||
|
{
|
||||||
|
set_bool( "[Resume]", &global_settings.resume );
|
||||||
|
}
|
||||||
|
|
||||||
static void backlight_timer(void)
|
static void backlight_timer(void)
|
||||||
{
|
{
|
||||||
char* names[] = { "off", "on ",
|
char* names[] = { "off", "on ",
|
||||||
|
@ -153,13 +158,13 @@ void settings_menu(void)
|
||||||
{ "Time/Date", timedate_set },
|
{ "Time/Date", timedate_set },
|
||||||
#endif
|
#endif
|
||||||
{ "FF/Rewind", ff_rewind },
|
{ "FF/Rewind", ff_rewind },
|
||||||
|
{ "Resume", resume },
|
||||||
};
|
};
|
||||||
bool old_shuffle = global_settings.playlist_shuffle;
|
bool old_shuffle = global_settings.playlist_shuffle;
|
||||||
|
|
||||||
m=menu_init( items, sizeof items / sizeof(struct menu_items) );
|
m=menu_init( items, sizeof items / sizeof(struct menu_items) );
|
||||||
menu_run(m);
|
menu_run(m);
|
||||||
menu_exit(m);
|
menu_exit(m);
|
||||||
settings_save();
|
|
||||||
|
|
||||||
if (old_shuffle != global_settings.playlist_shuffle)
|
if (old_shuffle != global_settings.playlist_shuffle)
|
||||||
{
|
{
|
||||||
|
|
129
apps/tree.c
129
apps/tree.c
|
@ -102,12 +102,14 @@ extern unsigned char bitmap_icons_6x8[LastIcon][6];
|
||||||
#define TREE_EXIT BUTTON_LEFT
|
#define TREE_EXIT BUTTON_LEFT
|
||||||
#define TREE_ENTER BUTTON_RIGHT
|
#define TREE_ENTER BUTTON_RIGHT
|
||||||
#define TREE_MENU BUTTON_F1
|
#define TREE_MENU BUTTON_F1
|
||||||
|
#define RELEASE_MASK (BUTTON_OFF)
|
||||||
#else
|
#else
|
||||||
#define TREE_NEXT BUTTON_RIGHT
|
#define TREE_NEXT BUTTON_RIGHT
|
||||||
#define TREE_PREV BUTTON_LEFT
|
#define TREE_PREV BUTTON_LEFT
|
||||||
#define TREE_EXIT BUTTON_STOP
|
#define TREE_EXIT BUTTON_STOP
|
||||||
#define TREE_ENTER BUTTON_PLAY
|
#define TREE_ENTER BUTTON_PLAY
|
||||||
#define TREE_MENU BUTTON_MENU
|
#define TREE_MENU BUTTON_MENU
|
||||||
|
#define RELEASE_MASK (BUTTON_STOP)
|
||||||
#endif /* HAVE_RECORDER_KEYPAD */
|
#endif /* HAVE_RECORDER_KEYPAD */
|
||||||
|
|
||||||
#define TREE_ATTR_M3U 0x80 /* unused by FAT attributes */
|
#define TREE_ATTR_M3U 0x80 /* unused by FAT attributes */
|
||||||
|
@ -292,6 +294,98 @@ static int showdir(char *path, int start)
|
||||||
return filesindir;
|
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)
|
bool dirbrowse(char *root)
|
||||||
{
|
{
|
||||||
int numentries=0;
|
int numentries=0;
|
||||||
|
@ -317,6 +411,9 @@ bool dirbrowse(char *root)
|
||||||
tree_max_on_screen = TREE_MAX_ON_SCREEN;
|
tree_max_on_screen = TREE_MAX_ON_SCREEN;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
start_resume();
|
||||||
|
button_set_release(RELEASE_MASK);
|
||||||
|
|
||||||
memcpy(currdir,root,sizeof(currdir));
|
memcpy(currdir,root,sizeof(currdir));
|
||||||
numentries = showdir(root, start);
|
numentries = showdir(root, start);
|
||||||
if (numentries == -1)
|
if (numentries == -1)
|
||||||
|
@ -350,6 +447,7 @@ bool dirbrowse(char *root)
|
||||||
restore = true;
|
restore = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef HAVE_RECORDER_KEYPAD
|
#ifdef HAVE_RECORDER_KEYPAD
|
||||||
case BUTTON_OFF:
|
case BUTTON_OFF:
|
||||||
mpeg_stop();
|
mpeg_stop();
|
||||||
|
@ -357,7 +455,15 @@ bool dirbrowse(char *root)
|
||||||
status_draw();
|
status_draw();
|
||||||
restore = true;
|
restore = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BUTTON_OFF | BUTTON_REL:
|
||||||
|
#else
|
||||||
|
case BUTTON_STOP | BUTTON_REL:
|
||||||
#endif
|
#endif
|
||||||
|
global_settings.resume_index = -1;
|
||||||
|
settings_save();
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case TREE_ENTER:
|
case TREE_ENTER:
|
||||||
#ifdef HAVE_RECORDER_KEYPAD
|
#ifdef HAVE_RECORDER_KEYPAD
|
||||||
|
@ -383,16 +489,34 @@ bool dirbrowse(char *root)
|
||||||
dircursor=0;
|
dircursor=0;
|
||||||
start=0;
|
start=0;
|
||||||
} else {
|
} else {
|
||||||
|
int seed = current_tick;
|
||||||
lcd_stop_scroll();
|
lcd_stop_scroll();
|
||||||
if(dircache[dircursor+start].attr & TREE_ATTR_M3U )
|
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,
|
play_list(currdir,
|
||||||
dircache[dircursor+start].name, 0);
|
dircache[dircursor+start].name,
|
||||||
|
0, 0, seed );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if ( global_settings.resume )
|
||||||
|
strncpy(global_settings.resume_file,
|
||||||
|
currdir, MAX_PATH);
|
||||||
start_index = build_playlist(dircursor+start);
|
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_set_playmode(STATUS_PLAY);
|
||||||
status_draw();
|
status_draw();
|
||||||
lcd_stop_scroll();
|
lcd_stop_scroll();
|
||||||
|
@ -405,6 +529,7 @@ bool dirbrowse(char *root)
|
||||||
dirlevel = 0;
|
dirlevel = 0;
|
||||||
dircursor = 0;
|
dircursor = 0;
|
||||||
start = 0;
|
start = 0;
|
||||||
|
global_settings.resume_index = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
restore = true;
|
restore = true;
|
||||||
|
|
22
apps/wps.c
22
apps/wps.c
|
@ -34,6 +34,7 @@
|
||||||
#include "powermgmt.h"
|
#include "powermgmt.h"
|
||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "main_menu.h"
|
#include "main_menu.h"
|
||||||
|
#include "ata.h"
|
||||||
#ifdef HAVE_LCD_BITMAP
|
#ifdef HAVE_LCD_BITMAP
|
||||||
#include "icons.h"
|
#include "icons.h"
|
||||||
#include "widgets.h"
|
#include "widgets.h"
|
||||||
|
@ -462,6 +463,13 @@ int wps_show(void)
|
||||||
{
|
{
|
||||||
mpeg_pause();
|
mpeg_pause();
|
||||||
status_set_playmode(STATUS_PAUSE);
|
status_set_playmode(STATUS_PAUSE);
|
||||||
|
if (global_settings.resume) {
|
||||||
|
status_draw();
|
||||||
|
settings_save();
|
||||||
|
#ifndef HAVE_RTC
|
||||||
|
ata_flush();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -577,7 +585,6 @@ int wps_show(void)
|
||||||
mpeg_ff_rewind(ff_rewind_count);
|
mpeg_ff_rewind(ff_rewind_count);
|
||||||
ff_rewind_count = 0;
|
ff_rewind_count = 0;
|
||||||
ff_rewind = false;
|
ff_rewind = false;
|
||||||
status_set_playmode(STATUS_PLAY);
|
|
||||||
#ifdef HAVE_LCD_CHARCELLS
|
#ifdef HAVE_LCD_CHARCELLS
|
||||||
draw_screen(id3);
|
draw_screen(id3);
|
||||||
#endif
|
#endif
|
||||||
|
@ -589,7 +596,6 @@ int wps_show(void)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
mpeg_prev();
|
mpeg_prev();
|
||||||
status_set_playmode(STATUS_PLAY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef HAVE_PLAYER_KEYPAD
|
#ifdef HAVE_PLAYER_KEYPAD
|
||||||
|
@ -612,7 +618,6 @@ int wps_show(void)
|
||||||
mpeg_ff_rewind(ff_rewind_count);
|
mpeg_ff_rewind(ff_rewind_count);
|
||||||
ff_rewind_count = 0;
|
ff_rewind_count = 0;
|
||||||
ff_rewind = false;
|
ff_rewind = false;
|
||||||
status_set_playmode(STATUS_PLAY);
|
|
||||||
#ifdef HAVE_LCD_CHARCELLS
|
#ifdef HAVE_LCD_CHARCELLS
|
||||||
draw_screen(id3);
|
draw_screen(id3);
|
||||||
#endif
|
#endif
|
||||||
|
@ -624,7 +629,6 @@ int wps_show(void)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
mpeg_next();
|
mpeg_next();
|
||||||
status_set_playmode(STATUS_PLAY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef HAVE_PLAYER_KEYPAD
|
#ifdef HAVE_PLAYER_KEYPAD
|
||||||
|
@ -862,6 +866,16 @@ int wps_show(void)
|
||||||
if (mpeg_is_playing() && id3)
|
if (mpeg_is_playing() && id3)
|
||||||
display_file_time(id3->elapsed, id3->length);
|
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();
|
status_draw();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,6 +304,7 @@ extern void ata_delayed_write(unsigned long sector, void* buf)
|
||||||
extern void ata_flush(void)
|
extern void ata_flush(void)
|
||||||
{
|
{
|
||||||
if ( delayed_write ) {
|
if ( delayed_write ) {
|
||||||
|
DEBUGF("ata_flush()\n");
|
||||||
delayed_write = false;
|
delayed_write = false;
|
||||||
ata_write_sectors(delayed_sector_num, 1, delayed_sector);
|
ata_write_sectors(delayed_sector_num, 1, delayed_sector);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,10 @@ struct mp3entry {
|
||||||
/* these following two fields are used for local buffering */
|
/* these following two fields are used for local buffering */
|
||||||
char id3v2buf[300];
|
char id3v2buf[300];
|
||||||
char id3v1buf[3][32];
|
char id3v1buf[3][32];
|
||||||
|
|
||||||
|
/* resume related */
|
||||||
|
int offset; /* bytes played */
|
||||||
|
int index; /* playlist index */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VBR_FRAMES_FLAG 0x01
|
#define VBR_FRAMES_FLAG 0x01
|
||||||
|
|
|
@ -52,7 +52,8 @@
|
||||||
#define MPEG_SWAP_DATA 101
|
#define MPEG_SWAP_DATA 101
|
||||||
#define MPEG_TRACK_CHANGE 102
|
#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[] =
|
static char *units[] =
|
||||||
{
|
{
|
||||||
|
@ -243,6 +244,7 @@ static void remove_all_tags(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool paused; /* playback is paused */
|
||||||
#ifdef SIMULATOR
|
#ifdef SIMULATOR
|
||||||
static bool playing = false;
|
static bool playing = false;
|
||||||
static bool play_pending = false;
|
static bool play_pending = false;
|
||||||
|
@ -502,7 +504,7 @@ static void stop_dma(void)
|
||||||
|
|
||||||
static void dma_tick(void)
|
static void dma_tick(void)
|
||||||
{
|
{
|
||||||
if(playing)
|
if(playing && !paused)
|
||||||
{
|
{
|
||||||
/* Start DMA if it is disabled and the DEMAND pin is high */
|
/* Start DMA if it is disabled and the DEMAND pin is high */
|
||||||
if(!dma_on && (PBDR & 0x4000))
|
if(!dma_on && (PBDR & 0x4000))
|
||||||
|
@ -594,6 +596,7 @@ void DEI3(void)
|
||||||
|
|
||||||
DTCR3 = last_dma_chunk_size & 0xffff;
|
DTCR3 = last_dma_chunk_size & 0xffff;
|
||||||
SAR3 = (unsigned int)mp3buf + mp3buf_read;
|
SAR3 = (unsigned int)mp3buf + mp3buf_read;
|
||||||
|
id3tags[tag_read_idx]->id3.offset += last_dma_chunk_size;
|
||||||
}
|
}
|
||||||
else
|
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 */
|
/* If next_track is true, opens the next track, if false, opens prev track */
|
||||||
static int new_file(int steps)
|
static int new_file(int steps)
|
||||||
{
|
{
|
||||||
char *trackname;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
trackname = playlist_next( steps );
|
char *trackname;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
trackname = playlist_next( steps, &index );
|
||||||
if ( !trackname )
|
if ( !trackname )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -666,6 +670,8 @@ static int new_file(int steps)
|
||||||
lseek(mpeg_file,
|
lseek(mpeg_file,
|
||||||
id3tags[tag_read_idx]->id3.id3v2len & ~1,
|
id3tags[tag_read_idx]->id3.id3v2len & ~1,
|
||||||
SEEK_SET);
|
SEEK_SET);
|
||||||
|
id3tags[tag_read_idx]->id3.index = index;
|
||||||
|
id3tags[tag_read_idx]->id3.offset = 0;
|
||||||
}
|
}
|
||||||
} while ( mpeg_file < 0 );
|
} while ( mpeg_file < 0 );
|
||||||
|
|
||||||
|
@ -706,6 +712,7 @@ static void mpeg_thread(void)
|
||||||
int amount_to_read;
|
int amount_to_read;
|
||||||
int amount_to_swap;
|
int amount_to_swap;
|
||||||
int t1, t2;
|
int t1, t2;
|
||||||
|
int start_offset;
|
||||||
|
|
||||||
play_pending = false;
|
play_pending = false;
|
||||||
playing = false;
|
playing = false;
|
||||||
|
@ -720,7 +727,7 @@ static void mpeg_thread(void)
|
||||||
switch(ev.id)
|
switch(ev.id)
|
||||||
{
|
{
|
||||||
case MPEG_PLAY:
|
case MPEG_PLAY:
|
||||||
DEBUGF("MPEG_PLAY %s\n",ev.data);
|
DEBUGF("MPEG_PLAY\n");
|
||||||
/* Stop the current stream */
|
/* Stop the current stream */
|
||||||
play_pending = false;
|
play_pending = false;
|
||||||
playing = false;
|
playing = false;
|
||||||
|
@ -732,18 +739,21 @@ static void mpeg_thread(void)
|
||||||
if(mpeg_file >= 0)
|
if(mpeg_file >= 0)
|
||||||
close(mpeg_file);
|
close(mpeg_file);
|
||||||
|
|
||||||
mpeg_file = open((char*)ev.data, O_RDONLY);
|
if ( new_file(0) == -1 )
|
||||||
while (mpeg_file < 0) {
|
return;
|
||||||
DEBUGF("Couldn't open file: %s\n",ev.data);
|
|
||||||
if ( new_file(1) == -1 )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_track_to_tag_list((char *)ev.data);
|
start_offset = (int)ev.data;
|
||||||
/* skip past id3v2 tag (to an even byte) */
|
if (start_offset) {
|
||||||
lseek(mpeg_file,
|
lseek(mpeg_file, start_offset, SEEK_SET);
|
||||||
id3tags[tag_read_idx]->id3.id3v2len & ~1,
|
id3tags[tag_read_idx]->id3.offset = start_offset;
|
||||||
SEEK_SET);
|
}
|
||||||
|
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 */
|
/* Make it read more data */
|
||||||
filling = true;
|
filling = true;
|
||||||
|
@ -752,6 +762,7 @@ static void mpeg_thread(void)
|
||||||
/* Tell the file loading code that we want to start playing
|
/* Tell the file loading code that we want to start playing
|
||||||
as soon as we have some data */
|
as soon as we have some data */
|
||||||
play_pending = true;
|
play_pending = true;
|
||||||
|
paused = false;
|
||||||
|
|
||||||
current_track_counter++;
|
current_track_counter++;
|
||||||
break;
|
break;
|
||||||
|
@ -764,6 +775,7 @@ static void mpeg_thread(void)
|
||||||
case MPEG_PAUSE:
|
case MPEG_PAUSE:
|
||||||
DEBUGF("MPEG_PAUSE\n");
|
DEBUGF("MPEG_PAUSE\n");
|
||||||
/* Stop the current stream */
|
/* Stop the current stream */
|
||||||
|
paused = true;
|
||||||
playing = false;
|
playing = false;
|
||||||
pause_tick = current_tick;
|
pause_tick = current_tick;
|
||||||
stop_dma();
|
stop_dma();
|
||||||
|
@ -775,6 +787,7 @@ static void mpeg_thread(void)
|
||||||
playing = true;
|
playing = true;
|
||||||
last_dma_tick += current_tick - pause_tick;
|
last_dma_tick += current_tick - pause_tick;
|
||||||
pause_tick = 0;
|
pause_tick = 0;
|
||||||
|
paused = false;
|
||||||
start_dma();
|
start_dma();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -799,7 +812,8 @@ static void mpeg_thread(void)
|
||||||
play_pending = true;
|
play_pending = true;
|
||||||
} else {
|
} else {
|
||||||
playing = true;
|
playing = true;
|
||||||
start_dma();
|
if (!paused)
|
||||||
|
start_dma();
|
||||||
}
|
}
|
||||||
|
|
||||||
track_change();
|
track_change();
|
||||||
|
@ -931,7 +945,8 @@ static void mpeg_thread(void)
|
||||||
playing = true;
|
playing = true;
|
||||||
last_dma_tick = current_tick;
|
last_dma_tick = current_tick;
|
||||||
init_dma();
|
init_dma();
|
||||||
start_dma();
|
if (!paused)
|
||||||
|
start_dma();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1016,7 +1031,8 @@ static void mpeg_thread(void)
|
||||||
|
|
||||||
last_dma_tick = current_tick;
|
last_dma_tick = current_tick;
|
||||||
init_dma();
|
init_dma();
|
||||||
start_dma();
|
if (!paused)
|
||||||
|
start_dma();
|
||||||
|
|
||||||
/* Tell ourselves that we need more data */
|
/* Tell ourselves that we need more data */
|
||||||
queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
|
queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
|
||||||
|
@ -1188,7 +1204,7 @@ static void setup_sci0(void)
|
||||||
static struct mp3entry taginfo;
|
static struct mp3entry taginfo;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct mp3entry* mpeg_current_track(void)
|
struct mp3entry* mpeg_current_track()
|
||||||
{
|
{
|
||||||
#ifdef SIMULATOR
|
#ifdef SIMULATOR
|
||||||
return &taginfo;
|
return &taginfo;
|
||||||
|
@ -1210,13 +1226,17 @@ bool mpeg_has_changed_track(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mpeg_play(char* trackname)
|
void mpeg_play(int offset)
|
||||||
{
|
{
|
||||||
#ifdef SIMULATOR
|
#ifdef SIMULATOR
|
||||||
mp3info(&taginfo, trackname);
|
char* trackname = playlist_next( 0, NULL );
|
||||||
playing = true;
|
if ( trackname ) {
|
||||||
|
mp3info(&taginfo, trackname);
|
||||||
|
playing = true;
|
||||||
|
}
|
||||||
|
(void)offset;
|
||||||
#else
|
#else
|
||||||
queue_post(&mpeg_queue, MPEG_PLAY, trackname);
|
queue_post(&mpeg_queue, MPEG_PLAY, (void*)offset);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1252,7 +1272,7 @@ void mpeg_next(void)
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
queue_post(&mpeg_queue, MPEG_NEXT, NULL);
|
queue_post(&mpeg_queue, MPEG_NEXT, NULL);
|
||||||
#else
|
#else
|
||||||
char* file = playlist_next(1);
|
char* file = playlist_next(1,NULL);
|
||||||
mp3info(&taginfo, file);
|
mp3info(&taginfo, file);
|
||||||
current_track_counter++;
|
current_track_counter++;
|
||||||
playing = true;
|
playing = true;
|
||||||
|
@ -1264,7 +1284,7 @@ void mpeg_prev(void)
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
queue_post(&mpeg_queue, MPEG_PREV, NULL);
|
queue_post(&mpeg_queue, MPEG_PREV, NULL);
|
||||||
#else
|
#else
|
||||||
char* file = playlist_next(-1);
|
char* file = playlist_next(-1,NULL);
|
||||||
mp3info(&taginfo, file);
|
mp3info(&taginfo, file);
|
||||||
current_track_counter--;
|
current_track_counter--;
|
||||||
playing = true;
|
playing = true;
|
||||||
|
@ -1282,7 +1302,7 @@ void mpeg_ff_rewind(int change)
|
||||||
|
|
||||||
bool mpeg_is_playing(void)
|
bool mpeg_is_playing(void)
|
||||||
{
|
{
|
||||||
return playing || play_pending;
|
return (playing || play_pending) && (!paused) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
void mpeg_init(int volume, int bass, int treble, int balance, int loudness, int bass_boost, int avc);
|
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_stop(void);
|
||||||
void mpeg_pause(void);
|
void mpeg_pause(void);
|
||||||
void mpeg_resume(void);
|
void mpeg_resume(void);
|
||||||
|
|
|
@ -80,3 +80,7 @@ void ata_delayed_write(unsigned long sector, void* buf)
|
||||||
{
|
{
|
||||||
ata_write_sectors(sector,1,buf);
|
ata_write_sectors(sector,1,buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ata_flush(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue