diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2005-07-02 16:52:30 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2005-07-02 16:52:30 +0000 |
commit | d54811fe22c274ed31d897864ac0a33349f460e0 (patch) | |
tree | b8c7928c46c4989f43eb1b63db07408daa70b4bb | |
parent | a8cadd8181e53320109d2af61f0c7edea262d325 (diff) | |
download | rockbox-d54811fe22c274ed31d897864ac0a33349f460e0.tar.gz rockbox-d54811fe22c274ed31d897864ac0a33349f460e0.zip |
Fixed mono playback support for mp3. Added two other event handlers in
playback.c.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6986 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/codecs/mpa.c | 56 | ||||
-rw-r--r-- | apps/dsp.c | 20 | ||||
-rw-r--r-- | apps/playback.c | 96 | ||||
-rw-r--r-- | apps/playback.h | 5 |
4 files changed, 139 insertions, 38 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c index f2fd8a6e2b..a52dc12a40 100644 --- a/apps/codecs/mpa.c +++ b/apps/codecs/mpa.c | |||
@@ -57,15 +57,6 @@ extern char iramstart[]; | |||
57 | extern char iramend[]; | 57 | extern char iramend[]; |
58 | #endif | 58 | #endif |
59 | 59 | ||
60 | /* | ||
61 | long resample(long *in, long *out, int num, struct resampler *s) | ||
62 | { | ||
63 | if (s->delta >= (1 << 16)) | ||
64 | return downsample(in, out, num, s); | ||
65 | else | ||
66 | return upsample(in, out, num, s); | ||
67 | } | ||
68 | */ | ||
69 | /* this is the codec entry point */ | 60 | /* this is the codec entry point */ |
70 | enum codec_status codec_start(struct codec_api* api) | 61 | enum codec_status codec_start(struct codec_api* api) |
71 | { | 62 | { |
@@ -79,9 +70,10 @@ enum codec_status codec_start(struct codec_api* api) | |||
79 | unsigned int samplesdone; | 70 | unsigned int samplesdone; |
80 | bool first_frame; | 71 | bool first_frame; |
81 | int stop_skip, start_skip; | 72 | int stop_skip, start_skip; |
82 | // struct resampler lr = { 0, 0, 0 }, rr = { 0, 0, 0 }; | 73 | int current_stereo_mode = -1; |
74 | int frequency_divider; | ||
75 | |||
83 | /* Generic codec inititialisation */ | 76 | /* Generic codec inititialisation */ |
84 | |||
85 | TEST_CODEC_API(api); | 77 | TEST_CODEC_API(api); |
86 | 78 | ||
87 | #ifdef USE_IRAM | 79 | #ifdef USE_IRAM |
@@ -102,7 +94,6 @@ enum codec_status codec_start(struct codec_api* api) | |||
102 | ci->configure(DSP_SET_CLIP_MAX, (int *)(MAD_F_ONE - 1)); | 94 | ci->configure(DSP_SET_CLIP_MAX, (int *)(MAD_F_ONE - 1)); |
103 | ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(MAD_F_FRACBITS)); | 95 | ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(MAD_F_FRACBITS)); |
104 | ci->configure(DSP_DITHER, (bool *)false); | 96 | ci->configure(DSP_DITHER, (bool *)false); |
105 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED); | ||
106 | ci->configure(CODEC_DSP_ENABLE, (bool *)true); | 97 | ci->configure(CODEC_DSP_ENABLE, (bool *)true); |
107 | 98 | ||
108 | ci->memset(&Stream, 0, sizeof(struct mad_stream)); | 99 | ci->memset(&Stream, 0, sizeof(struct mad_stream)); |
@@ -128,6 +119,7 @@ enum codec_status codec_start(struct codec_api* api) | |||
128 | first_frame = false; | 119 | first_frame = false; |
129 | file_end = 0; | 120 | file_end = 0; |
130 | OutputPtr = OutputBuffer; | 121 | OutputPtr = OutputBuffer; |
122 | frequency_divider = ci->id3->frequency / 100; | ||
131 | 123 | ||
132 | while (!*ci->taginfo_ready) | 124 | while (!*ci->taginfo_ready) |
133 | ci->yield(); | 125 | ci->yield(); |
@@ -154,16 +146,16 @@ enum codec_status codec_start(struct codec_api* api) | |||
154 | /* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3, | 146 | /* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3, |
155 | it's probably not correct at all for MPEG2 and layer 1 */ | 147 | it's probably not correct at all for MPEG2 and layer 1 */ |
156 | samplecount = info->frame_count*1152 - (start_skip + stop_skip); | 148 | samplecount = info->frame_count*1152 - (start_skip + stop_skip); |
157 | samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10; | 149 | samplesdone = ci->id3->elapsed * frequency_divider / 10; |
158 | } else { | 150 | } else { |
159 | samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10; | 151 | samplecount = ci->id3->length * frequency_divider / 10; |
160 | samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10; | 152 | samplesdone = ci->id3->elapsed * frequency_divider / 10; |
161 | } | 153 | } |
162 | 154 | ||
163 | /* This is the decoding loop. */ | 155 | /* This is the decoding loop. */ |
164 | while (1) { | 156 | while (1) { |
165 | ci->yield(); | 157 | ci->yield(); |
166 | if (ci->stop_codec || ci->reload_codec) { | 158 | if (ci->stop_codec || ci->reload_codec) { |
167 | break ; | 159 | break ; |
168 | } | 160 | } |
169 | 161 | ||
@@ -171,11 +163,12 @@ enum codec_status codec_start(struct codec_api* api) | |||
171 | unsigned int sample_loc; | 163 | unsigned int sample_loc; |
172 | int newpos; | 164 | int newpos; |
173 | 165 | ||
174 | sample_loc = ci->seek_time/1000 * ci->id3->frequency; | 166 | sample_loc = ci->seek_time * frequency_divider / 10; |
175 | newpos = ci->mp3_get_filepos(ci->seek_time-1); | 167 | newpos = ci->mp3_get_filepos(ci->seek_time-1); |
168 | if (sample_loc >= samplecount + samplesdone) | ||
169 | break ; | ||
170 | |||
176 | if (ci->seek_buffer(newpos)) { | 171 | if (ci->seek_buffer(newpos)) { |
177 | if (sample_loc >= samplecount + samplesdone) | ||
178 | break ; | ||
179 | samplecount += samplesdone - sample_loc; | 172 | samplecount += samplesdone - sample_loc; |
180 | samplesdone = sample_loc; | 173 | samplesdone = sample_loc; |
181 | } | 174 | } |
@@ -232,17 +225,28 @@ enum codec_status codec_start(struct codec_api* api) | |||
232 | /* We skip start_skip number of samples here, this should only happen for | 225 | /* We skip start_skip number of samples here, this should only happen for |
233 | very first frame in the stream. */ | 226 | very first frame in the stream. */ |
234 | /* TODO: possible for start_skip to exceed one frames worth of samples? */ | 227 | /* TODO: possible for start_skip to exceed one frames worth of samples? */ |
235 | //length = resample((long *)&Synth.pcm.samples[0][start_skip], resampled_data[0], Synth.pcm.length, &lr); | 228 | |
236 | //if (MAD_NCHANNELS(&Frame.header) == 2) | 229 | if (MAD_NCHANNELS(&Frame.header) == 2) { |
237 | // resample((long *)&Synth.pcm.samples[1][start_skip], resampled_data[1], Synth.pcm.length, &rr); | 230 | if (current_stereo_mode != STEREO_NONINTERLEAVED) { |
238 | ci->audiobuffer_insert_split(&Synth.pcm.samples[0][start_skip], | 231 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED); |
239 | &Synth.pcm.samples[1][start_skip], | 232 | current_stereo_mode = STEREO_NONINTERLEAVED; |
240 | (Synth.pcm.length - start_skip) * 4); | 233 | } |
234 | ci->audiobuffer_insert_split(&Synth.pcm.samples[0][start_skip], | ||
235 | &Synth.pcm.samples[1][start_skip], | ||
236 | (Synth.pcm.length - start_skip) * 4); | ||
237 | } else { | ||
238 | if (current_stereo_mode != STEREO_MONO) { | ||
239 | ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_MONO); | ||
240 | current_stereo_mode = STEREO_MONO; | ||
241 | } | ||
242 | ci->audiobuffer_insert((char *)&Synth.pcm.samples[0][start_skip], | ||
243 | (Synth.pcm.length - start_skip) * 4); | ||
244 | } | ||
241 | start_skip = 0; /* not very elegant, and might want to keep this value */ | 245 | start_skip = 0; /* not very elegant, and might want to keep this value */ |
242 | 246 | ||
243 | samplesdone += Synth.pcm.length; | 247 | samplesdone += Synth.pcm.length; |
244 | samplecount -= Synth.pcm.length; | 248 | samplecount -= Synth.pcm.length; |
245 | ci->set_elapsed(samplesdone / (ci->id3->frequency/1000)); | 249 | ci->set_elapsed(samplesdone / (frequency_divider / 10)); |
246 | } | 250 | } |
247 | 251 | ||
248 | Stream.error = 0; | 252 | Stream.error = 0; |
diff --git a/apps/dsp.c b/apps/dsp.c index 56ebacb24c..b24e261371 100644 --- a/apps/dsp.c +++ b/apps/dsp.c | |||
@@ -269,7 +269,6 @@ void convert_stereo_mode(long *dest, long *src, int samplecount) | |||
269 | } | 269 | } |
270 | } | 270 | } |
271 | 271 | ||
272 | /* Not yet functional. */ | ||
273 | void scale_up(long *dest, short *src, int samplecount) | 272 | void scale_up(long *dest, short *src, int samplecount) |
274 | { | 273 | { |
275 | int i; | 274 | int i; |
@@ -287,8 +286,6 @@ void scale_up_convert_stereo_mode(long *dest, short *src, int samplecount) | |||
287 | for (i = 0; i < samplecount; i++) { | 286 | for (i = 0; i < samplecount; i++) { |
288 | dest[i] = (long)(src[i*2+0] << SAMPLE_DEPTH); | 287 | dest[i] = (long)(src[i*2+0] << SAMPLE_DEPTH); |
289 | dest[i+samplecount] = (long)(src[i*2+1] << SAMPLE_DEPTH); | 288 | dest[i+samplecount] = (long)(src[i*2+1] << SAMPLE_DEPTH); |
290 | //dest[i] = (long)(((src[i*2 + 0] << 8)&0x7fff) | ((1L << 31) & src[i*2+0]<<15)); | ||
291 | //dest[i+samplecount] = (long)(((src[i*2 + 1] << 8)&0x7fff) | ((1L << 31) & src[i*2+1]<<15)); | ||
292 | } | 289 | } |
293 | } | 290 | } |
294 | 291 | ||
@@ -307,21 +304,22 @@ int dsp_process(char *dest, char *src, int samplecount) | |||
307 | p = src; | 304 | p = src; |
308 | /* Scale up to 32-bit samples. */ | 305 | /* Scale up to 32-bit samples. */ |
309 | if (dsp_config.sample_depth <= SAMPLE_DEPTH) { | 306 | if (dsp_config.sample_depth <= SAMPLE_DEPTH) { |
310 | if (dsp_config.stereo_mode == STEREO_INTERLEAVED) | 307 | if (dsp_config.stereo_mode == STEREO_INTERLEAVED) { |
311 | scale_up_convert_stereo_mode((long *)samplebuf, | 308 | scale_up_convert_stereo_mode((long *)samplebuf, |
312 | (short *)p, copy_n); | 309 | (short *)p, copy_n); |
313 | else | 310 | } else { |
314 | scale_up((long *)samplebuf, (short *)p, copy_n); | 311 | scale_up((long *)samplebuf, (short *)p, copy_n); |
312 | } | ||
315 | p = samplebuf; | 313 | p = samplebuf; |
316 | fracbits = 31; | 314 | fracbits = 31; |
317 | } | 315 | } |
318 | 316 | ||
319 | /* Convert to non-interleaved stereo. */ | 317 | /* Convert to non-interleaved stereo. */ |
320 | else if (dsp_config.stereo_mode == STEREO_INTERLEAVED) { | 318 | else if (dsp_config.stereo_mode == STEREO_INTERLEAVED) { |
321 | convert_stereo_mode((long *)samplebuf, (long *)p, copy_n); | 319 | convert_stereo_mode((long *)samplebuf, (long *)p, copy_n / 2); |
322 | p = samplebuf; | 320 | p = samplebuf; |
323 | } | 321 | } |
324 | 322 | ||
325 | /* Apply DSP functions. */ | 323 | /* Apply DSP functions. */ |
326 | if (dsp_config.stereo_mode == STEREO_INTERLEAVED) { | 324 | if (dsp_config.stereo_mode == STEREO_INTERLEAVED) { |
327 | channel = 0; | 325 | channel = 0; |
@@ -330,6 +328,12 @@ int dsp_process(char *dest, char *src, int samplecount) | |||
330 | channel = 1; | 328 | channel = 1; |
331 | process((short *)dest, (long *)p, copy_n / 2); | 329 | process((short *)dest, (long *)p, copy_n / 2); |
332 | dest += rc; | 330 | dest += rc; |
331 | } else if (dsp_config.stereo_mode == STEREO_MONO) { | ||
332 | channel = 0; | ||
333 | rc = process((short *)dest, (long *)p, copy_n) * 4; | ||
334 | channel = 1; | ||
335 | process((short *)dest, (long *)p, copy_n); | ||
336 | dest += rc; | ||
333 | } else { | 337 | } else { |
334 | rc = process((short *)dest, (long *)p, copy_n) * 2; | 338 | rc = process((short *)dest, (long *)p, copy_n) * 2; |
335 | dest += rc * 2; | 339 | dest += rc * 2; |
diff --git a/apps/playback.c b/apps/playback.c index 70cb36341b..3a5eeb328f 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -165,6 +165,8 @@ static int new_track; | |||
165 | 165 | ||
166 | /* Callback function to call when current track has really changed. */ | 166 | /* Callback function to call when current track has really changed. */ |
167 | void (*track_changed_callback)(struct track_info *ti); | 167 | void (*track_changed_callback)(struct track_info *ti); |
168 | void (*track_buffer_callback)(struct mp3entry *id3, bool last_track); | ||
169 | void (*track_unbuffer_callback)(struct mp3entry *id3, bool disk_spinning); | ||
168 | 170 | ||
169 | /* Configuration */ | 171 | /* Configuration */ |
170 | static int conf_bufferlimit; | 172 | static int conf_bufferlimit; |
@@ -266,10 +268,14 @@ bool codec_audiobuffer_insert_callback(char *buf, long length) | |||
266 | int factor; | 268 | int factor; |
267 | int next_channel = 0; | 269 | int next_channel = 0; |
268 | int processed_length; | 270 | int processed_length; |
271 | int mono = 0; | ||
269 | 272 | ||
270 | /* If non-interleaved stereo mode. */ | 273 | /* If non-interleaved stereo mode. */ |
271 | if (dsp_config.stereo_mode == STEREO_NONINTERLEAVED) { | 274 | if (dsp_config.stereo_mode == STEREO_NONINTERLEAVED) |
272 | next_channel = length / 2; | 275 | next_channel = length / 2; |
276 | else if (dsp_config.stereo_mode == STEREO_MONO) { | ||
277 | length *= 2; | ||
278 | mono = 1; | ||
273 | } | 279 | } |
274 | 280 | ||
275 | if (dsp_config.sample_depth > 16) { | 281 | if (dsp_config.sample_depth > 16) { |
@@ -296,11 +302,11 @@ bool codec_audiobuffer_insert_callback(char *buf, long length) | |||
296 | processed_length = dsp_process(dest, buf, realsize / 4) * 2; | 302 | processed_length = dsp_process(dest, buf, realsize / 4) * 2; |
297 | dsp_process(dest, buf + next_channel, realsize / 4); | 303 | dsp_process(dest, buf + next_channel, realsize / 4); |
298 | } else { | 304 | } else { |
299 | processed_length = dsp_process(dest, buf, realsize / 2); | 305 | processed_length = dsp_process(dest, buf, realsize >> (mono + 1)); |
300 | } | 306 | } |
301 | pcm_flush_buffer(processed_length); | 307 | pcm_flush_buffer(processed_length); |
302 | length -= realsize; | 308 | length -= realsize; |
303 | buf += realsize << factor; | 309 | buf += realsize << (factor + mono); |
304 | } | 310 | } |
305 | 311 | ||
306 | return true; | 312 | return true; |
@@ -589,6 +595,18 @@ void codec_configure_callback(int setting, void *value) | |||
589 | } | 595 | } |
590 | } | 596 | } |
591 | 597 | ||
598 | void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3, | ||
599 | bool last_track)) | ||
600 | { | ||
601 | track_buffer_callback = handler; | ||
602 | } | ||
603 | |||
604 | void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3, | ||
605 | bool disk_spinning)) | ||
606 | { | ||
607 | track_unbuffer_callback = handler; | ||
608 | } | ||
609 | |||
592 | void audio_set_track_changed_event(void (*handler)(struct track_info *ti)) | 610 | void audio_set_track_changed_event(void (*handler)(struct track_info *ti)) |
593 | { | 611 | { |
594 | track_changed_callback = handler; | 612 | track_changed_callback = handler; |
@@ -934,6 +952,10 @@ void audio_play_start(int offset) | |||
934 | last_peek_offset = 0; | 952 | last_peek_offset = 0; |
935 | if (audio_load_track(offset, true, 0)) { | 953 | if (audio_load_track(offset, true, 0)) { |
936 | last_peek_offset++; | 954 | last_peek_offset++; |
955 | if (track_buffer_callback) { | ||
956 | cur_ti->event_sent = true; | ||
957 | track_buffer_callback(&cur_ti->id3, true); | ||
958 | } | ||
937 | ata_sleep(); | 959 | ata_sleep(); |
938 | } else { | 960 | } else { |
939 | logf("Failure"); | 961 | logf("Failure"); |
@@ -950,10 +972,46 @@ void audio_clear_track_entries(void) | |||
950 | for (i = 0; i < MAX_TRACK - track_count; i++) { | 972 | for (i = 0; i < MAX_TRACK - track_count; i++) { |
951 | if (++cur_idx >= MAX_TRACK) | 973 | if (++cur_idx >= MAX_TRACK) |
952 | cur_idx = 0; | 974 | cur_idx = 0; |
975 | |||
976 | /* Send event to notify that track has finished. */ | ||
977 | if (track_unbuffer_callback && tracks[cur_idx].event_sent) | ||
978 | track_unbuffer_callback(&tracks[cur_idx].id3, filling); | ||
953 | memset(&tracks[cur_idx], 0, sizeof(struct track_info)); | 979 | memset(&tracks[cur_idx], 0, sizeof(struct track_info)); |
954 | } | 980 | } |
955 | } | 981 | } |
956 | 982 | ||
983 | /* Send callback events to notify about new tracks. */ | ||
984 | static void generate_postbuffer_events(void) | ||
985 | { | ||
986 | int i; | ||
987 | int cur_ridx, event_count; | ||
988 | |||
989 | if (!track_buffer_callback) | ||
990 | return ; | ||
991 | |||
992 | /* At first determine how many unsent events we have. */ | ||
993 | cur_ridx = track_ridx; | ||
994 | event_count = 0; | ||
995 | for (i = 0; i < track_count; i++) { | ||
996 | if (!tracks[cur_ridx].event_sent) | ||
997 | event_count++; | ||
998 | if (++cur_ridx >= MAX_TRACK) | ||
999 | cur_ridx -= MAX_TRACK; | ||
1000 | } | ||
1001 | |||
1002 | /* Now sent these events. */ | ||
1003 | cur_ridx = track_ridx; | ||
1004 | for (i = 0; i < track_count; i++) { | ||
1005 | if (!tracks[cur_ridx].event_sent) { | ||
1006 | tracks[cur_ridx].event_sent = true; | ||
1007 | event_count--; | ||
1008 | track_buffer_callback(&tracks[cur_ridx].id3, event_count == 0); | ||
1009 | } | ||
1010 | if (++cur_ridx >= MAX_TRACK) | ||
1011 | cur_ridx -= MAX_TRACK; | ||
1012 | } | ||
1013 | } | ||
1014 | |||
957 | void initialize_buffer_fill(void) | 1015 | void initialize_buffer_fill(void) |
958 | { | 1016 | { |
959 | int cur_idx, i; | 1017 | int cur_idx, i; |
@@ -1014,6 +1072,7 @@ void audio_check_buffer(void) | |||
1014 | if (audio_load_track(0, false, last_peek_offset)) { | 1072 | if (audio_load_track(0, false, last_peek_offset)) { |
1015 | last_peek_offset++; | 1073 | last_peek_offset++; |
1016 | } else if (tracks[track_widx].filerem == 0 || fill_bytesleft == 0) { | 1074 | } else if (tracks[track_widx].filerem == 0 || fill_bytesleft == 0) { |
1075 | generate_postbuffer_events(); | ||
1017 | filling = false; | 1076 | filling = false; |
1018 | conf_bufferlimit = 0; | 1077 | conf_bufferlimit = 0; |
1019 | pcm_set_boost_mode(false); | 1078 | pcm_set_boost_mode(false); |
@@ -1069,6 +1128,8 @@ void audio_change_track(void) | |||
1069 | logf("No more tracks"); | 1128 | logf("No more tracks"); |
1070 | while (pcm_is_playing()) | 1129 | while (pcm_is_playing()) |
1071 | yield(); | 1130 | yield(); |
1131 | track_count = 0; | ||
1132 | audio_clear_track_entries(); | ||
1072 | playing = false; | 1133 | playing = false; |
1073 | return ; | 1134 | return ; |
1074 | } | 1135 | } |
@@ -1206,6 +1267,8 @@ void audio_thread(void) | |||
1206 | } | 1267 | } |
1207 | pcm_play_stop(); | 1268 | pcm_play_stop(); |
1208 | pcm_play_pause(true); | 1269 | pcm_play_pause(true); |
1270 | track_count = 0; | ||
1271 | audio_clear_track_entries(); | ||
1209 | break ; | 1272 | break ; |
1210 | 1273 | ||
1211 | case AUDIO_PAUSE: | 1274 | case AUDIO_PAUSE: |
@@ -1233,6 +1296,8 @@ void audio_thread(void) | |||
1233 | 1296 | ||
1234 | #ifndef SIMULATOR | 1297 | #ifndef SIMULATOR |
1235 | case SYS_USB_CONNECTED: | 1298 | case SYS_USB_CONNECTED: |
1299 | track_count = 0; | ||
1300 | audio_clear_track_entries(); | ||
1236 | playing = false; | 1301 | playing = false; |
1237 | filling = false; | 1302 | filling = false; |
1238 | ci.stop_codec = true; | 1303 | ci.stop_codec = true; |
@@ -1269,6 +1334,8 @@ void codec_thread(void) | |||
1269 | codecsize = cur_ti->codecsize; | 1334 | codecsize = cur_ti->codecsize; |
1270 | if (codecsize == 0) { | 1335 | if (codecsize == 0) { |
1271 | logf("Codec slot is empty!"); | 1336 | logf("Codec slot is empty!"); |
1337 | track_count = 0; | ||
1338 | audio_clear_track_entries(); | ||
1272 | playing = false; | 1339 | playing = false; |
1273 | break ; | 1340 | break ; |
1274 | } | 1341 | } |
@@ -1296,6 +1363,8 @@ void codec_thread(void) | |||
1296 | if (status != CODEC_OK) { | 1363 | if (status != CODEC_OK) { |
1297 | logf("Codec failure"); | 1364 | logf("Codec failure"); |
1298 | splash(HZ*2, true, "Codec failure"); | 1365 | splash(HZ*2, true, "Codec failure"); |
1366 | track_count = 0; | ||
1367 | audio_clear_track_entries(); | ||
1299 | playing = false; | 1368 | playing = false; |
1300 | } else { | 1369 | } else { |
1301 | logf("Codec finished"); | 1370 | logf("Codec finished"); |
@@ -1597,6 +1666,18 @@ void mpeg_id3_options(bool _v1first) | |||
1597 | v1first = _v1first; | 1666 | v1first = _v1first; |
1598 | } | 1667 | } |
1599 | 1668 | ||
1669 | /* | ||
1670 | void test_buffer_event(struct mp3entry *id3, bool last_track) | ||
1671 | { | ||
1672 | logf("be:%d%s", last_track, id3->title); | ||
1673 | } | ||
1674 | |||
1675 | void test_unbuffer_event(struct mp3entry *id3, bool disk_spinning) | ||
1676 | { | ||
1677 | logf("ube:%d%s", disk_spinning, id3->title); | ||
1678 | } | ||
1679 | */ | ||
1680 | |||
1600 | void audio_init(void) | 1681 | void audio_init(void) |
1601 | { | 1682 | { |
1602 | logf("audio api init"); | 1683 | logf("audio api init"); |
@@ -1611,12 +1692,19 @@ void audio_init(void) | |||
1611 | paused = false; | 1692 | paused = false; |
1612 | track_changed = false; | 1693 | track_changed = false; |
1613 | current_fd = -1; | 1694 | current_fd = -1; |
1695 | track_buffer_callback = NULL; | ||
1696 | track_unbuffer_callback = NULL; | ||
1614 | track_changed_callback = NULL; | 1697 | track_changed_callback = NULL; |
1615 | 1698 | ||
1616 | logf("abuf:%0x", PCMBUF_SIZE); | 1699 | logf("abuf:%0x", PCMBUF_SIZE); |
1617 | logf("fbuf:%0x", codecbuflen); | 1700 | logf("fbuf:%0x", codecbuflen); |
1618 | logf("mbuf:%0x", MALLOC_BUFSIZE); | 1701 | logf("mbuf:%0x", MALLOC_BUFSIZE); |
1619 | 1702 | ||
1703 | /* | ||
1704 | audio_set_track_buffer_event(test_buffer_event); | ||
1705 | audio_set_track_unbuffer_event(test_unbuffer_event); | ||
1706 | */ | ||
1707 | |||
1620 | /* Initialize codec api. */ | 1708 | /* Initialize codec api. */ |
1621 | ci.read_filebuf = codec_filebuf_callback; | 1709 | ci.read_filebuf = codec_filebuf_callback; |
1622 | ci.audiobuffer_insert = pcm_insert_buffer; | 1710 | ci.audiobuffer_insert = pcm_insert_buffer; |
diff --git a/apps/playback.h b/apps/playback.h index 5cebfa84b3..8148a3445c 100644 --- a/apps/playback.h +++ b/apps/playback.h | |||
@@ -58,10 +58,15 @@ struct track_info { | |||
58 | volatile int available; /* Available bytes to read from buffer */ | 58 | volatile int available; /* Available bytes to read from buffer */ |
59 | bool taginfo_ready; /* Is metadata read */ | 59 | bool taginfo_ready; /* Is metadata read */ |
60 | int playlist_offset; /* File location in playlist */ | 60 | int playlist_offset; /* File location in playlist */ |
61 | bool event_sent; /* Has event callback functions been called? */ | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | /* Functions */ | 64 | /* Functions */ |
64 | void audio_set_track_changed_event(void (*handler)(struct track_info *ti)); | 65 | void audio_set_track_changed_event(void (*handler)(struct track_info *ti)); |
66 | void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3, | ||
67 | bool last_track)); | ||
68 | void audio_set_track_unbufer_event(void (*handler)(struct mp3entry *id3, | ||
69 | bool disk_spinning)); | ||
65 | void audio_invalidate_tracks(void); | 70 | void audio_invalidate_tracks(void); |
66 | 71 | ||
67 | #endif | 72 | #endif |