diff options
author | Stuart Martin <mister_wavey@rockbox.org> | 2002-04-30 19:16:15 +0000 |
---|---|---|
committer | Stuart Martin <mister_wavey@rockbox.org> | 2002-04-30 19:16:15 +0000 |
commit | 16cd64236e4e01dabeafd59c6462f538788c1772 (patch) | |
tree | 01778f35f9d08ac8bc95625bbfc5d7802bb35eba /firmware/playlist.c | |
parent | 9db78d37b8f1cfdc662ecb543eec83884abafd39 (diff) | |
download | rockbox-16cd64236e4e01dabeafd59c6462f538788c1772.tar.gz rockbox-16cd64236e4e01dabeafd59c6462f538788c1772.zip |
functions for playlist manipulation
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@333 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/playlist.c')
-rw-r--r-- | firmware/playlist.c | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/firmware/playlist.c b/firmware/playlist.c new file mode 100644 index 0000000000..47764c12b6 --- /dev/null +++ b/firmware/playlist.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by wavey@wavey.org | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include <stdio.h> | ||
21 | #include <malloc.h> | ||
22 | #include <time.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <string.h> | ||
25 | #include "playlist.h" | ||
26 | #include "debug.h" | ||
27 | #include "disk.h" | ||
28 | |||
29 | /* | ||
30 | * load playlist info from disk | ||
31 | */ | ||
32 | int reload_playlist_info( playlist_info_t *playlist ) | ||
33 | { | ||
34 | debug( "reload_playlist_info()\n" ); | ||
35 | |||
36 | /* this is a TEMP stub version */ | ||
37 | |||
38 | /* return a dummy playlist entry */ | ||
39 | |||
40 | sprintf( playlist->filename, "\\playlists\\1.m3u" ); | ||
41 | |||
42 | playlist->indices_count = 4; | ||
43 | |||
44 | playlist->indices = (void *)malloc( playlist->indices_count * sizeof( int ) ); | ||
45 | |||
46 | playlist->indices[0] = 3; | ||
47 | playlist->indices[1] = 2; | ||
48 | playlist->indices[2] = 1; | ||
49 | playlist->indices[3] = 9; | ||
50 | |||
51 | playlist->index = 3; | ||
52 | |||
53 | return 1; | ||
54 | } | ||
55 | |||
56 | /* | ||
57 | * read the contents of an m3u file from disk and store | ||
58 | * the indices of each listed track in an array | ||
59 | */ | ||
60 | void load_playlist( playlist_info_t *playlist, const char *filename ) { | ||
61 | |||
62 | char *m3u_buf = NULL; | ||
63 | char debug_message[128]; | ||
64 | |||
65 | sprintf( debug_message, "load_playlist( %s )\n", filename ); | ||
66 | debug( debug_message ); | ||
67 | |||
68 | /* read file */ | ||
69 | |||
70 | read_file_into_buffer( &m3u_buf, filename ); | ||
71 | |||
72 | /* store playlist filename */ | ||
73 | |||
74 | sprintf( playlist->filename, filename ); | ||
75 | |||
76 | /* add track indices to playlist data structure */ | ||
77 | |||
78 | add_indices_to_playlist( m3u_buf, playlist ); | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * remove any filename and indices associated with the playlist | ||
83 | */ | ||
84 | void empty_playlist( playlist_info_t *playlist ) { | ||
85 | |||
86 | debug( "empty_playlist()\n" ); | ||
87 | |||
88 | playlist->filename[0] = '\0'; | ||
89 | playlist->indices_count = 0; | ||
90 | free( (void *)(playlist->indices) ); | ||
91 | playlist->indices = NULL; | ||
92 | playlist->index = 0; | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * calculate track offsets within a playlist buffer | ||
97 | */ | ||
98 | void add_indices_to_playlist( char *buf, playlist_info_t *playlist ) | ||
99 | { | ||
100 | char *p; | ||
101 | int i = 0; | ||
102 | |||
103 | /*debug( "add_indices_to_playlist()\n" ); */ | ||
104 | |||
105 | p = buf; | ||
106 | |||
107 | /* loop thru buffer, store index whenever we get a new line */ | ||
108 | |||
109 | while( p[i] != '\0' ) | ||
110 | { | ||
111 | /* move thru (any) newlines */ | ||
112 | |||
113 | while( ( p[i] != '\0' ) && ( ( p[i] == '\n' ) || ( p[i] == '\r' ) ) ) | ||
114 | { | ||
115 | i++; | ||
116 | } | ||
117 | |||
118 | /* did we get to the end of the buffer? */ | ||
119 | |||
120 | if( p[i] == '\0' ) | ||
121 | { | ||
122 | break; | ||
123 | } | ||
124 | |||
125 | /* we're now at the start of a new track filename. store index */ | ||
126 | |||
127 | extend_indices( playlist, i ); | ||
128 | |||
129 | /* we're now inside a track name. move to next newline */ | ||
130 | |||
131 | while( ( p[i] != '\0' ) && ( ( p[i] != '\n' ) && ( p[i] != '\r' ) ) ) | ||
132 | { | ||
133 | i++; | ||
134 | } | ||
135 | } | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * extend the array of ints | ||
140 | */ | ||
141 | void extend_indices( playlist_info_t *playlist, int new_index ) | ||
142 | { | ||
143 | /*sprintf( debug_message, "extend_indices(%d)\n", new_index ); | ||
144 | debug( debug_message );*/ | ||
145 | |||
146 | /* increase array size count */ | ||
147 | |||
148 | playlist->indices_count++; | ||
149 | |||
150 | /* increase size of array to new count size */ | ||
151 | |||
152 | playlist->indices = (int *)realloc( playlist->indices, (playlist->indices_count) * sizeof( int ) ); | ||
153 | |||
154 | /* add new element to end of array */ | ||
155 | |||
156 | playlist->indices[ playlist->indices_count - 1 ] = new_index; | ||
157 | } | ||
158 | |||
159 | track_t next_playlist_track( playlist_info_t *playlist ) { | ||
160 | |||
161 | track_t track; | ||
162 | sprintf( track.filename, "boogie" ); | ||
163 | return track; | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * randomly rearrange the array of indices for the playlist | ||
168 | */ | ||
169 | void randomise_playlist( playlist_info_t *playlist ) { | ||
170 | |||
171 | unsigned seed; | ||
172 | int count = 0; | ||
173 | int candidate; | ||
174 | int adjusted_candidate; | ||
175 | int found_next_number; | ||
176 | int index_list[ playlist->indices_count ]; | ||
177 | int *randomised_list; | ||
178 | int i; | ||
179 | |||
180 | debug( "randomise_playlist()\n" ); | ||
181 | |||
182 | /* create dynamic storage for randomised list so it can be freed later */ | ||
183 | |||
184 | randomised_list = (int *)malloc( playlist->indices_count * sizeof( int ) ); | ||
185 | |||
186 | /* use date as random seed */ | ||
187 | |||
188 | seed = time(0); | ||
189 | srand( seed ); | ||
190 | |||
191 | /* randomise entire indices list */ | ||
192 | |||
193 | while( count < playlist->indices_count ) | ||
194 | { | ||
195 | found_next_number = 0; | ||
196 | |||
197 | /* loop until we successfully get the next number */ | ||
198 | |||
199 | while( ! found_next_number ) | ||
200 | { | ||
201 | /* get the next random number */ | ||
202 | |||
203 | candidate = rand(); | ||
204 | |||
205 | /* the rand is from 0 to RAND_MAX, so adjust to our value range */ | ||
206 | |||
207 | adjusted_candidate = candidate % ( playlist->indices_count + 1 ); | ||
208 | |||
209 | /* has this number already been used? */ | ||
210 | |||
211 | if( is_unused_random_in_list( adjusted_candidate, index_list, playlist->indices_count ) ) | ||
212 | { | ||
213 | /* store value found at random location in original list */ | ||
214 | |||
215 | index_list[ count ] = adjusted_candidate; | ||
216 | |||
217 | /* leave loop */ | ||
218 | |||
219 | found_next_number = 1; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | /* move along */ | ||
224 | |||
225 | count++; | ||
226 | } | ||
227 | |||
228 | /* populate actual replacement list with values | ||
229 | * found at indexes specified in index_list */ | ||
230 | |||
231 | for( i = 0; i < playlist->indices_count; i++ ) | ||
232 | { | ||
233 | randomised_list[i] = playlist->indices[ index_list[ i ] ]; | ||
234 | } | ||
235 | |||
236 | /* release memory from old array */ | ||
237 | |||
238 | free( (void *)playlist->indices ); | ||
239 | |||
240 | /* use newly randomise list */ | ||
241 | |||
242 | playlist->indices = randomised_list; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * check if random number has been used previously | ||
247 | */ | ||
248 | int is_unused_random_in_list( int number, int *new_list, int count ) | ||
249 | { | ||
250 | int i = 0; | ||
251 | int *p = new_list; | ||
252 | |||
253 | /* examine all in list */ | ||
254 | |||
255 | while( i < count ) | ||
256 | { | ||
257 | /* did we find the number in the list already? */ | ||
258 | |||
259 | if( p[i] == number ) | ||
260 | { | ||
261 | /* yes - return false */ | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | /* move along list */ | ||
267 | |||
268 | i++; | ||
269 | } | ||
270 | |||
271 | /* if we got here, we didn't find the number. return true */ | ||
272 | |||
273 | return 1; | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * dump the details of a track to stdout | ||
278 | */ | ||
279 | void display_playlist_track( track_t *track ) | ||
280 | { | ||
281 | debugf( "track: %s\n", track->filename ); | ||
282 | } | ||
283 | |||
284 | /* | ||
285 | * dump the current playlist info | ||
286 | */ | ||
287 | void display_current_playlist( playlist_info_t *playlist ) | ||
288 | { | ||
289 | char indices[2048]; | ||
290 | indices[0]='\0'; | ||
291 | |||
292 | /*debug( "\ndisplay_current_playlist()\n" ); */ | ||
293 | |||
294 | if( playlist->indices_count != 0 ) | ||
295 | { | ||
296 | get_indices_as_string( indices, playlist ); | ||
297 | } | ||
298 | |||
299 | debugf( "\nfilename:\t%s\ntotal:\t\t%d\nindices:\t%s\ncurrent index:\t%d\n\n", | ||
300 | playlist->filename, | ||
301 | playlist->indices_count, | ||
302 | indices, | ||
303 | playlist->index ); | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | * produce a string of the playlist indices | ||
308 | */ | ||
309 | void get_indices_as_string( char *string, playlist_info_t *playlist ) | ||
310 | { | ||
311 | char tmp[8]; | ||
312 | int count = 0; | ||
313 | int *p = playlist->indices; | ||
314 | |||
315 | /*debug( "get_indices_as_string()\n" ); */ | ||
316 | |||
317 | while( count < playlist->indices_count ) { | ||
318 | |||
319 | if( strlen( string ) == 0 ) | ||
320 | { | ||
321 | /* first iteration - no comma */ | ||
322 | |||
323 | sprintf( tmp, "%d", p[count] ); | ||
324 | } | ||
325 | else | ||
326 | { | ||
327 | /* normal iteration - insert comma */ | ||
328 | |||
329 | sprintf( tmp, ",%d", p[count] ); | ||
330 | } | ||
331 | |||
332 | strcat( string, tmp ); | ||
333 | |||
334 | count++; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | /* | ||
339 | Session Start (devlin.openprojects.net:alan): Thu Apr 25 15:13:27 2002 | ||
340 | <alan> for shuffle mode, it's really easy to use the array as a random stack | ||
341 | <alan> just peek one randomly and exchange it with the last element in the stack | ||
342 | <alan> when stack is void, just grow the stack with its initial size : elements are still there but in a random order | ||
343 | <alan> note : | ||
344 | <alan> a stack is void when all songs were played | ||
345 | <alan> it is an O(1) algo | ||
346 | <alan> i don't see how you can do it with a list | ||
347 | */ | ||
348 | |||
349 | |||