summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2002-08-06 13:09:48 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2002-08-06 13:09:48 +0000
commitd8cc2850342ef7c6386c4347b7fb55d204847f91 (patch)
tree616d0f63db553d194cf01b0d64dc3d28b954e446
parentaba19c95b7723babef2a39ce9364cad60f09be3e (diff)
downloadrockbox-d8cc2850342ef7c6386c4347b7fb55d204847f91.zip
rockbox-d8cc2850342ef7c6386c4347b7fb55d204847f91.tar.gz
rockbox-d8cc2850342ef7c6386c4347b7fb55d204847f91.tar.bz2
rockbox-d8cc2850342ef7c6386c4347b7fb55d204847f91.tar.xz
RAM-based playlists added
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@1559 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/playlist.c300
-rw-r--r--apps/playlist.h16
2 files changed, 198 insertions, 118 deletions
diff --git a/apps/playlist.c b/apps/playlist.c
index fdd88a1..465470c 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -33,157 +33,224 @@
playlist_info_t playlist;
+#define PLAYLIST_BUFFER_SIZE (MAX_PATH*200)
+
+unsigned char playlist_buffer[PLAYLIST_BUFFER_SIZE];
+static int playlist_end_pos = 0;
+
char now_playing[MAX_PATH+1];
-char* playlist_next(int steps, char *dirname)
+void playlist_clear(void)
+{
+ playlist_end_pos = 0;
+ playlist_buffer[0] = 0;
+}
+
+int playlist_add(char *filename)
+{
+ int len = strlen(filename);
+
+ if(len+2 > PLAYLIST_BUFFER_SIZE - playlist_end_pos)
+ return -1;
+
+ strcpy(&playlist_buffer[playlist_end_pos], filename);
+ playlist_end_pos += len;
+ playlist_buffer[playlist_end_pos++] = '\n';
+ playlist_buffer[playlist_end_pos] = '\0';
+ return 0;
+}
+
+char* playlist_next(int steps)
{
int seek;
int max;
int fd;
int i;
- char buf[MAX_PATH+1];
+ char *buf;
char dir_buf[MAX_PATH+1];
char *dir_end;
playlist.index = (playlist.index+steps) % playlist.amount;
seek = playlist.indices[playlist.index];
- fd = open(playlist.filename, O_RDONLY);
- if(-1 != fd) {
- lseek(fd, seek, SEEK_SET);
- max = read(fd, buf, sizeof(buf)-1);
- close(fd);
-
- /* Zero-terminate the file name */
- seek=0;
- while((buf[seek] != '\n') &&
- (buf[seek] != '\r') &&
- (seek < max))
+ if(playlist.in_ram)
+ {
+ buf = playlist_buffer + seek;
+ max = playlist_end_pos - seek;
+ }
+ else
+ {
+ fd = open(playlist.filename, O_RDONLY);
+ if(-1 != fd)
+ {
+ buf = playlist_buffer;
+ lseek(fd, seek, SEEK_SET);
+ max = read(fd, buf, MAX_PATH);
+ close(fd);
+ }
+ else
+ return NULL;
+ }
+
+
+ /* Zero-terminate the file name */
+ seek=0;
+ while((buf[seek] != '\n') &&
+ (buf[seek] != '\r') &&
+ (seek < max))
seek++;
- /* Now work back killing white space */
- while((buf[seek-1] == ' ') ||
- (buf[seek-1] == '\t'))
- seek--;
+ /* Now work back killing white space */
+ while((buf[seek-1] == ' ') ||
+ (buf[seek-1] == '\t'))
+ seek--;
- buf[seek]=0;
+ buf[seek]=0;
- /* replace backslashes with forward slashes */
- for ( i=0; i<seek; i++ )
- if ( buf[i] == '\\' )
- buf[i] = '/';
-
- if('/' == buf[0]) {
- strcpy(now_playing, &buf[0]);
- return now_playing;
- }
- else {
- /* handle dos style drive letter */
- if ( ':' == buf[1] ) {
- strcpy(now_playing, &buf[2]);
- return now_playing;
- }
- else if ( '.' == buf[0] && '.' == buf[1] && '/' == buf[2] ) {
- /* handle relative paths */
- seek=3;
- while(buf[seek] == '.' &&
- buf[seek+1] == '.' &&
- buf[seek+2] == '/')
- seek += 3;
- strcpy(dir_buf, dirname);
- for (i=0; i<seek/3; i++) {
- dir_end = strrchr(dir_buf, '/');
- if (dir_end)
- *dir_end = '\0';
- else
- break;
- }
- snprintf(now_playing, MAX_PATH+1, "%s/%s", dir_buf, &buf[seek]);
- return now_playing;
- }
- else if ( '.' == buf[0] && '/' == buf[1] ) {
- snprintf(now_playing, MAX_PATH+1, "%s/%s", dirname, &buf[2]);
- return now_playing;
- }
- else {
- snprintf(now_playing, MAX_PATH+1, "%s/%s", dirname, buf);
- return now_playing;
- }
- }
+ /* replace backslashes with forward slashes */
+ for ( i=0; i<seek; i++ )
+ if ( buf[i] == '\\' )
+ buf[i] = '/';
+
+ if('/' == buf[0]) {
+ strcpy(now_playing, &buf[0]);
+ return now_playing;
+ }
+ else {
+ strncpy(dir_buf, playlist.filename, playlist.dirlen);
+ dir_buf[playlist.dirlen] = 0;
+
+ /* handle dos style drive letter */
+ if ( ':' == buf[1] ) {
+ strcpy(now_playing, &buf[2]);
+ return now_playing;
+ }
+ else if ( '.' == buf[0] && '.' == buf[1] && '/' == buf[2] ) {
+ /* handle relative paths */
+ seek=3;
+ while(buf[seek] == '.' &&
+ buf[seek+1] == '.' &&
+ buf[seek+2] == '/')
+ seek += 3;
+ for (i=0; i<seek/3; i++) {
+ dir_end = strrchr(dir_buf, '/');
+ if (dir_end)
+ *dir_end = '\0';
+ else
+ break;
+ }
+ snprintf(now_playing, MAX_PATH+1, "%s/%s", dir_buf, &buf[seek]);
+ return now_playing;
+ }
+ else if ( '.' == buf[0] && '/' == buf[1] ) {
+ snprintf(now_playing, MAX_PATH+1, "%s/%s", dir_buf, &buf[2]);
+ return now_playing;
+ }
+ else {
+ snprintf(now_playing, MAX_PATH+1, "%s/%s", dir_buf, buf);
+ return now_playing;
+ }
}
- else
- return NULL;
}
void play_list(char *dir, char *file)
{
char *sep="";
+ int dirlen;
- lcd_clear_display();
- lcd_puts(0,0,"Loading...");
- lcd_update();
- empty_playlist(&playlist);
+ empty_playlist();
+
+ /* If file is NULL, the list is in RAM */
+ if(file) {
+ lcd_clear_display();
+ lcd_puts(0,0,"Loading...");
+ lcd_update();
+ playlist.in_ram = false;
+ } else {
+ /* Assign a dummy filename */
+ file = "";
+ playlist.in_ram = true;
+ }
- /* If the dir does not end in trailing new line, we use a separator.
+ dirlen = strlen(dir);
+
+ /* If the dir does not end in trailing slash, we use a separator.
Otherwise we don't. */
- if('/' != dir[strlen(dir)-1])
+ if('/' != dir[dirlen-1]) {
sep="/";
+ dirlen++;
+ }
+
+ playlist.dirlen = dirlen;
snprintf(playlist.filename, sizeof(playlist.filename),
"%s%s%s",
dir, sep, file);
/* add track indices to playlist data structure */
- add_indices_to_playlist(&playlist);
-
+ add_indices_to_playlist();
+
if(global_settings.playlist_shuffle) {
- lcd_puts(0,0,"Shuffling...");
- lcd_update();
- randomise_playlist( &playlist, current_tick );
+ if(!playlist.in_ram) {
+ lcd_puts(0,0,"Shuffling...");
+ lcd_update();
+ }
+ randomise_playlist( current_tick );
}
- lcd_puts(0,0,"Playing... ");
- lcd_update();
+ if(!playlist.in_ram) {
+ lcd_puts(0,0,"Playing... ");
+ lcd_update();
+ }
/* also make the first song get playing */
- mpeg_play(playlist_next(0, dir));
- sleep(HZ);
+ mpeg_play(playlist_next(0));
}
/*
* remove any filename and indices associated with the playlist
*/
-void empty_playlist( playlist_info_t *playlist )
+void empty_playlist(void)
{
- playlist->filename[0] = '\0';
- playlist->index = 0;
- playlist->amount = 0;
+ playlist.filename[0] = '\0';
+ playlist.index = 0;
+ playlist.amount = 0;
}
/*
* calculate track offsets within a playlist file
*/
-void add_indices_to_playlist( playlist_info_t *playlist )
+void add_indices_to_playlist(void)
{
int nread;
- int fd;
+ int fd = -1;
int i = 0;
int store_index = 0;
int count = 0;
int next_tick = current_tick + HZ;
- unsigned char *p;
- unsigned char buf[512];
+ unsigned char *p = playlist_buffer;
char line[16];
- fd = open(playlist->filename, O_RDONLY);
- if(-1 == fd)
- return; /* failure */
+ if(!playlist.in_ram) {
+ fd = open(playlist.filename, O_RDONLY);
+ if(-1 == fd)
+ return; /* failure */
+ }
store_index = 1;
- while((nread = read(fd, &buf, sizeof(buf))) != 0)
+ while(1)
{
- p = buf;
+ if(playlist.in_ram) {
+ nread = playlist_end_pos;
+ } else {
+ nread = read(fd, playlist_buffer, PLAYLIST_BUFFER_SIZE);
+ /* Terminate on EOF */
+ if(nread <= 0)
+ break;
+ }
+
+ p = playlist_buffer;
for(count=0; count < nread; count++,p++) {
@@ -203,36 +270,45 @@ void add_indices_to_playlist( playlist_info_t *playlist )
{
/* Store a new entry */
- playlist->indices[ playlist->amount ] = i+count;
- playlist->amount++;
- if ( playlist->amount >= MAX_PLAYLIST_SIZE ) {
- close(fd);
+ playlist.indices[ playlist.amount ] = i+count;
+ playlist.amount++;
+ if ( playlist.amount >= MAX_PLAYLIST_SIZE ) {
+ if(!playlist.in_ram)
+ close(fd);
return;
}
store_index = 0;
- if ( current_tick >= next_tick ) {
- next_tick = current_tick + HZ;
- snprintf(line, sizeof line, "%d files", playlist->amount);
- lcd_puts(0,1,line);
- lcd_update();
+ /* Update the screen if it takes very long */
+ if(!playlist.in_ram) {
+ if ( current_tick >= next_tick ) {
+ next_tick = current_tick + HZ;
+ snprintf(line, sizeof line, "%d files",
+ playlist.amount);
+ lcd_puts(0,1,line);
+ lcd_update();
+ }
}
}
}
i+= count;
- }
- snprintf(line, sizeof line, "%d files", playlist->amount);
- lcd_puts(0,1,line);
- lcd_update();
- close(fd);
+ if(playlist.in_ram)
+ break;
+ }
+ if(!playlist.in_ram) {
+ snprintf(line, sizeof line, "%d files", playlist.amount);
+ lcd_puts(0,1,line);
+ lcd_update();
+ close(fd);
+ }
}
/*
* randomly rearrange the array of indices for the playlist
*/
-void randomise_playlist( playlist_info_t *playlist, unsigned int seed )
+void randomise_playlist( unsigned int seed )
{
int count;
int candidate;
@@ -242,15 +318,15 @@ void randomise_playlist( playlist_info_t *playlist, unsigned int seed )
srand( seed );
/* randomise entire indices list */
- for(count = playlist->amount - 1; count >= 0; count--)
+ for(count = playlist.amount - 1; count >= 0; count--)
{
/* the rand is from 0 to RAND_MAX, so adjust to our value range */
candidate = rand() % (count + 1);
/* now swap the values at the 'count' and 'candidate' positions */
- store = playlist->indices[candidate];
- playlist->indices[candidate] = playlist->indices[count];
- playlist->indices[count] = store;
+ store = playlist.indices[candidate];
+ playlist.indices[candidate] = playlist.indices[count];
+ playlist.indices[count] = store;
}
}
@@ -265,11 +341,11 @@ static int compare(const void* p1, const void* p2)
/*
* sort the array of indices for the playlist
*/
-void sort_playlist( playlist_info_t *playlist )
+void sort_playlist(void)
{
- if (playlist->amount > 0)
+ if (playlist.amount > 0)
{
- qsort(&playlist->indices, playlist->amount, sizeof(playlist->indices[0]), compare);
+ qsort(&playlist.indices, playlist.amount, sizeof(playlist.indices[0]), compare);
}
}
diff --git a/apps/playlist.h b/apps/playlist.h
index 3d37c5d..a218209 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -29,20 +29,24 @@
typedef struct
{
char filename[MAX_PATH]; /* path name of m3u playlist on disk */
+ int dirlen; /* Length of the path to the playlist file */
int indices[MAX_PLAYLIST_SIZE]; /* array of indices */
int index; /* index of *NEXT* track to play */
int seed; /* random seed */
int amount; /* number of tracks in the index */
+ bool in_ram; /* True if the playlist is RAM-based */
} playlist_info_t;
-extern playlist_info_t playlist;
+//extern playlist_info_t playlist;
extern bool playlist_shuffle;
void play_list(char *dir, char *file);
-char* playlist_next(int steps, char *dirname);
-void randomise_playlist( playlist_info_t *playlist, unsigned int seed );
-void sort_playlist( playlist_info_t *playlist );
-void empty_playlist( playlist_info_t *playlist );
-void add_indices_to_playlist( playlist_info_t *playlist );
+char* playlist_next(int steps);
+void randomise_playlist( unsigned int seed );
+void sort_playlist(void);
+void empty_playlist(void);
+void add_indices_to_playlist(void);
+void playlist_clear(void);
+int playlist_add(char *filename);
#endif /* __PLAYLIST_H__ */