rockbox/firmware/playlist.c
Daniel Stenberg a68445f2b0 Changed how indices are read from a playlist. We just can't read the full
file into memory first, and then scan for newlines. The file might be very
big. This version instead scans through the file. This could probably be
further improved too, to not use this read-single-bytes approach.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@442 a1c6a512-1295-4272-9138-f99709370657
2002-05-05 11:59:14 +00:00

260 lines
6.6 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by wavey@wavey.org
*
* 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 <stdio.h>
#include <malloc.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include "playlist.h"
#include "debug.h"
#include <file.h>
/*
* load playlist info from disk
*/
int reload_playlist_info( playlist_info_t *playlist )
{
DEBUGF( "reload_playlist_info()\n" );
/* this is a TEMP stub version */
/* return a dummy playlist entry */
strncpy( playlist->filename, "test.m3u", sizeof(playlist->filename) );
playlist->indices_count = 4;
playlist->indices = (void *)malloc( playlist->indices_count * sizeof( int ) );
playlist->indices[0] = 3;
playlist->indices[1] = 2;
playlist->indices[2] = 1;
playlist->indices[3] = 9;
playlist->index = 3;
return 1;
}
/*
* read the contents of an m3u file from disk and store
* the indices of each listed track in an array
*/
void load_playlist( playlist_info_t *playlist, const char *filename ) {
DEBUGF( "load_playlist( %s )\n", filename );
/* store playlist filename */
strncpy( playlist->filename, filename, sizeof(playlist->filename) );
/* add track indices to playlist data structure */
add_indices_to_playlist( playlist );
}
/*
* remove any filename and indices associated with the playlist
*/
void empty_playlist( playlist_info_t *playlist ) {
DEBUGF( "empty_playlist()\n" );
playlist->filename[0] = '\0';
playlist->indices_count = 0;
free( (void *)(playlist->indices) );
playlist->indices = NULL;
playlist->index = 0;
}
/*
* calculate track offsets within a playlist file
*/
void add_indices_to_playlist( playlist_info_t *playlist )
{
char *p;
int i = 0;
unsigned char byte;
unsigned char lastbyte='\n';
int nread;
int fd;
fd = open(playlist->filename, O_RDONLY);
if(-1 == fd)
return; /* failure */
/*DEBUGF( "add_indices_to_playlist()\n" ); */
p = &byte;
/* loop thru buffer, store index whenever we get a new line */
while((nread = read(fd, &byte, 1)) == 1)
{
/* move thru (any) newlines */
if(( byte != '\n' ) && ( byte != '\r' ) &&
((lastbyte == '\n') || (lastbyte == '\r')))
/* we're now at the start of a new track filename. store index */
extend_indices( playlist, i );
lastbyte = byte;
i++;
}
close(fd);
}
/*
* extend the array of ints
*/
void extend_indices( playlist_info_t *playlist, int new_index )
{
/*DEBUGF( "extend_indices(%d)\n", new_index ); */
/* increase array size count */
playlist->indices_count++;
/* increase size of array to new count size */
playlist->indices = (int *)realloc( playlist->indices, (playlist->indices_count) * sizeof( int ) );
/* add new element to end of array */
playlist->indices[ playlist->indices_count - 1 ] = new_index;
}
track_t next_playlist_track( playlist_info_t *playlist )
{
track_t track;
strncpy( track.filename, "boogie", sizeof(track.filename) );
return track;
}
/*
* randomly rearrange the array of indices for the playlist
*/
void randomise_playlist( playlist_info_t *playlist, unsigned int seed )
{
int count = 0;
int candidate;
int store;
DEBUGF( "randomise_playlist()\n" );
/* seed with the given seed */
srand( seed );
/* randomise entire indices list */
while( count < playlist->indices_count )
{
/* the rand is from 0 to RAND_MAX, so adjust to our value range */
candidate = rand() % ( playlist->indices_count );
/* now swap the values at the 'count' and 'candidate' positions */
store = playlist->indices[candidate];
playlist->indices[candidate] = playlist->indices[count];
playlist->indices[count] = store;
/* move along */
count++;
}
}
/*
* dump the details of a track to stdout
*/
void display_playlist_track( track_t *track )
{
DEBUGF( "track: %s\n", track->filename );
}
/*
* dump the current playlist info
*/
void display_current_playlist( playlist_info_t *playlist )
{
char indices[2048];
indices[0]='\0';
/*DEBUGF( "\ndisplay_current_playlist()\n" ); */
if( playlist->indices_count != 0 )
{
get_indices_as_string( indices, playlist );
}
DEBUGF( "\nfilename:\t%s\ntotal:\t\t%d\nindices:\t%s\ncurrent index:\t%d\n\n",
playlist->filename,
playlist->indices_count,
indices,
playlist->index );
}
/*
* produce a string of the playlist indices
*/
void get_indices_as_string( char *string, playlist_info_t *playlist )
{
char tmp[8];
int count = 0;
int *p = playlist->indices;
/*DEBUGF( "get_indices_as_string()\n" ); */
while( count < playlist->indices_count ) {
if( strlen( string ) == 0 )
{
/* first iteration - no comma */
snprintf( tmp, sizeof(tmp), "%d", p[count] );
}
else
{
/* normal iteration - insert comma */
snprintf( tmp, sizeof(tmp), ",%d", p[count] );
}
strcat( string, tmp );
count++;
}
}
/*
Session Start (devlin.openprojects.net:alan): Thu Apr 25 15:13:27 2002
<alan> for shuffle mode, it's really easy to use the array as a random stack
<alan> just peek one randomly and exchange it with the last element in the stack
<alan> when stack is void, just grow the stack with its initial size : elements are still there but in a random order
<alan> note :
<alan> a stack is void when all songs were played
<alan> it is an O(1) algo
<alan> i don't see how you can do it with a list
*/
/* -----------------------------------------------------------------
* local variables:
* eval: (load-file "rockbox-mode.el")
* end:
*/