summaryrefslogtreecommitdiff
path: root/apps/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'apps/codecs')
-rw-r--r--apps/codecs/a52.c53
-rw-r--r--apps/codecs/a52_rm.c77
-rw-r--r--apps/codecs/aac.c62
-rw-r--r--apps/codecs/adx.c40
-rw-r--r--apps/codecs/aiff.c108
-rw-r--r--apps/codecs/aiff_enc.c54
-rw-r--r--apps/codecs/alac.c188
-rw-r--r--apps/codecs/ape.c54
-rw-r--r--apps/codecs/asap.c32
-rw-r--r--apps/codecs/atrac3_oma.c136
-rw-r--r--apps/codecs/atrac3_rm.c67
-rw-r--r--apps/codecs/au.c80
-rw-r--r--apps/codecs/codec_crt0.c50
-rw-r--r--apps/codecs/cook.c63
-rw-r--r--apps/codecs/flac.c62
-rw-r--r--apps/codecs/lib/codeclib.c25
-rw-r--r--apps/codecs/lib/codeclib.h3
-rw-r--r--apps/codecs/mod.c67
-rw-r--r--apps/codecs/mp3_enc.c59
-rw-r--r--apps/codecs/mpa.c76
-rw-r--r--apps/codecs/mpc.c76
-rw-r--r--apps/codecs/nsf.c82
-rw-r--r--apps/codecs/raac.c98
-rw-r--r--apps/codecs/shorten.c40
-rw-r--r--apps/codecs/sid.c72
-rw-r--r--apps/codecs/smaf.c82
-rw-r--r--apps/codecs/spc.c128
-rw-r--r--apps/codecs/speex.c61
-rw-r--r--apps/codecs/tta.c61
-rw-r--r--apps/codecs/vorbis.c74
-rw-r--r--apps/codecs/vox.c78
-rw-r--r--apps/codecs/wav.c106
-rw-r--r--apps/codecs/wav64.c113
-rw-r--r--apps/codecs/wav_enc.c54
-rw-r--r--apps/codecs/wavpack.c78
-rw-r--r--apps/codecs/wavpack_enc.c112
-rw-r--r--apps/codecs/wma.c77
-rw-r--r--apps/codecs/wmapro.c68
-rw-r--r--apps/codecs/wmavoice.c68
39 files changed, 1384 insertions, 1500 deletions
diff --git a/apps/codecs/a52.c b/apps/codecs/a52.c
index 00fdeea309..4cd293e37f 100644
--- a/apps/codecs/a52.c
+++ b/apps/codecs/a52.c
@@ -116,27 +116,31 @@ static void a52_decode_data(uint8_t *start, uint8_t *end)
116} 116}
117 117
118/* this is the codec entry point */ 118/* this is the codec entry point */
119enum codec_status codec_main(void) 119enum codec_status codec_main(enum codec_entry_call_reason reason)
120{
121 if (reason == CODEC_LOAD) {
122 /* Generic codec initialisation */
123 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
124 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
125 }
126 else if (reason == CODEC_UNLOAD) {
127 if (state)
128 a52_free(state);
129 }
130
131 return CODEC_OK;
132}
133
134/* this is called for each file to process */
135enum codec_status codec_run(void)
120{ 136{
121 size_t n; 137 size_t n;
122 unsigned char *filebuf; 138 unsigned char *filebuf;
123 int sample_loc; 139 int sample_loc;
124 int retval; 140 intptr_t param;
125 141
126 /* Generic codec initialisation */ 142 if (codec_init())
127 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); 143 return CODEC_ERROR;
128 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
129
130next_track:
131 retval = CODEC_OK;
132
133 if (codec_init()) {
134 retval = CODEC_ERROR;
135 goto exit;
136 }
137
138 if (codec_wait_taginfo() != 0)
139 goto request_next_track;
140 144
141 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 145 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
142 codec_set_replaygain(ci->id3); 146 codec_set_replaygain(ci->id3);
@@ -153,15 +157,18 @@ next_track:
153 } 157 }
154 } 158 }
155 else { 159 else {
160 ci->seek_buffer(ci->id3->first_frame_offset);
156 samplesdone = 0; 161 samplesdone = 0;
157 } 162 }
158 163
159 while (1) { 164 while (1) {
160 if (ci->stop_codec || ci->new_track) 165 enum codec_command_action action = ci->get_command(&param);
166
167 if (action == CODEC_ACTION_HALT)
161 break; 168 break;
162 169
163 if (ci->seek_time) { 170 if (action == CODEC_ACTION_SEEK_TIME) {
164 sample_loc = (ci->seek_time - 1)/1000 * ci->id3->frequency; 171 sample_loc = param/1000 * ci->id3->frequency;
165 172
166 if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) { 173 if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) {
167 samplesdone = sample_loc; 174 samplesdone = sample_loc;
@@ -179,11 +186,5 @@ next_track:
179 ci->advance_buffer(n); 186 ci->advance_buffer(n);
180 } 187 }
181 188
182request_next_track: 189 return CODEC_OK;
183 if (ci->request_next_track())
184 goto next_track;
185
186exit:
187 a52_free(state);
188 return retval;
189} 190}
diff --git a/apps/codecs/a52_rm.c b/apps/codecs/a52_rm.c
index f5e4923292..c1930aa7b4 100644
--- a/apps/codecs/a52_rm.c
+++ b/apps/codecs/a52_rm.c
@@ -124,36 +124,44 @@ static void a52_decode_data(uint8_t *start, uint8_t *end)
124 } 124 }
125} 125}
126 126
127
128/* this is the codec entry point */ 127/* this is the codec entry point */
129enum codec_status codec_main(void) 128enum codec_status codec_main(enum codec_entry_call_reason reason)
129{
130 if (reason == CODEC_LOAD) {
131 /* Generic codec initialisation */
132 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
133 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
134 }
135 else if (reason == CODEC_UNLOAD) {
136 if (state)
137 a52_free(state);
138 }
139
140 return CODEC_OK;
141}
142
143/* this is called for each file to process */
144enum codec_status codec_run(void)
130{ 145{
131 size_t n; 146 size_t n;
132 uint8_t *filebuf; 147 uint8_t *filebuf;
133 int retval, consumed, packet_offset; 148 int consumed, packet_offset;
134 int playback_on = -1; 149 int playback_on = -1;
135 size_t resume_offset; 150 size_t resume_offset;
136 151 intptr_t param;
137 /* Generic codec initialisation */ 152 enum codec_command_action action = CODEC_ACTION_NULL;
138 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
139 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
140
141next_track:
142 retval = CODEC_OK;
143 153
144 if (codec_init()) { 154 if (codec_init()) {
145 retval = CODEC_ERROR; 155 return CODEC_ERROR;
146 goto exit;
147 } 156 }
148 157
149 if (codec_wait_taginfo() != 0)
150 goto request_next_track;
151
152 resume_offset = ci->id3->offset; 158 resume_offset = ci->id3->offset;
153 159
154 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 160 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
155 codec_set_replaygain(ci->id3); 161 codec_set_replaygain(ci->id3);
156 162
163 ci->seek_buffer(ci->id3->first_frame_offset);
164
157 /* Intializations */ 165 /* Intializations */
158 state = a52_init(0); 166 state = a52_init(0);
159 ci->memset(&rmctx,0,sizeof(RMContext)); 167 ci->memset(&rmctx,0,sizeof(RMContext));
@@ -165,26 +173,34 @@ next_track:
165 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; 173 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
166 /* put number of subpackets to skip in resume_offset */ 174 /* put number of subpackets to skip in resume_offset */
167 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); 175 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
168 ci->seek_time = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); 176 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
177 action = CODEC_ACTION_SEEK_TIME;
178 }
179 else {
180 /* Seek to the first packet */
181 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE );
169 } 182 }
170
171 /* Seek to the first packet */
172 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE );
173 183
174 /* The main decoding loop */ 184 /* The main decoding loop */
175 while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) { 185 while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) {
176 ci->yield(); 186 if (action == CODEC_ACTION_NULL)
177 if (ci->stop_codec || ci->new_track) 187 action = ci->get_command(&param);
188
189 if (action == CODEC_ACTION_HALT)
178 break; 190 break;
179 191
180 if (ci->seek_time) { 192 if (action == CODEC_ACTION_SEEK_TIME) {
181 packet_offset = ci->seek_time / ((rmctx.block_align*8*1000)/rmctx.bit_rate); 193 packet_offset = param / ((rmctx.block_align*8*1000)/rmctx.bit_rate);
182 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE)); 194 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE +
195 packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE));
183 rmctx.audio_pkt_cnt = packet_offset; 196 rmctx.audio_pkt_cnt = packet_offset;
184 samplesdone = (rmctx.sample_rate/1000 * ci->seek_time); 197 samplesdone = (rmctx.sample_rate/1000 * param);
198 ci->set_elapsed(samplesdone/(frequency/1000));
185 ci->seek_complete(); 199 ci->seek_complete();
186 } 200 }
187 201
202 action = CODEC_ACTION_NULL;
203
188 filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE); 204 filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE);
189 consumed = rm_get_packet(&filebuf, &rmctx, &pkt); 205 consumed = rm_get_packet(&filebuf, &rmctx, &pkt);
190 206
@@ -195,8 +211,7 @@ next_track:
195 return CODEC_ERROR; 211 return CODEC_ERROR;
196 } 212 }
197 else { 213 else {
198 retval = CODEC_OK; 214 break;
199 goto exit;
200 } 215 }
201 } 216 }
202 217
@@ -205,11 +220,5 @@ next_track:
205 ci->advance_buffer(pkt.length); 220 ci->advance_buffer(pkt.length);
206 } 221 }
207 222
208request_next_track: 223 return CODEC_OK;
209 if (ci->request_next_track())
210 goto next_track;
211
212exit:
213 a52_free(state);
214 return retval;
215} 224}
diff --git a/apps/codecs/aac.c b/apps/codecs/aac.c
index 5638dc49a9..90cf0438ce 100644
--- a/apps/codecs/aac.c
+++ b/apps/codecs/aac.c
@@ -33,7 +33,19 @@ CODEC_HEADER
33#define FAAD_BYTE_BUFFER_SIZE (2048-12) 33#define FAAD_BYTE_BUFFER_SIZE (2048-12)
34 34
35/* this is the codec entry point */ 35/* this is the codec entry point */
36enum codec_status codec_main(void) 36enum codec_status codec_main(enum codec_entry_call_reason reason)
37{
38 if (reason == CODEC_LOAD) {
39 /* Generic codec initialisation */
40 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
41 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
42 }
43
44 return CODEC_OK;
45}
46
47/* this is called for each file to process */
48enum codec_status codec_run(void)
37{ 49{
38 /* Note that when dealing with QuickTime/MPEG4 files, terminology is 50 /* Note that when dealing with QuickTime/MPEG4 files, terminology is
39 * a bit confusing. Files with sound are split up in chunks, where 51 * a bit confusing. Files with sound are split up in chunks, where
@@ -59,25 +71,15 @@ enum codec_status codec_main(void)
59 uint32_t sbr_fac = 1; 71 uint32_t sbr_fac = 1;
60 unsigned char c = 0; 72 unsigned char c = 0;
61 void *ret; 73 void *ret;
62 74 intptr_t param;
63 /* Generic codec initialisation */
64 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
65 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
66
67next_track:
68 err = CODEC_OK;
69 75
70 /* Clean and initialize decoder structures */ 76 /* Clean and initialize decoder structures */
71 memset(&demux_res , 0, sizeof(demux_res)); 77 memset(&demux_res , 0, sizeof(demux_res));
72 if (codec_init()) { 78 if (codec_init()) {
73 LOGF("FAAD: Codec init error\n"); 79 LOGF("FAAD: Codec init error\n");
74 err = CODEC_ERROR; 80 return CODEC_ERROR;
75 goto exit;
76 } 81 }
77 82
78 if (codec_wait_taginfo() != 0)
79 goto done;
80
81 file_offset = ci->id3->offset; 83 file_offset = ci->id3->offset;
82 84
83 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 85 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -85,12 +87,13 @@ next_track:
85 87
86 stream_create(&input_stream,ci); 88 stream_create(&input_stream,ci);
87 89
90 ci->seek_buffer(ci->id3->first_frame_offset);
91
88 /* if qtmovie_read returns successfully, the stream is up to 92 /* if qtmovie_read returns successfully, the stream is up to
89 * the movie data, which can be used directly by the decoder */ 93 * the movie data, which can be used directly by the decoder */
90 if (!qtmovie_read(&input_stream, &demux_res)) { 94 if (!qtmovie_read(&input_stream, &demux_res)) {
91 LOGF("FAAD: File init error\n"); 95 LOGF("FAAD: File init error\n");
92 err = CODEC_ERROR; 96 return CODEC_ERROR;
93 goto done;
94 } 97 }
95 98
96 /* initialise the sound converter */ 99 /* initialise the sound converter */
@@ -98,8 +101,7 @@ next_track:
98 101
99 if (!decoder) { 102 if (!decoder) {
100 LOGF("FAAD: Decode open error\n"); 103 LOGF("FAAD: Decode open error\n");
101 err = CODEC_ERROR; 104 return CODEC_ERROR;
102 goto done;
103 } 105 }
104 106
105 NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); 107 NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
@@ -109,8 +111,7 @@ next_track:
109 err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c); 111 err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c);
110 if (err) { 112 if (err) {
111 LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type); 113 LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type);
112 err = CODEC_ERROR; 114 return CODEC_ERROR;
113 goto done;
114 } 115 }
115 116
116#ifdef SBR_DEC 117#ifdef SBR_DEC
@@ -150,20 +151,19 @@ next_track:
150 151
151 /* The main decoding loop */ 152 /* The main decoding loop */
152 while (i < demux_res.num_sample_byte_sizes) { 153 while (i < demux_res.num_sample_byte_sizes) {
153 ci->yield(); 154 enum codec_command_action action = ci->get_command(&param);
154 155
155 if (ci->stop_codec || ci->new_track) { 156 if (action == CODEC_ACTION_HALT)
156 break; 157 break;
157 }
158 158
159 /* Deal with any pending seek requests */ 159 /* Deal with any pending seek requests */
160 if (ci->seek_time) { 160 if (action == CODEC_ACTION_SEEK_TIME) {
161 /* Seek to the desired time position. Important: When seeking in SBR 161 /* Seek to the desired time position. Important: When seeking in SBR
162 * upsampling files the seek_time must be divided by 2 when calling 162 * upsampling files the seek_time must be divided by 2 when calling
163 * m4a_seek and the resulting sound_samples_done must be expanded 163 * m4a_seek and the resulting sound_samples_done must be expanded
164 * by a factor 2. This is done via using sbr_fac. */ 164 * by a factor 2. This is done via using sbr_fac. */
165 if (m4a_seek(&demux_res, &input_stream, 165 if (m4a_seek(&demux_res, &input_stream,
166 ((ci->seek_time-1)/10/sbr_fac)*(ci->id3->frequency/100), 166 (param/10/sbr_fac)*(ci->id3->frequency/100),
167 &sound_samples_done, (int*) &i)) { 167 &sound_samples_done, (int*) &i)) {
168 sound_samples_done *= sbr_fac; 168 sound_samples_done *= sbr_fac;
169 elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100); 169 elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
@@ -194,8 +194,7 @@ next_track:
194 else if (file_offset == 0) 194 else if (file_offset == 0)
195 { 195 {
196 LOGF("AAC: get_sample_offset error\n"); 196 LOGF("AAC: get_sample_offset error\n");
197 err = CODEC_ERROR; 197 return CODEC_ERROR;
198 goto done;
199 } 198 }
200 199
201 /* Request the required number of bytes from the input buffer */ 200 /* Request the required number of bytes from the input buffer */
@@ -207,8 +206,7 @@ next_track:
207 /* NeAACDecDecode may sometimes return NULL without setting error. */ 206 /* NeAACDecDecode may sometimes return NULL without setting error. */
208 if (ret == NULL || frame_info.error > 0) { 207 if (ret == NULL || frame_info.error > 0) {
209 LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error)); 208 LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
210 err = CODEC_ERROR; 209 return CODEC_ERROR;
211 goto done;
212 } 210 }
213 211
214 /* Advance codec buffer (no need to call set_offset because of this) */ 212 /* Advance codec buffer (no need to call set_offset because of this) */
@@ -251,12 +249,6 @@ next_track:
251 i++; 249 i++;
252 } 250 }
253 251
254done:
255 LOGF("AAC: Decoded %lu samples\n", (unsigned long)sound_samples_done); 252 LOGF("AAC: Decoded %lu samples\n", (unsigned long)sound_samples_done);
256 253 return CODEC_OK;
257 if (ci->request_next_track())
258 goto next_track;
259
260exit:
261 return err;
262} 254}
diff --git a/apps/codecs/adx.c b/apps/codecs/adx.c
index 832b94797b..a1b57fce58 100644
--- a/apps/codecs/adx.c
+++ b/apps/codecs/adx.c
@@ -45,7 +45,19 @@ static const long cutoff = 500;
45static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR; 45static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR;
46 46
47/* this is the codec entry point */ 47/* this is the codec entry point */
48enum codec_status codec_main(void) 48enum codec_status codec_main(enum codec_entry_call_reason reason)
49{
50 if (reason == CODEC_LOAD) {
51 /* Generic codec initialisation */
52 /* we only render 16 bits */
53 ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
54 }
55
56 return CODEC_OK;
57}
58
59/* this is called for each file to process */
60enum codec_status codec_run(void)
49{ 61{
50 int channels; 62 int channels;
51 int sampleswritten, i; 63 int sampleswritten, i;
@@ -62,12 +74,8 @@ enum codec_status codec_main(void)
62 off_t chanstart, bufoff; 74 off_t chanstart, bufoff;
63 /*long coef1=0x7298L,coef2=-0x3350L;*/ 75 /*long coef1=0x7298L,coef2=-0x3350L;*/
64 long coef1, coef2; 76 long coef1, coef2;
77 intptr_t param;
65 78
66 /* Generic codec initialisation */
67 /* we only render 16 bits */
68 ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
69
70next_track:
71 DEBUGF("ADX: next_track\n"); 79 DEBUGF("ADX: next_track\n");
72 if (codec_init()) { 80 if (codec_init()) {
73 return CODEC_ERROR; 81 return CODEC_ERROR;
@@ -77,10 +85,6 @@ next_track:
77 /* init history */ 85 /* init history */
78 ch1_1=ch1_2=ch2_1=ch2_2=0; 86 ch1_1=ch1_2=ch2_1=ch2_2=0;
79 87
80 /* wait for track info to load */
81 if (codec_wait_taginfo() != 0)
82 goto request_next_track;
83
84 codec_set_replaygain(ci->id3); 88 codec_set_replaygain(ci->id3);
85 89
86 /* Get header */ 90 /* Get header */
@@ -226,10 +230,10 @@ next_track:
226 /* The main decoder loop */ 230 /* The main decoder loop */
227 231
228 while (!endofstream) { 232 while (!endofstream) {
229 ci->yield(); 233 enum codec_command_action action = ci->get_command(&param);
230 if (ci->stop_codec || ci->new_track) { 234
235 if (action == CODEC_ACTION_HALT)
231 break; 236 break;
232 }
233 237
234 /* do we need to loop? */ 238 /* do we need to loop? */
235 if (bufoff > end_adr-18*channels && looping) { 239 if (bufoff > end_adr-18*channels && looping) {
@@ -254,17 +258,17 @@ next_track:
254 } 258 }
255 259
256 /* do we need to seek? */ 260 /* do we need to seek? */
257 if (ci->seek_time) { 261 if (action == CODEC_ACTION_SEEK_TIME) {
258 uint32_t newpos; 262 uint32_t newpos;
259 263
260 DEBUGF("ADX: seek to %ldms\n",ci->seek_time); 264 DEBUGF("ADX: seek to %ldms\n", (long)param);
261 265
262 endofstream = 0; 266 endofstream = 0;
263 loop_count = 0; 267 loop_count = 0;
264 fade_count = -1; /* disable fade */ 268 fade_count = -1; /* disable fade */
265 fade_frames = 1; 269 fade_frames = 1;
266 270
267 newpos = (((uint64_t)avgbytespersec*(ci->seek_time - 1)) 271 newpos = (((uint64_t)avgbytespersec*param)
268 / (1000LL*18*channels))*(18*channels); 272 / (1000LL*18*channels))*(18*channels);
269 bufoff = chanstart + newpos; 273 bufoff = chanstart + newpos;
270 while (bufoff > end_adr-18*channels) { 274 while (bufoff > end_adr-18*channels) {
@@ -385,9 +389,5 @@ next_track:
385 1000LL/avgbytespersec); 389 1000LL/avgbytespersec);
386 } 390 }
387 391
388request_next_track:
389 if (ci->request_next_track())
390 goto next_track;
391
392 return CODEC_OK; 392 return CODEC_OK;
393} 393}
diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c
index d4cf8660dd..3fc137eaeb 100644
--- a/apps/codecs/aiff.c
+++ b/apps/codecs/aiff.c
@@ -61,9 +61,20 @@ static const struct pcm_codec *get_codec(uint32_t formattag)
61 return NULL; 61 return NULL;
62} 62}
63 63
64enum codec_status codec_main(void) 64/* this is the codec entry point */
65enum codec_status codec_main(enum codec_entry_call_reason reason)
66{
67 if (reason == CODEC_LOAD) {
68 /* Generic codec initialisation */
69 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
70 }
71
72 return CODEC_OK;
73}
74
75/* this is called for each file to process */
76enum codec_status codec_run(void)
65{ 77{
66 int status;
67 struct pcm_format format; 78 struct pcm_format format;
68 uint32_t bytesdone, decodedsamples; 79 uint32_t bytesdone, decodedsamples;
69 uint32_t num_sample_frames = 0; 80 uint32_t num_sample_frames = 0;
@@ -77,38 +88,28 @@ enum codec_status codec_main(void)
77 bool is_aifc = false; 88 bool is_aifc = false;
78 const struct pcm_codec *codec; 89 const struct pcm_codec *codec;
79 uint32_t size; 90 uint32_t size;
80 91 intptr_t param;
81 /* Generic codec initialisation */
82 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
83
84next_track:
85 status = CODEC_OK;
86 92
87 if (codec_init()) { 93 if (codec_init()) {
88 status = CODEC_ERROR; 94 return CODEC_ERROR;
89 goto exit;
90 } 95 }
91 96
92 if (codec_wait_taginfo() != 0)
93 goto done;
94
95 codec_set_replaygain(ci->id3); 97 codec_set_replaygain(ci->id3);
96 98
97 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 99 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
98 bytesdone = ci->id3->offset; 100 bytesdone = ci->id3->offset;
99 101
100 /* assume the AIFF header is less than 1024 bytes */ 102 /* assume the AIFF header is less than 1024 bytes */
103 ci->seek_buffer(0);
101 buf = ci->request_buffer(&n, 1024); 104 buf = ci->request_buffer(&n, 1024);
102 if (n < 54) { 105 if (n < 54) {
103 status = CODEC_ERROR; 106 return CODEC_ERROR;
104 goto done;
105 } 107 }
106 108
107 if (memcmp(buf, "FORM", 4) != 0) 109 if (memcmp(buf, "FORM", 4) != 0)
108 { 110 {
109 DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]); 111 DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]);
110 status = CODEC_ERROR; 112 return CODEC_ERROR;
111 goto done;
112 } 113 }
113 if (memcmp(&buf[8], "AIFF", 4) == 0) 114 if (memcmp(&buf[8], "AIFF", 4) == 0)
114 is_aifc = false; 115 is_aifc = false;
@@ -117,8 +118,7 @@ next_track:
117 else 118 else
118 { 119 {
119 DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]); 120 DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]);
120 status = CODEC_ERROR; 121 return CODEC_ERROR;
121 goto done;
122 } 122 }
123 123
124 buf += 12; 124 buf += 12;
@@ -141,8 +141,7 @@ next_track:
141 { 141 {
142 DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n", 142 DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n",
143 (unsigned long)size, (is_aifc)?22:18); 143 (unsigned long)size, (is_aifc)?22:18);
144 status = CODEC_ERROR; 144 return CODEC_ERROR;
145 goto done;
146 } 145 }
147 /* num_channels */ 146 /* num_channels */
148 format.channels = ((buf[8]<<8)|buf[9]); 147 format.channels = ((buf[8]<<8)|buf[9]);
@@ -154,8 +153,7 @@ next_track:
154 /* sample_rate (don't use last 4 bytes, only integer fs) */ 153 /* sample_rate (don't use last 4 bytes, only integer fs) */
155 if (buf[16] != 0x40) { 154 if (buf[16] != 0x40) {
156 DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n"); 155 DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n");
157 status = CODEC_ERROR; 156 return CODEC_ERROR;
158 goto done;
159 } 157 }
160 format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1; 158 format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1;
161 format.samplespersec >>= (16 + 14 - buf[17]); 159 format.samplespersec >>= (16 + 14 - buf[17]);
@@ -181,8 +179,7 @@ next_track:
181 } else if (memcmp(buf, "SSND", 4)==0) { 179 } else if (memcmp(buf, "SSND", 4)==0) {
182 if (format.bitspersample == 0) { 180 if (format.bitspersample == 0) {
183 DEBUGF("CODEC_ERROR: unsupported chunk order\n"); 181 DEBUGF("CODEC_ERROR: unsupported chunk order\n");
184 status = CODEC_ERROR; 182 return CODEC_ERROR;
185 goto done;
186 } 183 }
187 /* offset2snd */ 184 /* offset2snd */
188 offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; 185 offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11];
@@ -205,21 +202,18 @@ next_track:
205 buf += size; 202 buf += size;
206 if (n < size) { 203 if (n < size) {
207 DEBUGF("CODEC_ERROR: AIFF header size > 1024\n"); 204 DEBUGF("CODEC_ERROR: AIFF header size > 1024\n");
208 status = CODEC_ERROR; 205 return CODEC_ERROR;
209 goto done;
210 } 206 }
211 n -= size; 207 n -= size;
212 } /* while 'SSND' */ 208 } /* while 'SSND' */
213 209
214 if (format.channels == 0) { 210 if (format.channels == 0) {
215 DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n"); 211 DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n");
216 status = CODEC_ERROR; 212 return CODEC_ERROR;
217 goto done;
218 } 213 }
219 if (format.numbytes == 0) { 214 if (format.numbytes == 0) {
220 DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n"); 215 DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n");
221 status = CODEC_ERROR; 216 return CODEC_ERROR;
222 goto done;
223 } 217 }
224 218
225 codec = get_codec(format.formattag); 219 codec = get_codec(format.formattag);
@@ -227,14 +221,12 @@ next_track:
227 { 221 {
228 DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n", 222 DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n",
229 (unsigned int)format.formattag); 223 (unsigned int)format.formattag);
230 status = CODEC_ERROR; 224 return CODEC_ERROR;
231 goto done;
232 } 225 }
233 226
234 if (!codec->set_format(&format)) 227 if (!codec->set_format(&format))
235 { 228 {
236 status = CODEC_ERROR; 229 return CODEC_ERROR;
237 goto done;
238 } 230 }
239 231
240 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 232 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -245,21 +237,18 @@ next_track:
245 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 237 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
246 } else { 238 } else {
247 DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); 239 DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n");
248 status = CODEC_ERROR; 240 return CODEC_ERROR;
249 goto done;
250 } 241 }
251 242
252 if (format.samplesperblock == 0) 243 if (format.samplesperblock == 0)
253 { 244 {
254 DEBUGF("CODEC_ERROR: samplesperblock is 0\n"); 245 DEBUGF("CODEC_ERROR: samplesperblock is 0\n");
255 status = CODEC_ERROR; 246 return CODEC_ERROR;
256 goto done;
257 } 247 }
258 if (format.blockalign == 0) 248 if (format.blockalign == 0)
259 { 249 {
260 DEBUGF("CODEC_ERROR: blockalign is 0\n"); 250 DEBUGF("CODEC_ERROR: blockalign is 0\n");
261 status = CODEC_ERROR; 251 return CODEC_ERROR;
262 goto done;
263 } 252 }
264 253
265 /* check chunksize */ 254 /* check chunksize */
@@ -269,8 +258,7 @@ next_track:
269 if (format.chunksize == 0) 258 if (format.chunksize == 0)
270 { 259 {
271 DEBUGF("CODEC_ERROR: chunksize is 0\n"); 260 DEBUGF("CODEC_ERROR: chunksize is 0\n");
272 status = CODEC_ERROR; 261 return CODEC_ERROR;
273 goto done;
274 } 262 }
275 263
276 firstblockposn = 1024 - n; 264 firstblockposn = 1024 - n;
@@ -283,13 +271,13 @@ next_track:
283 PCM_SEEK_POS, NULL); 271 PCM_SEEK_POS, NULL);
284 272
285 if (newpos->pos > format.numbytes) 273 if (newpos->pos > format.numbytes)
286 goto done; 274 return CODEC_OK;
275
287 if (ci->seek_buffer(firstblockposn + newpos->pos)) 276 if (ci->seek_buffer(firstblockposn + newpos->pos))
288 { 277 {
289 bytesdone = newpos->pos; 278 bytesdone = newpos->pos;
290 decodedsamples = newpos->samples; 279 decodedsamples = newpos->samples;
291 } 280 }
292 ci->seek_complete();
293 } else { 281 } else {
294 /* already where we need to be */ 282 /* already where we need to be */
295 bytesdone = 0; 283 bytesdone = 0;
@@ -299,21 +287,29 @@ next_track:
299 endofstream = 0; 287 endofstream = 0;
300 288
301 while (!endofstream) { 289 while (!endofstream) {
302 ci->yield(); 290 enum codec_command_action action = ci->get_command(&param);
303 if (ci->stop_codec || ci->new_track) 291
292 if (action == CODEC_ACTION_HALT)
304 break; 293 break;
305 294
306 if (ci->seek_time) { 295 if (action == CODEC_ACTION_SEEK_TIME) {
307 /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */ 296 /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */
308 struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); 297 struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL);
309 298
310 if (newpos->pos > format.numbytes) 299 if (newpos->pos > format.numbytes)
300 {
301 ci->set_elapsed(ci->id3->length);
302 ci->seek_complete();
311 break; 303 break;
304 }
305
312 if (ci->seek_buffer(firstblockposn + newpos->pos)) 306 if (ci->seek_buffer(firstblockposn + newpos->pos))
313 { 307 {
314 bytesdone = newpos->pos; 308 bytesdone = newpos->pos;
315 decodedsamples = newpos->samples; 309 decodedsamples = newpos->samples;
316 } 310 }
311
312 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
317 ci->seek_complete(); 313 ci->seek_complete();
318 } 314 }
319 aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); 315 aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize);
@@ -326,11 +322,10 @@ next_track:
326 endofstream = 1; 322 endofstream = 1;
327 } 323 }
328 324
329 status = codec->decode(aifbuf, n, samples, &bufcount); 325 if (codec->decode(aifbuf, n, samples, &bufcount) == CODEC_ERROR)
330 if (status == CODEC_ERROR)
331 { 326 {
332 DEBUGF("codec error\n"); 327 DEBUGF("codec error\n");
333 goto done; 328 return CODEC_ERROR;
334 } 329 }
335 330
336 ci->pcmbuf_insert(samples, NULL, bufcount); 331 ci->pcmbuf_insert(samples, NULL, bufcount);
@@ -343,13 +338,6 @@ next_track:
343 338
344 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); 339 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
345 } 340 }
346 status = CODEC_OK;
347
348done:
349 if (ci->request_next_track())
350 goto next_track;
351 341
352exit: 342 return CODEC_OK;
353 return status;
354} 343}
355
diff --git a/apps/codecs/aiff_enc.c b/apps/codecs/aiff_enc.c
index 69496f70ac..fc44196eb0 100644
--- a/apps/codecs/aiff_enc.c
+++ b/apps/codecs/aiff_enc.c
@@ -359,40 +359,42 @@ static bool init_encoder(void)
359 return true; 359 return true;
360} /* init_encoder */ 360} /* init_encoder */
361 361
362/* main codec entry point */ 362/* this is the codec entry point */
363enum codec_status codec_main(void) 363enum codec_status codec_main(enum codec_entry_call_reason reason)
364{ 364{
365 if (!init_encoder()) 365 if (reason == CODEC_LOAD) {
366 return CODEC_ERROR; 366 if (!init_encoder())
367 return CODEC_ERROR;
368 }
369 else if (reason == CODEC_UNLOAD) {
370 /* reset parameters to initial state */
371 ci->enc_set_parameters(NULL);
372 }
367 373
374 return CODEC_OK;
375}
376
377/* this is called for each file to process */
378enum codec_status codec_run(void)
379{
368 /* main encoding loop */ 380 /* main encoding loop */
369 while(!ci->stop_codec) 381 while (ci->get_command(NULL) != CODEC_ACTION_HALT)
370 { 382 {
371 uint32_t *src; 383 uint32_t *src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE);
384 struct enc_chunk_hdr *chunk;
372 385
373 while ((src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL) 386 if (src == NULL)
374 { 387 continue;
375 struct enc_chunk_hdr *chunk;
376
377 if (ci->stop_codec)
378 break;
379 388
380 chunk = ci->enc_get_chunk(); 389 chunk = ci->enc_get_chunk();
381 chunk->enc_size = enc_size; 390 chunk->enc_size = enc_size;
382 chunk->num_pcm = PCM_SAMP_PER_CHUNK; 391 chunk->num_pcm = PCM_SAMP_PER_CHUNK;
383 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); 392 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
384 393
385 chunk_to_aiff_format(src, (uint32_t *)chunk->enc_data); 394 chunk_to_aiff_format(src, (uint32_t *)chunk->enc_data);
386
387 ci->enc_finish_chunk();
388 ci->yield();
389 }
390 395
391 ci->yield(); 396 ci->enc_finish_chunk();
392 } 397 }
393 398
394 /* reset parameters to initial state */
395 ci->enc_set_parameters(NULL);
396
397 return CODEC_OK; 399 return CODEC_OK;
398} /* codec_start */ 400}
diff --git a/apps/codecs/alac.c b/apps/codecs/alac.c
index cd9129a278..82bda264c3 100644
--- a/apps/codecs/alac.c
+++ b/apps/codecs/alac.c
@@ -32,116 +32,114 @@ CODEC_HEADER
32static int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR; 32static int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR;
33 33
34/* this is the codec entry point */ 34/* this is the codec entry point */
35enum codec_status codec_main(void) 35enum codec_status codec_main(enum codec_entry_call_reason reason)
36{ 36{
37 size_t n; 37 if (reason == CODEC_LOAD) {
38 demux_res_t demux_res; 38 /* Generic codec initialisation */
39 stream_t input_stream; 39 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
40 uint32_t samplesdone; 40 ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1);
41 uint32_t elapsedtime; 41 }
42 int samplesdecoded;
43 unsigned int i;
44 unsigned char* buffer;
45 alac_file alac;
46 int retval;
47
48 /* Generic codec initialisation */
49 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
50 ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1);
51
52 next_track:
53 retval = CODEC_OK;
54
55 /* Clean and initialize decoder structures */
56 memset(&demux_res , 0, sizeof(demux_res));
57 if (codec_init()) {
58 LOGF("ALAC: Error initialising codec\n");
59 retval = CODEC_ERROR;
60 goto exit;
61 }
62
63 if (codec_wait_taginfo() != 0)
64 goto done;
65
66 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
67 codec_set_replaygain(ci->id3);
68 42
69 stream_create(&input_stream,ci); 43 return CODEC_OK;
44}
70 45
71 /* Read from ci->id3->offset before calling qtmovie_read. */ 46/* this is called for each file to process */
72 samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) / 47enum codec_status codec_run(void)
73 (ci->id3->bitrate*128)); 48{
74 49 size_t n;
75 /* if qtmovie_read returns successfully, the stream is up to 50 demux_res_t demux_res;
76 * the movie data, which can be used directly by the decoder */ 51 stream_t input_stream;
77 if (!qtmovie_read(&input_stream, &demux_res)) { 52 uint32_t samplesdone;
78 LOGF("ALAC: Error initialising file\n"); 53 uint32_t elapsedtime = 0;
79 retval = CODEC_ERROR; 54 int samplesdecoded;
80 goto done; 55 unsigned int i;
81 } 56 unsigned char* buffer;
82 57 alac_file alac;
83 /* initialise the sound converter */ 58 intptr_t param;
84 create_alac(demux_res.sound_sample_size, demux_res.num_channels,&alac); 59
85 alac_set_info(&alac, demux_res.codecdata); 60 /* Clean and initialize decoder structures */
86 61 memset(&demux_res , 0, sizeof(demux_res));
87 /* Set i for first frame, seek to desired sample position for resuming. */ 62 if (codec_init()) {
88 i=0; 63 LOGF("ALAC: Error initialising codec\n");
89 if (samplesdone > 0) { 64 return CODEC_ERROR;
90 if (m4a_seek(&demux_res, &input_stream, samplesdone,
91 &samplesdone, (int*) &i)) {
92 elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100);
93 ci->set_elapsed(elapsedtime);
94 } else {
95 samplesdone = 0;
96 } 65 }
97 }
98 66
99 /* The main decoding loop */ 67 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
100 while (i < demux_res.num_sample_byte_sizes) { 68 codec_set_replaygain(ci->id3);
101 ci->yield(); 69
102 if (ci->stop_codec || ci->new_track) { 70 ci->seek_buffer(0);
103 break; 71
72 stream_create(&input_stream,ci);
73
74 /* Read from ci->id3->offset before calling qtmovie_read. */
75 samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) /
76 (ci->id3->bitrate*128));
77
78 /* if qtmovie_read returns successfully, the stream is up to
79 * the movie data, which can be used directly by the decoder */
80 if (!qtmovie_read(&input_stream, &demux_res)) {
81 LOGF("ALAC: Error initialising file\n");
82 return CODEC_ERROR;
104 } 83 }
105 84
106 /* Deal with any pending seek requests */ 85 /* initialise the sound converter */
107 if (ci->seek_time) { 86 create_alac(demux_res.sound_sample_size, demux_res.num_channels,&alac);
108 if (m4a_seek(&demux_res, &input_stream, 87 alac_set_info(&alac, demux_res.codecdata);
109 ((ci->seek_time-1)/10) * (ci->id3->frequency/100), 88
110 &samplesdone, (int *)&i)) { 89 /* Set i for first frame, seek to desired sample position for resuming. */
111 elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); 90 i=0;
112 ci->set_elapsed(elapsedtime); 91 if (samplesdone > 0) {
113 } 92 if (m4a_seek(&demux_res, &input_stream, samplesdone,
114 ci->seek_complete(); 93 &samplesdone, (int*) &i)) {
94 elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100);
95 ci->set_elapsed(elapsedtime);
96 } else {
97 samplesdone = 0;
98 }
115 } 99 }
116 100
117 /* Request the required number of bytes from the input buffer */ 101 /* The main decoding loop */
118 buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); 102 while (i < demux_res.num_sample_byte_sizes) {
103 enum codec_command_action action = ci->get_command(&param);
104
105 if (action == CODEC_ACTION_HALT)
106 break;
119 107
120 /* Decode one block - returned samples will be host-endian */ 108 /* Request the required number of bytes from the input buffer */
121 ci->yield(); 109 buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE);
122 samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield);
123 110
124 /* Advance codec buffer by amount of consumed bytes */ 111 /* Deal with any pending seek requests */
125 ci->advance_buffer(alac.bytes_consumed); 112 if (action == CODEC_ACTION_SEEK_TIME) {
113 if (m4a_seek(&demux_res, &input_stream,
114 (param/10) * (ci->id3->frequency/100),
115 &samplesdone, (int *)&i)) {
116 elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
117 }
118 ci->set_elapsed(elapsedtime);
119 ci->seek_complete();
120 }
126 121
127 /* Output the audio */ 122 /* Request the required number of bytes from the input buffer */
128 ci->yield(); 123 buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE);
129 ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded);
130 124
131 /* Update the elapsed-time indicator */ 125 /* Decode one block - returned samples will be host-endian */
132 samplesdone+=samplesdecoded; 126 samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield);
133 elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); 127 ci->yield();
134 ci->set_elapsed(elapsedtime);
135 128
136 i++; 129 /* Advance codec buffer by amount of consumed bytes */
137 } 130 ci->advance_buffer(alac.bytes_consumed);
138 131
139done: 132 /* Output the audio */
140 LOGF("ALAC: Decoded %lu samples\n",(unsigned long)samplesdone); 133 ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded);
141 134
142 if (ci->request_next_track()) 135 /* Update the elapsed-time indicator */
143 goto next_track; 136 samplesdone+=samplesdecoded;
137 elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
138 ci->set_elapsed(elapsedtime);
139
140 i++;
141 }
144 142
145exit: 143 LOGF("ALAC: Decoded %lu samples\n",(unsigned long)samplesdone);
146 return retval; 144 return CODEC_OK;
147} 145}
diff --git a/apps/codecs/ape.c b/apps/codecs/ape.c
index 11d973ab26..8f95a01ec7 100644
--- a/apps/codecs/ape.c
+++ b/apps/codecs/ape.c
@@ -127,13 +127,23 @@ static void ape_resume(struct ape_ctx_t* ape_ctx, size_t resume_offset,
127} 127}
128 128
129/* this is the codec entry point */ 129/* this is the codec entry point */
130enum codec_status codec_main(void) 130enum codec_status codec_main(enum codec_entry_call_reason reason)
131{
132 if (reason == CODEC_LOAD) {
133 /* Generic codec initialisation */
134 ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1);
135 }
136
137 return CODEC_OK;
138}
139
140/* this is called for each file to process */
141enum codec_status codec_run(void)
131{ 142{
132 struct ape_ctx_t ape_ctx; 143 struct ape_ctx_t ape_ctx;
133 uint32_t samplesdone; 144 uint32_t samplesdone;
134 uint32_t elapsedtime; 145 uint32_t elapsedtime;
135 size_t bytesleft; 146 size_t bytesleft;
136 int retval;
137 147
138 uint32_t currentframe; 148 uint32_t currentframe;
139 uint32_t newfilepos; 149 uint32_t newfilepos;
@@ -145,33 +155,24 @@ enum codec_status codec_main(void)
145 int res; 155 int res;
146 int firstbyte; 156 int firstbyte;
147 size_t resume_offset; 157 size_t resume_offset;
148 158 intptr_t param;
149 /* Generic codec initialisation */
150 ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1);
151
152next_track:
153 retval = CODEC_OK;
154 159
155 if (codec_init()) { 160 if (codec_init()) {
156 LOGF("APE: Error initialising codec\n"); 161 LOGF("APE: Error initialising codec\n");
157 retval = CODEC_ERROR; 162 return CODEC_ERROR;
158 goto exit;
159 } 163 }
160 164
161 if (codec_wait_taginfo() != 0)
162 goto done;
163
164 /* Remember the resume position - when the codec is opened, the 165 /* Remember the resume position - when the codec is opened, the
165 playback engine will reset it. */ 166 playback engine will reset it. */
166 resume_offset = ci->id3->offset; 167 resume_offset = ci->id3->offset;
167 168
169 ci->seek_buffer(0);
168 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); 170 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
169 171
170 /* Read the file headers to populate the ape_ctx struct */ 172 /* Read the file headers to populate the ape_ctx struct */
171 if (ape_parseheaderbuf(inbuffer,&ape_ctx) < 0) { 173 if (ape_parseheaderbuf(inbuffer,&ape_ctx) < 0) {
172 LOGF("APE: Error reading header\n"); 174 LOGF("APE: Error reading header\n");
173 retval = CODEC_ERROR; 175 return CODEC_ERROR;
174 goto exit;
175 } 176 }
176 177
177 /* Initialise the seektable for this file */ 178 /* Initialise the seektable for this file */
@@ -243,16 +244,16 @@ frame_start:
243 /* Decode the frame a chunk at a time */ 244 /* Decode the frame a chunk at a time */
244 while (nblocks > 0) 245 while (nblocks > 0)
245 { 246 {
246 ci->yield(); 247 enum codec_command_action action = ci->get_command(&param);
247 if (ci->stop_codec || ci->new_track) { 248
249 if (action == CODEC_ACTION_HALT)
248 goto done; 250 goto done;
249 }
250 251
251 /* Deal with any pending seek requests */ 252 /* Deal with any pending seek requests */
252 if (ci->seek_time) 253 if (action == CODEC_ACTION_SEEK_TIME)
253 { 254 {
254 if (ape_calc_seekpos(&ape_ctx, 255 if (ape_calc_seekpos(&ape_ctx,
255 ((ci->seek_time-1)/10) * (ci->id3->frequency/100), 256 (param/10) * (ci->id3->frequency/100),
256 &currentframe, 257 &currentframe,
257 &newfilepos, 258 &newfilepos,
258 &samplestoskip)) 259 &samplestoskip))
@@ -266,9 +267,12 @@ frame_start:
266 ci->seek_buffer(newfilepos); 267 ci->seek_buffer(newfilepos);
267 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); 268 inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
268 269
270 elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
271 ci->set_elapsed(elapsedtime);
269 ci->seek_complete(); 272 ci->seek_complete();
270 goto frame_start; /* Sorry... */ 273 goto frame_start; /* Sorry... */
271 } 274 }
275
272 ci->seek_complete(); 276 ci->seek_complete();
273 } 277 }
274 278
@@ -281,8 +285,7 @@ frame_start:
281 { 285 {
282 /* Frame decoding error, abort */ 286 /* Frame decoding error, abort */
283 LOGF("APE: Frame %lu, error %d\n",(unsigned long)currentframe,res); 287 LOGF("APE: Frame %lu, error %d\n",(unsigned long)currentframe,res);
284 retval = CODEC_ERROR; 288 return CODEC_ERROR;
285 goto done;
286 } 289 }
287 290
288 ci->yield(); 291 ci->yield();
@@ -320,10 +323,5 @@ frame_start:
320 323
321done: 324done:
322 LOGF("APE: Decoded %lu samples\n",(unsigned long)samplesdone); 325 LOGF("APE: Decoded %lu samples\n",(unsigned long)samplesdone);
323 326 return CODEC_OK;
324 if (ci->request_next_track())
325 goto next_track;
326
327exit:
328 return retval;
329} 327}
diff --git a/apps/codecs/asap.c b/apps/codecs/asap.c
index 9447c738d2..f12dc6a0c5 100644
--- a/apps/codecs/asap.c
+++ b/apps/codecs/asap.c
@@ -29,24 +29,21 @@ CODEC_HEADER
29static byte samples[CHUNK_SIZE] IBSS_ATTR; /* The sample buffer */ 29static byte samples[CHUNK_SIZE] IBSS_ATTR; /* The sample buffer */
30static ASAP_State asap; /* asap codec state */ 30static ASAP_State asap; /* asap codec state */
31 31
32/* this is the codec entry point */ 32/* this is called for each file to process */
33enum codec_status codec_main(void) 33enum codec_status codec_run(void)
34{ 34{
35 int n_bytes; 35 int n_bytes;
36 int song; 36 int song;
37 int duration; 37 int duration;
38 char* module; 38 char* module;
39 int bytesPerSample =2; 39 int bytesPerSample =2;
40 intptr_t param;
40 41
41next_track:
42 if (codec_init()) { 42 if (codec_init()) {
43 DEBUGF("codec init failed\n"); 43 DEBUGF("codec init failed\n");
44 return CODEC_ERROR; 44 return CODEC_ERROR;
45 } 45 }
46 46
47 if (codec_wait_taginfo() != 0)
48 goto request_next_track;
49
50 codec_set_replaygain(ci->id3); 47 codec_set_replaygain(ci->id3);
51 48
52 int bytes_done =0; 49 int bytes_done =0;
@@ -97,19 +94,20 @@ next_track:
97 94
98 /* The main decoder loop */ 95 /* The main decoder loop */
99 while (1) { 96 while (1) {
100 ci->yield(); 97 enum codec_command_action action = ci->get_command(&param);
101 if (ci->stop_codec || ci->new_track) 98
99 if (action == CODEC_ACTION_HALT)
102 break; 100 break;
103 101
104 if (ci->seek_time) { 102 if (action == CODEC_ACTION_SEEK_TIME) {
105 /* New time is ready in ci->seek_time */ 103 /* New time is ready in param */
106 104
107 /* seek to pos */ 105 /* seek to pos */
108 ASAP_Seek(&asap,ci->seek_time); 106 ASAP_Seek(&asap,param);
109 /* update elapsed */
110 ci->set_elapsed(ci->seek_time);
111 /* update bytes_done */ 107 /* update bytes_done */
112 bytes_done = ci->seek_time*44.1*2; 108 bytes_done = param*44.1*2;
109 /* update elapsed */
110 ci->set_elapsed((bytes_done / 2) / 44.1);
113 /* seek ready */ 111 /* seek ready */
114 ci->seek_complete(); 112 ci->seek_complete();
115 } 113 }
@@ -129,10 +127,6 @@ next_track:
129 if(n_bytes != sizeof(samples)) 127 if(n_bytes != sizeof(samples))
130 break; 128 break;
131 } 129 }
132
133request_next_track:
134 if (ci->request_next_track())
135 goto next_track;
136 130
137 return CODEC_OK; 131 return CODEC_OK;
138} 132}
diff --git a/apps/codecs/atrac3_oma.c b/apps/codecs/atrac3_oma.c
index 73f3ad29fd..ab24783368 100644
--- a/apps/codecs/atrac3_oma.c
+++ b/apps/codecs/atrac3_oma.c
@@ -33,24 +33,22 @@ CODEC_HEADER
33 33
34static ATRAC3Context q IBSS_ATTR; 34static ATRAC3Context q IBSS_ATTR;
35 35
36/* this is the codec entry point */ 36/* this is called for each file to process */
37enum codec_status codec_main(void) 37enum codec_status codec_run(void)
38{ 38{
39 static size_t buff_size; 39 static size_t buff_size;
40 int datasize, res, frame_counter, total_frames, seek_frame_offset; 40 int datasize, res, frame_counter, total_frames, seek_frame_offset;
41 uint8_t *bit_buffer; 41 uint8_t *bit_buffer;
42 int elapsed = 0; 42 int elapsed = 0;
43 size_t resume_offset; 43 size_t resume_offset;
44 intptr_t param;
45 enum codec_command_action action = CODEC_ACTION_NULL;
44 46
45next_track:
46 if (codec_init()) { 47 if (codec_init()) {
47 DEBUGF("codec init failed\n"); 48 DEBUGF("codec init failed\n");
48 return CODEC_ERROR; 49 return CODEC_ERROR;
49 } 50 }
50 51
51 if (codec_wait_taginfo() != 0)
52 goto done;
53
54 resume_offset = ci->id3->offset; 52 resume_offset = ci->id3->offset;
55 53
56 codec_set_replaygain(ci->id3); 54 codec_set_replaygain(ci->id3);
@@ -60,84 +58,88 @@ next_track:
60 ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */ 58 ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */
61 ci->configure(DSP_SET_STEREO_MODE, ci->id3->channels == 1 ? 59 ci->configure(DSP_SET_STEREO_MODE, ci->id3->channels == 1 ?
62 STEREO_MONO : STEREO_NONINTERLEAVED); 60 STEREO_MONO : STEREO_NONINTERLEAVED);
63 61
64 res =atrac3_decode_init(&q, ci->id3); 62 ci->seek_buffer(0);
63
64 res = atrac3_decode_init(&q, ci->id3);
65 if(res < 0) { 65 if(res < 0) {
66 DEBUGF("failed to initialize OMA atrac decoder\n"); 66 DEBUGF("failed to initialize OMA atrac decoder\n");
67 return CODEC_ERROR; 67 return CODEC_ERROR;
68 } 68 }
69 69
70 total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE;
71 frame_counter = 0;
72
70 /* check for a mid-track resume and force a seek time accordingly */ 73 /* check for a mid-track resume and force a seek time accordingly */
71 if(resume_offset > ci->id3->first_frame_offset) { 74 if(resume_offset > ci->id3->first_frame_offset) {
72 resume_offset -= ci->id3->first_frame_offset; 75 resume_offset -= ci->id3->first_frame_offset;
73 /* calculate resume_offset in frames */ 76 /* calculate resume_offset in frames */
74 resume_offset = (int)resume_offset / FRAMESIZE; 77 resume_offset = (int)resume_offset / FRAMESIZE;
75 ci->seek_time = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE); 78 param = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE);
79 action = CODEC_ACTION_SEEK_TIME;
80 }
81 else {
82 ci->set_elapsed(0);
83 ci->seek_buffer(ci->id3->first_frame_offset);
76 } 84 }
77 total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE;
78 frame_counter = 0;
79
80 ci->set_elapsed(0);
81 ci->seek_buffer(0);
82 ci->advance_buffer(ci->id3->first_frame_offset);
83 85
84 /* The main decoder loop */ 86 /* The main decoder loop */
85seek_start :
86 while(frame_counter < total_frames) 87 while(frame_counter < total_frames)
87 { 88 {
89 if (action == CODEC_ACTION_NULL)
90 action = ci->get_command(&param);
91
92 if (action == CODEC_ACTION_HALT)
93 break;
94
88 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); 95 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
89 96
90 ci->yield(); 97 if (action == CODEC_ACTION_SEEK_TIME) {
91 if (ci->stop_codec || ci->new_track) 98 /* Do not allow seeking beyond the file's length */
92 goto done; 99 if ((unsigned) param > ci->id3->length) {
93 100 ci->set_elapsed(ci->id3->length);
94 if (ci->seek_time) { 101 ci->seek_complete();
95 ci->set_elapsed(ci->seek_time); 102 break;
96 103 }
97 /* Do not allow seeking beyond the file's length */ 104
98 if ((unsigned) ci->seek_time > ci->id3->length) { 105 /* Seek to the start of the track */
99 ci->seek_complete(); 106 if (param == 0) {
100 goto done; 107 elapsed = 0;
101 } 108 ci->set_elapsed(0);
102 109 ci->seek_buffer(ci->id3->first_frame_offset);
103 /* Seek to the start of the track */ 110 ci->seek_complete();
104 if (ci->seek_time == 1) { 111 action = CODEC_ACTION_NULL;
105 ci->set_elapsed(0); 112 continue;
106 ci->seek_complete(); 113 }
107 ci->seek_buffer(ci->id3->first_frame_offset); 114
108 elapsed = 0; 115 seek_frame_offset = (param * BITRATE) / (8 * FRAMESIZE);
109 goto seek_start; 116 frame_counter = seek_frame_offset;
110 } 117 ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE);
111 seek_frame_offset = (ci->seek_time * BITRATE) / (8 * FRAMESIZE); 118 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
112 frame_counter = seek_frame_offset; 119 elapsed = param;
113 ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE);
114 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
115 elapsed = ci->seek_time;
116
117 ci->set_elapsed(elapsed);
118 ci->seek_complete();
119 }
120
121 res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE);
122
123 if(res != (int)FRAMESIZE) {
124 DEBUGF("codec error\n");
125 return CODEC_ERROR;
126 }
127
128 if(datasize)
129 ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, q.samples_per_frame / ci->id3->channels);
130
131 elapsed += (FRAMESIZE * 8) / BITRATE;
132 ci->set_elapsed(elapsed); 120 ci->set_elapsed(elapsed);
133 121 ci->seek_complete();
134 ci->advance_buffer(FRAMESIZE); 122 }
135 frame_counter++; 123
136 } 124 action = CODEC_ACTION_NULL;
137 125
138 done: 126 res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE);
139 if (ci->request_next_track()) 127
140 goto next_track; 128 if(res != (int)FRAMESIZE) {
129 DEBUGF("codec error\n");
130 return CODEC_ERROR;
131 }
132
133 if(datasize)
134 ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024,
135 q.samples_per_frame / ci->id3->channels);
136
137 elapsed += (FRAMESIZE * 8) / BITRATE;
138 ci->set_elapsed(elapsed);
139
140 ci->advance_buffer(FRAMESIZE);
141 frame_counter++;
142 }
141 143
142 return CODEC_OK; 144 return CODEC_OK;
143} 145}
diff --git a/apps/codecs/atrac3_rm.c b/apps/codecs/atrac3_rm.c
index 6a77d24283..1322e917ed 100644
--- a/apps/codecs/atrac3_rm.c
+++ b/apps/codecs/atrac3_rm.c
@@ -41,9 +41,9 @@ static void init_rm(RMContext *rmctx)
41 memcpy(ci->id3->id3v2buf, (char*)rmctx->codec_extradata, rmctx->extradata_size*sizeof(char)); 41 memcpy(ci->id3->id3v2buf, (char*)rmctx->codec_extradata, rmctx->extradata_size*sizeof(char));
42} 42}
43 43
44/* this is the codec entry point */ 44/* this is called for each file to process */
45enum codec_status codec_main(void) 45enum codec_status codec_run(void)
46{ 46{
47 static size_t buff_size; 47 static size_t buff_size;
48 int datasize, res, consumed, i, time_offset; 48 int datasize, res, consumed, i, time_offset;
49 uint8_t *bit_buffer; 49 uint8_t *bit_buffer;
@@ -52,16 +52,14 @@ enum codec_status codec_main(void)
52 int scrambling_unit_size, num_units, elapsed = 0; 52 int scrambling_unit_size, num_units, elapsed = 0;
53 int playback_on = -1; 53 int playback_on = -1;
54 size_t resume_offset; 54 size_t resume_offset;
55 intptr_t param;
56 enum codec_command_action action = CODEC_ACTION_NULL;
55 57
56next_track:
57 if (codec_init()) { 58 if (codec_init()) {
58 DEBUGF("codec init failed\n"); 59 DEBUGF("codec init failed\n");
59 return CODEC_ERROR; 60 return CODEC_ERROR;
60 } 61 }
61 62
62 if (codec_wait_taginfo() != 0)
63 goto done;
64
65 resume_offset = ci->id3->offset; 63 resume_offset = ci->id3->offset;
66 64
67 codec_set_replaygain(ci->id3); 65 codec_set_replaygain(ci->id3);
@@ -69,6 +67,7 @@ next_track:
69 ci->memset(&pkt,0,sizeof(RMPacket)); 67 ci->memset(&pkt,0,sizeof(RMPacket));
70 ci->memset(&q,0,sizeof(ATRAC3Context)); 68 ci->memset(&q,0,sizeof(ATRAC3Context));
71 69
70 ci->seek_buffer(0);
72 init_rm(&rmctx); 71 init_rm(&rmctx);
73 72
74 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); 73 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
@@ -84,22 +83,25 @@ next_track:
84 h = rmctx.sub_packet_h; 83 h = rmctx.sub_packet_h;
85 scrambling_unit_size = h*fs; 84 scrambling_unit_size = h*fs;
86 85
87 res =atrac3_decode_init(&q, ci->id3); 86 res = atrac3_decode_init(&q, ci->id3);
88 if(res < 0) { 87 if(res < 0) {
89 DEBUGF("failed to initialize RM atrac decoder\n"); 88 DEBUGF("failed to initialize RM atrac decoder\n");
90 return CODEC_ERROR; 89 return CODEC_ERROR;
91 } 90 }
92 91
93 /* check for a mid-track resume and force a seek time accordingly */ 92 /* check for a mid-track resume and force a seek time accordingly */
94 if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { 93 if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
95 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; 94 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
96 num_units = (int)resume_offset / scrambling_unit_size; 95 num_units = (int)resume_offset / scrambling_unit_size;
97 /* put number of subpackets to skip in resume_offset */ 96 /* put number of subpackets to skip in resume_offset */
98 resume_offset /= (sps + PACKET_HEADER_SIZE); 97 resume_offset /= (sps + PACKET_HEADER_SIZE);
99 ci->seek_time = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); 98 param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);
99 action = CODEC_ACTION_SEEK_TIME;
100 } 100 }
101 101 else {
102 ci->set_elapsed(0); 102 ci->set_elapsed(0);
103 }
104
103 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); 105 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
104 106
105 /* The main decoder loop */ 107 /* The main decoder loop */
@@ -115,22 +117,23 @@ seek_start :
115 return CODEC_ERROR; 117 return CODEC_ERROR;
116 } 118 }
117 else 119 else
118 goto done; 120 return CODEC_OK;
119 } 121 }
120 122
121 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) 123 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
122 { 124 {
123 ci->yield(); 125 if (action == CODEC_ACTION_NULL)
124 if (ci->stop_codec || ci->new_track) 126 action = ci->get_command(&param);
125 goto done;
126 127
127 if (ci->seek_time) { 128 if (action == CODEC_ACTION_HALT)
128 ci->set_elapsed(ci->seek_time); 129 return CODEC_OK;
129 130
131 if (action == CODEC_ACTION_SEEK_TIME) {
130 /* Do not allow seeking beyond the file's length */ 132 /* Do not allow seeking beyond the file's length */
131 if ((unsigned) ci->seek_time > ci->id3->length) { 133 if ((unsigned) param > ci->id3->length) {
134 ci->set_elapsed(ci->id3->length);
132 ci->seek_complete(); 135 ci->seek_complete();
133 goto done; 136 return CODEC_OK;
134 } 137 }
135 138
136 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); 139 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
@@ -139,12 +142,13 @@ seek_start :
139 rmctx.frame_number = 0; 142 rmctx.frame_number = 0;
140 143
141 /* Seek to the start of the track */ 144 /* Seek to the start of the track */
142 if (ci->seek_time == 1) { 145 if (param == 0) {
143 ci->set_elapsed(0); 146 ci->set_elapsed(0);
144 ci->seek_complete(); 147 ci->seek_complete();
148 action = CODEC_ACTION_NULL;
145 goto seek_start; 149 goto seek_start;
146 } 150 }
147 num_units = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); 151 num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps));
148 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); 152 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units);
149 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); 153 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
150 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); 154 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
@@ -155,12 +159,12 @@ seek_start :
155 return CODEC_ERROR; 159 return CODEC_ERROR;
156 } 160 }
157 else 161 else
158 goto done; 162 return CODEC_OK;
159 } 163 }
160 164
161 packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; 165 packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units;
162 rmctx.frame_number = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate)); 166 rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate));
163 while(rmctx.audiotimestamp > (unsigned) ci->seek_time) { 167 while(rmctx.audiotimestamp > (unsigned) param) {
164 rmctx.audio_pkt_cnt = 0; 168 rmctx.audio_pkt_cnt = 0;
165 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); 169 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1));
166 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); 170 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
@@ -168,16 +172,19 @@ seek_start :
168 packet_count += rmctx.audio_pkt_cnt; 172 packet_count += rmctx.audio_pkt_cnt;
169 num_units--; 173 num_units--;
170 } 174 }
171 time_offset = ci->seek_time - rmctx.audiotimestamp; 175 time_offset = param - rmctx.audiotimestamp;
172 i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); 176 i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate));
173 elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i; 177 elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i;
174 ci->set_elapsed(elapsed); 178 ci->set_elapsed(elapsed);
175 ci->seek_complete(); 179 ci->seek_complete();
176 } 180 }
181
182 action = CODEC_ACTION_NULL;
183
177 if(pkt.length) 184 if(pkt.length)
178 res = atrac3_decode_frame(rmctx.block_align, &q, &datasize, pkt.frames[i], rmctx.block_align); 185 res = atrac3_decode_frame(rmctx.block_align, &q, &datasize, pkt.frames[i], rmctx.block_align);
179 else /* indicates that there are no remaining frames */ 186 else /* indicates that there are no remaining frames */
180 goto done; 187 return CODEC_OK;
181 188
182 if(res != rmctx.block_align) { 189 if(res != rmctx.block_align) {
183 DEBUGF("codec error\n"); 190 DEBUGF("codec error\n");
@@ -196,9 +203,5 @@ seek_start :
196 ci->advance_buffer(consumed); 203 ci->advance_buffer(consumed);
197 } 204 }
198 205
199 done : 206 return CODEC_OK;
200 if (ci->request_next_track())
201 goto next_track;
202
203 return CODEC_OK;
204} 207}
diff --git a/apps/codecs/au.c b/apps/codecs/au.c
index 3f9436c9e7..e06f931cf9 100644
--- a/apps/codecs/au.c
+++ b/apps/codecs/au.c
@@ -106,9 +106,19 @@ static int convert_au_format(unsigned int encoding, struct pcm_format *fmt)
106} 106}
107 107
108/* this is the codec entry point */ 108/* this is the codec entry point */
109enum codec_status codec_main(void) 109enum codec_status codec_main(enum codec_entry_call_reason reason)
110{
111 if (reason == CODEC_LOAD) {
112 /* Generic codec initialisation */
113 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
114 }
115
116 return CODEC_OK;
117}
118
119/* this is called for each file to process */
120enum codec_status codec_run(void)
110{ 121{
111 int status;
112 struct pcm_format format; 122 struct pcm_format format;
113 uint32_t bytesdone, decodedsamples; 123 uint32_t bytesdone, decodedsamples;
114 size_t n; 124 size_t n;
@@ -119,22 +129,13 @@ enum codec_status codec_main(void)
119 off_t firstblockposn; /* position of the first block in file */ 129 off_t firstblockposn; /* position of the first block in file */
120 const struct pcm_codec *codec; 130 const struct pcm_codec *codec;
121 int offset = 0; 131 int offset = 0;
122 132 intptr_t param;
123 /* Generic codec initialisation */ 133
124 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
125
126next_track:
127 status = CODEC_OK;
128
129 if (codec_init()) { 134 if (codec_init()) {
130 DEBUGF("codec_init() error\n"); 135 DEBUGF("codec_init() error\n");
131 status = CODEC_ERROR; 136 return CODEC_ERROR;
132 goto exit;
133 } 137 }
134 138
135 if (codec_wait_taginfo() != 0)
136 goto done;
137
138 codec_set_replaygain(ci->id3); 139 codec_set_replaygain(ci->id3);
139 140
140 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 141 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
@@ -145,6 +146,7 @@ next_track:
145 format.is_little_endian = false; 146 format.is_little_endian = false;
146 147
147 /* set format */ 148 /* set format */
149 ci->seek_buffer(0);
148 buf = ci->request_buffer(&n, 24); 150 buf = ci->request_buffer(&n, 24);
149 if (n < 24 || (memcmp(buf, ".snd", 4) != 0)) 151 if (n < 24 || (memcmp(buf, ".snd", 4) != 0))
150 { 152 {
@@ -170,8 +172,7 @@ next_track:
170 if (offset < 24) 172 if (offset < 24)
171 { 173 {
172 DEBUGF("CODEC_ERROR: sun audio offset size is small: %d\n", offset); 174 DEBUGF("CODEC_ERROR: sun audio offset size is small: %d\n", offset);
173 status = CODEC_ERROR; 175 return CODEC_ERROR;
174 goto done;
175 } 176 }
176 /* data size */ 177 /* data size */
177 format.numbytes = get_be32(buf + 8); 178 format.numbytes = get_be32(buf + 8);
@@ -182,8 +183,7 @@ next_track:
182 if (format.formattag == AU_FORMAT_UNSUPPORT) 183 if (format.formattag == AU_FORMAT_UNSUPPORT)
183 { 184 {
184 DEBUGF("CODEC_ERROR: sun audio unsupport format: %d\n", get_be32(buf + 12)); 185 DEBUGF("CODEC_ERROR: sun audio unsupport format: %d\n", get_be32(buf + 12));
185 status = CODEC_ERROR; 186 return CODEC_ERROR;
186 goto done;
187 } 187 }
188 /* skip sample rate */ 188 /* skip sample rate */
189 format.channels = get_be32(buf + 20); 189 format.channels = get_be32(buf + 20);
@@ -202,20 +202,17 @@ next_track:
202 if (!codec) 202 if (!codec)
203 { 203 {
204 DEBUGF("CODEC_ERROR: unsupport sun audio format: %x\n", (int)format.formattag); 204 DEBUGF("CODEC_ERROR: unsupport sun audio format: %x\n", (int)format.formattag);
205 status = CODEC_ERROR; 205 return CODEC_ERROR;
206 goto done;
207 } 206 }
208 207
209 if (!codec->set_format(&format)) 208 if (!codec->set_format(&format))
210 { 209 {
211 status = CODEC_ERROR; 210 return CODEC_ERROR;
212 goto done;
213 } 211 }
214 212
215 if (format.numbytes == 0) { 213 if (format.numbytes == 0) {
216 DEBUGF("CODEC_ERROR: data size is 0\n"); 214 DEBUGF("CODEC_ERROR: data size is 0\n");
217 status = CODEC_ERROR; 215 return CODEC_ERROR;
218 goto done;
219 } 216 }
220 217
221 /* check chunksize */ 218 /* check chunksize */
@@ -225,8 +222,7 @@ next_track:
225 if (format.chunksize == 0) 222 if (format.chunksize == 0)
226 { 223 {
227 DEBUGF("CODEC_ERROR: chunksize is 0\n"); 224 DEBUGF("CODEC_ERROR: chunksize is 0\n");
228 status = CODEC_ERROR; 225 return CODEC_ERROR;
229 goto done;
230 } 226 }
231 227
232 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 228 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -236,8 +232,7 @@ next_track:
236 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 232 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
237 } else { 233 } else {
238 DEBUGF("CODEC_ERROR: more than 2 channels\n"); 234 DEBUGF("CODEC_ERROR: more than 2 channels\n");
239 status = CODEC_ERROR; 235 return CODEC_ERROR;
240 goto done;
241 } 236 }
242 237
243 /* make sure we're at the correct offset */ 238 /* make sure we're at the correct offset */
@@ -253,7 +248,6 @@ next_track:
253 bytesdone = newpos->pos; 248 bytesdone = newpos->pos;
254 decodedsamples = newpos->samples; 249 decodedsamples = newpos->samples;
255 } 250 }
256 ci->seek_complete();
257 } else { 251 } else {
258 /* already where we need to be */ 252 /* already where we need to be */
259 bytesdone = 0; 253 bytesdone = 0;
@@ -263,22 +257,29 @@ next_track:
263 endofstream = 0; 257 endofstream = 0;
264 258
265 while (!endofstream) { 259 while (!endofstream) {
266 ci->yield(); 260 enum codec_command_action action = ci->get_command(&param);
267 if (ci->stop_codec || ci->new_track) { 261
262 if (action == CODEC_ACTION_HALT)
268 break; 263 break;
269 }
270 264
271 if (ci->seek_time) { 265 if (action == CODEC_ACTION_SEEK_TIME) {
272 /* 3rd args(read_buffer) is unnecessary in the format which Sun Audio supports. */ 266 /* 3rd args(read_buffer) is unnecessary in the format which Sun Audio supports. */
273 struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); 267 struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL);
274 268
275 if (newpos->pos > format.numbytes) 269 if (newpos->pos > format.numbytes)
270 {
271 ci->set_elapsed(ci->id3->length);
272 ci->seek_complete();
276 break; 273 break;
274 }
275
277 if (ci->seek_buffer(firstblockposn + newpos->pos)) 276 if (ci->seek_buffer(firstblockposn + newpos->pos))
278 { 277 {
279 bytesdone = newpos->pos; 278 bytesdone = newpos->pos;
280 decodedsamples = newpos->samples; 279 decodedsamples = newpos->samples;
281 } 280 }
281
282 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
282 ci->seek_complete(); 283 ci->seek_complete();
283 } 284 }
284 285
@@ -290,11 +291,10 @@ next_track:
290 endofstream = 1; 291 endofstream = 1;
291 } 292 }
292 293
293 status = codec->decode(aubuf, n, samples, &bufcount); 294 if (codec->decode(aubuf, n, samples, &bufcount) == CODEC_ERROR)
294 if (status == CODEC_ERROR)
295 { 295 {
296 DEBUGF("codec error\n"); 296 DEBUGF("codec error\n");
297 goto done; 297 return CODEC_ERROR;
298 } 298 }
299 299
300 ci->pcmbuf_insert(samples, NULL, bufcount); 300 ci->pcmbuf_insert(samples, NULL, bufcount);
@@ -308,9 +308,5 @@ next_track:
308 } 308 }
309 309
310done: 310done:
311 if (ci->request_next_track()) 311 return CODEC_OK;
312 goto next_track;
313
314exit:
315 return status;
316} 312}
diff --git a/apps/codecs/codec_crt0.c b/apps/codecs/codec_crt0.c
index cf14e460ec..33876272c6 100644
--- a/apps/codecs/codec_crt0.c
+++ b/apps/codecs/codec_crt0.c
@@ -27,39 +27,45 @@ struct codec_api *ci DATA_ATTR;
27extern unsigned char plugin_bss_start[]; 27extern unsigned char plugin_bss_start[];
28extern unsigned char plugin_end_addr[]; 28extern unsigned char plugin_end_addr[];
29 29
30extern enum codec_status codec_main(void); 30extern enum codec_status codec_main(enum codec_entry_call_reason reason);
31 31
32/* stub, the entry point is called via its reference in __header to 32/* stub, the entry point is called via its reference in __header to
33 * avoid warning with certain compilers */ 33 * avoid warning with certain compilers */
34int _start(void) {return 0;} 34int _start(void) {return 0;}
35 35
36enum codec_status codec_start(void) 36enum codec_status codec_start(enum codec_entry_call_reason reason)
37{ 37{
38#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 38#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
39#ifdef USE_IRAM 39 if (reason == CODEC_LOAD)
40 extern char iramcopy[], iramstart[], iramend[], iedata[], iend[];
41 size_t iram_size = iramend - iramstart;
42 size_t ibss_size = iend - iedata;
43 if (iram_size > 0 || ibss_size > 0)
44 { 40 {
45 ci->memcpy(iramstart, iramcopy, iram_size); 41#ifdef USE_IRAM
46 ci->memset(iedata, 0, ibss_size); 42 extern char iramcopy[], iramstart[], iramend[], iedata[], iend[];
47 /* make the icache (if it exists) up to date with the new code */ 43 size_t iram_size = iramend - iramstart;
44 size_t ibss_size = iend - iedata;
45 if (iram_size > 0 || ibss_size > 0)
46 {
47 ci->memcpy(iramstart, iramcopy, iram_size);
48 ci->memset(iedata, 0, ibss_size);
49 /* make the icache (if it exists) up to date with the new code */
50 ci->cpucache_invalidate();
51 /* barrier to prevent reordering iram copy and BSS clearing,
52 * because the BSS segment alias the IRAM copy.
53 */
54 asm volatile ("" ::: "memory");
55 }
56#endif /* PLUGIN_USE_IRAM */
57 ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start);
58 /* Some parts of bss may be used via a no-cache alias (at least
59 * portalplayer has this). If we don't clear the cache, those aliases
60 * may read garbage */
48 ci->cpucache_invalidate(); 61 ci->cpucache_invalidate();
49 /* barrier to prevent reordering iram copy and BSS clearing,
50 * because the BSS segment alias the IRAM copy.
51 */
52 asm volatile ("" ::: "memory");
53 } 62 }
54#endif /* PLUGIN_USE_IRAM */ 63#endif /* CONFIG_PLATFORM */
55 ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start);
56 /* Some parts of bss may be used via a no-cache alias (at least
57 * portalplayer has this). If we don't clear the cache, those aliases
58 * may read garbage */
59 ci->cpucache_invalidate();
60#endif
61 64
62 return codec_main(); 65 /* Note: If for any reason codec_main would not be called with CODEC_LOAD
66 * because the above code failed then it must not be ever be called with
67 * any other value and some strategy to avoid doing so must be conceived */
68 return codec_main(reason);
63} 69}
64 70
65#if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE) 71#if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE)
diff --git a/apps/codecs/cook.c b/apps/codecs/cook.c
index 015618986c..a6b4a1153e 100644
--- a/apps/codecs/cook.c
+++ b/apps/codecs/cook.c
@@ -38,9 +38,9 @@ static void init_rm(RMContext *rmctx)
38 memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext)); 38 memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
39} 39}
40 40
41/* this is the codec entry point */ 41/* this is called for each file to process */
42enum codec_status codec_main(void) 42enum codec_status codec_run(void)
43{ 43{
44 static size_t buff_size; 44 static size_t buff_size;
45 int datasize, res, consumed, i, time_offset; 45 int datasize, res, consumed, i, time_offset;
46 uint8_t *bit_buffer; 46 uint8_t *bit_buffer;
@@ -48,16 +48,14 @@ enum codec_status codec_main(void)
48 uint32_t packet_count; 48 uint32_t packet_count;
49 int scrambling_unit_size, num_units; 49 int scrambling_unit_size, num_units;
50 size_t resume_offset; 50 size_t resume_offset;
51 intptr_t param = 0;
52 enum codec_command_action action = CODEC_ACTION_NULL;
51 53
52next_track:
53 if (codec_init()) { 54 if (codec_init()) {
54 DEBUGF("codec init failed\n"); 55 DEBUGF("codec init failed\n");
55 return CODEC_ERROR; 56 return CODEC_ERROR;
56 } 57 }
57 58
58 if (codec_wait_taginfo() != 0)
59 goto done;
60
61 resume_offset = ci->id3->offset; 59 resume_offset = ci->id3->offset;
62 60
63 codec_set_replaygain(ci->id3); 61 codec_set_replaygain(ci->id3);
@@ -65,6 +63,8 @@ next_track:
65 ci->memset(&pkt,0,sizeof(RMPacket)); 63 ci->memset(&pkt,0,sizeof(RMPacket));
66 ci->memset(&q,0,sizeof(COOKContext)); 64 ci->memset(&q,0,sizeof(COOKContext));
67 65
66 ci->seek_buffer(0);
67
68 init_rm(&rmctx); 68 init_rm(&rmctx);
69 69
70 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); 70 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
@@ -87,20 +87,21 @@ next_track:
87 DEBUGF("failed to initialize cook decoder\n"); 87 DEBUGF("failed to initialize cook decoder\n");
88 return CODEC_ERROR; 88 return CODEC_ERROR;
89 } 89 }
90 90
91 /* check for a mid-track resume and force a seek time accordingly */ 91 /* check for a mid-track resume and force a seek time accordingly */
92 if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { 92 if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
93 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; 93 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
94 num_units = (int)resume_offset / scrambling_unit_size; 94 num_units = (int)resume_offset / scrambling_unit_size;
95 /* put number of subpackets to skip in resume_offset */ 95 /* put number of subpackets to skip in resume_offset */
96 resume_offset /= (sps + PACKET_HEADER_SIZE); 96 resume_offset /= (sps + PACKET_HEADER_SIZE);
97 ci->seek_time = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); 97 param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);
98 action = CODEC_ACTION_SEEK_TIME;
98 } 99 }
99 100
100 ci->set_elapsed(0); 101 ci->set_elapsed(0);
101 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); 102 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
102 103
103 /* The main decoder loop */ 104 /* The main decoder loop */
104seek_start : 105seek_start :
105 while(packet_count) 106 while(packet_count)
106 { 107 {
@@ -112,18 +113,19 @@ seek_start :
112 } 113 }
113 114
114 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) 115 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
115 { 116 {
116 ci->yield(); 117 if (action == CODEC_ACTION_NULL)
117 if (ci->stop_codec || ci->new_track) 118 action = ci->get_command(&param);
118 goto done;
119 119
120 if (ci->seek_time) { 120 if (action == CODEC_ACTION_HALT)
121 ci->set_elapsed(ci->seek_time); 121 return CODEC_OK;
122 122
123 if (action == CODEC_ACTION_SEEK_TIME) {
123 /* Do not allow seeking beyond the file's length */ 124 /* Do not allow seeking beyond the file's length */
124 if ((unsigned) ci->seek_time > ci->id3->length) { 125 if ((unsigned) param > ci->id3->length) {
126 ci->set_elapsed(ci->id3->length);
125 ci->seek_complete(); 127 ci->seek_complete();
126 goto done; 128 return CODEC_OK;
127 } 129 }
128 130
129 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); 131 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
@@ -132,22 +134,24 @@ seek_start :
132 rmctx.frame_number = 0; 134 rmctx.frame_number = 0;
133 135
134 /* Seek to the start of the track */ 136 /* Seek to the start of the track */
135 if (ci->seek_time == 1) { 137 if (param == 0) {
136 ci->set_elapsed(0); 138 ci->set_elapsed(0);
137 ci->seek_complete(); 139 ci->seek_complete();
140 action = CODEC_ACTION_NULL;
138 goto seek_start; 141 goto seek_start;
139 } 142 }
140 num_units = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); 143 num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps));
141 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); 144 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units);
142 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); 145 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
143 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); 146 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
144 if(consumed < 0) { 147 if(consumed < 0) {
145 DEBUGF("rm_get_packet failed\n"); 148 DEBUGF("rm_get_packet failed\n");
146 return CODEC_ERROR; 149 ci->seek_complete();
150 return CODEC_ERROR;
147 } 151 }
148 packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; 152 packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units;
149 rmctx.frame_number = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate)); 153 rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate));
150 while(rmctx.audiotimestamp > (unsigned) ci->seek_time) { 154 while(rmctx.audiotimestamp > (unsigned) param) {
151 rmctx.audio_pkt_cnt = 0; 155 rmctx.audio_pkt_cnt = 0;
152 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); 156 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1));
153 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); 157 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
@@ -155,11 +159,14 @@ seek_start :
155 packet_count += rmctx.audio_pkt_cnt; 159 packet_count += rmctx.audio_pkt_cnt;
156 num_units--; 160 num_units--;
157 } 161 }
158 time_offset = ci->seek_time - rmctx.audiotimestamp; 162 time_offset = param - rmctx.audiotimestamp;
159 i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); 163 i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate));
160 ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); 164 ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i);
161 ci->seek_complete(); 165 ci->seek_complete();
162 } 166 }
167
168 action = CODEC_ACTION_NULL;
169
163 res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], rmctx.block_align); 170 res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], rmctx.block_align);
164 rmctx.frame_number++; 171 rmctx.frame_number++;
165 172
@@ -181,9 +188,5 @@ seek_start :
181 ci->advance_buffer(consumed); 188 ci->advance_buffer(consumed);
182 } 189 }
183 190
184 done : 191 return CODEC_OK;
185 if (ci->request_next_track())
186 goto next_track;
187
188 return CODEC_OK;
189} 192}
diff --git a/apps/codecs/flac.c b/apps/codecs/flac.c
index 89d14b98a7..a5521b584f 100644
--- a/apps/codecs/flac.c
+++ b/apps/codecs/flac.c
@@ -418,40 +418,40 @@ static bool flac_seek_offset(FLACContext* fc, uint32_t offset) {
418} 418}
419 419
420/* this is the codec entry point */ 420/* this is the codec entry point */
421enum codec_status codec_main(void) 421enum codec_status codec_main(enum codec_entry_call_reason reason)
422{
423 if (reason == CODEC_LOAD) {
424 /* Generic codec initialisation */
425 ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1);
426 }
427
428 return CODEC_OK;
429}
430
431/* this is called for each file to process */
432enum codec_status codec_run(void)
422{ 433{
423 int8_t *buf; 434 int8_t *buf;
424 FLACContext fc; 435 FLACContext fc;
425 uint32_t samplesdone = 0; 436 uint32_t samplesdone;
426 uint32_t elapsedtime; 437 uint32_t elapsedtime;
427 size_t bytesleft; 438 size_t bytesleft;
428 int consumed; 439 int consumed;
429 int res; 440 int res;
430 int frame; 441 int frame;
431 int retval; 442 intptr_t param;
432
433 /* Generic codec initialisation */
434 ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1);
435 443
436next_track:
437 retval = CODEC_OK;
438
439 if (codec_init()) { 444 if (codec_init()) {
440 LOGF("FLAC: Error initialising codec\n"); 445 LOGF("FLAC: Error initialising codec\n");
441 retval = CODEC_ERROR; 446 return CODEC_ERROR;
442 goto exit;
443 } 447 }
444 448
445 if (codec_wait_taginfo() != 0)
446 goto done;
447
448 /* Need to save offset for later use (cleared indirectly by flac_init) */ 449 /* Need to save offset for later use (cleared indirectly by flac_init) */
449 samplesdone = ci->id3->offset; 450 samplesdone = ci->id3->offset;
450 451
451 if (!flac_init(&fc,ci->id3->first_frame_offset)) { 452 if (!flac_init(&fc,ci->id3->first_frame_offset)) {
452 LOGF("FLAC: Error initialising codec\n"); 453 LOGF("FLAC: Error initialising codec\n");
453 retval = CODEC_ERROR; 454 return CODEC_ERROR;
454 goto done;
455 } 455 }
456 456
457 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 457 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -459,35 +459,34 @@ next_track:
459 STEREO_MONO : STEREO_NONINTERLEAVED); 459 STEREO_MONO : STEREO_NONINTERLEAVED);
460 codec_set_replaygain(ci->id3); 460 codec_set_replaygain(ci->id3);
461 461
462 if (samplesdone) { 462 flac_seek_offset(&fc, samplesdone);
463 flac_seek_offset(&fc, samplesdone); 463 samplesdone=0;
464 samplesdone=0;
465 }
466 464
467 /* The main decoding loop */ 465 /* The main decoding loop */
468 frame=0; 466 frame=0;
469 buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); 467 buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE);
470 while (bytesleft) { 468 while (bytesleft) {
471 ci->yield(); 469 enum codec_command_action action = ci->get_command(&param);
472 if (ci->stop_codec || ci->new_track) { 470
471 if (action == CODEC_ACTION_HALT)
473 break; 472 break;
474 }
475 473
476 /* Deal with any pending seek requests */ 474 /* Deal with any pending seek requests */
477 if (ci->seek_time) { 475 if (action == CODEC_ACTION_SEEK_TIME) {
478 if (flac_seek(&fc,(uint32_t)(((uint64_t)(ci->seek_time-1) 476 if (flac_seek(&fc,(uint32_t)(((uint64_t)param
479 *ci->id3->frequency)/1000))) { 477 *ci->id3->frequency)/1000))) {
480 /* Refill the input buffer */ 478 /* Refill the input buffer */
481 buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); 479 buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE);
482 } 480 }
481
482 ci->set_elapsed(param);
483 ci->seek_complete(); 483 ci->seek_complete();
484 } 484 }
485 485
486 if((res=flac_decode_frame(&fc,decoded0,decoded1,buf, 486 if((res=flac_decode_frame(&fc,decoded0,decoded1,buf,
487 bytesleft,ci->yield)) < 0) { 487 bytesleft,ci->yield)) < 0) {
488 LOGF("FLAC: Frame %d, error %d\n",frame,res); 488 LOGF("FLAC: Frame %d, error %d\n",frame,res);
489 retval = CODEC_ERROR; 489 return CODEC_ERROR;
490 goto done;
491 } 490 }
492 consumed=fc.gb.index/8; 491 consumed=fc.gb.index/8;
493 frame++; 492 frame++;
@@ -507,14 +506,7 @@ next_track:
507 506
508 buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); 507 buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE);
509 } 508 }
510 retval = CODEC_OK;
511 509
512done:
513 LOGF("FLAC: Decoded %lu samples\n",(unsigned long)samplesdone); 510 LOGF("FLAC: Decoded %lu samples\n",(unsigned long)samplesdone);
514 511 return CODEC_OK;
515 if (ci->request_next_track())
516 goto next_track;
517
518exit:
519 return retval;
520} 512}
diff --git a/apps/codecs/lib/codeclib.c b/apps/codecs/lib/codeclib.c
index af0894c498..443c0bbdcf 100644
--- a/apps/codecs/lib/codeclib.c
+++ b/apps/codecs/lib/codeclib.c
@@ -33,6 +33,16 @@ unsigned char* mp3buf; // The actual MP3 buffer from Rockbox
33unsigned char* mallocbuf; // 512K from the start of MP3 buffer 33unsigned char* mallocbuf; // 512K from the start of MP3 buffer
34unsigned char* filebuf; // The rest of the MP3 buffer 34unsigned char* filebuf; // The rest of the MP3 buffer
35 35
36/* this is the default codec entry point for when nothing needs to be done
37 on load or unload */
38enum codec_status __attribute__((weak))
39codec_main(enum codec_entry_call_reason reason)
40{
41 /* Nothing to do */
42 return CODEC_OK;
43 (void)reason;
44}
45
36int codec_init(void) 46int codec_init(void)
37{ 47{
38 mem_ptr = 0; 48 mem_ptr = 0;
@@ -41,7 +51,7 @@ int codec_init(void)
41 return 0; 51 return 0;
42} 52}
43 53
44void codec_set_replaygain(struct mp3entry* id3) 54void codec_set_replaygain(const struct mp3entry *id3)
45{ 55{
46 ci->configure(DSP_SET_TRACK_GAIN, id3->track_gain); 56 ci->configure(DSP_SET_TRACK_GAIN, id3->track_gain);
47 ci->configure(DSP_SET_ALBUM_GAIN, id3->album_gain); 57 ci->configure(DSP_SET_ALBUM_GAIN, id3->album_gain);
@@ -49,19 +59,6 @@ void codec_set_replaygain(struct mp3entry* id3)
49 ci->configure(DSP_SET_ALBUM_PEAK, id3->album_peak); 59 ci->configure(DSP_SET_ALBUM_PEAK, id3->album_peak);
50} 60}
51 61
52/* Note: codec really needs its own private metdata copy for the current
53 track being processed in order to be stable. */
54int codec_wait_taginfo(void)
55{
56 while (!*ci->taginfo_ready && !ci->stop_codec && !ci->new_track)
57 ci->sleep(0);
58 if (ci->stop_codec)
59 return -1;
60 if (ci->new_track)
61 return 1;
62 return 0;
63}
64
65/* Various "helper functions" common to all the xxx2wav decoder plugins */ 62/* Various "helper functions" common to all the xxx2wav decoder plugins */
66 63
67 64
diff --git a/apps/codecs/lib/codeclib.h b/apps/codecs/lib/codeclib.h
index 41b466ed1f..30091c5333 100644
--- a/apps/codecs/lib/codeclib.h
+++ b/apps/codecs/lib/codeclib.h
@@ -156,8 +156,7 @@ static inline unsigned int bs_generic(unsigned int v, int mode)
156/* Various codec helper functions */ 156/* Various codec helper functions */
157 157
158int codec_init(void); 158int codec_init(void);
159void codec_set_replaygain(struct mp3entry* id3); 159void codec_set_replaygain(const struct mp3entry *id3);
160int codec_wait_taginfo(void); /* 0 = success */
161 160
162#ifdef RB_PROFILE 161#ifdef RB_PROFILE
163void __cyg_profile_func_enter(void *this_fn, void *call_site) 162void __cyg_profile_func_enter(void *this_fn, void *call_site)
diff --git a/apps/codecs/mod.c b/apps/codecs/mod.c
index 4ace721a1e..3dfaac663f 100644
--- a/apps/codecs/mod.c
+++ b/apps/codecs/mod.c
@@ -1218,47 +1218,37 @@ void synthrender(int32_t *renderbuffer, int samplecount)
1218 } 1218 }
1219} 1219}
1220 1220
1221/* this is the codec entry point */
1222enum codec_status codec_main(enum codec_entry_call_reason reason)
1223{
1224 if (reason == CODEC_LOAD) {
1225 /* Make use of 44.1khz */
1226 ci->configure(DSP_SET_FREQUENCY, 44100);
1227 /* Sample depth is 28 bit host endian */
1228 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
1229 /* Stereo output */
1230 ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
1231 }
1232
1233 return CODEC_OK;
1234}
1221 1235
1222enum codec_status codec_main(void) 1236/* this is called for each file to process */
1237enum codec_status codec_run(void)
1223{ 1238{
1224 size_t n; 1239 size_t n;
1225 unsigned char *modfile; 1240 unsigned char *modfile;
1226 int old_patterntableposition; 1241 int old_patterntableposition;
1227
1228 int bytesdone; 1242 int bytesdone;
1243 intptr_t param;
1229 1244
1230next_track:
1231 if (codec_init()) { 1245 if (codec_init()) {
1232 return CODEC_ERROR; 1246 return CODEC_ERROR;
1233 } 1247 }
1234 1248
1235 if (codec_wait_taginfo() != 0)
1236 goto request_next_track;
1237
1238 codec_set_replaygain(ci->id3); 1249 codec_set_replaygain(ci->id3);
1239 1250
1240 /* Load MOD file */ 1251 /* Load MOD file */
1241 /*
1242 * This is the save way
1243
1244 size_t bytesfree;
1245 unsigned int filesize;
1246
1247 p = modfile;
1248 bytesfree=sizeof(modfile);
1249 while ((n = ci->read_filebuf(p, bytesfree)) > 0) {
1250 p += n;
1251 bytesfree -= n;
1252 if (bytesfree == 0)
1253 return CODEC_ERROR;
1254 }
1255 filesize = p-modfile;
1256
1257 if (filesize == 0)
1258 return CODEC_ERROR;
1259 */
1260
1261 /* Directly use mod in buffer */
1262 ci->seek_buffer(0); 1252 ci->seek_buffer(0);
1263 modfile = ci->request_buffer(&n, ci->filesize); 1253 modfile = ci->request_buffer(&n, ci->filesize);
1264 if (!modfile || n < (size_t)ci->filesize) { 1254 if (!modfile || n < (size_t)ci->filesize) {
@@ -1268,27 +1258,22 @@ next_track:
1268 initmodplayer(); 1258 initmodplayer();
1269 loadmod(modfile); 1259 loadmod(modfile);
1270 1260
1271 /* Make use of 44.1khz */
1272 ci->configure(DSP_SET_FREQUENCY, 44100);
1273 /* Sample depth is 28 bit host endian */
1274 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
1275 /* Stereo output */
1276 ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
1277
1278 /* The main decoder loop */ 1261 /* The main decoder loop */
1279 ci->set_elapsed(0); 1262 ci->set_elapsed(0);
1280 bytesdone = 0; 1263 bytesdone = 0;
1281 old_patterntableposition = 0; 1264 old_patterntableposition = 0;
1282 1265
1283 while (1) { 1266 while (1) {
1284 ci->yield(); 1267 enum codec_command_action action = ci->get_command(&param);
1285 if (ci->stop_codec || ci->new_track) 1268
1269 if (action == CODEC_ACTION_HALT)
1286 break; 1270 break;
1287 1271
1288 if (ci->seek_time) { 1272 if (action == CODEC_ACTION_SEEK_TIME) {
1289 /* New time is ready in ci->seek_time */ 1273 /* New time is ready in param */
1290 modplayer.patterntableposition = ci->seek_time/1000; 1274 modplayer.patterntableposition = param/1000;
1291 modplayer.currentline = 0; 1275 modplayer.currentline = 0;
1276 ci->set_elapsed(modplayer.patterntableposition*1000+500);
1292 ci->seek_complete(); 1277 ci->seek_complete();
1293 } 1278 }
1294 1279
@@ -1305,9 +1290,5 @@ next_track:
1305 1290
1306 } 1291 }
1307 1292
1308request_next_track:
1309 if (ci->request_next_track())
1310 goto next_track;
1311
1312 return CODEC_OK; 1293 return CODEC_OK;
1313} 1294}
diff --git a/apps/codecs/mp3_enc.c b/apps/codecs/mp3_enc.c
index e7893fd14a..2f5528f74c 100644
--- a/apps/codecs/mp3_enc.c
+++ b/apps/codecs/mp3_enc.c
@@ -2584,45 +2584,46 @@ static bool enc_init(void)
2584 return true; 2584 return true;
2585} /* enc_init */ 2585} /* enc_init */
2586 2586
2587enum codec_status codec_main(void) 2587/* this is the codec entry point */
2588enum codec_status codec_main(enum codec_entry_call_reason reason)
2588{ 2589{
2589 /* Generic codec initialisation */ 2590 if (reason == CODEC_LOAD) {
2590 if (!enc_init()) 2591 if (!enc_init())
2591 return CODEC_ERROR; 2592 return CODEC_ERROR;
2593 }
2594 else if (reason == CODEC_UNLOAD) {
2595 /* reset parameters to initial state */
2596 ci->enc_set_parameters(NULL);
2597 }
2598
2599 return CODEC_OK;
2600}
2592 2601
2602/* this is called for each file to process */
2603enum codec_status codec_run(void)
2604{
2593 /* main encoding loop */ 2605 /* main encoding loop */
2594 while (!ci->stop_codec) 2606 while(ci->get_command(NULL) != CODEC_ACTION_HALT)
2595 { 2607 {
2596 char *buffer; 2608 char *buffer = buffer = ci->enc_get_pcm_data(pcm_chunk_size);
2597 2609 struct enc_chunk_hdr *chunk;
2598 while ((buffer = ci->enc_get_pcm_data(pcm_chunk_size)) != NULL)
2599 {
2600 struct enc_chunk_hdr *chunk;
2601
2602 if (ci->stop_codec)
2603 break;
2604 2610
2605 chunk = ci->enc_get_chunk(); 2611 if(buffer == NULL)
2606 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); 2612 continue;
2607 2613
2608 encode_frame(buffer, chunk); 2614 chunk = ci->enc_get_chunk();
2615 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
2609 2616
2610 if (chunk->num_pcm < samp_per_frame) 2617 encode_frame(buffer, chunk);
2611 {
2612 ci->enc_unget_pcm_data(pcm_chunk_size - chunk->num_pcm*4);
2613 chunk->num_pcm = samp_per_frame;
2614 }
2615 2618
2616 ci->enc_finish_chunk(); 2619 if (chunk->num_pcm < samp_per_frame)
2617 2620 {
2618 ci->yield(); 2621 ci->enc_unget_pcm_data(pcm_chunk_size - chunk->num_pcm*4);
2622 chunk->num_pcm = samp_per_frame;
2619 } 2623 }
2620 2624
2621 ci->yield(); 2625 ci->enc_finish_chunk();
2622 } 2626 }
2623 2627
2624 /* reset parameters to initial state */
2625 ci->enc_set_parameters(NULL);
2626
2627 return CODEC_OK; 2628 return CODEC_OK;
2628} /* codec_start */ 2629}
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c
index 4b49775029..c9e2131450 100644
--- a/apps/codecs/mpa.c
+++ b/apps/codecs/mpa.c
@@ -268,8 +268,8 @@ static bool mad_synth_thread_create(void)
268 268
269static void mad_synth_thread_quit(void) 269static void mad_synth_thread_quit(void)
270{ 270{
271 /*mop up COP thread*/ 271 /* mop up COP thread */
272 die=1; 272 die = 1;
273 ci->semaphore_release(&synth_pending_sem); 273 ci->semaphore_release(&synth_pending_sem);
274 ci->thread_wait(mad_synth_thread_id); 274 ci->thread_wait(mad_synth_thread_id);
275 ci->cpucache_invalidate(); 275 ci->cpucache_invalidate();
@@ -299,9 +299,30 @@ static inline void mad_synth_thread_unwait_pcm(void)
299#endif /* MPA_SYNTH_ON_COP */ 299#endif /* MPA_SYNTH_ON_COP */
300 300
301/* this is the codec entry point */ 301/* this is the codec entry point */
302enum codec_status codec_main(void) 302enum codec_status codec_main(enum codec_entry_call_reason reason)
303{
304 if (reason == CODEC_LOAD) {
305 /* Create a decoder instance */
306 if (codec_init())
307 return CODEC_ERROR;
308
309 ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
310
311 /* does nothing on 1 processor systems except return true */
312 if(!mad_synth_thread_create())
313 return CODEC_ERROR;
314 }
315 else if (reason == CODEC_UNLOAD) {
316 /* mop up COP thread - MT only */
317 mad_synth_thread_quit();
318 }
319
320 return CODEC_OK;
321}
322
323/* this is called for each file to process */
324enum codec_status codec_run(void)
303{ 325{
304 int status;
305 size_t size; 326 size_t size;
306 int file_end; 327 int file_end;
307 int samples_to_skip; /* samples to skip in total for this file (at start) */ 328 int samples_to_skip; /* samples to skip in total for this file (at start) */
@@ -312,27 +333,12 @@ enum codec_status codec_main(void)
312 unsigned long current_frequency = 0; 333 unsigned long current_frequency = 0;
313 int framelength; 334 int framelength;
314 int padding = MAD_BUFFER_GUARD; /* to help mad decode the last frame */ 335 int padding = MAD_BUFFER_GUARD; /* to help mad decode the last frame */
315 336 intptr_t param;
316 if (codec_init())
317 return CODEC_ERROR;
318
319 /* Create a decoder instance */
320
321 ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS);
322
323 /*does nothing on 1 processor systems except return true*/
324 if(!mad_synth_thread_create())
325 return CODEC_ERROR;
326
327next_track:
328 status = CODEC_OK;
329 337
330 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */ 338 /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */
331 init_mad(); 339 init_mad();
332 340
333 file_end = 0; 341 file_end = 0;
334 if (codec_wait_taginfo() != 0)
335 goto request_next_track;
336 342
337 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 343 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
338 current_frequency = ci->id3->frequency; 344 current_frequency = ci->id3->frequency;
@@ -379,29 +385,35 @@ next_track:
379 385
380 /* This is the decoding loop. */ 386 /* This is the decoding loop. */
381 while (1) { 387 while (1) {
382 ci->yield(); 388 enum codec_command_action action = ci->get_command(&param);
383 if (ci->stop_codec || ci->new_track) 389
390 if (action == CODEC_ACTION_HALT)
384 break; 391 break;
385 392
386 if (ci->seek_time) { 393 if (action == CODEC_ACTION_SEEK_TIME) {
387 int newpos; 394 int newpos;
388 395
389 /*make sure the synth thread is idle before seeking - MT only*/ 396 /*make sure the synth thread is idle before seeking - MT only*/
390 mad_synth_thread_wait_pcm(); 397 mad_synth_thread_wait_pcm();
391 mad_synth_thread_unwait_pcm(); 398 mad_synth_thread_unwait_pcm();
392 399
393 samplesdone = ((int64_t)(ci->seek_time-1))*current_frequency/1000; 400 samplesdone = ((int64_t)param)*current_frequency/1000;
394 401
395 if (ci->seek_time-1 == 0) { 402 if (param == 0) {
396 newpos = ci->id3->first_frame_offset; 403 newpos = ci->id3->first_frame_offset;
397 samples_to_skip = start_skip; 404 samples_to_skip = start_skip;
398 } else { 405 } else {
399 newpos = get_file_pos(ci->seek_time-1); 406 newpos = get_file_pos(param);
400 samples_to_skip = 0; 407 samples_to_skip = 0;
401 } 408 }
402 409
403 if (!ci->seek_buffer(newpos)) 410 if (!ci->seek_buffer(newpos))
411 {
412 ci->seek_complete();
404 break; 413 break;
414 }
415
416 ci->set_elapsed((samplesdone * 1000) / current_frequency);
405 ci->seek_complete(); 417 ci->seek_complete();
406 init_mad(); 418 init_mad();
407 framelength = 0; 419 framelength = 0;
@@ -435,8 +447,7 @@ next_track:
435 continue; 447 continue;
436 } else { 448 } else {
437 /* Some other unrecoverable error */ 449 /* Some other unrecoverable error */
438 status = CODEC_ERROR; 450 return CODEC_ERROR;
439 break;
440 } 451 }
441 } 452 }
442 453
@@ -504,12 +515,5 @@ next_track:
504 framelength - stop_skip); 515 framelength - stop_skip);
505 } 516 }
506 517
507request_next_track: 518 return CODEC_OK;
508 if (ci->request_next_track())
509 goto next_track;
510
511 /*mop up COP thread - MT only*/
512 mad_synth_thread_quit();
513
514 return status;
515} 519}
diff --git a/apps/codecs/mpc.c b/apps/codecs/mpc.c
index 187c37e597..bbe2d9943b 100644
--- a/apps/codecs/mpc.c
+++ b/apps/codecs/mpc.c
@@ -52,8 +52,20 @@ static mpc_int32_t get_size_impl(mpc_reader *reader)
52 return ci->filesize; 52 return ci->filesize;
53} 53}
54 54
55/* This is the codec entry point. */ 55/* this is the codec entry point */
56enum codec_status codec_main(void) 56enum codec_status codec_main(enum codec_entry_call_reason reason)
57{
58 if (reason == CODEC_LOAD) {
59 /* musepack's sample representation is 18.14
60 * DSP_SET_SAMPLE_DEPTH = 14 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 29 */
61 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
62 }
63
64 return CODEC_OK;
65}
66
67/* this is called for each file to process */
68enum codec_status codec_run(void)
57{ 69{
58 mpc_int64_t samplesdone; 70 mpc_int64_t samplesdone;
59 uint32_t frequency; /* 0.1 kHz accuracy */ 71 uint32_t frequency; /* 0.1 kHz accuracy */
@@ -64,39 +76,27 @@ enum codec_status codec_main(void)
64 mpc_streaminfo info; 76 mpc_streaminfo info;
65 mpc_frame_info frame; 77 mpc_frame_info frame;
66 mpc_demux *demux = NULL; 78 mpc_demux *demux = NULL;
67 int retval; 79 intptr_t param;
68 80
69 frame.buffer = sample_buffer; 81 frame.buffer = sample_buffer;
70 82
71 /* musepack's sample representation is 18.14
72 * DSP_SET_SAMPLE_DEPTH = 14 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 29 */
73 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
74
75 /* Create a decoder instance */ 83 /* Create a decoder instance */
76 reader.read = read_impl; 84 reader.read = read_impl;
77 reader.seek = seek_impl; 85 reader.seek = seek_impl;
78 reader.tell = tell_impl; 86 reader.tell = tell_impl;
79 reader.get_size = get_size_impl; 87 reader.get_size = get_size_impl;
80 88
81next_track:
82 retval = CODEC_OK;
83
84 if (codec_init()) 89 if (codec_init())
85 { 90 return CODEC_ERROR;
86 retval = CODEC_ERROR;
87 goto exit;
88 }
89 91
90 if (codec_wait_taginfo() != 0) 92 /* Prep position */
91 goto done; 93 ci->seek_buffer(0);
92 94
93 /* Initialize demux/decoder. */ 95 /* Initialize demux/decoder. */
94 demux = mpc_demux_init(&reader); 96 demux = mpc_demux_init(&reader);
95 if (NULL == demux) 97 if (NULL == demux)
96 { 98 return CODEC_ERROR;
97 retval = CODEC_ERROR; 99
98 goto done;
99 }
100 /* Read file's streaminfo data. */ 100 /* Read file's streaminfo data. */
101 mpc_demux_get_info(demux, &info); 101 mpc_demux_get_info(demux, &info);
102 102
@@ -117,11 +117,8 @@ next_track:
117 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); 117 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
118 else if (info.channels == 1) 118 else if (info.channels == 1)
119 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 119 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
120 else 120 else
121 { 121 return CODEC_ERROR;
122 retval = CODEC_ERROR;
123 goto done;
124 }
125 122
126 codec_set_replaygain(ci->id3); 123 codec_set_replaygain(ci->id3);
127 124
@@ -142,21 +139,24 @@ next_track:
142 /* This is the decoding loop. */ 139 /* This is the decoding loop. */
143 do 140 do
144 { 141 {
142 enum codec_command_action action = ci->get_command(&param);
143
144 if (action == CODEC_ACTION_HALT)
145 return CODEC_OK;
146
145 /* Complete seek handler. */ 147 /* Complete seek handler. */
146 if (ci->seek_time) 148 if (action == CODEC_ACTION_SEEK_TIME)
147 { 149 {
148 mpc_int64_t new_offset = ((ci->seek_time - 1)/10)*frequency; 150 mpc_int64_t new_offset = (param/10)*frequency;
149 if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK) 151 if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK)
150 { 152 {
151 samplesdone = new_offset; 153 samplesdone = new_offset;
152 ci->set_elapsed(ci->seek_time);
153 } 154 }
155
156 elapsed_time = (samplesdone*10)/frequency;
157 ci->set_elapsed(elapsed_time);
154 ci->seek_complete(); 158 ci->seek_complete();
155 } 159 }
156
157 /* Stop or skip occured, exit decoding loop. */
158 if (ci->stop_codec || ci->new_track)
159 break;
160 160
161 /* Decode one frame. */ 161 /* Decode one frame. */
162 status = mpc_demux_decode(demux, &frame); 162 status = mpc_demux_decode(demux, &frame);
@@ -164,8 +164,7 @@ next_track:
164 if (frame.bits == -1) 164 if (frame.bits == -1)
165 { 165 {
166 /* Decoding error, exit decoding loop. */ 166 /* Decoding error, exit decoding loop. */
167 retval = (status == MPC_STATUS_OK) ? CODEC_OK : CODEC_ERROR; 167 return (status == MPC_STATUS_OK) ? CODEC_OK : CODEC_ERROR;
168 goto done;
169 } 168 }
170 else 169 else
171 { 170 {
@@ -181,11 +180,4 @@ next_track:
181 ci->set_offset( (samplesdone * byterate)/(frequency*100) ); 180 ci->set_offset( (samplesdone * byterate)/(frequency*100) );
182 } 181 }
183 } while (true); 182 } while (true);
184
185done:
186 if (ci->request_next_track())
187 goto next_track;
188
189exit:
190 return retval;
191} 183}
diff --git a/apps/codecs/nsf.c b/apps/codecs/nsf.c
index 2f37da81d2..72f6974214 100644
--- a/apps/codecs/nsf.c
+++ b/apps/codecs/nsf.c
@@ -4307,46 +4307,44 @@ static void set_codec_track(int t, int d) {
4307 nSilenceTrackMS=5000; 4307 nSilenceTrackMS=5000;
4308 SetFadeTime(track,track+fade, fNSFPlaybackSpeed,def); 4308 SetFadeTime(track,track+fade, fNSFPlaybackSpeed,def);
4309 } 4309 }
4310 ci->id3->elapsed=d*1000; /* d is track no to display */ 4310 ci->set_elapsed(d*1000); /* d is track no to display */
4311} 4311}
4312 4312
4313/** Operational info **/
4314static int track = 0;
4315static char last_path[MAX_PATH];
4316static int dontresettrack = 0;
4317
4313/* this is the codec entry point */ 4318/* this is the codec entry point */
4314enum codec_status codec_main(void) 4319enum codec_status codec_main(enum codec_entry_call_reason reason)
4320{
4321 if (reason == CODEC_LOAD) {
4322 /* we only render 16 bits, 44.1KHz, Stereo */
4323 ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
4324 ci->configure(DSP_SET_FREQUENCY, 44100);
4325 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
4326
4327 RebuildOutputTables();
4328 }
4329
4330 return CODEC_OK;
4331}
4332
4333/* this is called for each file to process */
4334enum codec_status codec_run(void)
4315{ 4335{
4316 int written; 4336 int written;
4317 uint8_t *buf; 4337 uint8_t *buf;
4318 size_t n; 4338 size_t n;
4319 int endofstream; /* end of stream flag */ 4339 int endofstream; /* end of stream flag */
4320 int track; 4340 int usingplaylist = 0;
4321 int dontresettrack;
4322 char last_path[MAX_PATH];
4323 int usingplaylist;
4324
4325 /* we only render 16 bits */
4326 ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
4327
4328 ci->configure(DSP_SET_FREQUENCY, 44100);
4329 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
4330
4331 RebuildOutputTables();
4332
4333 dontresettrack=0;
4334 last_path[0]='\0';
4335 track=0;
4336 4341
4337next_track:
4338 usingplaylist=0;
4339 DEBUGF("NSF: next_track\n"); 4342 DEBUGF("NSF: next_track\n");
4340 if (codec_init()) { 4343 if (codec_init()) {
4341 return CODEC_ERROR; 4344 return CODEC_ERROR;
4342 } 4345 }
4343 DEBUGF("NSF: after init\n"); 4346 DEBUGF("NSF: after init\n");
4344 4347
4345
4346 /* wait for track info to load */
4347 if (codec_wait_taginfo() != 0)
4348 goto request_next_track;
4349
4350 codec_set_replaygain(ci->id3); 4348 codec_set_replaygain(ci->id3);
4351 4349
4352 /* Read the entire file */ 4350 /* Read the entire file */
@@ -4408,22 +4406,27 @@ init_nsf:
4408 reset_profile_timers(); 4406 reset_profile_timers();
4409 4407
4410 while (!endofstream) { 4408 while (!endofstream) {
4409 intptr_t param;
4410 enum codec_command_action action = ci->get_command(&param);
4411 4411
4412 ci->yield(); 4412 if (action == CODEC_ACTION_HALT)
4413 if (ci->stop_codec || ci->new_track) {
4414 break; 4413 break;
4415 }
4416 4414
4417 if (ci->seek_time >0) { 4415 if (action == CODEC_ACTION_SEEK_TIME) {
4418 track=ci->seek_time/1000; 4416 if (param > 0) {
4419 if (usingplaylist) { 4417 track=param/1000;
4420 if (track>=nPlaylistSize) break; 4418 if (usingplaylist) {
4421 } else { 4419 if (track>=nPlaylistSize) break;
4422 if (track>=nTrackCount) break; 4420 } else {
4421 if (track>=nTrackCount) break;
4422 }
4423 dontresettrack=1;
4424 ci->seek_complete();
4425 goto init_nsf;
4426 }
4427 else {
4428 ci->seek_complete();
4423 } 4429 }
4424 ci->seek_complete();
4425 dontresettrack=1;
4426 goto init_nsf;
4427 } 4430 }
4428 4431
4429 ENTER_TIMER(total); 4432 ENTER_TIMER(total);
@@ -4449,22 +4452,17 @@ init_nsf:
4449 4452
4450 print_timers(last_path,track); 4453 print_timers(last_path,track);
4451 4454
4452request_next_track:
4453 if (ci->request_next_track()) {
4454 if (ci->global_settings->repeat_mode==REPEAT_ONE) { 4455 if (ci->global_settings->repeat_mode==REPEAT_ONE) {
4455 /* in repeat one mode just advance to the next track */ 4456 /* in repeat one mode just advance to the next track */
4456 track++; 4457 track++;
4457 if (track>=nTrackCount) track=0; 4458 if (track>=nTrackCount) track=0;
4458 dontresettrack=1; 4459 dontresettrack=1;
4459 /* at this point we can't tell if another file has been selected */ 4460 /* at this point we can't tell if another file has been selected */
4460 goto next_track;
4461 } else { 4461 } else {
4462 /* otherwise do a proper load of the next file */ 4462 /* otherwise do a proper load of the next file */
4463 dontresettrack=0; 4463 dontresettrack=0;
4464 last_path[0]='\0'; 4464 last_path[0]='\0';
4465 } 4465 }
4466 goto next_track; /* when we fall through here we'll reload the file */
4467 }
4468 4466
4469 return CODEC_OK; 4467 return CODEC_OK;
4470} 4468}
diff --git a/apps/codecs/raac.c b/apps/codecs/raac.c
index b322ae7df3..4b73f41462 100644
--- a/apps/codecs/raac.c
+++ b/apps/codecs/raac.c
@@ -35,8 +35,21 @@ static void init_rm(RMContext *rmctx)
35 35
36static RMContext rmctx; 36static RMContext rmctx;
37static RMPacket pkt; 37static RMPacket pkt;
38
38/* this is the codec entry point */ 39/* this is the codec entry point */
39enum codec_status codec_main(void) 40enum codec_status codec_main(enum codec_entry_call_reason reason)
41{
42 if (reason == CODEC_LOAD) {
43 /* Generic codec initialisation */
44 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
45 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
46 }
47
48 return CODEC_OK;
49}
50
51/* this is called for each file to process */
52enum codec_status codec_run(void)
40{ 53{
41 static NeAACDecFrameInfo frame_info; 54 static NeAACDecFrameInfo frame_info;
42 NeAACDecHandle decoder; 55 NeAACDecHandle decoder;
@@ -49,26 +62,21 @@ enum codec_status codec_main(void)
49 unsigned char c = 0; /* channels */ 62 unsigned char c = 0; /* channels */
50 int playback_on = -1; 63 int playback_on = -1;
51 size_t resume_offset; 64 size_t resume_offset;
52 65 intptr_t param;
53 /* Generic codec initialisation */ 66 enum codec_command_action action = CODEC_ACTION_NULL;
54 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
55 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
56
57next_track:
58 err = CODEC_OK;
59 67
60 if (codec_init()) { 68 if (codec_init()) {
61 DEBUGF("FAAD: Codec init error\n"); 69 DEBUGF("FAAD: Codec init error\n");
62 return CODEC_ERROR; 70 return CODEC_ERROR;
63 } 71 }
64 72
65 if (codec_wait_taginfo() != 0)
66 goto done;
67
68 resume_offset = ci->id3->offset; 73 resume_offset = ci->id3->offset;
69 74
70 ci->memset(&rmctx,0,sizeof(RMContext)); 75 ci->memset(&rmctx,0,sizeof(RMContext));
71 ci->memset(&pkt,0,sizeof(RMPacket)); 76 ci->memset(&pkt,0,sizeof(RMPacket));
77
78 ci->seek_buffer(0);
79
72 init_rm(&rmctx); 80 init_rm(&rmctx);
73 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 81 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
74 codec_set_replaygain(ci->id3); 82 codec_set_replaygain(ci->id3);
@@ -78,9 +86,9 @@ next_track:
78 86
79 if (!decoder) { 87 if (!decoder) {
80 DEBUGF("FAAD: Decode open error\n"); 88 DEBUGF("FAAD: Decode open error\n");
81 err = CODEC_ERROR; 89 return CODEC_ERROR;
82 goto done; 90 }
83 } 91
84 NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); 92 NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
85 conf->outputFormat = FAAD_FMT_16BIT; /* irrelevant, we don't convert */ 93 conf->outputFormat = FAAD_FMT_16BIT; /* irrelevant, we don't convert */
86 NeAACDecSetConfiguration(decoder, conf); 94 NeAACDecSetConfiguration(decoder, conf);
@@ -91,8 +99,7 @@ next_track:
91 99
92 if (err) { 100 if (err) {
93 DEBUGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type); 101 DEBUGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type);
94 err = CODEC_ERROR; 102 return CODEC_ERROR;
95 goto done;
96 } 103 }
97 104
98 /* check for a mid-track resume and force a seek time accordingly */ 105 /* check for a mid-track resume and force a seek time accordingly */
@@ -100,36 +107,38 @@ next_track:
100 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; 107 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
101 /* put number of subpackets to skip in resume_offset */ 108 /* put number of subpackets to skip in resume_offset */
102 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); 109 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
103 ci->seek_time = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); 110 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
111 action = CODEC_ACTION_SEEK_TIME;
104 } 112 }
105 113
106 ci->id3->frequency = s; 114 ci->id3->frequency = s; /* FIXME: Won't get it to the UI */
107 ci->set_elapsed(0); 115 ci->set_elapsed(0);
108 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); 116 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
109 117
110 /* The main decoding loop */ 118 /* The main decoding loop */
111seek_start:
112 while (1) { 119 while (1) {
113 ci->yield(); 120 if (action == CODEC_ACTION_NULL)
114 if (ci->stop_codec || ci->new_track) { 121 action = ci->get_command(&param);
122
123 if (action == CODEC_ACTION_HALT)
115 break; 124 break;
116 }
117 125
118 if (ci->seek_time) { 126 if (action == CODEC_ACTION_SEEK_TIME) {
119
120 /* Do not allow seeking beyond the file's length */ 127 /* Do not allow seeking beyond the file's length */
121 if ((unsigned) ci->seek_time > ci->id3->length) { 128 if ((unsigned) param > ci->id3->length) {
129 ci->set_elapsed(ci->id3->length);
122 ci->seek_complete(); 130 ci->seek_complete();
123 goto done; 131 break;
124 } 132 }
125 133
126 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); 134 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
127 135
128 /* Seek to the start of the track */ 136 /* Seek to the start of the track */
129 if (ci->seek_time == 1) { 137 if (param == 0) {
130 ci->set_elapsed(0); 138 ci->set_elapsed(0);
131 ci->seek_complete(); 139 ci->seek_complete();
132 goto seek_start; 140 action = CODEC_ACTION_NULL;
141 continue;
133 } 142 }
134 143
135 skipped = 0; 144 skipped = 0;
@@ -141,21 +150,30 @@ seek_start:
141 if(playback_on == -1) { 150 if(playback_on == -1) {
142 /* Error only if packet-parsing failed and playback hadn't started */ 151 /* Error only if packet-parsing failed and playback hadn't started */
143 DEBUGF("rm_get_packet failed\n"); 152 DEBUGF("rm_get_packet failed\n");
153 ci->seek_complete();
144 return CODEC_ERROR; 154 return CODEC_ERROR;
145 } 155 }
146 else 156 else {
147 goto done; 157 ci->seek_complete();
158 return CODEC_OK;
159 }
148 } 160 }
149 skipped += pkt.length; 161 skipped += pkt.length;
150 if(pkt.timestamp > (unsigned)ci->seek_time) break; 162
163 if(pkt.timestamp > (unsigned)param)
164 break;
165
151 ci->advance_buffer(pkt.length); 166 ci->advance_buffer(pkt.length);
152 } 167 }
153 ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE); 168 ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE);
154 buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000); 169 buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000);
155 NeAACDecPostSeekReset(decoder, decoder->frame); 170 NeAACDecPostSeekReset(decoder, decoder->frame);
171 ci->set_elapsed(pkt.timestamp);
156 ci->seek_complete(); 172 ci->seek_complete();
157 } 173 }
158 174
175 action = CODEC_ACTION_NULL;
176
159 /* Request the required number of bytes from the input buffer */ 177 /* Request the required number of bytes from the input buffer */
160 buffer=ci->request_buffer(&n,rmctx.audio_framesize + 1000); 178 buffer=ci->request_buffer(&n,rmctx.audio_framesize + 1000);
161 consumed = rm_get_packet(&buffer, &rmctx, &pkt); 179 consumed = rm_get_packet(&buffer, &rmctx, &pkt);
@@ -167,20 +185,20 @@ seek_start:
167 return CODEC_ERROR; 185 return CODEC_ERROR;
168 } 186 }
169 else 187 else
170 goto done; 188 break;
171 } 189 }
172 190
173 playback_on = 1; 191 playback_on = 1;
174 if (pkt.timestamp >= ci->id3->length) 192 if (pkt.timestamp >= ci->id3->length)
175 goto done; 193 break;
194
176 /* Decode one block - returned samples will be host-endian */ 195 /* Decode one block - returned samples will be host-endian */
177 for(i = 0; i < rmctx.sub_packet_cnt; i++) { 196 for(i = 0; i < rmctx.sub_packet_cnt; i++) {
178 ret = NeAACDecDecode(decoder, &frame_info, buffer, rmctx.sub_packet_lengths[i]); 197 ret = NeAACDecDecode(decoder, &frame_info, buffer, rmctx.sub_packet_lengths[i]);
179 buffer += rmctx.sub_packet_lengths[i]; 198 buffer += rmctx.sub_packet_lengths[i];
180 if (frame_info.error > 0) { 199 if (frame_info.error > 0) {
181 DEBUGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error)); 200 DEBUGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
182 err = CODEC_ERROR; 201 return CODEC_ERROR;
183 goto exit;
184 } 202 }
185 ci->pcmbuf_insert(decoder->time_out[0], 203 ci->pcmbuf_insert(decoder->time_out[0],
186 decoder->time_out[1], 204 decoder->time_out[1],
@@ -191,11 +209,5 @@ seek_start:
191 ci->advance_buffer(pkt.length); 209 ci->advance_buffer(pkt.length);
192 } 210 }
193 211
194done: 212 return CODEC_OK;
195 if (ci->request_next_track())
196 goto next_track;
197
198exit:
199 return err;
200} 213}
201
diff --git a/apps/codecs/shorten.c b/apps/codecs/shorten.c
index 83a9c34da8..db66991679 100644
--- a/apps/codecs/shorten.c
+++ b/apps/codecs/shorten.c
@@ -37,7 +37,19 @@ static int32_t offset1[MAX_OFFSET_SIZE] IBSS_ATTR;
37static int8_t ibuf[MAX_BUFFER_SIZE] IBSS_ATTR; 37static int8_t ibuf[MAX_BUFFER_SIZE] IBSS_ATTR;
38 38
39/* this is the codec entry point */ 39/* this is the codec entry point */
40enum codec_status codec_main(void) 40enum codec_status codec_main(enum codec_entry_call_reason reason)
41{
42 if (reason == CODEC_LOAD) {
43 /* Generic codec initialisation */
44 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
45 ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1);
46 }
47
48 return CODEC_OK;
49}
50
51/* this is called for each file to process */
52enum codec_status codec_run(void)
41{ 53{
42 ShortenContext sc; 54 ShortenContext sc;
43 uint32_t samplesdone; 55 uint32_t samplesdone;
@@ -45,21 +57,14 @@ enum codec_status codec_main(void)
45 int8_t *buf; 57 int8_t *buf;
46 int consumed, res, nsamples; 58 int consumed, res, nsamples;
47 size_t bytesleft; 59 size_t bytesleft;
60 intptr_t param;
48 61
49 /* Generic codec initialisation */
50 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
51 ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1);
52
53next_track:
54 /* Codec initialization */ 62 /* Codec initialization */
55 if (codec_init()) { 63 if (codec_init()) {
56 LOGF("Shorten: codec_init error\n"); 64 LOGF("Shorten: codec_init error\n");
57 return CODEC_ERROR; 65 return CODEC_ERROR;
58 } 66 }
59 67
60 if (codec_wait_taginfo() != 0)
61 goto request_next_track;
62
63 codec_set_replaygain(ci->id3); 68 codec_set_replaygain(ci->id3);
64 69
65 /* Shorten decoder initialization */ 70 /* Shorten decoder initialization */
@@ -103,14 +108,15 @@ seek_start:
103 samplesdone = 0; 108 samplesdone = 0;
104 buf = ci->request_buffer(&bytesleft, MAX_BUFFER_SIZE); 109 buf = ci->request_buffer(&bytesleft, MAX_BUFFER_SIZE);
105 while (bytesleft) { 110 while (bytesleft) {
106 ci->yield(); 111 enum codec_command_action action = ci->get_command(&param);
107 if (ci->stop_codec || ci->new_track) { 112
113 if (action == CODEC_ACTION_HALT)
108 break; 114 break;
109 }
110 115
111 /* Seek to start of track */ 116 /* Seek to start of track */
112 if (ci->seek_time == 1) { 117 if (action == CODEC_ACTION_SEEK_TIME) {
113 if (ci->seek_buffer(sc.header_bits/8 + ci->id3->first_frame_offset)) { 118 if (param == 0 &&
119 ci->seek_buffer(sc.header_bits/8 + ci->id3->first_frame_offset)) {
114 sc.bitindex = sc.header_bits - 8*(sc.header_bits/8); 120 sc.bitindex = sc.header_bits - 8*(sc.header_bits/8);
115 ci->set_elapsed(0); 121 ci->set_elapsed(0);
116 ci->seek_complete(); 122 ci->seek_complete();
@@ -128,7 +134,7 @@ seek_start:
128 if (res == FN_ERROR) { 134 if (res == FN_ERROR) {
129 LOGF("Shorten: shorten_decode_frames error (%lu)\n", 135 LOGF("Shorten: shorten_decode_frames error (%lu)\n",
130 (unsigned long)samplesdone); 136 (unsigned long)samplesdone);
131 break; 137 return CODEC_ERROR;
132 } else { 138 } else {
133 /* Insert decoded samples in pcmbuf */ 139 /* Insert decoded samples in pcmbuf */
134 if (nsamples) { 140 if (nsamples) {
@@ -153,9 +159,5 @@ seek_start:
153 sc.bitindex = sc.gb.index - 8*consumed; 159 sc.bitindex = sc.gb.index - 8*consumed;
154 } 160 }
155 161
156request_next_track:
157 if (ci->request_next_track())
158 goto next_track;
159
160 return CODEC_OK; 162 return CODEC_OK;
161} 163}
diff --git a/apps/codecs/sid.c b/apps/codecs/sid.c
index 52c1289fff..0edbabe0b6 100644
--- a/apps/codecs/sid.c
+++ b/apps/codecs/sid.c
@@ -1203,34 +1203,47 @@ unsigned short LoadSIDFromMemory(void *pSidData, unsigned short *load_addr,
1203 return *load_addr; 1203 return *load_addr;
1204} 1204}
1205 1205
1206static int nSamplesRendered = 0;
1207static int nSamplesPerCall = 882; /* This is PAL SID single speed (44100/50Hz) */
1208static int nSamplesToRender = 0;
1206 1209
1207enum codec_status codec_main(void) 1210/* this is the codec entry point */
1211enum codec_status codec_main(enum codec_entry_call_reason reason)
1208{ 1212{
1209 unsigned int filesize; 1213 if (reason == CODEC_LOAD) {
1214 /* Make use of 44.1khz */
1215 ci->configure(DSP_SWITCH_FREQUENCY, 44100);
1216 /* Sample depth is 28 bit host endian */
1217 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
1218 /* Mono output */
1219 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
1220 }
1221
1222 return CODEC_OK;
1223}
1210 1224
1225/* this is called for each file to process */
1226enum codec_status codec_run(void)
1227{
1228 unsigned int filesize;
1211 unsigned short load_addr, init_addr, play_addr; 1229 unsigned short load_addr, init_addr, play_addr;
1212 unsigned char subSongsMax, subSong, song_speed; 1230 unsigned char subSongsMax, subSong, song_speed;
1231 intptr_t param;
1213 1232
1214 int nSamplesRendered = 0;
1215 int nSamplesPerCall = 882; /* This is PAL SID single speed (44100/50Hz) */
1216 int nSamplesToRender = 0;
1217
1218next_track:
1219 if (codec_init()) { 1233 if (codec_init()) {
1220 return CODEC_ERROR; 1234 return CODEC_ERROR;
1221 } 1235 }
1222 1236
1223 if (codec_wait_taginfo() != 0)
1224 goto request_next_track;
1225
1226 codec_set_replaygain(ci->id3); 1237 codec_set_replaygain(ci->id3);
1227 1238
1228 /* Load SID file the read_filebuf callback will return the full requested 1239 /* Load SID file the read_filebuf callback will return the full requested
1229 * size if at all possible, so there is no need to loop */ 1240 * size if at all possible, so there is no need to loop */
1241 ci->seek_buffer(0);
1230 filesize = ci->read_filebuf(sidfile, sizeof(sidfile)); 1242 filesize = ci->read_filebuf(sidfile, sizeof(sidfile));
1231 1243
1232 if (filesize == 0) 1244 if (filesize == 0) {
1233 return CODEC_ERROR; 1245 return CODEC_ERROR;
1246 }
1234 1247
1235 c64Init(44100); 1248 c64Init(44100);
1236 LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, 1249 LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr,
@@ -1239,37 +1252,30 @@ next_track:
1239 cpuJSR(init_addr, subSong); /* Start the song initialize */ 1252 cpuJSR(init_addr, subSong); /* Start the song initialize */
1240 1253
1241 1254
1242 /* Make use of 44.1khz */
1243 ci->configure(DSP_SWITCH_FREQUENCY, 44100);
1244 /* Sample depth is 28 bit host endian */
1245 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
1246 /* Mono output */
1247 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
1248
1249
1250 /* Set the elapsed time to the current subsong (in seconds) */ 1255 /* Set the elapsed time to the current subsong (in seconds) */
1251 ci->set_elapsed(subSong*1000); 1256 ci->set_elapsed(subSong*1000);
1252 1257
1253 /* The main decoder loop */ 1258 /* The main decoder loop */
1254 while (1) { 1259 while (1) {
1255 ci->yield(); 1260 enum codec_command_action action = ci->get_command(&param);
1256 if (ci->stop_codec || ci->new_track) 1261
1262 if (action == CODEC_ACTION_HALT)
1257 break; 1263 break;
1258 1264
1259 if (ci->seek_time) { 1265 if (action == CODEC_ACTION_SEEK_TIME) {
1260 /* New time is ready in ci->seek_time */ 1266 /* New time is ready in param */
1261 1267
1262 /* Start playing from scratch */ 1268 /* Start playing from scratch */
1263 c64Init(44100); 1269 c64Init(44100);
1264 LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, &subSongsMax, &subSong, &song_speed, filesize); 1270 LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr,
1265 sidPoke(24, 15); /* Turn on full volume */ 1271 &subSongsMax, &subSong, &song_speed, filesize);
1266 subSong = ci->seek_time / 1000; /* Now use the current seek time in seconds as subsong */ 1272 sidPoke(24, 15); /* Turn on full volume */
1267 cpuJSR(init_addr, subSong); /* Start the song initialize */ 1273 subSong = param / 1000; /* Now use the current seek time in seconds as subsong */
1268 nSamplesToRender = 0; /* Start the rendering from scratch */ 1274 cpuJSR(init_addr, subSong); /* Start the song initialize */
1269 1275 nSamplesToRender = 0; /* Start the rendering from scratch */
1270 ci->seek_complete();
1271 1276
1272 /* Set the elapsed time to the current subsong (in seconds) */ 1277 /* Set the elapsed time to the current subsong (in seconds) */
1278 ci->seek_complete();
1273 ci->set_elapsed(subSong*1000); 1279 ci->set_elapsed(subSong*1000);
1274 } 1280 }
1275 1281
@@ -1306,9 +1312,5 @@ next_track:
1306 ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE); 1312 ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE);
1307 } 1313 }
1308 1314
1309request_next_track:
1310 if (ci->request_next_track())
1311 goto next_track;
1312
1313 return CODEC_OK; 1315 return CODEC_OK;
1314} 1316}
diff --git a/apps/codecs/smaf.c b/apps/codecs/smaf.c
index 3e8a41387d..9211daa9aa 100644
--- a/apps/codecs/smaf.c
+++ b/apps/codecs/smaf.c
@@ -332,9 +332,20 @@ static uint8_t *read_buffer(size_t *realsize)
332 return buffer; 332 return buffer;
333} 333}
334 334
335enum codec_status codec_main(void) 335/* this is the codec entry point */
336enum codec_status codec_main(enum codec_entry_call_reason reason)
337{
338 if (reason == CODEC_LOAD) {
339 /* Generic codec initialisation */
340 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
341 }
342
343 return CODEC_OK;
344}
345
346/* this is called for each file to process */
347enum codec_status codec_run(void)
336{ 348{
337 int status;
338 uint32_t decodedsamples; 349 uint32_t decodedsamples;
339 size_t n; 350 size_t n;
340 int bufcount; 351 int bufcount;
@@ -342,20 +353,10 @@ enum codec_status codec_main(void)
342 uint8_t *smafbuf; 353 uint8_t *smafbuf;
343 off_t firstblockposn; /* position of the first block in file */ 354 off_t firstblockposn; /* position of the first block in file */
344 const struct pcm_codec *codec; 355 const struct pcm_codec *codec;
345 356 intptr_t param;
346 /* Generic codec initialisation */
347 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
348 357
349next_track: 358 if (codec_init())
350 status = CODEC_OK; 359 return CODEC_ERROR;
351
352 if (codec_init()) {
353 status = CODEC_ERROR;
354 goto exit;
355 }
356
357 if (codec_wait_taginfo() != 0)
358 goto done;
359 360
360 codec_set_replaygain(ci->id3); 361 codec_set_replaygain(ci->id3);
361 362
@@ -365,24 +366,22 @@ next_track:
365 decodedsamples = 0; 366 decodedsamples = 0;
366 codec = 0; 367 codec = 0;
367 368
369 ci->seek_buffer(0);
368 if (!parse_header(&format, &firstblockposn)) 370 if (!parse_header(&format, &firstblockposn))
369 { 371 {
370 status = CODEC_ERROR; 372 return CODEC_ERROR;
371 goto done;
372 } 373 }
373 374
374 codec = get_codec(format.formattag); 375 codec = get_codec(format.formattag);
375 if (codec == 0) 376 if (codec == 0)
376 { 377 {
377 DEBUGF("CODEC_ERROR: unsupport audio format: 0x%x\n", (int)format.formattag); 378 DEBUGF("CODEC_ERROR: unsupport audio format: 0x%x\n", (int)format.formattag);
378 status = CODEC_ERROR; 379 return CODEC_ERROR;
379 goto done;
380 } 380 }
381 381
382 if (!codec->set_format(&format)) 382 if (!codec->set_format(&format))
383 { 383 {
384 status = CODEC_ERROR; 384 return CODEC_ERROR;
385 goto done;
386 } 385 }
387 386
388 /* check chunksize */ 387 /* check chunksize */
@@ -392,8 +391,7 @@ next_track:
392 if (format.chunksize == 0) 391 if (format.chunksize == 0)
393 { 392 {
394 DEBUGF("CODEC_ERROR: chunksize is 0\n"); 393 DEBUGF("CODEC_ERROR: chunksize is 0\n");
395 status = CODEC_ERROR; 394 return CODEC_ERROR;
396 goto done;
397 } 395 }
398 396
399 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 397 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -404,12 +402,10 @@ next_track:
404 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 402 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
405 } else { 403 } else {
406 DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); 404 DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n");
407 status = CODEC_ERROR; 405 return CODEC_ERROR;
408 goto done;
409 } 406 }
410 407
411 ci->seek_buffer(firstblockposn); 408 ci->seek_buffer(firstblockposn);
412 ci->seek_complete();
413 409
414 /* make sure we're at the correct offset */ 410 /* make sure we're at the correct offset */
415 if (bytesdone > (uint32_t) firstblockposn) 411 if (bytesdone > (uint32_t) firstblockposn)
@@ -419,13 +415,13 @@ next_track:
419 PCM_SEEK_POS, &read_buffer); 415 PCM_SEEK_POS, &read_buffer);
420 416
421 if (newpos->pos > format.numbytes) 417 if (newpos->pos > format.numbytes)
422 goto done; 418 return CODEC_OK;
419
423 if (ci->seek_buffer(firstblockposn + newpos->pos)) 420 if (ci->seek_buffer(firstblockposn + newpos->pos))
424 { 421 {
425 bytesdone = newpos->pos; 422 bytesdone = newpos->pos;
426 decodedsamples = newpos->samples; 423 decodedsamples = newpos->samples;
427 } 424 }
428 ci->seek_complete();
429 } 425 }
430 else 426 else
431 { 427 {
@@ -437,23 +433,32 @@ next_track:
437 endofstream = 0; 433 endofstream = 0;
438 434
439 while (!endofstream) { 435 while (!endofstream) {
440 ci->yield(); 436 enum codec_command_action action = ci->get_command(&param);
441 if (ci->stop_codec || ci->new_track) 437
438 if (action == CODEC_ACTION_HALT)
442 break; 439 break;
443 440
444 if (ci->seek_time) { 441 if (action == CODEC_ACTION_SEEK_TIME) {
445 struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, 442 struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME,
446 &read_buffer); 443 &read_buffer);
447 444
448 if (newpos->pos > format.numbytes) 445 if (newpos->pos > format.numbytes)
446 {
447 ci->set_elapsed(ci->id3->length);
448 ci->seek_complete();
449 break; 449 break;
450 }
451
450 if (ci->seek_buffer(firstblockposn + newpos->pos)) 452 if (ci->seek_buffer(firstblockposn + newpos->pos))
451 { 453 {
452 bytesdone = newpos->pos; 454 bytesdone = newpos->pos;
453 decodedsamples = newpos->samples; 455 decodedsamples = newpos->samples;
454 } 456 }
457
458 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
455 ci->seek_complete(); 459 ci->seek_complete();
456 } 460 }
461
457 smafbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); 462 smafbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize);
458 463
459 if (n == 0) 464 if (n == 0)
@@ -464,11 +469,10 @@ next_track:
464 endofstream = 1; 469 endofstream = 1;
465 } 470 }
466 471
467 status = codec->decode(smafbuf, n, samples, &bufcount); 472 if (codec->decode(smafbuf, n, samples, &bufcount) == CODEC_ERROR)
468 if (status == CODEC_ERROR)
469 { 473 {
470 DEBUGF("codec error\n"); 474 DEBUGF("codec error\n");
471 goto done; 475 return CODEC_ERROR;
472 } 476 }
473 477
474 ci->pcmbuf_insert(samples, NULL, bufcount); 478 ci->pcmbuf_insert(samples, NULL, bufcount);
@@ -482,11 +486,5 @@ next_track:
482 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); 486 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
483 } 487 }
484 488
485done: 489 return CODEC_OK;
486 if (ci->request_next_track())
487 goto next_track;
488
489exit:
490 return status;
491} 490}
492
diff --git a/apps/codecs/spc.c b/apps/codecs/spc.c
index 4db2878964..1b49761810 100644
--- a/apps/codecs/spc.c
+++ b/apps/codecs/spc.c
@@ -260,14 +260,6 @@ static inline void samples_release_rdbuf(void)
260static inline int32_t * samples_get_rdbuf(void) 260static inline int32_t * samples_get_rdbuf(void)
261{ 261{
262 ci->semaphore_wait(&sample_queue.emu_sem_head, TIMEOUT_BLOCK); 262 ci->semaphore_wait(&sample_queue.emu_sem_head, TIMEOUT_BLOCK);
263
264 if (ci->stop_codec || ci->new_track)
265 {
266 /* Told to stop. Buffer must be released. */
267 samples_release_rdbuf();
268 return NULL;
269 }
270
271 return sample_queue.wav_chunk[sample_queue.head & WAV_CHUNK_MASK].audio; 263 return sample_queue.wav_chunk[sample_queue.head & WAV_CHUNK_MASK].audio;
272} 264}
273 265
@@ -390,11 +382,10 @@ static inline void spc_emu_quit(void)
390 } 382 }
391} 383}
392 384
393static inline bool spc_play_get_samples(int32_t **samples) 385static inline int32_t * spc_play_get_samples(void)
394{ 386{
395 /* obtain filled samples buffer */ 387 /* obtain filled samples buffer */
396 *samples = samples_get_rdbuf(); 388 return samples_get_rdbuf();
397 return *samples != NULL;
398} 389}
399 390
400static inline void spc_play_send_samples(int32_t *samples) 391static inline void spc_play_send_samples(int32_t *samples)
@@ -433,15 +424,14 @@ static inline void spc_play_send_samples(int32_t *samples)
433#define spc_emu_quit() 424#define spc_emu_quit()
434#define samples_release_rdbuf() 425#define samples_release_rdbuf()
435 426
436static inline bool spc_play_get_samples(int32_t **samples) 427static inline int32_t * spc_play_get_samples(void)
437{ 428{
438 ENTER_TIMER(render); 429 ENTER_TIMER(render);
439 /* fill samples buffer */ 430 /* fill samples buffer */
440 if ( SPC_play(&spc_emu,WAV_CHUNK_SIZE*2,wav_chunk) ) 431 if ( SPC_play(&spc_emu,WAV_CHUNK_SIZE*2,wav_chunk) )
441 assert( false ); 432 assert( false );
442 EXIT_TIMER(render); 433 EXIT_TIMER(render);
443 *samples = wav_chunk; 434 return wav_chunk;
444 return true;
445} 435}
446#endif /* SPC_DUAL_CORE */ 436#endif /* SPC_DUAL_CORE */
447 437
@@ -454,6 +444,7 @@ static int play_track( void )
454 unsigned long fadeendsample = (ID666.length+ID666.fade)*(long long) SAMPLE_RATE/1000; 444 unsigned long fadeendsample = (ID666.length+ID666.fade)*(long long) SAMPLE_RATE/1000;
455 int fadedec = 0; 445 int fadedec = 0;
456 int fadevol = 0x7fffffffl; 446 int fadevol = 0x7fffffffl;
447 intptr_t param;
457 448
458 if (fadeendsample>fadestartsample) 449 if (fadeendsample>fadestartsample)
459 fadedec=0x7fffffffl/(fadeendsample-fadestartsample)+1; 450 fadedec=0x7fffffffl/(fadeendsample-fadestartsample)+1;
@@ -462,25 +453,26 @@ static int play_track( void )
462 453
463 while ( 1 ) 454 while ( 1 )
464 { 455 {
465 ci->yield(); 456 enum codec_command_action action = ci->get_command(&param);
466 if (ci->stop_codec || ci->new_track) { 457
458 if (action == CODEC_ACTION_HALT)
467 break; 459 break;
468 }
469 460
470 if (ci->seek_time) { 461 if (action == CODEC_ACTION_SEEK_TIME) {
471 int curtime = sampleswritten*1000LL/SAMPLE_RATE; 462 int curtime = sampleswritten*1000LL/SAMPLE_RATE;
472 DEBUGF("seek to %ld\ncurrently at %d\n",ci->seek_time,curtime); 463 DEBUGF("seek to %ld\ncurrently at %d\n", (long)param, curtime);
473 if (ci->seek_time < curtime) { 464 if (param < curtime) {
474 DEBUGF("seek backwards = reset\n"); 465 DEBUGF("seek backwards = reset\n");
466 ci->set_elapsed(0);
475 ci->seek_complete(); 467 ci->seek_complete();
476 return 1; 468 return 1;
477 } 469 }
470
471 ci->set_elapsed(curtime);
478 ci->seek_complete(); 472 ci->seek_complete();
479 } 473 }
480 474
481 int32_t *samples; 475 int32_t *samples = spc_play_get_samples();
482 if (!spc_play_get_samples(&samples))
483 break;
484 476
485 sampleswritten += WAV_CHUNK_SIZE; 477 sampleswritten += WAV_CHUNK_SIZE;
486 478
@@ -532,67 +524,61 @@ static int play_track( void )
532} 524}
533 525
534/* this is the codec entry point */ 526/* this is the codec entry point */
535enum codec_status codec_main(void) 527enum codec_status codec_main(enum codec_entry_call_reason reason)
536{ 528{
537 enum codec_status stat = CODEC_ERROR; 529 if (reason == CODEC_LOAD) {
538 530 if (!spc_emu_start())
539 if (!spc_emu_start()) 531 return CODEC_ERROR;
540 goto codec_quit;
541
542 do
543 {
544 DEBUGF("SPC: next_track\n");
545 if (codec_init()) {
546 goto codec_quit;
547 }
548 DEBUGF("SPC: after init\n");
549 532
550 ci->configure(DSP_SET_SAMPLE_DEPTH, 24); 533 ci->configure(DSP_SET_SAMPLE_DEPTH, 24);
551 ci->configure(DSP_SET_FREQUENCY, SAMPLE_RATE); 534 ci->configure(DSP_SET_FREQUENCY, SAMPLE_RATE);
552 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); 535 ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
536 }
537 else if (reason == CODEC_UNLOAD) {
538 spc_emu_quit();
539 }
553 540
554 /* wait for track info to load */ 541 return CODEC_OK;
555 if (codec_wait_taginfo() != 0) 542}
556 continue;
557
558 codec_set_replaygain(ci->id3);
559 543
560 /* Read the entire file */ 544/* this is called for each file to process */
561 DEBUGF("SPC: request initial buffer\n"); 545enum codec_status codec_run(void)
562 ci->seek_buffer(0); 546{
563 size_t buffersize; 547 DEBUGF("SPC: next_track\n");
564 uint8_t* buffer = ci->request_buffer(&buffersize, ci->filesize); 548 if (codec_init())
565 if (!buffer) { 549 return CODEC_ERROR;
566 goto codec_quit; 550 DEBUGF("SPC: after init\n");
551
552 codec_set_replaygain(ci->id3);
553
554 /* Read the entire file */
555 DEBUGF("SPC: request initial buffer\n");
556 ci->seek_buffer(0);
557 size_t buffersize;
558 uint8_t* buffer = ci->request_buffer(&buffersize, ci->filesize);
559 if (!buffer)
560 return CODEC_ERROR;
561
562 DEBUGF("SPC: read size = 0x%lx\n",(unsigned long)buffersize);
563 do
564 {
565 if (load_spc_buffer(buffer, buffersize)) {
566 DEBUGF("SPC load failure\n");
567 return CODEC_ERROR;
567 } 568 }
568 569
569 DEBUGF("SPC: read size = 0x%lx\n",(unsigned long)buffersize); 570 LoadID666(buffer+0x2e);
570 do
571 {
572 if (load_spc_buffer(buffer, buffersize)) {
573 DEBUGF("SPC load failure\n");
574 goto codec_quit;
575 }
576
577 LoadID666(buffer+0x2e);
578 571
579 if (ci->global_settings->repeat_mode!=REPEAT_ONE && ID666.length==0) { 572 if (ci->global_settings->repeat_mode!=REPEAT_ONE && ID666.length==0) {
580 ID666.length=3*60*1000; /* 3 minutes */ 573 ID666.length=3*60*1000; /* 3 minutes */
581 ID666.fade=5*1000; /* 5 seconds */ 574 ID666.fade=5*1000; /* 5 seconds */
582 }
583
584 reset_profile_timers();
585 } 575 }
586 while ( play_track() );
587 576
588 print_timers(ci->id3->path); 577 reset_profile_timers();
589 } 578 }
590 while ( ci->request_next_track() ); 579 while ( play_track() );
591 580
592 stat = CODEC_OK; 581 print_timers(ci->id3->path);
593 582
594codec_quit: 583 return CODEC_OK;
595 spc_emu_quit();
596
597 return stat;
598} 584}
diff --git a/apps/codecs/speex.c b/apps/codecs/speex.c
index 7a1efa9753..e394efc3d5 100644
--- a/apps/codecs/speex.c
+++ b/apps/codecs/speex.c
@@ -367,11 +367,12 @@ static void *process_header(spx_ogg_packet *op,
367 return st; 367 return st;
368} 368}
369 369
370/* this is the codec entry point */ 370/* this is called for each file to process */
371enum codec_status codec_main(void) 371enum codec_status codec_run(void)
372{ 372{
373 int error = CODEC_ERROR;
374
373 SpeexBits bits; 375 SpeexBits bits;
374 int error;
375 int eof = 0; 376 int eof = 0;
376 spx_ogg_sync_state oy; 377 spx_ogg_sync_state oy;
377 spx_ogg_page og; 378 spx_ogg_page og;
@@ -383,7 +384,7 @@ enum codec_status codec_main(void)
383 int eos = 0; 384 int eos = 0;
384 SpeexStereoState *stereo; 385 SpeexStereoState *stereo;
385 int channels = -1; 386 int channels = -1;
386 int rate = 0, samplerate = 0; 387 int samplerate = 0;
387 int extra_headers = 0; 388 int extra_headers = 0;
388 int stream_init = 0; 389 int stream_init = 0;
389 int page_nb_packets, frame_size, packet_count = 0; 390 int page_nb_packets, frame_size, packet_count = 0;
@@ -392,26 +393,22 @@ enum codec_status codec_main(void)
392 unsigned long strtoffset = 0; 393 unsigned long strtoffset = 0;
393 void *st = NULL; 394 void *st = NULL;
394 int j = 0; 395 int j = 0;
396 intptr_t param;
395 397
396 memset(&bits, 0, sizeof(bits)); 398 memset(&bits, 0, sizeof(bits));
397 memset(&oy, 0, sizeof(oy)); 399 memset(&oy, 0, sizeof(oy));
398 400
399 /* Ogg handling still uses mallocs, so reset the malloc buffer per track */ 401 /* Ogg handling still uses mallocs, so reset the malloc buffer per track */
400next_track:
401 error = CODEC_OK;
402
403 if (codec_init()) { 402 if (codec_init()) {
404 error = CODEC_ERROR;
405 goto exit; 403 goto exit;
406 } 404 }
407 405
406 ci->seek_buffer(0);
407
408 stereo = speex_stereo_state_init(); 408 stereo = speex_stereo_state_init();
409 spx_ogg_sync_init(&oy); 409 spx_ogg_sync_init(&oy);
410 spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE); 410 spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE);
411 411
412 if (codec_wait_taginfo() != 0)
413 goto done;
414
415 strtoffset = ci->id3->offset; 412 strtoffset = ci->id3->offset;
416 413
417 samplerate = ci->id3->frequency; 414 samplerate = ci->id3->frequency;
@@ -419,30 +416,32 @@ next_track:
419 416
420 eof = 0; 417 eof = 0;
421 while (!eof) { 418 while (!eof) {
422 ci->yield(); 419 enum codec_command_action action = ci->get_command(&param);
423 if (ci->stop_codec || ci->new_track) 420
421 if (action == CODEC_ACTION_HALT)
424 break; 422 break;
425 423
426 /*seek (seeks to the page before the position) */ 424 /*seek (seeks to the page before the position) */
427 if (ci->seek_time) { 425 if (action == CODEC_ACTION_SEEK_TIME) {
428 if(samplerate!=0&&packet_count>1){ 426 if(samplerate!=0&&packet_count>1){
429 LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n", 427 LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n",
430 ((spx_int64_t)ci->seek_time/1000) * 428 ((spx_int64_t)param/1000) *
431 (spx_int64_t)samplerate, 429 (spx_int64_t)samplerate,
432 page_granule, ci->seek_time, 430 page_granule, param,
433 (page_granule/samplerate)*1000, samplerate); 431 (page_granule/samplerate)*1000, samplerate);
434 432
435 speex_seek_page_granule(((spx_int64_t)ci->seek_time/1000) * 433 speex_seek_page_granule(((spx_int64_t)param/1000) *
436 (spx_int64_t)samplerate, 434 (spx_int64_t)samplerate,
437 page_granule, &oy, headerssize); 435 page_granule, &oy, headerssize);
438 ci->seek_complete();
439 } 436 }
437
438 ci->set_elapsed(param);
439 ci->seek_complete();
440 } 440 }
441 441
442next_page: 442next_page:
443 /*Get the ogg buffer for writing*/ 443 /*Get the ogg buffer for writing*/
444 if(get_more_data(&oy)<1){/*read error*/ 444 if(get_more_data(&oy)<1){/*read error*/
445 error=CODEC_ERROR;
446 goto done; 445 goto done;
447 } 446 }
448 447
@@ -477,8 +476,7 @@ next_page:
477 nframes=1; 476 nframes=1;
478 477
479 if (!st){ 478 if (!st){
480 error=CODEC_ERROR; 479 goto done;
481 goto exit;
482 } 480 }
483 481
484 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); 482 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
@@ -557,31 +555,18 @@ next_page:
557 } 555 }
558 556
559done: 557done:
560 if (ci->request_next_track()) { 558 /* Clean things up for the next track */
561 559 speex_bits_destroy(&bits);
562 /* Clean things up for the next track */
563 560
561 if (st)
564 if (st) 562 if (st)
565 speex_decoder_destroy(st); 563 speex_decoder_destroy(st);
566 564
567 if (stream_init == 1)
568 spx_ogg_stream_reset(&os);
569
570 spx_ogg_sync_reset(&oy);
571
572 cur_granule = stream_init = rate = samplerate = headerssize
573 = packet_count = eos = 0;
574
575 goto next_track;
576 }
577
578exit:
579 speex_bits_destroy(&bits);
580
581 if (stream_init) 565 if (stream_init)
582 spx_ogg_stream_destroy(&os); 566 spx_ogg_stream_destroy(&os);
583 567
584 spx_ogg_sync_destroy(&oy); 568 spx_ogg_sync_destroy(&oy);
585 569
570exit:
586 return error; 571 return error;
587} 572}
diff --git a/apps/codecs/tta.c b/apps/codecs/tta.c
index 1d0846ea61..c75f2b0a57 100644
--- a/apps/codecs/tta.c
+++ b/apps/codecs/tta.c
@@ -34,36 +34,36 @@ CODEC_HEADER
34static int32_t samples[PCM_BUFFER_LENGTH * 2] IBSS_ATTR; 34static int32_t samples[PCM_BUFFER_LENGTH * 2] IBSS_ATTR;
35 35
36/* this is the codec entry point */ 36/* this is the codec entry point */
37enum codec_status codec_main(void) 37enum codec_status codec_main(enum codec_entry_call_reason reason)
38{
39 if (reason == CODEC_LOAD) {
40 /* Generic codec initialisation */
41 ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1);
42 }
43
44 return CODEC_OK;
45}
46
47/* this is called for each file to process */
48enum codec_status codec_run(void)
38{ 49{
39 tta_info info; 50 tta_info info;
40 int status;
41 unsigned int decodedsamples; 51 unsigned int decodedsamples;
42 int endofstream; 52 int endofstream;
43 int new_pos = 0; 53 int new_pos = 0;
44 int sample_count; 54 int sample_count;
45 55 intptr_t param;
46 /* Generic codec initialisation */
47 ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1);
48 56
49next_track:
50 status = CODEC_OK;
51
52 if (codec_init()) 57 if (codec_init())
53 { 58 {
54 DEBUGF("codec_init() error\n"); 59 DEBUGF("codec_init() error\n");
55 status = CODEC_ERROR; 60 return CODEC_ERROR;
56 goto exit;
57 } 61 }
58 62
59 if (codec_wait_taginfo() != 0) 63 ci->seek_buffer(0);
60 goto done;
61 64
62 if (set_tta_info(&info) < 0 || player_init(&info) < 0) 65 if (set_tta_info(&info) < 0 || player_init(&info) < 0)
63 { 66 return CODEC_ERROR;
64 status = CODEC_ERROR;
65 goto exit;
66 }
67 67
68 codec_set_replaygain(ci->id3); 68 codec_set_replaygain(ci->id3);
69 69
@@ -74,8 +74,8 @@ next_track:
74 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 74 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
75 } else { 75 } else {
76 DEBUGF("CODEC_ERROR: more than 2 channels\n"); 76 DEBUGF("CODEC_ERROR: more than 2 channels\n");
77 status = CODEC_ERROR; 77 player_stop();
78 goto done; 78 return CODEC_ERROR;
79 } 79 }
80 80
81 /* The main decoder loop */ 81 /* The main decoder loop */
@@ -88,31 +88,31 @@ next_track:
88 new_pos = set_position(ci->id3->offset, TTA_SEEK_POS); 88 new_pos = set_position(ci->id3->offset, TTA_SEEK_POS);
89 if (new_pos >= 0) 89 if (new_pos >= 0)
90 decodedsamples = new_pos; 90 decodedsamples = new_pos;
91 ci->seek_complete();
92 } 91 }
93 92
94 while (!endofstream) 93 while (!endofstream)
95 { 94 {
96 ci->yield(); 95 enum codec_command_action action = ci->get_command(&param);
97 if (ci->stop_codec || ci->new_track) 96
97 if (action == CODEC_ACTION_HALT)
98 break; 98 break;
99 99
100 if (ci->seek_time) 100 if (action == CODEC_ACTION_SEEK_TIME)
101 { 101 {
102 new_pos = set_position(ci->seek_time / SEEK_STEP, TTA_SEEK_TIME); 102 new_pos = set_position(param / SEEK_STEP, TTA_SEEK_TIME);
103 if (new_pos >= 0) 103 if (new_pos >= 0)
104 { 104 {
105 decodedsamples = new_pos; 105 decodedsamples = new_pos;
106 ci->seek_complete();
107 } 106 }
107
108 ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);
109 ci->seek_complete();
108 } 110 }
109 111
110 sample_count = get_samples(samples); 112 sample_count = get_samples(samples);
111 if (sample_count < 0) 113 if (sample_count < 0)
112 {
113 status = CODEC_ERROR;
114 break; 114 break;
115 } 115
116 ci->pcmbuf_insert(samples, NULL, sample_count); 116 ci->pcmbuf_insert(samples, NULL, sample_count);
117 decodedsamples += sample_count; 117 decodedsamples += sample_count;
118 if (decodedsamples >= info.DATALENGTH) 118 if (decodedsamples >= info.DATALENGTH)
@@ -120,11 +120,6 @@ next_track:
120 ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH); 120 ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);
121 } 121 }
122 122
123done:
124 player_stop(); 123 player_stop();
125 if (ci->request_next_track()) 124 return CODEC_OK;
126 goto next_track;
127
128exit:
129 return status;
130} 125}
diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c
index 0a36a37c8b..e02d459262 100644
--- a/apps/codecs/vorbis.c
+++ b/apps/codecs/vorbis.c
@@ -104,14 +104,25 @@ static bool vorbis_set_codec_parameters(OggVorbis_File *vf)
104} 104}
105 105
106/* this is the codec entry point */ 106/* this is the codec entry point */
107enum codec_status codec_main(void) 107enum codec_status codec_main(enum codec_entry_call_reason reason)
108{
109 if (reason == CODEC_LOAD) {
110 if (codec_init())
111 return CODEC_ERROR;
112 ci->configure(DSP_SET_SAMPLE_DEPTH, 24);
113 }
114
115 return CODEC_OK;
116}
117
118/* this is called for each file to process */
119enum codec_status codec_run(void)
108{ 120{
109 ov_callbacks callbacks; 121 ov_callbacks callbacks;
110 OggVorbis_File vf; 122 OggVorbis_File vf;
111 ogg_int32_t **pcm; 123 ogg_int32_t **pcm;
112 124
113 bool initialized = false; /* First init done? */ 125 int error = CODEC_ERROR;
114 int error;
115 long n; 126 long n;
116 int current_section; 127 int current_section;
117 int previous_section; 128 int previous_section;
@@ -120,36 +131,24 @@ enum codec_status codec_main(void)
120 ogg_int64_t vf_dataoffsets; 131 ogg_int64_t vf_dataoffsets;
121 ogg_uint32_t vf_serialnos; 132 ogg_uint32_t vf_serialnos;
122 ogg_int64_t vf_pcmlengths[2]; 133 ogg_int64_t vf_pcmlengths[2];
123 134 intptr_t param;
124 ci->configure(DSP_SET_SAMPLE_DEPTH, 24);
125
126 if (codec_init()) {
127 error = CODEC_ERROR;
128 goto exit;
129 }
130 135
131#if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS) 136#if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS)
132 if (setjmp(rb_jump_buf) != 0) { 137 if (setjmp(rb_jump_buf) != 0) {
133 /* malloc failed; skip to next track */ 138 /* malloc failed; finish with this track */
134 error = CODEC_ERROR;
135 goto done; 139 goto done;
136 } 140 }
137#endif 141#endif
138
139next_track:
140 error = CODEC_OK;
141
142 ogg_malloc_init(); 142 ogg_malloc_init();
143 143
144 if (codec_wait_taginfo() != 0)
145 goto done;
146
147 /* Create a decoder instance */ 144 /* Create a decoder instance */
148 callbacks.read_func = read_handler; 145 callbacks.read_func = read_handler;
149 callbacks.seek_func = initial_seek_handler; 146 callbacks.seek_func = initial_seek_handler;
150 callbacks.tell_func = tell_handler; 147 callbacks.tell_func = tell_handler;
151 callbacks.close_func = close_handler; 148 callbacks.close_func = close_handler;
152 149
150 ci->seek_buffer(0);
151
153 /* Open a non-seekable stream */ 152 /* Open a non-seekable stream */
154 error = ov_open_callbacks(ci, &vf, NULL, 0, callbacks); 153 error = ov_open_callbacks(ci, &vf, NULL, 0, callbacks);
155 154
@@ -186,15 +185,13 @@ next_track:
186 vf.end = ci->id3->filesize; 185 vf.end = ci->id3->filesize;
187 vf.ready_state = OPENED; 186 vf.ready_state = OPENED;
188 vf.links = 1; 187 vf.links = 1;
189 initialized = true;
190 } else { 188 } else {
191 DEBUGF("Vorbis: ov_open failed: %d\n", error); 189 DEBUGF("Vorbis: ov_open failed: %d\n", error);
192 error = CODEC_ERROR;
193 goto done; 190 goto done;
194 } 191 }
195 192
196 if (ci->id3->offset) { 193 if (ci->id3->offset) {
197 ci->advance_buffer(ci->id3->offset); 194 ci->seek_buffer(ci->id3->offset);
198 ov_raw_seek(&vf, ci->id3->offset); 195 ov_raw_seek(&vf, ci->id3->offset);
199 ci->set_elapsed(ov_time_tell(&vf)); 196 ci->set_elapsed(ov_time_tell(&vf));
200 ci->set_offset(ov_raw_tell(&vf)); 197 ci->set_offset(ov_raw_tell(&vf));
@@ -203,14 +200,17 @@ next_track:
203 previous_section = -1; 200 previous_section = -1;
204 eof = 0; 201 eof = 0;
205 while (!eof) { 202 while (!eof) {
206 ci->yield(); 203 enum codec_command_action action = ci->get_command(&param);
207 if (ci->stop_codec || ci->new_track) 204
205 if (action == CODEC_ACTION_HALT)
208 break; 206 break;
209 207
210 if (ci->seek_time) { 208 if (action == CODEC_ACTION_SEEK_TIME) {
211 if (ov_time_seek(&vf, ci->seek_time - 1)) { 209 if (ov_time_seek(&vf, param)) {
212 //ci->logf("ov_time_seek failed"); 210 //ci->logf("ov_time_seek failed");
213 } 211 }
212
213 ci->set_elapsed(ov_time_tell(&vf));
214 ci->seek_complete(); 214 ci->seek_complete();
215 } 215 }
216 216
@@ -220,7 +220,6 @@ next_track:
220 /* Change DSP and buffer settings for this bitstream */ 220 /* Change DSP and buffer settings for this bitstream */
221 if (current_section != previous_section) { 221 if (current_section != previous_section) {
222 if (!vorbis_set_codec_parameters(&vf)) { 222 if (!vorbis_set_codec_parameters(&vf)) {
223 error = CODEC_ERROR;
224 goto done; 223 goto done;
225 } else { 224 } else {
226 previous_section = current_section; 225 previous_section = current_section;
@@ -238,6 +237,7 @@ next_track:
238 } 237 }
239 } 238 }
240 239
240 error = CODEC_OK;
241done: 241done:
242#if 0 /* defined(SIMULATOR) */ 242#if 0 /* defined(SIMULATOR) */
243 { 243 {
@@ -249,18 +249,12 @@ done:
249#endif 249#endif
250 ogg_malloc_destroy(); 250 ogg_malloc_destroy();
251 251
252 if (ci->request_next_track()) { 252 /* Clean things up for the next track */
253 if (!initialized) 253 vf.dataoffsets = NULL;
254 goto next_track; 254 vf.offsets = NULL;
255 /* Clean things up for the next track */ 255 vf.serialnos = NULL;
256 vf.dataoffsets = NULL; 256 vf.pcmlengths = NULL;
257 vf.offsets = NULL; 257 ov_clear(&vf);
258 vf.serialnos = NULL; 258
259 vf.pcmlengths = NULL;
260 ov_clear(&vf);
261 goto next_track;
262 }
263
264exit:
265 return error; 259 return error;
266} 260}
diff --git a/apps/codecs/vox.c b/apps/codecs/vox.c
index c7f39342c3..bf274c6917 100644
--- a/apps/codecs/vox.c
+++ b/apps/codecs/vox.c
@@ -44,9 +44,19 @@ static uint8_t *read_buffer(size_t *realsize)
44} 44}
45 45
46/* this is the codec entry point */ 46/* this is the codec entry point */
47enum codec_status codec_main(void) 47enum codec_status codec_main(enum codec_entry_call_reason reason)
48{
49 if (reason == CODEC_LOAD) {
50 /* Generic codec initialisation */
51 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
52 }
53
54 return CODEC_OK;
55}
56
57/* this is called for each file to process */
58enum codec_status codec_run(void)
48{ 59{
49 int status;
50 uint32_t decodedsamples; 60 uint32_t decodedsamples;
51 size_t n; 61 size_t n;
52 int bufcount; 62 int bufcount;
@@ -54,26 +64,18 @@ enum codec_status codec_main(void)
54 uint8_t *voxbuf; 64 uint8_t *voxbuf;
55 off_t firstblockposn = 0; /* position of the first block in file */ 65 off_t firstblockposn = 0; /* position of the first block in file */
56 const struct pcm_codec *codec; 66 const struct pcm_codec *codec;
57 67 intptr_t param;
58 /* Generic codec initialisation */
59 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
60
61next_track:
62 status = CODEC_OK;
63 68
64 if (codec_init()) { 69 if (codec_init()) {
65 DEBUGF("codec_init() error\n"); 70 DEBUGF("codec_init() error\n");
66 status = CODEC_ERROR; 71 return CODEC_ERROR;
67 goto exit;
68 } 72 }
69 73
70 if (codec_wait_taginfo() != 0)
71 goto done;
72
73 codec_set_replaygain(ci->id3); 74 codec_set_replaygain(ci->id3);
74 75
75 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 76 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
76 bytesdone = ci->id3->offset; 77 bytesdone = ci->id3->offset;
78 ci->seek_buffer(0);
77 79
78 ci->memset(&format, 0, sizeof(struct pcm_format)); 80 ci->memset(&format, 0, sizeof(struct pcm_format));
79 81
@@ -96,20 +98,16 @@ next_track:
96 if (!codec) 98 if (!codec)
97 { 99 {
98 DEBUGF("CODEC_ERROR: dialogic oki adpcm codec does not load.\n"); 100 DEBUGF("CODEC_ERROR: dialogic oki adpcm codec does not load.\n");
99 status = CODEC_ERROR; 101 return CODEC_ERROR;
100 goto done;
101 } 102 }
102 103
103 if (!codec->set_format(&format)) 104 if (!codec->set_format(&format)) {
104 { 105 return CODEC_ERROR;
105 status = CODEC_ERROR;
106 goto done;
107 } 106 }
108 107
109 if (format.numbytes == 0) { 108 if (format.numbytes == 0) {
110 DEBUGF("CODEC_ERROR: data size is 0\n"); 109 DEBUGF("CODEC_ERROR: data size is 0\n");
111 status = CODEC_ERROR; 110 return CODEC_ERROR;
112 goto done;
113 } 111 }
114 112
115 /* check chunksize */ 113 /* check chunksize */
@@ -118,8 +116,7 @@ next_track:
118 if (format.chunksize == 0) 116 if (format.chunksize == 0)
119 { 117 {
120 DEBUGF("CODEC_ERROR: chunksize is 0\n"); 118 DEBUGF("CODEC_ERROR: chunksize is 0\n");
121 status = CODEC_ERROR; 119 return CODEC_ERROR;
122 goto done;
123 } 120 }
124 121
125 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 122 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -131,14 +128,14 @@ next_track:
131 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, 128 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
132 PCM_SEEK_POS, &read_buffer); 129 PCM_SEEK_POS, &read_buffer);
133 130
134 if (newpos->pos > format.numbytes) 131 if (newpos->pos > format.numbytes) {
135 goto done; 132 return CODEC_OK;
133 }
136 if (ci->seek_buffer(firstblockposn + newpos->pos)) 134 if (ci->seek_buffer(firstblockposn + newpos->pos))
137 { 135 {
138 bytesdone = newpos->pos; 136 bytesdone = newpos->pos;
139 decodedsamples = newpos->samples; 137 decodedsamples = newpos->samples;
140 } 138 }
141 ci->seek_complete();
142 } else { 139 } else {
143 /* already where we need to be */ 140 /* already where we need to be */
144 bytesdone = 0; 141 bytesdone = 0;
@@ -148,22 +145,29 @@ next_track:
148 endofstream = 0; 145 endofstream = 0;
149 146
150 while (!endofstream) { 147 while (!endofstream) {
151 ci->yield(); 148 enum codec_command_action action = ci->get_command(&param);
152 if (ci->stop_codec || ci->new_track) { 149
150 if (action == CODEC_ACTION_HALT)
153 break; 151 break;
154 }
155 152
156 if (ci->seek_time) { 153 if (action == CODEC_ACTION_SEEK_TIME) {
157 struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, 154 struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME,
158 &read_buffer); 155 &read_buffer);
159 156
160 if (newpos->pos > format.numbytes) 157 if (newpos->pos > format.numbytes)
158 {
159 ci->set_elapsed(ci->id3->length);
160 ci->seek_complete();
161 break; 161 break;
162 }
163
162 if (ci->seek_buffer(firstblockposn + newpos->pos)) 164 if (ci->seek_buffer(firstblockposn + newpos->pos))
163 { 165 {
164 bytesdone = newpos->pos; 166 bytesdone = newpos->pos;
165 decodedsamples = newpos->samples; 167 decodedsamples = newpos->samples;
166 } 168 }
169
170 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
167 ci->seek_complete(); 171 ci->seek_complete();
168 } 172 }
169 173
@@ -175,11 +179,10 @@ next_track:
175 endofstream = 1; 179 endofstream = 1;
176 } 180 }
177 181
178 status = codec->decode(voxbuf, n, samples, &bufcount); 182 if (codec->decode(voxbuf, n, samples, &bufcount) == CODEC_ERROR)
179 if (status == CODEC_ERROR)
180 { 183 {
181 DEBUGF("codec error\n"); 184 DEBUGF("codec error\n");
182 goto done; 185 return CODEC_ERROR;
183 } 186 }
184 187
185 ci->pcmbuf_insert(samples, NULL, bufcount); 188 ci->pcmbuf_insert(samples, NULL, bufcount);
@@ -192,10 +195,5 @@ next_track:
192 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); 195 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
193 } 196 }
194 197
195done: 198 return CODEC_OK;
196 if (ci->request_next_track())
197 goto next_track;
198
199exit:
200 return status;
201} 199}
diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c
index e179470f27..42bcc7081f 100644
--- a/apps/codecs/wav.c
+++ b/apps/codecs/wav.c
@@ -151,9 +151,19 @@ static uint8_t *read_buffer(size_t *realsize)
151} 151}
152 152
153/* this is the codec entry point */ 153/* this is the codec entry point */
154enum codec_status codec_main(void) 154enum codec_status codec_main(enum codec_entry_call_reason reason)
155{
156 if (reason == CODEC_LOAD) {
157 /* Generic codec initialisation */
158 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
159 }
160
161 return CODEC_OK;
162}
163
164/* this is called for each file to process */
165enum codec_status codec_run(void)
155{ 166{
156 int status;
157 uint32_t decodedsamples; 167 uint32_t decodedsamples;
158 size_t n; 168 size_t n;
159 int bufcount; 169 int bufcount;
@@ -163,38 +173,28 @@ enum codec_status codec_main(void)
163 off_t firstblockposn; /* position of the first block in file */ 173 off_t firstblockposn; /* position of the first block in file */
164 const struct pcm_codec *codec; 174 const struct pcm_codec *codec;
165 uint32_t size; 175 uint32_t size;
166 176 intptr_t param;
167 /* Generic codec initialisation */
168 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
169
170next_track:
171 status = CODEC_OK;
172 177
173 if (codec_init()) { 178 if (codec_init()) {
174 DEBUGF("codec_init() error\n"); 179 DEBUGF("codec_init() error\n");
175 status = CODEC_ERROR; 180 return CODEC_ERROR;
176 goto exit;
177 } 181 }
178 182
179 if (codec_wait_taginfo() != 0)
180 goto done;
181
182 codec_set_replaygain(ci->id3); 183 codec_set_replaygain(ci->id3);
183 184
184 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 185 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
185 bytesdone = ci->id3->offset; 186 bytesdone = ci->id3->offset;
186 187
187 /* get RIFF chunk header */ 188 /* get RIFF chunk header */
189 ci->seek_buffer(0);
188 buf = ci->request_buffer(&n, 12); 190 buf = ci->request_buffer(&n, 12);
189 if (n < 12) { 191 if (n < 12) {
190 DEBUGF("request_buffer error\n"); 192 DEBUGF("request_buffer error\n");
191 status = CODEC_ERROR; 193 return CODEC_ERROR;
192 goto done;
193 } 194 }
194 if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { 195 if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) {
195 DEBUGF("CODEC_ERROR: missing riff header\n"); 196 DEBUGF("CODEC_ERROR: missing riff header\n");
196 status = CODEC_ERROR; 197 return CODEC_ERROR;
197 goto done;
198 } 198 }
199 199
200 /* advance to first WAVE chunk */ 200 /* advance to first WAVE chunk */
@@ -215,8 +215,7 @@ next_track:
215 if (n < 8) { 215 if (n < 8) {
216 DEBUGF("data chunk request_buffer error\n"); 216 DEBUGF("data chunk request_buffer error\n");
217 /* no more chunks, 'data' chunk must not have been found */ 217 /* no more chunks, 'data' chunk must not have been found */
218 status = CODEC_ERROR; 218 return CODEC_ERROR;
219 goto done;
220 } 219 }
221 220
222 /* chunkSize */ 221 /* chunkSize */
@@ -225,8 +224,7 @@ next_track:
225 if (size < 16) { 224 if (size < 16) {
226 DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", 225 DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n",
227 (unsigned long)size); 226 (unsigned long)size);
228 status = CODEC_ERROR; 227 return CODEC_ERROR;
229 goto done;
230 } 228 }
231 /* wFormatTag */ 229 /* wFormatTag */
232 format.formattag=buf[8]|(buf[9]<<8); 230 format.formattag=buf[8]|(buf[9]<<8);
@@ -256,8 +254,7 @@ next_track:
256 if (format.size < 22) { 254 if (format.size < 22) {
257 DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " 255 DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is "
258 "missing extension\n"); 256 "missing extension\n");
259 status = CODEC_ERROR; 257 return CODEC_ERROR;
260 goto done;
261 } 258 }
262 /* wValidBitsPerSample */ 259 /* wValidBitsPerSample */
263 format.bitspersample = buf[26]|(buf[27]<<8); 260 format.bitspersample = buf[26]|(buf[27]<<8);
@@ -273,8 +270,7 @@ next_track:
273 { 270 {
274 if (!set_msadpcm_coeffs(buf)) 271 if (!set_msadpcm_coeffs(buf))
275 { 272 {
276 status = CODEC_ERROR; 273 return CODEC_ERROR;
277 goto done;
278 } 274 }
279 } 275 }
280 276
@@ -284,8 +280,7 @@ next_track:
284 { 280 {
285 DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", 281 DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n",
286 (unsigned int) format.formattag); 282 (unsigned int) format.formattag);
287 status = CODEC_ERROR; 283 return CODEC_ERROR;
288 goto done;
289 } 284 }
290 285
291 /* riff 8bit linear pcm is unsigned */ 286 /* riff 8bit linear pcm is unsigned */
@@ -295,8 +290,7 @@ next_track:
295 /* set format, parse codec specific tag, check format, and calculate chunk size */ 290 /* set format, parse codec specific tag, check format, and calculate chunk size */
296 if (!codec->set_format(&format)) 291 if (!codec->set_format(&format))
297 { 292 {
298 status = CODEC_ERROR; 293 return CODEC_ERROR;
299 goto done;
300 } 294 }
301 } else if (memcmp(buf, "data", 4) == 0) { 295 } else if (memcmp(buf, "data", 4) == 0) {
302 format.numbytes = size; 296 format.numbytes = size;
@@ -324,31 +318,26 @@ next_track:
324 if (!codec) 318 if (!codec)
325 { 319 {
326 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); 320 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n");
327 status = CODEC_ERROR; 321 return CODEC_ERROR;
328 goto done;
329 } 322 }
330 323
331 /* common format check */ 324 /* common format check */
332 if (format.channels == 0) { 325 if (format.channels == 0) {
333 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); 326 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n");
334 status = CODEC_ERROR; 327 return CODEC_ERROR;
335 goto done;
336 } 328 }
337 if (format.samplesperblock == 0) { 329 if (format.samplesperblock == 0) {
338 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); 330 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n");
339 status = CODEC_ERROR; 331 return CODEC_ERROR;
340 goto done;
341 } 332 }
342 if (format.blockalign == 0) 333 if (format.blockalign == 0)
343 { 334 {
344 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); 335 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n");
345 status = CODEC_ERROR; 336 return CODEC_ERROR;
346 goto done;
347 } 337 }
348 if (format.numbytes == 0) { 338 if (format.numbytes == 0) {
349 DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); 339 DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n");
350 status = CODEC_ERROR; 340 return CODEC_ERROR;
351 goto done;
352 } 341 }
353 342
354 /* check chunksize */ 343 /* check chunksize */
@@ -358,8 +347,7 @@ next_track:
358 if (format.chunksize == 0) 347 if (format.chunksize == 0)
359 { 348 {
360 DEBUGF("CODEC_ERROR: chunksize is 0\n"); 349 DEBUGF("CODEC_ERROR: chunksize is 0\n");
361 status = CODEC_ERROR; 350 return CODEC_ERROR;
362 goto done;
363 } 351 }
364 352
365 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 353 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -369,8 +357,7 @@ next_track:
369 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 357 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
370 } else { 358 } else {
371 DEBUGF("CODEC_ERROR: more than 2 channels\n"); 359 DEBUGF("CODEC_ERROR: more than 2 channels\n");
372 status = CODEC_ERROR; 360 return CODEC_ERROR;
373 goto done;
374 } 361 }
375 362
376 /* make sure we're at the correct offset */ 363 /* make sure we're at the correct offset */
@@ -380,13 +367,12 @@ next_track:
380 PCM_SEEK_POS, &read_buffer); 367 PCM_SEEK_POS, &read_buffer);
381 368
382 if (newpos->pos > format.numbytes) 369 if (newpos->pos > format.numbytes)
383 goto done; 370 return CODEC_OK;
384 if (ci->seek_buffer(firstblockposn + newpos->pos)) 371 if (ci->seek_buffer(firstblockposn + newpos->pos))
385 { 372 {
386 bytesdone = newpos->pos; 373 bytesdone = newpos->pos;
387 decodedsamples = newpos->samples; 374 decodedsamples = newpos->samples;
388 } 375 }
389 ci->seek_complete();
390 } else { 376 } else {
391 /* already where we need to be */ 377 /* already where we need to be */
392 bytesdone = 0; 378 bytesdone = 0;
@@ -396,22 +382,28 @@ next_track:
396 endofstream = 0; 382 endofstream = 0;
397 383
398 while (!endofstream) { 384 while (!endofstream) {
399 ci->yield(); 385 enum codec_command_action action = ci->get_command(&param);
400 if (ci->stop_codec || ci->new_track) { 386
387 if (action == CODEC_ACTION_HALT)
401 break; 388 break;
402 }
403 389
404 if (ci->seek_time) { 390 if (action == CODEC_ACTION_SEEK_TIME) {
405 struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, 391 struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME,
406 &read_buffer); 392 &read_buffer);
407
408 if (newpos->pos > format.numbytes) 393 if (newpos->pos > format.numbytes)
394 {
395 ci->set_elapsed(ci->id3->length);
396 ci->seek_complete();
409 break; 397 break;
398 }
399
410 if (ci->seek_buffer(firstblockposn + newpos->pos)) 400 if (ci->seek_buffer(firstblockposn + newpos->pos))
411 { 401 {
412 bytesdone = newpos->pos; 402 bytesdone = newpos->pos;
413 decodedsamples = newpos->samples; 403 decodedsamples = newpos->samples;
414 } 404 }
405
406 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
415 ci->seek_complete(); 407 ci->seek_complete();
416 } 408 }
417 409
@@ -423,11 +415,10 @@ next_track:
423 endofstream = 1; 415 endofstream = 1;
424 } 416 }
425 417
426 status = codec->decode(wavbuf, n, samples, &bufcount); 418 if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR)
427 if (status == CODEC_ERROR)
428 { 419 {
429 DEBUGF("codec error\n"); 420 DEBUGF("codec error\n");
430 goto done; 421 return CODEC_ERROR;
431 } 422 }
432 423
433 ci->pcmbuf_insert(samples, NULL, bufcount); 424 ci->pcmbuf_insert(samples, NULL, bufcount);
@@ -440,10 +431,5 @@ next_track:
440 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); 431 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
441 } 432 }
442 433
443done: 434 return CODEC_OK;
444 if (ci->request_next_track())
445 goto next_track;
446
447exit:
448 return status;
449} 435}
diff --git a/apps/codecs/wav64.c b/apps/codecs/wav64.c
index 9dbdab8368..c763e6f7f0 100644
--- a/apps/codecs/wav64.c
+++ b/apps/codecs/wav64.c
@@ -159,9 +159,19 @@ static uint8_t *read_buffer(size_t *realsize)
159} 159}
160 160
161/* this is the codec entry point */ 161/* this is the codec entry point */
162enum codec_status codec_main(void) 162enum codec_status codec_main(enum codec_entry_call_reason reason)
163{
164 if (reason == CODEC_LOAD) {
165 /* Generic codec initialisation */
166 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
167 }
168
169 return CODEC_OK;
170}
171
172/* this is called for each file to process */
173enum codec_status codec_run(void)
163{ 174{
164 int status;
165 uint32_t decodedsamples; 175 uint32_t decodedsamples;
166 size_t n; 176 size_t n;
167 int bufcount; 177 int bufcount;
@@ -171,39 +181,29 @@ enum codec_status codec_main(void)
171 off_t firstblockposn; /* position of the first block in file */ 181 off_t firstblockposn; /* position of the first block in file */
172 const struct pcm_codec *codec; 182 const struct pcm_codec *codec;
173 uint64_t size; 183 uint64_t size;
174 184 intptr_t param;
175 /* Generic codec initialisation */
176 ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
177
178next_track:
179 status = CODEC_OK;
180 185
181 if (codec_init()) { 186 if (codec_init()) {
182 DEBUGF("codec_init() error\n"); 187 DEBUGF("codec_init() error\n");
183 status = CODEC_ERROR; 188 return CODEC_ERROR;
184 goto exit;
185 } 189 }
186 190
187 if (codec_wait_taginfo() != 0)
188 goto done;
189
190 codec_set_replaygain(ci->id3); 191 codec_set_replaygain(ci->id3);
191 192
192 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 193 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
193 bytesdone = ci->id3->offset; 194 bytesdone = ci->id3->offset;
194 195
195 /* get RIFF chunk header */ 196 /* get RIFF chunk header */
197 ci->seek_buffer(0);
196 buf = ci->request_buffer(&n, 40); 198 buf = ci->request_buffer(&n, 40);
197 if (n < 40) { 199 if (n < 40) {
198 DEBUGF("request_buffer error\n"); 200 DEBUGF("request_buffer error\n");
199 status = CODEC_ERROR; 201 return CODEC_ERROR;
200 goto done;
201 } 202 }
202 if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0) || 203 if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0) ||
203 (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0)) 204 (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0))
204 { 205 {
205 status = CODEC_ERROR; 206 return CODEC_ERROR;
206 goto done;
207 } 207 }
208 208
209 /* advance to first WAVE chunk */ 209 /* advance to first WAVE chunk */
@@ -224,8 +224,7 @@ next_track:
224 if (n < 8) { 224 if (n < 8) {
225 DEBUGF("data chunk request_buffer error\n"); 225 DEBUGF("data chunk request_buffer error\n");
226 /* no more chunks, 'data' chunk must not have been found */ 226 /* no more chunks, 'data' chunk must not have been found */
227 status = CODEC_ERROR; 227 return CODEC_ERROR;
228 goto done;
229 } 228 }
230 229
231 /* chunkSize */ 230 /* chunkSize */
@@ -233,8 +232,7 @@ next_track:
233 if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) { 232 if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) {
234 if (size < 16) { 233 if (size < 16) {
235 DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size); 234 DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size);
236 status = CODEC_ERROR; 235 return CODEC_ERROR;
237 goto done;
238 } 236 }
239 /* wFormatTag */ 237 /* wFormatTag */
240 format.formattag=buf[24]|(buf[25]<<8); 238 format.formattag=buf[24]|(buf[25]<<8);
@@ -263,8 +261,7 @@ next_track:
263 if (format.size < 22) { 261 if (format.size < 22) {
264 DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " 262 DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is "
265 "missing extension\n"); 263 "missing extension\n");
266 status = CODEC_ERROR; 264 return CODEC_ERROR;
267 goto done;
268 } 265 }
269 /* wValidBitsPerSample */ 266 /* wValidBitsPerSample */
270 format.bitspersample = buf[42]|(buf[43]<<8); 267 format.bitspersample = buf[42]|(buf[43]<<8);
@@ -279,10 +276,7 @@ next_track:
279 if (format.formattag == WAVE_FORMAT_ADPCM) 276 if (format.formattag == WAVE_FORMAT_ADPCM)
280 { 277 {
281 if (!set_msadpcm_coeffs(buf)) 278 if (!set_msadpcm_coeffs(buf))
282 { 279 return CODEC_ERROR;
283 status = CODEC_ERROR;
284 goto done;
285 }
286 } 280 }
287 281
288 /* get codec */ 282 /* get codec */
@@ -291,8 +285,7 @@ next_track:
291 { 285 {
292 DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", 286 DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n",
293 (unsigned int) format.formattag); 287 (unsigned int) format.formattag);
294 status = CODEC_ERROR; 288 return CODEC_ERROR;
295 goto done;
296 } 289 }
297 290
298 /* riff 8bit linear pcm is unsigned */ 291 /* riff 8bit linear pcm is unsigned */
@@ -301,10 +294,7 @@ next_track:
301 294
302 /* check format, and calculate chunk size */ 295 /* check format, and calculate chunk size */
303 if (!codec->set_format(&format)) 296 if (!codec->set_format(&format))
304 { 297 return CODEC_ERROR;
305 status = CODEC_ERROR;
306 goto done;
307 }
308 } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) { 298 } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) {
309 format.numbytes = size; 299 format.numbytes = size;
310 /* advance to start of data */ 300 /* advance to start of data */
@@ -330,31 +320,26 @@ next_track:
330 if (!codec) 320 if (!codec)
331 { 321 {
332 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); 322 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n");
333 status = CODEC_ERROR; 323 return CODEC_ERROR;
334 goto done;
335 } 324 }
336 325
337 /* common format check */ 326 /* common format check */
338 if (format.channels == 0) { 327 if (format.channels == 0) {
339 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); 328 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n");
340 status = CODEC_ERROR; 329 return CODEC_ERROR;
341 goto done;
342 } 330 }
343 if (format.samplesperblock == 0) { 331 if (format.samplesperblock == 0) {
344 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); 332 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n");
345 status = CODEC_ERROR; 333 return CODEC_ERROR;
346 goto done;
347 } 334 }
348 if (format.blockalign == 0) 335 if (format.blockalign == 0)
349 { 336 {
350 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); 337 DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n");
351 status = CODEC_ERROR; 338 return CODEC_ERROR;
352 goto done;
353 } 339 }
354 if (format.numbytes == 0) { 340 if (format.numbytes == 0) {
355 DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); 341 DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n");
356 status = CODEC_ERROR; 342 return CODEC_ERROR;
357 goto done;
358 } 343 }
359 344
360 /* check chunksize */ 345 /* check chunksize */
@@ -364,8 +349,7 @@ next_track:
364 if (format.chunksize == 0) 349 if (format.chunksize == 0)
365 { 350 {
366 DEBUGF("CODEC_ERROR: chunksize is 0\n"); 351 DEBUGF("CODEC_ERROR: chunksize is 0\n");
367 status = CODEC_ERROR; 352 return CODEC_ERROR;
368 goto done;
369 } 353 }
370 354
371 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); 355 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
@@ -375,8 +359,7 @@ next_track:
375 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 359 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
376 } else { 360 } else {
377 DEBUGF("CODEC_ERROR: more than 2 channels\n"); 361 DEBUGF("CODEC_ERROR: more than 2 channels\n");
378 status = CODEC_ERROR; 362 return CODEC_ERROR;
379 goto done;
380 } 363 }
381 364
382 /* make sure we're at the correct offset */ 365 /* make sure we're at the correct offset */
@@ -385,14 +368,14 @@ next_track:
385 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, 368 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
386 PCM_SEEK_POS, &read_buffer); 369 PCM_SEEK_POS, &read_buffer);
387 370
388 if (newpos->pos > format.numbytes) 371 if (newpos->pos > format.numbytes) {
389 goto done; 372 return CODEC_OK;
373 }
390 if (ci->seek_buffer(firstblockposn + newpos->pos)) 374 if (ci->seek_buffer(firstblockposn + newpos->pos))
391 { 375 {
392 bytesdone = newpos->pos; 376 bytesdone = newpos->pos;
393 decodedsamples = newpos->samples; 377 decodedsamples = newpos->samples;
394 } 378 }
395 ci->seek_complete();
396 } else { 379 } else {
397 /* already where we need to be */ 380 /* already where we need to be */
398 bytesdone = 0; 381 bytesdone = 0;
@@ -402,22 +385,29 @@ next_track:
402 endofstream = 0; 385 endofstream = 0;
403 386
404 while (!endofstream) { 387 while (!endofstream) {
405 ci->yield(); 388 enum codec_command_action action = ci->get_command(&param);
406 if (ci->stop_codec || ci->new_track) { 389
390 if (action == CODEC_ACTION_HALT)
407 break; 391 break;
408 }
409 392
410 if (ci->seek_time) { 393 if (action == CODEC_ACTION_SEEK_TIME) {
411 struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, 394 struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME,
412 &read_buffer); 395 &read_buffer);
413 396
414 if (newpos->pos > format.numbytes) 397 if (newpos->pos > format.numbytes)
398 {
399 ci->set_elapsed(ci->id3->length);
400 ci->seek_complete();
415 break; 401 break;
402 }
403
416 if (ci->seek_buffer(firstblockposn + newpos->pos)) 404 if (ci->seek_buffer(firstblockposn + newpos->pos))
417 { 405 {
418 bytesdone = newpos->pos; 406 bytesdone = newpos->pos;
419 decodedsamples = newpos->samples; 407 decodedsamples = newpos->samples;
420 } 408 }
409
410 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
421 ci->seek_complete(); 411 ci->seek_complete();
422 } 412 }
423 413
@@ -429,11 +419,10 @@ next_track:
429 endofstream = 1; 419 endofstream = 1;
430 } 420 }
431 421
432 status = codec->decode(wavbuf, n, samples, &bufcount); 422 if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR)
433 if (status == CODEC_ERROR)
434 { 423 {
435 DEBUGF("codec error\n"); 424 DEBUGF("codec error\n");
436 goto done; 425 return CODEC_ERROR;
437 } 426 }
438 427
439 ci->pcmbuf_insert(samples, NULL, bufcount); 428 ci->pcmbuf_insert(samples, NULL, bufcount);
@@ -445,12 +434,6 @@ next_track:
445 endofstream = 1; 434 endofstream = 1;
446 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); 435 ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
447 } 436 }
448 status = CODEC_OK;
449
450done:
451 if (ci->request_next_track())
452 goto next_track;
453 437
454exit: 438 return CODEC_OK;
455 return status;
456} 439}
diff --git a/apps/codecs/wav_enc.c b/apps/codecs/wav_enc.c
index ef1a88ec23..e4afeaf93c 100644
--- a/apps/codecs/wav_enc.c
+++ b/apps/codecs/wav_enc.c
@@ -345,40 +345,42 @@ static bool init_encoder(void)
345 return true; 345 return true;
346} /* init_encoder */ 346} /* init_encoder */
347 347
348/* main codec entry point */ 348/* this is the codec entry point */
349enum codec_status codec_main(void) 349enum codec_status codec_main(enum codec_entry_call_reason reason)
350{ 350{
351 if (!init_encoder()) 351 if (reason == CODEC_LOAD) {
352 return CODEC_ERROR; 352 if (!init_encoder())
353 return CODEC_ERROR;
354 }
355 else if (reason == CODEC_UNLOAD) {
356 /* reset parameters to initial state */
357 ci->enc_set_parameters(NULL);
358 }
353 359
360 return CODEC_OK;
361}
362
363/* this is called for each file to process */
364enum codec_status codec_run(void)
365{
354 /* main encoding loop */ 366 /* main encoding loop */
355 while(!ci->stop_codec) 367 while(ci->get_command(NULL) != CODEC_ACTION_HALT)
356 { 368 {
357 uint32_t *src; 369 uint32_t *src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE);
370 struct enc_chunk_hdr *chunk;
358 371
359 while ((src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL) 372 if(src == NULL)
360 { 373 continue;
361 struct enc_chunk_hdr *chunk;
362
363 if (ci->stop_codec)
364 break;
365 374
366 chunk = ci->enc_get_chunk(); 375 chunk = ci->enc_get_chunk();
367 chunk->enc_size = enc_size; 376 chunk->enc_size = enc_size;
368 chunk->num_pcm = PCM_SAMP_PER_CHUNK; 377 chunk->num_pcm = PCM_SAMP_PER_CHUNK;
369 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); 378 chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
370 379
371 chunk_to_wav_format(src, (uint32_t *)chunk->enc_data); 380 chunk_to_wav_format(src, (uint32_t *)chunk->enc_data);
372 381
373 ci->enc_finish_chunk(); 382 ci->enc_finish_chunk();
374 ci->yield();
375 }
376
377 ci->yield();
378 } 383 }
379 384
380 /* reset parameters to initial state */
381 ci->enc_set_parameters(NULL);
382
383 return CODEC_OK; 385 return CODEC_OK;
384} /* codec_start */ 386}
diff --git a/apps/codecs/wavpack.c b/apps/codecs/wavpack.c
index d27a9fb621..ccb9f41190 100644
--- a/apps/codecs/wavpack.c
+++ b/apps/codecs/wavpack.c
@@ -31,39 +31,39 @@ static int32_t temp_buffer [BUFFER_SIZE] IBSS_ATTR;
31static int32_t read_callback (void *buffer, int32_t bytes) 31static int32_t read_callback (void *buffer, int32_t bytes)
32{ 32{
33 int32_t retval = ci->read_filebuf (buffer, bytes); 33 int32_t retval = ci->read_filebuf (buffer, bytes);
34 ci->id3->offset = ci->curpos; 34 ci->set_offset(ci->curpos);
35 return retval; 35 return retval;
36} 36}
37 37
38/* this is the codec entry point */ 38/* this is the codec entry point */
39enum codec_status codec_main(void) 39enum codec_status codec_main(enum codec_entry_call_reason reason)
40{
41 if (reason == CODEC_LOAD) {
42 /* Generic codec initialisation */
43 ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
44 }
45
46 return CODEC_OK;
47}
48
49/* this is called for each file to process */
50enum codec_status codec_run(void)
40{ 51{
41 WavpackContext *wpc; 52 WavpackContext *wpc;
42 char error [80]; 53 char error [80];
43 int bps, nchans, sr_100; 54 int bps, nchans, sr_100;
44 int retval; 55 intptr_t param;
45 56
46 /* Generic codec initialisation */ 57 if (codec_init())
47 ci->configure(DSP_SET_SAMPLE_DEPTH, 28); 58 return CODEC_ERROR;
48 59
49next_track: 60 ci->seek_buffer (ci->id3->offset);
50 retval = CODEC_OK;
51 61
52 if (codec_init()) {
53 retval = CODEC_ERROR;
54 goto exit;
55 }
56
57 if (codec_wait_taginfo() != 0)
58 goto done;
59
60 /* Create a decoder instance */ 62 /* Create a decoder instance */
61 wpc = WavpackOpenFileInput (read_callback, error); 63 wpc = WavpackOpenFileInput (read_callback, error);
62 64
63 if (!wpc) { 65 if (!wpc)
64 retval = CODEC_ERROR; 66 return CODEC_ERROR;
65 goto done;
66 }
67 67
68 ci->configure(DSP_SWITCH_FREQUENCY, WavpackGetSampleRate (wpc)); 68 ci->configure(DSP_SWITCH_FREQUENCY, WavpackGetSampleRate (wpc));
69 codec_set_replaygain(ci->id3); 69 codec_set_replaygain(ci->id3);
@@ -77,56 +77,48 @@ next_track:
77 /* The main decoder loop */ 77 /* The main decoder loop */
78 78
79 while (1) { 79 while (1) {
80 int32_t nsamples; 80 int32_t nsamples;
81 enum codec_command_action action = ci->get_command(&param);
82
83 if (action == CODEC_ACTION_HALT)
84 break;
81 85
82 if (ci->seek_time && ci->taginfo_ready && ci->id3->length) { 86 if (action == CODEC_ACTION_SEEK_TIME) {
83 ci->seek_time--;
84 int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10; 87 int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10;
85 int n, d, skip; 88 int n, d, skip;
86 89
87 if (ci->seek_time > curpos_ms) { 90 if (param > curpos_ms) {
88 n = ci->seek_time - curpos_ms; 91 n = param - curpos_ms;
89 d = ci->id3->length - curpos_ms; 92 d = ci->id3->length - curpos_ms;
90 skip = (int)((int64_t)(ci->filesize - ci->curpos) * n / d); 93 skip = (int)((int64_t)(ci->filesize - ci->curpos) * n / d);
91 ci->seek_buffer (ci->curpos + skip); 94 ci->seek_buffer (ci->curpos + skip);
92 } 95 }
93 else { 96 else if (curpos_ms != 0) {
94 n = curpos_ms - ci->seek_time; 97 n = curpos_ms - param;
95 d = curpos_ms; 98 d = curpos_ms;
96 skip = (int)((int64_t) ci->curpos * n / d); 99 skip = (int)((int64_t) ci->curpos * n / d);
97 ci->seek_buffer (ci->curpos - skip); 100 ci->seek_buffer (ci->curpos - skip);
98 } 101 }
99 102
100 wpc = WavpackOpenFileInput (read_callback, error); 103 wpc = WavpackOpenFileInput (read_callback, error);
101 ci->seek_complete();
102
103 if (!wpc) 104 if (!wpc)
105 {
106 ci->seek_complete();
104 break; 107 break;
108 }
105 109
106 ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); 110 ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
107 ci->yield (); 111 ci->seek_complete();
108 } 112 }
109 113
110 nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / nchans); 114 nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / nchans);
111 115
112 if (!nsamples || ci->stop_codec || ci->new_track) 116 if (!nsamples)
113 break;
114
115 ci->yield ();
116
117 if (ci->stop_codec || ci->new_track)
118 break; 117 break;
119 118
120 ci->pcmbuf_insert (temp_buffer, NULL, nsamples); 119 ci->pcmbuf_insert (temp_buffer, NULL, nsamples);
121
122 ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); 120 ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
123 ci->yield ();
124 } 121 }
125 122
126done: 123 return CODEC_OK;
127 if (ci->request_next_track())
128 goto next_track;
129
130exit:
131 return retval;
132} 124}
diff --git a/apps/codecs/wavpack_enc.c b/apps/codecs/wavpack_enc.c
index d908e284be..730cf0734b 100644
--- a/apps/codecs/wavpack_enc.c
+++ b/apps/codecs/wavpack_enc.c
@@ -389,77 +389,79 @@ static bool init_encoder(void)
389 return true; 389 return true;
390} /* init_encoder */ 390} /* init_encoder */
391 391
392enum codec_status codec_main(void) 392/* this is the codec entry point */
393enum codec_status codec_main(enum codec_entry_call_reason reason)
393{ 394{
394 /* initialize params and config */ 395 if (reason == CODEC_LOAD) {
395 if (!init_encoder()) 396 /* initialize params and config */
396 return CODEC_ERROR; 397 if (!init_encoder())
398 return CODEC_ERROR;
399 }
400 else if (reason == CODEC_UNLOAD) {
401 /* reset parameters to initial state */
402 ci->enc_set_parameters(NULL);
403 }
397 404
405 return CODEC_OK;
406}
407
408/* this is called for each file to process */
409enum codec_status codec_run(void)
410{
398 /* main encoding loop */ 411 /* main encoding loop */
399 while(!ci->stop_codec) 412 while(ci->get_command(NULL) != CODEC_ACTION_HALT)
400 { 413 {
401 uint8_t *src; 414 uint8_t *src = (uint8_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE);
415 struct enc_chunk_hdr *chunk;
416 bool abort_chunk;
417 uint8_t *dst;
418 uint8_t *src_end;
402 419
403 while ((src = ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL) 420 if(src == NULL)
404 { 421 continue;
405 struct enc_chunk_hdr *chunk;
406 bool abort_chunk;
407 uint8_t *dst;
408 uint8_t *src_end;
409
410 if(ci->stop_codec)
411 break;
412
413 abort_chunk = true;
414 422
415 chunk = ci->enc_get_chunk(); 423 chunk = ci->enc_get_chunk();
416 424
417 /* reset counts and pointer */ 425 /* reset counts and pointer */
418 chunk->enc_size = 0; 426 chunk->enc_size = 0;
419 chunk->num_pcm = 0; 427 chunk->num_pcm = 0;
420 chunk->enc_data = NULL; 428 chunk->enc_data = NULL;
421 429
422 dst = ENC_CHUNK_SKIP_HDR(dst, chunk); 430 dst = ENC_CHUNK_SKIP_HDR(dst, chunk);
423 431
424 WavpackStartBlock(wpc, dst, dst + data_size); 432 WavpackStartBlock(wpc, dst, dst + data_size);
425 433
426 chunk_to_int32((uint32_t*)src); 434 chunk_to_int32((uint32_t*)src);
427 src = input_buffer; 435 src = input_buffer;
428 src_end = src + input_size; 436 src_end = src + input_size;
429 437
430 /* encode chunk in four steps yielding between each */ 438 /* encode chunk in four steps yielding between each */
431 do 439 do
440 {
441 abort_chunk = true;
442 if (WavpackPackSamples(wpc, (int32_t *)src,
443 PCM_SAMP_PER_CHUNK/4))
432 { 444 {
433 if (WavpackPackSamples(wpc, (int32_t *)src, 445 chunk->num_pcm += PCM_SAMP_PER_CHUNK/4;
434 PCM_SAMP_PER_CHUNK/4)) 446 ci->yield();
435 { 447 /* could've been stopped in some way */
436 chunk->num_pcm += PCM_SAMP_PER_CHUNK/4; 448 abort_chunk = chunk->flags & CHUNKF_ABORT;
437 ci->yield();
438 /* could've been stopped in some way */
439 abort_chunk = ci->stop_codec ||
440 (chunk->flags & CHUNKF_ABORT);
441 }
442
443 src += input_step;
444 } 449 }
445 while (!abort_chunk && src < src_end);
446 450
447 if (!abort_chunk) 451 src += input_step;
448 {
449 chunk->enc_data = dst;
450 if (chunk->num_pcm < PCM_SAMP_PER_CHUNK)
451 ci->enc_unget_pcm_data(PCM_CHUNK_SIZE - chunk->num_pcm*4);
452 /* finish the chunk and store chunk size info */
453 chunk->enc_size = WavpackFinishBlock(wpc);
454 ci->enc_finish_chunk();
455 }
456 } 452 }
453 while (!abort_chunk && src < src_end);
457 454
458 ci->yield(); 455 if (!abort_chunk)
456 {
457 chunk->enc_data = dst;
458 if (chunk->num_pcm < PCM_SAMP_PER_CHUNK)
459 ci->enc_unget_pcm_data(PCM_CHUNK_SIZE - chunk->num_pcm*4);
460 /* finish the chunk and store chunk size info */
461 chunk->enc_size = WavpackFinishBlock(wpc);
462 ci->enc_finish_chunk();
463 }
459 } 464 }
460 465
461 /* reset parameters to initial state */
462 ci->enc_set_parameters(NULL);
463
464 return CODEC_OK; 466 return CODEC_OK;
465} /* codec_start */ 467}
diff --git a/apps/codecs/wma.c b/apps/codecs/wma.c
index 1b46813444..c327fafb5a 100644
--- a/apps/codecs/wma.c
+++ b/apps/codecs/wma.c
@@ -29,53 +29,52 @@ CODEC_HEADER
29static WMADecodeContext wmadec; 29static WMADecodeContext wmadec;
30 30
31/* this is the codec entry point */ 31/* this is the codec entry point */
32enum codec_status codec_main(void) 32enum codec_status codec_main(enum codec_entry_call_reason reason)
33{
34 if (reason == CODEC_LOAD) {
35 /* Generic codec initialisation */
36 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
37 }
38
39 return CODEC_OK;
40}
41
42/* this is called for each file to process */
43enum codec_status codec_run(void)
33{ 44{
34 uint32_t elapsedtime; 45 uint32_t elapsedtime;
35 int retval;
36 asf_waveformatex_t wfx; 46 asf_waveformatex_t wfx;
37 size_t resume_offset; 47 size_t resume_offset;
38 int i; 48 int i;
39 int wmares, res; 49 int wmares;
50 int res = 0;
40 uint8_t* audiobuf; 51 uint8_t* audiobuf;
41 int audiobufsize; 52 int audiobufsize;
42 int packetlength = 0; 53 int packetlength = 0;
43 int errcount = 0; 54 int errcount = 0;
44 55 intptr_t param;
45 /* Generic codec initialisation */
46 ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
47
48next_track:
49 retval = CODEC_OK;
50 56
51 /* Proper reset of the decoder context. */ 57 /* Proper reset of the decoder context. */
52 memset(&wmadec, 0, sizeof(wmadec)); 58 memset(&wmadec, 0, sizeof(wmadec));
53 59
54 /* Wait for the metadata to be read */
55 if (codec_wait_taginfo() != 0)
56 goto done;
57
58 /* Remember the resume position - when the codec is opened, the 60 /* Remember the resume position - when the codec is opened, the
59 playback engine will reset it. */ 61 playback engine will reset it. */
60 resume_offset = ci->id3->offset; 62 resume_offset = ci->id3->offset;
61 63
62restart_track: 64restart_track:
63 retval = CODEC_OK;
64
65 if (codec_init()) { 65 if (codec_init()) {
66 LOGF("WMA: Error initialising codec\n"); 66 LOGF("WMA: Error initialising codec\n");
67 retval = CODEC_ERROR; 67 return CODEC_ERROR;
68 goto exit;
69 } 68 }
70 69
71 /* Copy the format metadata we've stored in the id3 TOC field. This 70 /* Copy the format metadata we've stored in the id3 TOC field. This
72 saves us from parsing it again here. */ 71 saves us from parsing it again here. */
73 memcpy(&wfx, ci->id3->toc, sizeof(wfx)); 72 memcpy(&wfx, ci->id3->toc, sizeof(wfx));
74 73
74 ci->seek_buffer(ci->id3->first_frame_offset);
75 if (wma_decode_init(&wmadec,&wfx) < 0) { 75 if (wma_decode_init(&wmadec,&wfx) < 0) {
76 LOGF("WMA: Unsupported or corrupt file\n"); 76 LOGF("WMA: Unsupported or corrupt file\n");
77 retval = CODEC_ERROR; 77 return CODEC_ERROR;
78 goto exit;
79 } 78 }
80 79
81 if (resume_offset > ci->id3->first_frame_offset) 80 if (resume_offset > ci->id3->first_frame_offset)
@@ -101,34 +100,35 @@ restart_track:
101 codec_set_replaygain(ci->id3); 100 codec_set_replaygain(ci->id3);
102 101
103 /* The main decoding loop */ 102 /* The main decoding loop */
104
105 res = 1;
106 while (res >= 0) 103 while (res >= 0)
107 { 104 {
108 ci->yield(); 105 enum codec_command_action action = ci->get_command(&param);
109 if (ci->stop_codec || ci->new_track) { 106
110 goto done; 107 if (action == CODEC_ACTION_HALT)
111 } 108 break;
112 109
113 /* Deal with any pending seek requests */ 110 /* Deal with any pending seek requests */
114 if (ci->seek_time){ 111 if (action == CODEC_ACTION_SEEK_TIME) {
115 112
116 if (ci->seek_time == 1) { 113 if (param == 0) {
114 ci->set_elapsed(0);
117 ci->seek_complete(); 115 ci->seek_complete();
118 goto restart_track; /* Pretend you never saw this... */ 116 goto restart_track; /* Pretend you never saw this... */
119 } 117 }
120 118
121 elapsedtime = asf_seek(ci->seek_time, &wfx); 119 elapsedtime = asf_seek(param, &wfx);
122 if (elapsedtime < 1){ 120 if (elapsedtime < 1){
121 ci->set_elapsed(0);
123 ci->seek_complete(); 122 ci->seek_complete();
124 goto next_track; 123 break;
125 } 124 }
126 /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/ 125 /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/
127 ci->set_elapsed(elapsedtime);
128 126
129 /*flush the wma decoder state*/ 127 /*flush the wma decoder state*/
130 wmadec.last_superframe_len = 0; 128 wmadec.last_superframe_len = 0;
131 wmadec.last_bitoffset = 0; 129 wmadec.last_bitoffset = 0;
130
131 ci->set_elapsed(elapsedtime);
132 ci->seek_complete(); 132 ci->seek_complete();
133 } 133 }
134 errcount = 0; 134 errcount = 0;
@@ -140,10 +140,15 @@ new_packet:
140 * times. If we succeed, the error counter will be reset. 140 * times. If we succeed, the error counter will be reset.
141 */ 141 */
142 142
143 if (res == ASF_ERROR_EOF) {
144 /* File ended - not an error */
145 break;
146 }
147
143 errcount++; 148 errcount++;
144 DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount); 149 DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount);
145 if (errcount > 5) { 150 if (errcount > 5) {
146 goto done; 151 return CODEC_ERROR;
147 } else { 152 } else {
148 ci->advance_buffer(packetlength); 153 ci->advance_buffer(packetlength);
149 goto new_packet; 154 goto new_packet;
@@ -163,7 +168,7 @@ new_packet:
163 errcount++; 168 errcount++;
164 DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount); 169 DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount);
165 if (errcount > 5) { 170 if (errcount > 5) {
166 goto done; 171 return CODEC_ERROR;
167 } else { 172 } else {
168 ci->advance_buffer(packetlength); 173 ci->advance_buffer(packetlength);
169 goto new_packet; 174 goto new_packet;
@@ -173,18 +178,12 @@ new_packet:
173 elapsedtime += (wmares*10)/(wfx.rate/100); 178 elapsedtime += (wmares*10)/(wfx.rate/100);
174 ci->set_elapsed(elapsedtime); 179 ci->set_elapsed(elapsedtime);
175 } 180 }
176 ci->yield();
177 } 181 }
178 } 182 }
179 183
180 ci->advance_buffer(packetlength); 184 ci->advance_buffer(packetlength);
181 } 185 }
182 186
183done:
184 /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/ 187 /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/
185 188 return CODEC_OK;
186 if (ci->request_next_track())
187 goto next_track;
188exit:
189 return retval;
190} 189}
diff --git a/apps/codecs/wmapro.c b/apps/codecs/wmapro.c
index c02dddeeb3..b6a8e47f25 100644
--- a/apps/codecs/wmapro.c
+++ b/apps/codecs/wmapro.c
@@ -27,11 +27,22 @@ CODEC_HEADER
27 27
28int32_t *dec[2]; /* pointers to the output buffers in WMAProDecodeCtx in wmaprodec.c */ 28int32_t *dec[2]; /* pointers to the output buffers in WMAProDecodeCtx in wmaprodec.c */
29 29
30
30/* this is the codec entry point */ 31/* this is the codec entry point */
31enum codec_status codec_main(void) 32enum codec_status codec_main(enum codec_entry_call_reason reason)
33{
34 if (reason == CODEC_LOAD) {
35 /* Generic codec initialisation */
36 ci->configure(DSP_SET_SAMPLE_DEPTH, WMAPRO_DSP_SAMPLE_DEPTH);
37 }
38
39 return CODEC_OK;
40}
41
42/* this is called for each file to process */
43enum codec_status codec_run(void)
32{ 44{
33 uint32_t elapsedtime; 45 uint32_t elapsedtime;
34 int retval;
35 asf_waveformatex_t wfx; /* Holds the stream properties */ 46 asf_waveformatex_t wfx; /* Holds the stream properties */
36 size_t resume_offset; 47 size_t resume_offset;
37 int res; /* Return values from asf_read_packet() and decode_packet() */ 48 int res; /* Return values from asf_read_packet() and decode_packet() */
@@ -42,28 +53,15 @@ enum codec_status codec_main(void)
42 int pktcnt = 0; /* Count of the packets played */ 53 int pktcnt = 0; /* Count of the packets played */
43 uint8_t *data; /* Pointer to decoder input buffer */ 54 uint8_t *data; /* Pointer to decoder input buffer */
44 int size; /* Size of the input frame to the decoder */ 55 int size; /* Size of the input frame to the decoder */
45 56 intptr_t param;
46 /* Generic codec initialisation */
47 ci->configure(DSP_SET_SAMPLE_DEPTH, WMAPRO_DSP_SAMPLE_DEPTH);
48
49
50next_track:
51 retval = CODEC_OK;
52
53 /* Wait for the metadata to be read */
54 if (codec_wait_taginfo() != 0)
55 goto done;
56 57
57 /* Remember the resume position */ 58 /* Remember the resume position */
58 resume_offset = ci->id3->offset; 59 resume_offset = ci->id3->offset;
59 60
60restart_track: 61restart_track:
61 retval = CODEC_OK;
62
63 if (codec_init()) { 62 if (codec_init()) {
64 LOGF("(WMA PRO) Error: Error initialising codec\n"); 63 LOGF("(WMA PRO) Error: Error initialising codec\n");
65 retval = CODEC_ERROR; 64 return CODEC_ERROR;
66 goto done;
67 } 65 }
68 66
69 /* Copy the format metadata we've stored in the id3 TOC field. This 67 /* Copy the format metadata we've stored in the id3 TOC field. This
@@ -77,8 +75,7 @@ restart_track:
77 75
78 if (decode_init(&wfx) < 0) { 76 if (decode_init(&wfx) < 0) {
79 LOGF("(WMA PRO) Error: Unsupported or corrupt file\n"); 77 LOGF("(WMA PRO) Error: Unsupported or corrupt file\n");
80 retval = CODEC_ERROR; 78 return CODEC_ERROR;
81 goto done;
82 } 79 }
83 80
84 /* Now advance the file position to the first frame */ 81 /* Now advance the file position to the first frame */
@@ -91,23 +88,24 @@ restart_track:
91 88
92 while (pktcnt < wfx.numpackets) 89 while (pktcnt < wfx.numpackets)
93 { 90 {
94 ci->yield(); 91 enum codec_command_action action = ci->get_command(&param);
95 if (ci->stop_codec || ci->new_track) { 92
96 goto done; 93 if (action == CODEC_ACTION_HALT)
97 } 94 break;
98
99 /* Deal with any pending seek requests */
100 if (ci->seek_time){
101 95
102 if (ci->seek_time == 1) { 96 /* Deal with any pending seek requests */
97 if (action == CODEC_ACTION_SEEK_TIME) {
98 if (param == 0) {
99 ci->set_elapsed(0);
103 ci->seek_complete(); 100 ci->seek_complete();
104 goto restart_track; /* Pretend you never saw this... */ 101 goto restart_track; /* Pretend you never saw this... */
105 } 102 }
106 103
107 elapsedtime = asf_seek(ci->seek_time, &wfx); 104 elapsedtime = asf_seek(param, &wfx);
108 if (elapsedtime < 1){ 105 if (elapsedtime < 1){
106 ci->set_elapsed(0);
109 ci->seek_complete(); 107 ci->seek_complete();
110 goto next_track; 108 break;
111 } 109 }
112 110
113 ci->set_elapsed(elapsedtime); 111 ci->set_elapsed(elapsedtime);
@@ -117,8 +115,8 @@ restart_track:
117 res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx); 115 res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx);
118 116
119 if (res < 0) { 117 if (res < 0) {
120 LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res); 118 LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res);
121 goto done; 119 return CODEC_ERROR;
122 } else { 120 } else {
123 data = audiobuf; 121 data = audiobuf;
124 size = audiobufsize; 122 size = audiobufsize;
@@ -132,7 +130,7 @@ restart_track:
132 res = decode_packet(&wfx, dec, &outlen, data, size); 130 res = decode_packet(&wfx, dec, &outlen, data, size);
133 if(res < 0) { 131 if(res < 0) {
134 LOGF("(WMA PRO) Error: decode_packet returned %d", res); 132 LOGF("(WMA PRO) Error: decode_packet returned %d", res);
135 goto done; 133 return CODEC_ERROR;
136 } 134 }
137 data += res; 135 data += res;
138 size -= res; 136 size -= res;
@@ -152,10 +150,6 @@ restart_track:
152 ci->advance_buffer(packetlength); 150 ci->advance_buffer(packetlength);
153 } 151 }
154 152
155done: 153 return CODEC_OK;
156 if (ci->request_next_track())
157 goto next_track;
158
159 return retval;
160} 154}
161 155
diff --git a/apps/codecs/wmavoice.c b/apps/codecs/wmavoice.c
index ddf66828f1..64c8cd1692 100644
--- a/apps/codecs/wmavoice.c
+++ b/apps/codecs/wmavoice.c
@@ -52,10 +52,20 @@ static void init_codec_ctx(AVCodecContext *avctx, asf_waveformatex_t *wfx)
52} 52}
53 53
54/* this is the codec entry point */ 54/* this is the codec entry point */
55enum codec_status codec_main(void) 55enum codec_status codec_main(enum codec_entry_call_reason reason)
56{
57 if (reason == CODEC_LOAD) {
58 /* Generic codec initialisation */
59 ci->configure(DSP_SET_SAMPLE_DEPTH, 31);
60 }
61
62 return CODEC_OK;
63}
64
65/* this is called for each file to process */
66enum codec_status codec_run(void)
56{ 67{
57 uint32_t elapsedtime; 68 uint32_t elapsedtime;
58 int retval;
59 asf_waveformatex_t wfx; /* Holds the stream properties */ 69 asf_waveformatex_t wfx; /* Holds the stream properties */
60 size_t resume_offset; 70 size_t resume_offset;
61 int res; /* Return values from asf_read_packet() and decode_packet() */ 71 int res; /* Return values from asf_read_packet() and decode_packet() */
@@ -64,27 +74,14 @@ enum codec_status codec_main(void)
64 int packetlength = 0; /* Logical packet size (minus the header size) */ 74 int packetlength = 0; /* Logical packet size (minus the header size) */
65 int outlen = 0; /* Number of bytes written to the output buffer */ 75 int outlen = 0; /* Number of bytes written to the output buffer */
66 int pktcnt = 0; /* Count of the packets played */ 76 int pktcnt = 0; /* Count of the packets played */
67 77 intptr_t param;
68 /* Generic codec initialisation */
69 ci->configure(DSP_SET_SAMPLE_DEPTH, 31);
70
71
72next_track:
73 retval = CODEC_OK;
74
75 /* Wait for the metadata to be read */
76 if (codec_wait_taginfo() != 0)
77 goto done;
78 78
79 /* Remember the resume position */ 79 /* Remember the resume position */
80 resume_offset = ci->id3->offset; 80 resume_offset = ci->id3->offset;
81restart_track: 81restart_track:
82 retval = CODEC_OK;
83
84 if (codec_init()) { 82 if (codec_init()) {
85 LOGF("(WMA Voice) Error: Error initialising codec\n"); 83 LOGF("(WMA Voice) Error: Error initialising codec\n");
86 retval = CODEC_ERROR; 84 return CODEC_ERROR;
87 goto done;
88 } 85 }
89 86
90 /* Copy the format metadata we've stored in the id3 TOC field. This 87 /* Copy the format metadata we've stored in the id3 TOC field. This
@@ -97,14 +94,15 @@ restart_track:
97 ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ? 94 ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ?
98 STEREO_MONO : STEREO_INTERLEAVED); 95 STEREO_MONO : STEREO_INTERLEAVED);
99 codec_set_replaygain(ci->id3); 96 codec_set_replaygain(ci->id3);
97
98 ci->seek_buffer(0);
100 99
101 /* Initialise the AVCodecContext */ 100 /* Initialise the AVCodecContext */
102 init_codec_ctx(&avctx, &wfx); 101 init_codec_ctx(&avctx, &wfx);
103 102
104 if (wmavoice_decode_init(&avctx) < 0) { 103 if (wmavoice_decode_init(&avctx) < 0) {
105 LOGF("(WMA Voice) Error: Unsupported or corrupt file\n"); 104 LOGF("(WMA Voice) Error: Unsupported or corrupt file\n");
106 retval = CODEC_ERROR; 105 return CODEC_ERROR;
107 goto done;
108 } 106 }
109 107
110 /* Now advance the file position to the first frame */ 108 /* Now advance the file position to the first frame */
@@ -117,21 +115,24 @@ restart_track:
117 115
118 while (pktcnt < wfx.numpackets) 116 while (pktcnt < wfx.numpackets)
119 { 117 {
120 ci->yield(); 118 enum codec_command_action action = ci->get_command(&param);
121 if (ci->stop_codec || ci->new_track) { 119
122 goto done; 120 if (action == CODEC_ACTION_HALT)
123 } 121 break;
124 122
125 /* Deal with any pending seek requests */ 123 /* Deal with any pending seek requests */
126 if (ci->seek_time){ 124 if (action == CODEC_ACTION_SEEK_TIME) {
125 ci->set_elapsed(param);
127 126
128 if (ci->seek_time == 1) { 127 if (param == 0) {
128 ci->set_elapsed(0);
129 ci->seek_complete(); 129 ci->seek_complete();
130 goto restart_track; /* Pretend you never saw this... */ 130 goto restart_track; /* Pretend you never saw this... */
131 } 131 }
132 132
133 elapsedtime = asf_seek(ci->seek_time, &wfx); 133 elapsedtime = asf_seek(param, &wfx);
134 if (elapsedtime < 1){ 134 if (elapsedtime < 1){
135 ci->set_elapsed(0);
135 ci->seek_complete(); 136 ci->seek_complete();
136 goto next_track; 137 goto next_track;
137 } 138 }
@@ -145,7 +146,7 @@ new_packet:
145 146
146 if (res < 0) { 147 if (res < 0) {
147 LOGF("(WMA Voice) read_packet error %d\n",res); 148 LOGF("(WMA Voice) read_packet error %d\n",res);
148 goto done; 149 return CODEC_ERROR;
149 } else { 150 } else {
150 avpkt.data = audiobuf; 151 avpkt.data = audiobuf;
151 avpkt.size = audiobufsize; 152 avpkt.size = audiobufsize;
@@ -165,8 +166,9 @@ new_packet:
165 ci->advance_buffer(packetlength); 166 ci->advance_buffer(packetlength);
166 goto new_packet; 167 goto new_packet;
167 } 168 }
168 else 169 else {
169 goto done; 170 return CODEC_ERROR;
171 }
170 } 172 }
171 avpkt.data += res; 173 avpkt.data += res;
172 avpkt.size -= res; 174 avpkt.size -= res;
@@ -186,10 +188,6 @@ new_packet:
186 ci->advance_buffer(packetlength); 188 ci->advance_buffer(packetlength);
187 } 189 }
188 190
189done: 191 return CODEC_OK;
190 if (ci->request_next_track())
191 goto next_track;
192
193 return retval;
194} 192}
195 193