85 lines
3.5 KiB
Text
85 lines
3.5 KiB
Text
|
|
||
|
Playlists on the Rockbox
|
||
|
|
||
|
1. Demand-loading of Playlist Filenames from Disk
|
||
|
|
||
|
A playlist is simply a list of track names. These lists can either be
|
||
|
created dynamically by the user, or they can be predefined and placed
|
||
|
into a text file with an .m3u extension.
|
||
|
|
||
|
The 2048 KB of RAM is the reason we need to get this right. If an average
|
||
|
track name (i.e. \music\cure\disintegration\01-pictures_of_you.mp3)
|
||
|
is assumed to be 50 characters long, then:
|
||
|
|
||
|
A playlist of 15 tracks is 15 * 50 ~= 750 bytes
|
||
|
A playlist of 100 tracks is 100 * 50 ~= 5 kilobytes
|
||
|
A playlist of 3500 tracks is 3500 * 50 ~= 175 kilobytes
|
||
|
A playlist of 10000 tracks is 10000 * 50 ~= 1/4 megabyte
|
||
|
|
||
|
From these figures, it can be seen that for large playlists, storing
|
||
|
the entire list of track names in memory significantly reduces the
|
||
|
capacity available to the audio data buffer, which in turn has a negative
|
||
|
impact on the performance of the system.
|
||
|
|
||
|
One method of reducing the total memory consumption of a playlist is
|
||
|
to delay bringing the actual filenames into memory until needed. Instead,
|
||
|
the playlist text file can be scanned, and an in-memory array constructed
|
||
|
with one element for each track present in the text file. Progressing
|
||
|
through the playlist entails getting the appropriate entry from the array,
|
||
|
and using that to perform a lookup of the corresponding filename entry
|
||
|
from the playlist text file.
|
||
|
|
||
|
With this method, and given that an integer on the Rockbox's CPU is 4 bytes:
|
||
|
|
||
|
A playlist of 15 tracks is 15 * 4 ~= 60 bytes
|
||
|
A playlist of 100 tracks is 100 * 4 ~= 400 bytes
|
||
|
A playlist of 3500 tracks is 3500 * 4 ~= 13 kilobytes
|
||
|
A playlist of 10000 tracks is 10000 * 4 ~= 39 kilobytes
|
||
|
|
||
|
It is clear that these are substantial savings, albeit at the cost of
|
||
|
increased complexity and disk i/o. Prefetch strategies could improve
|
||
|
performance compared to demand-loading a single entry.
|
||
|
|
||
|
2. Implementation Options
|
||
|
|
||
|
Keeping the track names in a file on disk is easy enough for a predefined
|
||
|
m3u playlist, but for dynamically created playlists, where the user
|
||
|
browses the filesystem and adds tracks or entire directory hierarchies
|
||
|
at will, we will need to store the playlist track names in a dedicated
|
||
|
file. This will be called the Anonymous Playlist, the location of which
|
||
|
can be set by the user, but will default to \anonymous.m3u or somesuch.
|
||
|
The current contents of the Anonymous Playlist can be named and saved at
|
||
|
any time.
|
||
|
|
||
|
The data structure to support playlists would therefore be:
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
char filename[256] ; /* path name of m3u playlist on disk */
|
||
|
int *indices; /* array of indices into the playlist */
|
||
|
int index; /* index of current track within playlist */
|
||
|
} playlist_info_t;
|
||
|
|
||
|
So far, so good: we read from an existing m3u file, or we create an
|
||
|
anonymous one. But what do we do if we start with an existing m3u file,
|
||
|
and then the user wants to dynamically add tracks to it? A few options
|
||
|
exist:
|
||
|
|
||
|
a) we disallow playlist modification of existing m3u files, offering
|
||
|
instead to replace the current playlist with the new one.
|
||
|
|
||
|
b) we give the user the option of appending the new tracks to the
|
||
|
existing m3u file.
|
||
|
|
||
|
c) we copy the contents of the existing m3u playlist to the anonymous one,
|
||
|
and then append the new tracks to that. If the m3u playlist is large,
|
||
|
this could be wasteful and potentially time-consuming. However, choosing
|
||
|
this option would provide the facility to insert or append entire
|
||
|
existing m3u playlists 'into' one another, a feature missng from the
|
||
|
commercial firmware.
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|