diff options
Diffstat (limited to 'lib/rbcodec/codecs/ape.c')
-rw-r--r-- | lib/rbcodec/codecs/ape.c | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/lib/rbcodec/codecs/ape.c b/lib/rbcodec/codecs/ape.c index 577e7b65e2..a6c5254d45 100644 --- a/lib/rbcodec/codecs/ape.c +++ b/lib/rbcodec/codecs/ape.c | |||
@@ -155,6 +155,7 @@ enum codec_status codec_run(void) | |||
155 | int res; | 155 | int res; |
156 | int firstbyte; | 156 | int firstbyte; |
157 | size_t resume_offset; | 157 | size_t resume_offset; |
158 | enum codec_command_action action; | ||
158 | intptr_t param; | 159 | intptr_t param; |
159 | 160 | ||
160 | if (codec_init()) { | 161 | if (codec_init()) { |
@@ -162,8 +163,12 @@ enum codec_status codec_run(void) | |||
162 | return CODEC_ERROR; | 163 | return CODEC_ERROR; |
163 | } | 164 | } |
164 | 165 | ||
166 | action = CODEC_ACTION_NULL; | ||
167 | param = 0; | ||
168 | |||
165 | /* Remember the resume position - when the codec is opened, the | 169 | /* Remember the resume position - when the codec is opened, the |
166 | playback engine will reset it. */ | 170 | playback engine will reset it. */ |
171 | elapsedtime = ci->id3->elapsed; | ||
167 | resume_offset = ci->id3->offset; | 172 | resume_offset = ci->id3->offset; |
168 | 173 | ||
169 | ci->seek_buffer(0); | 174 | ci->seek_buffer(0); |
@@ -213,14 +218,21 @@ enum codec_status codec_run(void) | |||
213 | 218 | ||
214 | ape_resume(&ape_ctx, resume_offset, | 219 | ape_resume(&ape_ctx, resume_offset, |
215 | ¤tframe, &samplesdone, &samplestoskip, &firstbyte); | 220 | ¤tframe, &samplesdone, &samplestoskip, &firstbyte); |
216 | } else { | 221 | elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100); |
222 | } | ||
223 | else { | ||
217 | currentframe = 0; | 224 | currentframe = 0; |
218 | samplesdone = 0; | 225 | samplesdone = 0; |
219 | samplestoskip = 0; | 226 | samplestoskip = 0; |
220 | firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */ | 227 | firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */ |
228 | |||
229 | if (elapsedtime) { | ||
230 | /* Resume by simulated seeking */ | ||
231 | param = elapsedtime; | ||
232 | action = CODEC_ACTION_SEEK_TIME; | ||
233 | } | ||
221 | } | 234 | } |
222 | 235 | ||
223 | elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100); | ||
224 | ci->set_elapsed(elapsedtime); | 236 | ci->set_elapsed(elapsedtime); |
225 | 237 | ||
226 | /* Initialise the buffer */ | 238 | /* Initialise the buffer */ |
@@ -247,36 +259,44 @@ frame_start: | |||
247 | /* Decode the frame a chunk at a time */ | 259 | /* Decode the frame a chunk at a time */ |
248 | while (nblocks > 0) | 260 | while (nblocks > 0) |
249 | { | 261 | { |
250 | enum codec_command_action action = ci->get_command(¶m); | 262 | if (action == CODEC_ACTION_NULL) |
263 | action = ci->get_command(¶m); | ||
251 | 264 | ||
252 | if (action == CODEC_ACTION_HALT) | 265 | if (action != CODEC_ACTION_NULL) { |
253 | goto done; | 266 | if (action == CODEC_ACTION_HALT) |
267 | goto done; | ||
254 | 268 | ||
255 | /* Deal with any pending seek requests */ | 269 | /* Deal with any pending seek requests */ |
256 | if (action == CODEC_ACTION_SEEK_TIME) | 270 | if (action == CODEC_ACTION_SEEK_TIME) |
257 | { | ||
258 | if (ape_calc_seekpos(&ape_ctx, | ||
259 | (param/10) * (ci->id3->frequency/100), | ||
260 | ¤tframe, | ||
261 | &newfilepos, | ||
262 | &samplestoskip)) | ||
263 | { | 271 | { |
264 | samplesdone = currentframe * ape_ctx.blocksperframe; | 272 | if (ape_calc_seekpos(&ape_ctx, |
265 | 273 | (param/10) * (ci->id3->frequency/100), | |
266 | /* APE's bytestream is weird... */ | 274 | ¤tframe, |
267 | firstbyte = 3 - (newfilepos & 3); | 275 | &newfilepos, |
268 | newfilepos &= ~3; | 276 | &samplestoskip)) |
269 | 277 | { | |
270 | ci->seek_buffer(newfilepos); | 278 | samplesdone = currentframe * ape_ctx.blocksperframe; |
271 | inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); | 279 | |
280 | /* APE's bytestream is weird... */ | ||
281 | firstbyte = 3 - (newfilepos & 3); | ||
282 | newfilepos &= ~3; | ||
283 | |||
284 | ci->seek_buffer(newfilepos); | ||
285 | inbuffer = ci->request_buffer(&bytesleft, | ||
286 | INPUT_CHUNKSIZE); | ||
287 | |||
288 | elapsedtime = (samplesdone*10)/ | ||
289 | (ape_ctx.samplerate/100); | ||
290 | ci->set_elapsed(elapsedtime); | ||
291 | ci->seek_complete(); | ||
292 | action = CODEC_ACTION_NULL; | ||
293 | goto frame_start; /* Sorry... */ | ||
294 | } | ||
272 | 295 | ||
273 | elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100); | ||
274 | ci->set_elapsed(elapsedtime); | ||
275 | ci->seek_complete(); | 296 | ci->seek_complete(); |
276 | goto frame_start; /* Sorry... */ | ||
277 | } | 297 | } |
278 | 298 | ||
279 | ci->seek_complete(); | 299 | action = CODEC_ACTION_NULL; |
280 | } | 300 | } |
281 | 301 | ||
282 | blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks); | 302 | blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks); |