Added dynamic playlists. ON+PLAY->Playlist on a track, directory, or playlist from file browser to see available options.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3796 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
928a09e3f4
commit
9e4262081b
24 changed files with 2310 additions and 1005 deletions
|
@ -23,6 +23,5 @@
|
|||
#define AVERAGE_FILENAME_LENGTH 40
|
||||
#define MAX_DIR_LEVELS 10
|
||||
#define MAX_PLAYLIST_SIZE 10000
|
||||
#define MAX_QUEUED_FILES 100
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1632,3 +1632,93 @@ id: LANG_STAR
|
|||
desc: in the games menu
|
||||
eng: "Star"
|
||||
new:
|
||||
|
||||
id: LANG_QUEUE_LAST
|
||||
desc: in onplay menu. queue a track/playlist at end of playlist.
|
||||
eng: "Queue last"
|
||||
new:
|
||||
|
||||
id: LANG_INSERT
|
||||
desc: in onplay menu. insert a track/playlist into dynamic playlist.
|
||||
eng: "Insert"
|
||||
new:
|
||||
|
||||
id: LANG_INSERT_LAST
|
||||
desc: in onplay menu. append a track/playlist into dynamic playlist.
|
||||
eng: "Insert last"
|
||||
new:
|
||||
|
||||
id: LANG_QUEUE_FIRST
|
||||
desc: in onplay menu. queue a track/playlist into dynamic playlist.
|
||||
eng: "Queue first"
|
||||
new:
|
||||
|
||||
id: LANG_INSERT_FIRST
|
||||
desc: in onplay menu. insert a track/playlist into dynamic playlist.
|
||||
eng: "Insert first"
|
||||
new:
|
||||
|
||||
id: LANG_SAVE_DYNAMIC_PLAYLIST
|
||||
desc: in playlist menu.
|
||||
eng: "Save Dynamic Playlist"
|
||||
new:
|
||||
|
||||
id: LANG_PLAYLIST_MENU
|
||||
desc: in main menu.
|
||||
eng: "Playlist Options"
|
||||
new:
|
||||
|
||||
id: LANG_PLAYLIST_INSERT_COUNT
|
||||
desc: splash number of tracks inserted
|
||||
eng: "Inserted %d tracks (%s)"
|
||||
new:
|
||||
|
||||
id: LANG_PLAYLIST_QUEUE_COUNT
|
||||
desc: splash number of tracks queued
|
||||
eng: "Queued %d tracks (%s)"
|
||||
new:
|
||||
|
||||
id: LANG_PLAYLIST_SAVE_COUNT
|
||||
desc: splash number of tracks saved
|
||||
eng: "Saved %d tracks (%s)"
|
||||
new:
|
||||
|
||||
id: LANG_OFF_ABORT
|
||||
desc: Used on recorder models
|
||||
eng: "OFF to abort"
|
||||
new:
|
||||
|
||||
id: LANG_STOP_ABORT
|
||||
desc: Used on player models
|
||||
eng: "STOP to abort"
|
||||
new:
|
||||
|
||||
id: LANG_PLAYLIST_CONTROL_UPDATE_ERROR
|
||||
desc: Playlist error
|
||||
eng: "Error updating playlist control file"
|
||||
new:
|
||||
|
||||
id: LANG_PLAYLIST_ACCESS_ERROR
|
||||
desc: Playlist error
|
||||
eng: "Error accessing playlist file"
|
||||
new:
|
||||
|
||||
id: LANG_PLAYLIST_CONTROL_ACCESS_ERROR
|
||||
desc: Playlist error
|
||||
eng: "Error accessing playlist control file"
|
||||
new:
|
||||
|
||||
id: LANG_PLAYLIST_DIRECTORY_ACCESS_ERROR
|
||||
desc: Playlist error
|
||||
eng: "Error accessing directory"
|
||||
new:
|
||||
|
||||
id: LANG_PLAYLIST_CONTROL_INVALID
|
||||
desc: Playlist resume error
|
||||
eng: "Playlist control file is invalid"
|
||||
new:
|
||||
|
||||
id: LANG_RECURSE_DIRECTORY
|
||||
desc: In playlist menu
|
||||
eng: "Recursively Insert Directories"
|
||||
new:
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "wps.h"
|
||||
#include "buffer.h"
|
||||
#include "screens.h"
|
||||
#include "playlist_menu.h"
|
||||
#ifdef HAVE_FMRADIO
|
||||
#include "radio.h"
|
||||
#endif
|
||||
|
@ -266,7 +267,7 @@ bool main_menu(void)
|
|||
{ str(LANG_RECORDING), recording_screen },
|
||||
{ str(LANG_RECORDING_SETTINGS), recording_menu },
|
||||
#endif
|
||||
{ str(LANG_CREATE_PLAYLIST), create_playlist },
|
||||
{ str(LANG_PLAYLIST_MENU), playlist_menu },
|
||||
{ str(LANG_MENU_SHOW_ID3_INFO), browse_id3 },
|
||||
{ str(LANG_SLEEP_TIMER), sleeptimer_screen },
|
||||
#ifdef HAVE_ALARM_MOD
|
||||
|
|
116
apps/onplay.c
116
apps/onplay.c
|
@ -38,13 +38,103 @@
|
|||
#include "screens.h"
|
||||
#include "tree.h"
|
||||
#include "buffer.h"
|
||||
#include "settings.h"
|
||||
#include "status.h"
|
||||
#include "onplay.h"
|
||||
|
||||
static char* selected_file = NULL;
|
||||
static bool reload_dir = false;
|
||||
static int selected_file_attr = 0;
|
||||
static int onplay_result = ONPLAY_OK;
|
||||
|
||||
static bool queue_file(void)
|
||||
/* For playlist options */
|
||||
struct playlist_args {
|
||||
int position;
|
||||
bool queue;
|
||||
};
|
||||
|
||||
static bool add_to_playlist(int position, bool queue)
|
||||
{
|
||||
queue_add(selected_file);
|
||||
bool new_playlist = !(mpeg_status() & MPEG_STATUS_PLAY);
|
||||
|
||||
if (new_playlist)
|
||||
playlist_create(NULL, NULL);
|
||||
|
||||
if (selected_file_attr & TREE_ATTR_MPA)
|
||||
playlist_insert_track(selected_file, position, queue);
|
||||
else if (selected_file_attr & ATTR_DIRECTORY)
|
||||
playlist_insert_directory(selected_file, position, queue);
|
||||
else if (selected_file_attr & TREE_ATTR_M3U)
|
||||
playlist_insert_playlist(selected_file, position, queue);
|
||||
|
||||
if (new_playlist && (playlist_amount() > 0))
|
||||
{
|
||||
/* nothing is currently playing so begin playing what we just
|
||||
inserted */
|
||||
if (global_settings.playlist_shuffle)
|
||||
playlist_shuffle(current_tick, -1);
|
||||
playlist_start(0,0);
|
||||
status_set_playmode(STATUS_PLAY);
|
||||
status_draw(false);
|
||||
onplay_result = ONPLAY_START_PLAY;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Sub-menu for playlist options */
|
||||
static bool playlist_options(void)
|
||||
{
|
||||
struct menu_items menu[6];
|
||||
struct playlist_args args[6]; /* increase these 2 if you add entries! */
|
||||
int m, i=0, result;
|
||||
|
||||
if (mpeg_status() & MPEG_STATUS_PLAY)
|
||||
{
|
||||
menu[i].desc = str(LANG_INSERT);
|
||||
args[i].position = PLAYLIST_INSERT;
|
||||
args[i].queue = false;
|
||||
i++;
|
||||
|
||||
menu[i].desc = str(LANG_INSERT_FIRST);
|
||||
args[i].position = PLAYLIST_INSERT_FIRST;
|
||||
args[i].queue = false;
|
||||
i++;
|
||||
|
||||
menu[i].desc = str(LANG_INSERT_LAST);
|
||||
args[i].position = PLAYLIST_INSERT_LAST;
|
||||
args[i].queue = false;
|
||||
i++;
|
||||
|
||||
menu[i].desc = str(LANG_QUEUE);
|
||||
args[i].position = PLAYLIST_INSERT;
|
||||
args[i].queue = true;
|
||||
i++;
|
||||
|
||||
menu[i].desc = str(LANG_QUEUE_FIRST);
|
||||
args[i].position = PLAYLIST_INSERT_FIRST;
|
||||
args[i].queue = true;
|
||||
i++;
|
||||
|
||||
menu[i].desc = str(LANG_QUEUE_LAST);
|
||||
args[i].position = PLAYLIST_INSERT_LAST;
|
||||
args[i].queue = true;
|
||||
i++;
|
||||
}
|
||||
else if ((selected_file_attr & TREE_ATTR_MPA) ||
|
||||
(selected_file_attr & ATTR_DIRECTORY))
|
||||
{
|
||||
menu[i].desc = str(LANG_INSERT);
|
||||
args[i].position = PLAYLIST_INSERT;
|
||||
args[i].queue = false;
|
||||
i++;
|
||||
}
|
||||
|
||||
m = menu_init( menu, i );
|
||||
result = menu_show(m);
|
||||
if (result >= 0)
|
||||
add_to_playlist(args[result].position, args[result].queue);
|
||||
menu_exit(m);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -68,7 +158,7 @@ static bool delete_file(void)
|
|||
switch (btn) {
|
||||
case BUTTON_PLAY:
|
||||
if (!remove(selected_file)) {
|
||||
reload_dir = true;
|
||||
onplay_result = ONPLAY_RELOAD_DIR;
|
||||
lcd_clear_display();
|
||||
lcd_puts(0,0,str(LANG_DELETED));
|
||||
lcd_puts_scroll(0,1,selected_file);
|
||||
|
@ -104,7 +194,7 @@ static bool rename_file(void)
|
|||
sleep(HZ*2);
|
||||
}
|
||||
else
|
||||
reload_dir = true;
|
||||
onplay_result = ONPLAY_RELOAD_DIR;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -225,7 +315,7 @@ static bool vbr_fix(void)
|
|||
|
||||
if(mpeg_status()) {
|
||||
splash(HZ*2, 0, true, str(LANG_VBRFIX_STOP_PLAY));
|
||||
return reload_dir;
|
||||
return onplay_result;
|
||||
}
|
||||
|
||||
lcd_clear_display();
|
||||
|
@ -356,12 +446,16 @@ int onplay(char* file, int attr)
|
|||
struct menu_items menu[5]; /* increase this if you add entries! */
|
||||
int m, i=0, result;
|
||||
|
||||
onplay_result = ONPLAY_OK;
|
||||
|
||||
selected_file = file;
|
||||
|
||||
if ((mpeg_status() & MPEG_STATUS_PLAY) && (attr & TREE_ATTR_MPA))
|
||||
selected_file_attr = attr;
|
||||
|
||||
if ((attr & TREE_ATTR_MPA) || (attr & ATTR_DIRECTORY) ||
|
||||
(attr & TREE_ATTR_M3U))
|
||||
{
|
||||
menu[i].desc = str(LANG_QUEUE);
|
||||
menu[i].function = queue_file;
|
||||
menu[i].desc = str(LANG_PLAYINDICES_PLAYLIST);
|
||||
menu[i].function = playlist_options;
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -390,5 +484,5 @@ int onplay(char* file, int attr)
|
|||
menu[result].function();
|
||||
menu_exit(m);
|
||||
|
||||
return reload_dir;
|
||||
return onplay_result;
|
||||
}
|
||||
|
|
|
@ -21,4 +21,10 @@
|
|||
|
||||
int onplay(char* file, int attr);
|
||||
|
||||
enum {
|
||||
ONPLAY_OK,
|
||||
ONPLAY_RELOAD_DIR,
|
||||
ONPLAY_START_PLAY
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
2321
apps/playlist.c
2321
apps/playlist.c
File diff suppressed because it is too large
Load diff
|
@ -22,57 +22,56 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include "file.h"
|
||||
#include "applimits.h"
|
||||
#include "kernel.h"
|
||||
|
||||
/* playlist data */
|
||||
|
||||
struct playlist_info
|
||||
{
|
||||
char filename[MAX_PATH]; /* path name of m3u playlist on disk */
|
||||
int fd; /* file descriptor of the open playlist */
|
||||
int fd; /* descriptor of the open playlist file */
|
||||
int control_fd; /* descriptor of the open control file */
|
||||
int dirlen; /* Length of the path to the playlist file */
|
||||
int *indices; /* array of indices */
|
||||
int max_playlist_size; /* Max number of files in playlist. Mirror of
|
||||
unsigned int *indices; /* array of indices */
|
||||
int max_playlist_size; /* Max number of files in playlist. Mirror of
|
||||
global_settings.max_files_in_playlist */
|
||||
int buffer_size; /* Playlist buffer size */
|
||||
bool in_ram; /* playlist stored in ram (dirplay) */
|
||||
char *buffer; /* buffer for in-ram playlists */
|
||||
int buffer_size; /* size of buffer */
|
||||
int buffer_end_pos; /* last position where buffer was written */
|
||||
int index; /* index of current playing track */
|
||||
int first_index; /* index of first song in playlist */
|
||||
int seed; /* random seed */
|
||||
int amount; /* number of tracks in the index */
|
||||
bool in_ram; /* True if the playlist is RAM-based */
|
||||
|
||||
/* Queue function */
|
||||
int queue_indices[MAX_QUEUED_FILES]; /* array of queue indices */
|
||||
int last_queue_index; /* index of last queued track */
|
||||
int queue_index; /* index of current playing queued track */
|
||||
int num_queued; /* number of songs queued */
|
||||
int start_queue; /* the first song was queued */
|
||||
int last_insert_pos; /* last position we inserted a track */
|
||||
struct mutex control_mutex; /* mutex for control file access */
|
||||
};
|
||||
|
||||
extern struct playlist_info playlist;
|
||||
extern bool playlist_shuffle;
|
||||
|
||||
void playlist_init(void);
|
||||
int play_list(char *dir, char *file, int start_index,
|
||||
bool shuffled_index, int start_offset,
|
||||
int random_seed, int first_index, int queue_resume,
|
||||
int queue_resume_index);
|
||||
char* playlist_peek(int steps);
|
||||
char* playlist_name(char *name, int name_size);
|
||||
int playlist_next(int steps);
|
||||
bool playlist_check(int steps);
|
||||
void randomise_playlist( unsigned int seed );
|
||||
void sort_playlist(bool start_current);
|
||||
void add_indices_to_playlist(void);
|
||||
void playlist_clear(void);
|
||||
int playlist_create(char *dir, char *file);
|
||||
int playlist_resume(void);
|
||||
int playlist_add(char *filename);
|
||||
int queue_add(char *filename);
|
||||
int playlist_insert_track(char *filename, int position, bool queue);
|
||||
int playlist_insert_directory(char *dirname, int position, bool queue);
|
||||
int playlist_insert_playlist(char *filename, int position, bool queue);
|
||||
int playlist_delete(int index);
|
||||
int playlist_shuffle(int random_seed, int start_index);
|
||||
int playlist_randomise(unsigned int seed, bool start_current);
|
||||
int playlist_sort(bool start_current);
|
||||
int playlist_start(int start_index, int offset);
|
||||
bool playlist_check(int steps);
|
||||
char *playlist_peek(int steps);
|
||||
int playlist_next(int steps);
|
||||
int playlist_get_resume_info(int *resume_index);
|
||||
int playlist_get_display_index(void);
|
||||
int playlist_amount(void);
|
||||
int playlist_first_index(void);
|
||||
int playlist_get_resume_info(int *resume_index, int *queue_resume,
|
||||
int *queue_resume_index);
|
||||
char *playlist_name(char *buf, int buf_size);
|
||||
int playlist_save(char *filename);
|
||||
|
||||
enum { QUEUE_OFF, QUEUE_BEGIN_QUEUE, QUEUE_BEGIN_PLAYLIST, NUM_QUEUE_MODES };
|
||||
enum {
|
||||
PLAYLIST_PREPEND = -1,
|
||||
PLAYLIST_INSERT = -2,
|
||||
PLAYLIST_INSERT_LAST = -3,
|
||||
PLAYLIST_INSERT_FIRST = -4
|
||||
};
|
||||
|
||||
#endif /* __PLAYLIST_H__ */
|
||||
|
||||
|
|
71
apps/playlist_menu.c
Normal file
71
apps/playlist_menu.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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 <string.h>
|
||||
|
||||
#include "menu.h"
|
||||
#include "file.h"
|
||||
#include "keyboard.h"
|
||||
#include "playlist.h"
|
||||
#include "tree.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "lang.h"
|
||||
|
||||
#define DEFAULT_PLAYLIST_NAME "/dynamic.m3u"
|
||||
|
||||
static bool save_playlist(void)
|
||||
{
|
||||
char filename[MAX_PATH+1];
|
||||
|
||||
strncpy(filename, DEFAULT_PLAYLIST_NAME, sizeof(filename));
|
||||
|
||||
if (!kbd_input(filename, sizeof(filename)))
|
||||
{
|
||||
playlist_save(filename);
|
||||
|
||||
/* reload in case playlist was saved to cwd */
|
||||
reload_directory();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool recurse_directory(void)
|
||||
{
|
||||
return (set_bool( str(LANG_RECURSE_DIRECTORY),
|
||||
&global_settings.recursive_dir_insert));
|
||||
}
|
||||
|
||||
bool playlist_menu(void)
|
||||
{
|
||||
int m;
|
||||
bool result;
|
||||
|
||||
struct menu_items items[] = {
|
||||
{ str(LANG_CREATE_PLAYLIST), create_playlist },
|
||||
{ str(LANG_SAVE_DYNAMIC_PLAYLIST), save_playlist },
|
||||
{ str(LANG_RECURSE_DIRECTORY), recurse_directory },
|
||||
};
|
||||
|
||||
m = menu_init( items, sizeof items / sizeof(struct menu_items) );
|
||||
result = menu_run(m);
|
||||
menu_exit(m);
|
||||
return result;
|
||||
}
|
24
apps/playlist_menu.h
Normal file
24
apps/playlist_menu.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef _PLAYLIST_MENU_H
|
||||
#define _PLAYLIST_MENU_H
|
||||
|
||||
bool playlist_menu(void);
|
||||
|
||||
#endif
|
|
@ -341,9 +341,9 @@ bool f2_screen(void)
|
|||
if(mpeg_status() & MPEG_STATUS_PLAY)
|
||||
{
|
||||
if (global_settings.playlist_shuffle)
|
||||
randomise_playlist(current_tick);
|
||||
playlist_randomise(current_tick, true);
|
||||
else
|
||||
sort_playlist(true);
|
||||
playlist_sort(true);
|
||||
}
|
||||
used = true;
|
||||
break;
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
struct user_settings global_settings;
|
||||
char rockboxdir[] = ROCKBOX_DIR; /* config/font/data file directory */
|
||||
|
||||
#define CONFIG_BLOCK_VERSION 6
|
||||
#define CONFIG_BLOCK_VERSION 7
|
||||
#define CONFIG_BLOCK_SIZE 512
|
||||
#define RTC_BLOCK_SIZE 44
|
||||
|
||||
|
@ -98,10 +98,10 @@ offset abs
|
|||
0x12 0x26 <(int) Resume playlist index, or -1 if no playlist resume>
|
||||
0x16 0x2a <(int) Byte offset into resume file>
|
||||
0x1a 0x2e <time until disk spindown>
|
||||
0x1b 0x2f <browse current, play selected, queue_resume>
|
||||
0x1b 0x2f <browse current, play selected, recursive dir insert>
|
||||
0x1c 0x30 <peak meter hold timeout (bit 0-4),
|
||||
rec_editable (bit 7)>
|
||||
0x1d 0x31 <(int) queue resume index>
|
||||
0x1d 0x31 <unused>
|
||||
0x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2),
|
||||
mic gain (bit 4-7)>
|
||||
0x22 0x36 <rec. quality (bit 0-2), source (bit 3-4), frequency (bit 5-7)>
|
||||
|
@ -144,9 +144,9 @@ Rest of config block, only saved to disk:
|
|||
0xB8 (char[20]) WPS file
|
||||
0xCC (char[20]) Lang file
|
||||
0xE0 (char[20]) Font file
|
||||
0xF4 (int) Playlist first index
|
||||
0xF8 (int) Playlist shuffle seed
|
||||
0xFC-0x1FF (char[260]) Resume playlist (path/to/dir or path/to/playlist.m3u)
|
||||
0xF4 <unused>
|
||||
0xF8 <unused>
|
||||
0xFC <unused>
|
||||
|
||||
*************************************/
|
||||
|
||||
|
@ -343,18 +343,19 @@ int settings_save( void )
|
|||
|
||||
memcpy(&config_block[0x12], &global_settings.resume_index, 4);
|
||||
memcpy(&config_block[0x16], &global_settings.resume_offset, 4);
|
||||
DEBUGF( "+Resume index %X offset %X\n",
|
||||
global_settings.resume_index,
|
||||
global_settings.resume_offset );
|
||||
|
||||
config_block[0x1a] = (unsigned char)global_settings.disk_spindown;
|
||||
config_block[0x1b] = (unsigned char)
|
||||
(((global_settings.browse_current & 1)) |
|
||||
((global_settings.play_selected & 1) << 1) |
|
||||
((global_settings.queue_resume & 3) << 2));
|
||||
((global_settings.recursive_dir_insert & 1) << 2));
|
||||
|
||||
config_block[0x1c] = (unsigned char)global_settings.peak_meter_hold |
|
||||
(global_settings.rec_editable?0x80:0);
|
||||
|
||||
memcpy(&config_block[0x1d], &global_settings.queue_resume_index, 4);
|
||||
|
||||
config_block[0x21] = (unsigned char)
|
||||
((global_settings.repeat_mode & 3) |
|
||||
((global_settings.rec_channels & 1) << 2) |
|
||||
|
@ -415,17 +416,6 @@ int settings_save( void )
|
|||
strncpy(&config_block[0xb8], global_settings.wps_file, MAX_FILENAME);
|
||||
strncpy(&config_block[0xcc], global_settings.lang_file, MAX_FILENAME);
|
||||
strncpy(&config_block[0xe0], global_settings.font_file, MAX_FILENAME);
|
||||
memcpy(&config_block[0xF4], &global_settings.resume_first_index, 4);
|
||||
memcpy(&config_block[0xF8], &global_settings.resume_seed, 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())
|
||||
{
|
||||
|
@ -655,7 +645,8 @@ void settings_load(void)
|
|||
if (config_block[0x1b] != 0xFF) {
|
||||
global_settings.browse_current = (config_block[0x1b]) & 1;
|
||||
global_settings.play_selected = (config_block[0x1b] >> 1) & 1;
|
||||
global_settings.queue_resume = (config_block[0x1b] >> 2) & 3;
|
||||
global_settings.recursive_dir_insert =
|
||||
(config_block[0x1b] >> 2) & 1;
|
||||
}
|
||||
|
||||
if (config_block[0x1c] != 0xFF) {
|
||||
|
@ -664,10 +655,6 @@ void settings_load(void)
|
|||
(config_block[0x1c] & 0x80)?true:false;
|
||||
}
|
||||
|
||||
if (config_block[0x1d] != 0xFF)
|
||||
memcpy(&global_settings.queue_resume_index, &config_block[0x1d],
|
||||
4);
|
||||
|
||||
if (config_block[0x21] != 0xFF)
|
||||
{
|
||||
global_settings.repeat_mode = config_block[0x21] & 3;
|
||||
|
@ -745,14 +732,9 @@ void settings_load(void)
|
|||
global_settings.max_files_in_playlist =
|
||||
config_block[0xaa] | (config_block[0xab] << 8);
|
||||
|
||||
memcpy(&global_settings.resume_first_index, &config_block[0xF4], 4);
|
||||
memcpy(&global_settings.resume_seed, &config_block[0xF8], 4);
|
||||
|
||||
strncpy(global_settings.wps_file, &config_block[0xb8], MAX_FILENAME);
|
||||
strncpy(global_settings.lang_file, &config_block[0xcc], MAX_FILENAME);
|
||||
strncpy(global_settings.font_file, &config_block[0xe0], MAX_FILENAME);
|
||||
strncpy(global_settings.resume_file, &config_block[0xFC], MAX_PATH);
|
||||
global_settings.resume_file[MAX_PATH]=0;
|
||||
#ifdef HAVE_LCD_CHARCELLS
|
||||
if (config_block[0xa8] != 0xff)
|
||||
global_settings.jump_scroll = config_block[0xa8];
|
||||
|
@ -1097,6 +1079,8 @@ bool settings_load_config(char* file)
|
|||
else if (!strcasecmp(name, "max files in playlist"))
|
||||
set_cfg_int(&global_settings.max_files_in_playlist, value,
|
||||
1000, 20000);
|
||||
else if (!strcasecmp(name, "recursive directory insert"))
|
||||
set_cfg_bool(&global_settings.recursive_dir_insert, value);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
@ -1385,6 +1369,9 @@ bool settings_save_config(void)
|
|||
fprintf(fd, "max files in playlist: %d\r\n",
|
||||
global_settings.max_files_in_playlist);
|
||||
|
||||
fprintf(fd, "recursive directory insert: %s\r\n",
|
||||
boolopt[global_settings.recursive_dir_insert]);
|
||||
|
||||
close(fd);
|
||||
|
||||
lcd_clear_display();
|
||||
|
@ -1450,9 +1437,6 @@ void settings_reset(void) {
|
|||
global_settings.ff_rewind_accel = DEFAULT_FF_REWIND_ACCEL_SETTING;
|
||||
global_settings.resume_index = -1;
|
||||
global_settings.resume_offset = -1;
|
||||
global_settings.save_queue_resume = true;
|
||||
global_settings.queue_resume = 0;
|
||||
global_settings.queue_resume_index = -1;
|
||||
global_settings.disk_spindown = 5;
|
||||
global_settings.disk_poweroff = false;
|
||||
global_settings.buffer_margin = 0;
|
||||
|
@ -1475,6 +1459,7 @@ void settings_reset(void) {
|
|||
global_settings.max_files_in_dir = 400;
|
||||
global_settings.max_files_in_playlist = 10000;
|
||||
global_settings.show_icons = true;
|
||||
global_settings.recursive_dir_insert = false;
|
||||
}
|
||||
|
||||
bool set_bool(char* string, bool* variable )
|
||||
|
|
|
@ -103,16 +103,7 @@ struct user_settings
|
|||
int resume; /* resume option: 0=off, 1=ask, 2=on */
|
||||
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 */
|
||||
int resume_first_index; /* first index of playlist */
|
||||
|
||||
bool save_queue_resume; /* save queued songs for resume */
|
||||
int queue_resume; /* resume queue file?: 0 = no
|
||||
1 = resume at queue index
|
||||
2 = resume at playlist index */
|
||||
int queue_resume_index; /* queue index (seek point in queue file) */
|
||||
|
||||
unsigned char resume_file[MAX_PATH+1]; /* playlist name (or dir) */
|
||||
unsigned char font_file[MAX_FILENAME+1]; /* last font */
|
||||
unsigned char wps_file[MAX_FILENAME+1]; /* last wps */
|
||||
unsigned char lang_file[MAX_FILENAME+1]; /* last language */
|
||||
|
@ -175,6 +166,7 @@ struct user_settings
|
|||
int max_files_in_dir; /* Max entries in directory (file browser) */
|
||||
int max_files_in_playlist; /* Max entries in playlist */
|
||||
bool show_icons; /* 0=hide 1=show */
|
||||
bool recursive_dir_insert;/* should directories be inserted recursively */
|
||||
};
|
||||
|
||||
enum optiontype { INT, BOOL };
|
||||
|
|
|
@ -724,11 +724,11 @@ static bool playback_settings_menu(void)
|
|||
{
|
||||
if (global_settings.playlist_shuffle)
|
||||
{
|
||||
randomise_playlist(current_tick);
|
||||
playlist_randomise(current_tick, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
sort_playlist(true);
|
||||
playlist_sort(true);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
477
apps/tree.c
477
apps/tree.c
|
@ -66,10 +66,6 @@ static int max_files_in_dir;
|
|||
static char *name_buffer;
|
||||
static int name_buffer_size; /* Size of allocated buffer */
|
||||
static int name_buffer_length; /* Currently used amount */
|
||||
struct entry {
|
||||
short attr; /* FAT attributes + file type flags */
|
||||
char *name;
|
||||
};
|
||||
|
||||
static struct entry *dircache;
|
||||
|
||||
|
@ -87,6 +83,8 @@ static int boot_size = 0;
|
|||
static int boot_cluster;
|
||||
static bool boot_changed = false;
|
||||
|
||||
static bool dirbrowse(char *root);
|
||||
|
||||
void browse_root(void)
|
||||
{
|
||||
#ifndef SIMULATOR
|
||||
|
@ -158,14 +156,13 @@ static int build_playlist(int start_index)
|
|||
int i;
|
||||
int start=start_index;
|
||||
|
||||
playlist_clear();
|
||||
|
||||
for(i = 0;i < filesindir;i++)
|
||||
{
|
||||
if(dircache[i].attr & TREE_ATTR_MPA)
|
||||
{
|
||||
DEBUGF("Adding %s\n", dircache[i].name);
|
||||
playlist_add(dircache[i].name);
|
||||
if (playlist_add(dircache[i].name) < 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -237,6 +234,133 @@ static void showfileline(int line, int direntry, bool scroll)
|
|||
}
|
||||
}
|
||||
|
||||
/* load sorted directory into dircache. returns NULL on failure. */
|
||||
struct entry* load_and_sort_directory(char *dirname, int dirfilter,
|
||||
int *num_files, bool *buffer_full)
|
||||
{
|
||||
int i;
|
||||
|
||||
DIR *dir = opendir(dirname);
|
||||
if(!dir)
|
||||
return NULL; /* not a directory */
|
||||
|
||||
name_buffer_length = 0;
|
||||
*buffer_full = false;
|
||||
|
||||
for ( i=0; i < max_files_in_dir; i++ ) {
|
||||
int len;
|
||||
struct dirent *entry = readdir(dir);
|
||||
struct entry* dptr = &dircache[i];
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
len = strlen(entry->d_name);
|
||||
|
||||
/* skip directories . and .. */
|
||||
if ((entry->attribute & ATTR_DIRECTORY) &&
|
||||
(((len == 1) &&
|
||||
(!strncmp(entry->d_name, ".", 1))) ||
|
||||
((len == 2) &&
|
||||
(!strncmp(entry->d_name, "..", 2))))) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip FAT volume ID */
|
||||
if (entry->attribute & ATTR_VOLUME_ID) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out dotfiles and hidden files */
|
||||
if (dirfilter != SHOW_ALL &&
|
||||
((entry->d_name[0]=='.') ||
|
||||
(entry->attribute & ATTR_HIDDEN))) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
dptr->attr = entry->attribute;
|
||||
|
||||
/* mark mp? and m3u files as such */
|
||||
if ( !(dptr->attr & ATTR_DIRECTORY) && (len > 4) ) {
|
||||
if (!strcasecmp(&entry->d_name[len-4], ".mp3") ||
|
||||
(!strcasecmp(&entry->d_name[len-4], ".mp2")) ||
|
||||
(!strcasecmp(&entry->d_name[len-4], ".mpa")))
|
||||
dptr->attr |= TREE_ATTR_MPA;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".m3u"))
|
||||
dptr->attr |= TREE_ATTR_M3U;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".cfg"))
|
||||
dptr->attr |= TREE_ATTR_CFG;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".wps"))
|
||||
dptr->attr |= TREE_ATTR_WPS;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".txt"))
|
||||
dptr->attr |= TREE_ATTR_TXT;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".lng"))
|
||||
dptr->attr |= TREE_ATTR_LNG;
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".fnt"))
|
||||
dptr->attr |= TREE_ATTR_FONT;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".ajz"))
|
||||
#else
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".mod"))
|
||||
#endif
|
||||
dptr->attr |= TREE_ATTR_MOD;
|
||||
else if (!strcasecmp(&entry->d_name[len-5], ".rock"))
|
||||
dptr->attr |= TREE_ATTR_ROCK;
|
||||
}
|
||||
|
||||
/* memorize/compare details about the boot file */
|
||||
if ((currdir[1] == 0) && !strcmp(entry->d_name, BOOTFILE)) {
|
||||
if (boot_size) {
|
||||
if ((entry->size != boot_size) ||
|
||||
(entry->startcluster != boot_cluster))
|
||||
boot_changed = true;
|
||||
}
|
||||
boot_size = entry->size;
|
||||
boot_cluster = entry->startcluster;
|
||||
}
|
||||
|
||||
/* filter out all non-playlist files */
|
||||
if ( dirfilter == SHOW_PLAYLIST &&
|
||||
(!(dptr->attr &
|
||||
(ATTR_DIRECTORY|TREE_ATTR_M3U))) ) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out non-music files */
|
||||
if ( dirfilter == SHOW_MUSIC &&
|
||||
(!(dptr->attr &
|
||||
(ATTR_DIRECTORY|TREE_ATTR_MPA|TREE_ATTR_M3U))) ) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out non-supported files */
|
||||
if ( dirfilter == SHOW_SUPPORTED &&
|
||||
(!(dptr->attr & TREE_ATTR_MASK)) ) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len > name_buffer_size - name_buffer_length - 1) {
|
||||
/* Tell the world that we ran out of buffer space */
|
||||
*buffer_full = true;
|
||||
break;
|
||||
}
|
||||
dptr->name = &name_buffer[name_buffer_length];
|
||||
strcpy(dptr->name,entry->d_name);
|
||||
name_buffer_length += len + 1;
|
||||
}
|
||||
*num_files = i;
|
||||
closedir(dir);
|
||||
strncpy(lastdir,dirname,sizeof(lastdir));
|
||||
lastdir[sizeof(lastdir)-1] = 0;
|
||||
qsort(dircache,i,sizeof(struct entry),compare);
|
||||
|
||||
return dircache;
|
||||
}
|
||||
|
||||
static int showdir(char *path, int start)
|
||||
{
|
||||
|
@ -258,124 +382,9 @@ static int showdir(char *path, int start)
|
|||
|
||||
/* new dir? cache it */
|
||||
if (strncmp(path,lastdir,sizeof(lastdir)) || reload_dir) {
|
||||
DIR *dir = opendir(path);
|
||||
if(!dir)
|
||||
return -1; /* not a directory */
|
||||
|
||||
name_buffer_length = 0;
|
||||
dir_buffer_full = false;
|
||||
|
||||
for ( i=0; i < max_files_in_dir; i++ ) {
|
||||
int len;
|
||||
struct dirent *entry = readdir(dir);
|
||||
struct entry* dptr = &dircache[i];
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
len = strlen(entry->d_name);
|
||||
|
||||
/* skip directories . and .. */
|
||||
if ((entry->attribute & ATTR_DIRECTORY) &&
|
||||
(((len == 1) &&
|
||||
(!strncmp(entry->d_name, ".", 1))) ||
|
||||
((len == 2) &&
|
||||
(!strncmp(entry->d_name, "..", 2))))) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip FAT volume ID */
|
||||
if (entry->attribute & ATTR_VOLUME_ID) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out dotfiles and hidden files */
|
||||
if (global_settings.dirfilter != SHOW_ALL &&
|
||||
((entry->d_name[0]=='.') ||
|
||||
(entry->attribute & ATTR_HIDDEN))) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
dptr->attr = entry->attribute;
|
||||
|
||||
/* mark mp? and m3u files as such */
|
||||
if ( !(dptr->attr & ATTR_DIRECTORY) && (len > 4) ) {
|
||||
if (!strcasecmp(&entry->d_name[len-4], ".mp3") ||
|
||||
(!strcasecmp(&entry->d_name[len-4], ".mp2")) ||
|
||||
(!strcasecmp(&entry->d_name[len-4], ".mpa")))
|
||||
dptr->attr |= TREE_ATTR_MPA;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".m3u"))
|
||||
dptr->attr |= TREE_ATTR_M3U;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".cfg"))
|
||||
dptr->attr |= TREE_ATTR_CFG;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".wps"))
|
||||
dptr->attr |= TREE_ATTR_WPS;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".txt"))
|
||||
dptr->attr |= TREE_ATTR_TXT;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".lng"))
|
||||
dptr->attr |= TREE_ATTR_LNG;
|
||||
#ifdef HAVE_RECORDER_KEYPAD
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".fnt"))
|
||||
dptr->attr |= TREE_ATTR_FONT;
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".ajz"))
|
||||
#else
|
||||
else if (!strcasecmp(&entry->d_name[len-4], ".mod"))
|
||||
#endif
|
||||
dptr->attr |= TREE_ATTR_MOD;
|
||||
else if (!strcasecmp(&entry->d_name[len-5], ".rock"))
|
||||
dptr->attr |= TREE_ATTR_ROCK;
|
||||
}
|
||||
|
||||
/* memorize/compare details about the boot file */
|
||||
if ((currdir[1] == 0) && !strcmp(entry->d_name, BOOTFILE)) {
|
||||
if (boot_size) {
|
||||
if ((entry->size != boot_size) ||
|
||||
(entry->startcluster != boot_cluster))
|
||||
boot_changed = true;
|
||||
}
|
||||
boot_size = entry->size;
|
||||
boot_cluster = entry->startcluster;
|
||||
}
|
||||
|
||||
/* filter out all non-playlist files */
|
||||
if ( global_settings.dirfilter == SHOW_PLAYLIST &&
|
||||
(!(dptr->attr &
|
||||
(ATTR_DIRECTORY|TREE_ATTR_M3U))) ) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out non-music files */
|
||||
if ( global_settings.dirfilter == SHOW_MUSIC &&
|
||||
(!(dptr->attr &
|
||||
(ATTR_DIRECTORY|TREE_ATTR_MPA|TREE_ATTR_M3U))) ) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* filter out non-supported files */
|
||||
if ( global_settings.dirfilter == SHOW_SUPPORTED &&
|
||||
(!(dptr->attr & TREE_ATTR_MASK)) ) {
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len > name_buffer_size - name_buffer_length - 1) {
|
||||
/* Tell the world that we ran out of buffer space */
|
||||
dir_buffer_full = true;
|
||||
break;
|
||||
}
|
||||
dptr->name = &name_buffer[name_buffer_length];
|
||||
strcpy(dptr->name,entry->d_name);
|
||||
name_buffer_length += len + 1;
|
||||
}
|
||||
filesindir = i;
|
||||
closedir(dir);
|
||||
strncpy(lastdir,path,sizeof(lastdir));
|
||||
lastdir[sizeof(lastdir)-1] = 0;
|
||||
qsort(dircache,filesindir,sizeof(struct entry),compare);
|
||||
if (!load_and_sort_directory(path, global_settings.dirfilter,
|
||||
&filesindir, &dir_buffer_full))
|
||||
return -1;
|
||||
|
||||
if ( dir_buffer_full || filesindir == max_files_in_dir ) {
|
||||
#ifdef HAVE_LCD_CHARCELLS
|
||||
|
@ -531,7 +540,7 @@ static int showdir(char *path, int start)
|
|||
return filesindir;
|
||||
}
|
||||
|
||||
bool ask_resume(void)
|
||||
static bool ask_resume(void)
|
||||
{
|
||||
#ifdef HAVE_LCD_CHARCELLS
|
||||
lcd_double_height(false);
|
||||
|
@ -570,92 +579,62 @@ bool ask_resume(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
void start_resume(void)
|
||||
/* load tracks from specified directory to resume play */
|
||||
void resume_directory(char *dir)
|
||||
{
|
||||
bool buffer_full;
|
||||
|
||||
if (!load_and_sort_directory(dir, global_settings.dirfilter, &filesindir,
|
||||
&buffer_full))
|
||||
return;
|
||||
lastdir[0] = 0;
|
||||
|
||||
build_playlist(0);
|
||||
}
|
||||
|
||||
/* Returns the current working directory and also writes cwd to buf if
|
||||
non-NULL. In case of error, returns NULL. */
|
||||
char *getcwd(char *buf, int size)
|
||||
{
|
||||
if (!buf)
|
||||
return currdir;
|
||||
else if (size > 0)
|
||||
{
|
||||
strncpy(buf, currdir, size);
|
||||
return buf;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Force a reload of the directory next time directory browser is called */
|
||||
void reload_directory(void)
|
||||
{
|
||||
reload_dir = true;
|
||||
}
|
||||
|
||||
static 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;
|
||||
if (!ask_resume())
|
||||
return;
|
||||
|
||||
if (playlist_resume() != -1)
|
||||
{
|
||||
playlist_start(global_settings.resume_index,
|
||||
global_settings.resume_offset);
|
||||
|
||||
/* 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,
|
||||
true, /* the index is AFTER shuffle */
|
||||
global_settings.resume_offset,
|
||||
global_settings.resume_seed,
|
||||
global_settings.resume_first_index,
|
||||
global_settings.queue_resume,
|
||||
global_settings.queue_resume_index);
|
||||
*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,
|
||||
true,
|
||||
global_settings.resume_offset,
|
||||
global_settings.resume_seed,
|
||||
global_settings.resume_first_index,
|
||||
global_settings.queue_resume,
|
||||
global_settings.queue_resume_index);
|
||||
}
|
||||
status_set_playmode(STATUS_PLAY);
|
||||
status_draw(true);
|
||||
wps_show();
|
||||
}
|
||||
else {
|
||||
if (!ask_resume())
|
||||
return;
|
||||
|
||||
if (showdir(global_settings.resume_file, 0) < 0 )
|
||||
return;
|
||||
|
||||
lastdir[0] = '\0';
|
||||
|
||||
build_playlist(global_settings.resume_index);
|
||||
play_list(global_settings.resume_file,
|
||||
NULL,
|
||||
global_settings.resume_index,
|
||||
true,
|
||||
global_settings.resume_offset,
|
||||
global_settings.resume_seed,
|
||||
global_settings.resume_first_index,
|
||||
global_settings.queue_resume,
|
||||
global_settings.queue_resume_index);
|
||||
}
|
||||
|
||||
status_set_playmode(STATUS_PLAY);
|
||||
status_draw(true);
|
||||
wps_show();
|
||||
else
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -751,19 +730,33 @@ static bool handle_on(int* ds, int* dc, int numentries, int tree_max_on_screen)
|
|||
|
||||
case BUTTON_PLAY:
|
||||
case BUTTON_RC_PLAY:
|
||||
case BUTTON_ON | BUTTON_PLAY:
|
||||
case BUTTON_ON | BUTTON_PLAY: {
|
||||
int onplay_result;
|
||||
|
||||
if (currdir[1])
|
||||
snprintf(buf, sizeof buf, "%s/%s",
|
||||
currdir, dircache[dircursor+dirstart].name);
|
||||
else
|
||||
snprintf(buf, sizeof buf, "/%s",
|
||||
dircache[dircursor+dirstart].name);
|
||||
if (onplay(buf, dircache[dircursor+dirstart].attr))
|
||||
reload_dir = 1;
|
||||
onplay_result = onplay(buf,
|
||||
dircache[dircursor+dirstart].attr);
|
||||
switch (onplay_result)
|
||||
{
|
||||
case ONPLAY_OK:
|
||||
used = true;
|
||||
break;
|
||||
case ONPLAY_RELOAD_DIR:
|
||||
reload_dir = 1;
|
||||
used = true;
|
||||
break;
|
||||
case ONPLAY_START_PLAY:
|
||||
used = false; /* this will enable the wps */
|
||||
break;
|
||||
}
|
||||
exit = true;
|
||||
used = true;
|
||||
break;
|
||||
|
||||
}
|
||||
case BUTTON_ON | BUTTON_REL:
|
||||
case BUTTON_ON | TREE_PREV | BUTTON_REL:
|
||||
case BUTTON_ON | TREE_NEXT | BUTTON_REL:
|
||||
|
@ -793,7 +786,7 @@ static bool handle_on(int* ds, int* dc, int numentries, int tree_max_on_screen)
|
|||
return used;
|
||||
}
|
||||
|
||||
bool dirbrowse(char *root)
|
||||
static bool dirbrowse(char *root)
|
||||
{
|
||||
int numentries=0;
|
||||
char buf[MAX_PATH];
|
||||
|
@ -934,41 +927,36 @@ bool dirbrowse(char *root)
|
|||
lcd_stop_scroll();
|
||||
switch ( file->attr & TREE_ATTR_MASK ) {
|
||||
case TREE_ATTR_M3U:
|
||||
if ( global_settings.resume ) {
|
||||
if (currdir[1])
|
||||
snprintf(global_settings.resume_file,
|
||||
MAX_PATH, "%s/%s",
|
||||
currdir, file->name);
|
||||
else
|
||||
snprintf(global_settings.resume_file,
|
||||
MAX_PATH, "/%s", file->name);
|
||||
}
|
||||
play_list(currdir, file->name, 0, false, 0,
|
||||
seed, 0, 0, -1);
|
||||
start_index = 0;
|
||||
play = true;
|
||||
break;
|
||||
|
||||
case TREE_ATTR_MPA:
|
||||
if ( global_settings.resume )
|
||||
strncpy(global_settings.resume_file,
|
||||
currdir, MAX_PATH);
|
||||
|
||||
start_index =
|
||||
build_playlist(dircursor+dirstart);
|
||||
|
||||
/* when shuffling dir.: play all files even if the
|
||||
file selected by user is not the first one */
|
||||
if (global_settings.playlist_shuffle
|
||||
&& !global_settings.play_selected)
|
||||
if (playlist_create(currdir, file->name) != -1)
|
||||
{
|
||||
if (global_settings.playlist_shuffle)
|
||||
playlist_shuffle(seed, -1);
|
||||
start_index = 0;
|
||||
|
||||
/* it is important that we get back the index
|
||||
in the (shuffled) list and store that */
|
||||
start_index = play_list(currdir, NULL,
|
||||
start_index, false,
|
||||
0, seed, 0, 0, -1);
|
||||
play = true;
|
||||
playlist_start(start_index,0);
|
||||
play = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case TREE_ATTR_MPA:
|
||||
if (playlist_create(currdir, NULL) != -1)
|
||||
{
|
||||
start_index =
|
||||
build_playlist(dircursor+dirstart);
|
||||
if (global_settings.playlist_shuffle)
|
||||
{
|
||||
start_index =
|
||||
playlist_shuffle(seed,start_index);
|
||||
|
||||
/* when shuffling dir.: play all files
|
||||
even if the file selected by user is
|
||||
not the first one */
|
||||
if (!global_settings.play_selected)
|
||||
start_index = 0;
|
||||
}
|
||||
|
||||
playlist_start(start_index, 0);
|
||||
play = true;
|
||||
}
|
||||
break;
|
||||
|
||||
/* wps config file */
|
||||
|
@ -1055,9 +1043,6 @@ bool dirbrowse(char *root)
|
|||
shuffled list in case shuffle is enabled */
|
||||
global_settings.resume_index = start_index;
|
||||
global_settings.resume_offset = 0;
|
||||
global_settings.resume_first_index =
|
||||
playlist_first_index();
|
||||
global_settings.resume_seed = seed;
|
||||
settings_save();
|
||||
}
|
||||
|
||||
|
|
11
apps/tree.h
11
apps/tree.h
|
@ -21,6 +21,11 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct entry {
|
||||
short attr; /* FAT attributes + file type flags */
|
||||
char *name;
|
||||
};
|
||||
|
||||
/* using attribute not used by FAT */
|
||||
#define TREE_ATTR_MPA 0x40 /* mpeg audio file */
|
||||
#define TREE_ATTR_M3U 0x80 /* playlist */
|
||||
|
@ -36,7 +41,11 @@
|
|||
void tree_init(void);
|
||||
void browse_root(void);
|
||||
void set_current_file(char *path);
|
||||
bool dirbrowse(char *root);
|
||||
bool create_playlist(void);
|
||||
void resume_directory(char *dir);
|
||||
char *getcwd(char *buf, int size);
|
||||
void reload_directory(void);
|
||||
struct entry* load_and_sort_directory(char *dirname, int dirfilter,
|
||||
int *num_files, bool *buffer_full);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -418,12 +418,7 @@ static char* get_tag(struct mp3entry* id3,
|
|||
#endif
|
||||
case 'p': /* Playlist Position */
|
||||
*flags |= WPS_REFRESH_STATIC;
|
||||
{
|
||||
int index = id3->index - playlist_first_index();
|
||||
if (index < 0)
|
||||
index += playlist_amount();
|
||||
snprintf(buf, buf_size, "%d", index + 1);
|
||||
}
|
||||
snprintf(buf, buf_size, "%d", playlist_get_display_index());
|
||||
return buf;
|
||||
|
||||
case 'n': /* Playlist Name (without path) */
|
||||
|
|
13
apps/wps.c
13
apps/wps.c
|
@ -223,13 +223,8 @@ bool browse_id3(void)
|
|||
|
||||
case 7:
|
||||
lcd_puts(0, 0, str(LANG_ID3_PLAYLIST));
|
||||
{
|
||||
int index = id3->index - playlist_first_index();
|
||||
if (index < 0)
|
||||
index += playlist_amount();
|
||||
snprintf(scroll_text,sizeof(scroll_text), "%d/%d",
|
||||
index + 1, playlist_amount());
|
||||
}
|
||||
snprintf(scroll_text,sizeof(scroll_text), "%d/%d",
|
||||
playlist_get_display_index(), playlist_amount());
|
||||
lcd_puts_scroll(0, 1, scroll_text);
|
||||
break;
|
||||
|
||||
|
@ -455,9 +450,7 @@ static bool update(void)
|
|||
DEBUGF("R%X,%X (%X)\n", global_settings.resume_offset,
|
||||
id3->offset,id3);
|
||||
|
||||
if (!playlist_get_resume_info(&global_settings.resume_index,
|
||||
&global_settings.queue_resume,
|
||||
&global_settings.queue_resume_index))
|
||||
if (!playlist_get_resume_info(&global_settings.resume_index))
|
||||
{
|
||||
global_settings.resume_offset = id3->offset;
|
||||
settings_save();
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
The penalty is the RAM used for the cache and slightly more complex code.
|
||||
*/
|
||||
|
||||
#define MAX_OPEN_FILES 4
|
||||
#define MAX_OPEN_FILES 8
|
||||
|
||||
struct filedesc {
|
||||
unsigned char cache[SECTOR_SIZE];
|
||||
|
|
|
@ -100,7 +100,7 @@ APPS = main.c tree.c menu.c credits.c main_menu.c icons.c language.c \
|
|||
screens.c peakmeter.c sleeptimer.c keyboard.c onplay.c\
|
||||
misc.c plugin.c
|
||||
|
||||
MENUS = games_menu.c demo_menu.c settings_menu.c sound_menu.c
|
||||
MENUS = games_menu.c demo_menu.c settings_menu.c sound_menu.c playlist_menu.c
|
||||
|
||||
ifeq ($(DISPLAY),-DHAVE_LCD_BITMAP)
|
||||
APPS += bmp.c widgets.c
|
||||
|
@ -160,6 +160,9 @@ $(OBJDIR)/demo_menu.o: $(APPDIR)/demo_menu.c
|
|||
$(OBJDIR)/settings_menu.o: $(APPDIR)/settings_menu.c
|
||||
$(CC) $(APPCFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/playlist_menu.o: $(APPDIR)/playlist_menu.c
|
||||
$(CC) $(APPCFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/icons.o: $(MACHINEDIR)/icons.c
|
||||
$(CC) $(APPCFLAGS) -c $< -o $@
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ int win32_filesize(int fd);
|
|||
|
||||
#define rename(x,y) win32_rename(x,y)
|
||||
#define filesize(x) win32_filesize(x)
|
||||
#define flush(x) _commit(x)
|
||||
#define fsync(x) _commit(x)
|
||||
|
||||
#include "../../firmware/include/file.h"
|
||||
|
||||
|
|
|
@ -103,3 +103,15 @@ int set_irq_level (int level)
|
|||
static int _lv = 0;
|
||||
return (_lv = level);
|
||||
}
|
||||
|
||||
void mutex_init(struct mutex *m)
|
||||
{
|
||||
}
|
||||
|
||||
void mutex_lock(struct mutex *m)
|
||||
{
|
||||
}
|
||||
|
||||
void mutex_unlock(struct mutex *m)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ RSC=rc.exe
|
|||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../firmware/export" /I "../../firmware/drivers" /I "../../firmware/common" /I "../common" /I "../win32" /I "../../apps" /I "../../apps/recorder" /D "HAVE_LCD_BITMAP" /D "HAVE_RECORDER_KEYPAD" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_CONFIG_H" /D "GETTIMEOFDAY_TWO_ARGS" /D "SIMULATOR" /D APPSVERSION=\"WIN32SIM\" /FR /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../firmware/export" /I "../../firmware/drivers" /I "../../firmware/common" /I "../common" /I "../win32" /I "../../apps" /I "../../apps/recorder" /D "HAVE_LCD_BITMAP" /D "HAVE_RECORDER_KEYPAD" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_CONFIG_H" /D "GETTIMEOFDAY_TWO_ARGS" /D "SIMULATOR" /D APPSVERSION=\"WIN32SIM\" /FR /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x407 /d "_DEBUG"
|
||||
|
@ -69,7 +69,7 @@ LINK32=link.exe
|
|||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../../firmware/export" /I "../../firmware/drivers" /I "../../firmware/common" /I "../common" /I "../win32" /I "../../apps" /I "../../apps/player" /D "HAVE_LCD_CHARCELLS" /D "HAVE_PLAYER_KEYPAD" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_CONFIG_H" /D "GETTIMEOFDAY_TWO_ARGS" /D "SIMULATOR" /D APPSVERSION=\"WIN32SIM\" /FR /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../firmware/export" /I "../../firmware/drivers" /I "../../firmware/common" /I "../common" /I "../win32" /I "../../apps" /I "../../apps/player" /D "HAVE_LCD_CHARCELLS" /D "HAVE_PLAYER_KEYPAD" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "HAVE_CONFIG_H" /D "GETTIMEOFDAY_TWO_ARGS" /D "SIMULATOR" /D APPSVERSION=\"WIN32SIM\" /FR /YX /FD /GZ /c
|
||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
||||
# ADD BASE RSC /l 0x407 /d "_DEBUG"
|
||||
|
@ -369,6 +369,10 @@ SOURCE=..\..\apps\playlist.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\apps\playlist_menu.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\apps\plugin.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -95,7 +95,7 @@ APPS = main.c tree.c menu.c credits.c main_menu.c language.c\
|
|||
screens.c peakmeter.c sleeptimer.c keyboard.c onplay.c\
|
||||
misc.c plugin.c
|
||||
|
||||
MENUS = games_menu.c demo_menu.c settings_menu.c sound_menu.c
|
||||
MENUS = games_menu.c demo_menu.c settings_menu.c sound_menu.c playlist_menu.c
|
||||
|
||||
ifeq ($(DISPLAY),-DHAVE_LCD_BITMAP)
|
||||
APPS += bmp.c widgets.c
|
||||
|
@ -156,6 +156,9 @@ $(OBJDIR)/demo_menu.o: $(APPDIR)/demo_menu.c
|
|||
$(OBJDIR)/settings_menu.o: $(APPDIR)/settings_menu.c
|
||||
$(CC) $(APPCFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/playlist_menu.o: $(APPDIR)/playlist_menu.c
|
||||
$(CC) $(APPCFLAGS) -c $< -o $@
|
||||
|
||||
$(OBJDIR)/icons.o: $(MACHINEDIR)/icons.c
|
||||
$(CC) $(APPCFLAGS) -c $< -o $@
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#ifndef NO_REDEFINES_PLEASE
|
||||
|
||||
#define sleep(x) x11_sleep(x)
|
||||
#define mutex_init(x) (void)x
|
||||
#define mutex_lock(x) (void)x
|
||||
#define mutex_unlock(x) (void)x
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue