summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs')
-rw-r--r--lib/rbcodec/codecs/a52.c28
-rw-r--r--lib/rbcodec/codecs/a52_rm.c11
-rw-r--r--lib/rbcodec/codecs/aac.c15
-rw-r--r--lib/rbcodec/codecs/aiff.c17
-rw-r--r--lib/rbcodec/codecs/alac.c29
-rw-r--r--lib/rbcodec/codecs/ape.c70
-rw-r--r--lib/rbcodec/codecs/asap.c10
-rw-r--r--lib/rbcodec/codecs/atrac3_oma.c21
-rw-r--r--lib/rbcodec/codecs/atrac3_rm.c18
-rw-r--r--lib/rbcodec/codecs/au.c17
-rw-r--r--lib/rbcodec/codecs/ay.c6
-rw-r--r--lib/rbcodec/codecs/cook.c13
-rw-r--r--lib/rbcodec/codecs/flac.c16
-rw-r--r--lib/rbcodec/codecs/gbs.c5
-rw-r--r--lib/rbcodec/codecs/hes.c5
-rw-r--r--lib/rbcodec/codecs/kss.c5
-rw-r--r--lib/rbcodec/codecs/mod.c11
-rw-r--r--lib/rbcodec/codecs/mpa.c5
-rw-r--r--lib/rbcodec/codecs/mpc.c18
-rw-r--r--lib/rbcodec/codecs/nsf.c6
-rw-r--r--lib/rbcodec/codecs/opus.c47
-rw-r--r--lib/rbcodec/codecs/raac.c21
-rw-r--r--lib/rbcodec/codecs/sgc.c5
-rw-r--r--lib/rbcodec/codecs/sid.c22
-rw-r--r--lib/rbcodec/codecs/smaf.c21
-rw-r--r--lib/rbcodec/codecs/speex.c60
-rw-r--r--lib/rbcodec/codecs/tta.c16
-rw-r--r--lib/rbcodec/codecs/vgm.c5
-rw-r--r--lib/rbcodec/codecs/vorbis.c14
-rw-r--r--lib/rbcodec/codecs/vox.c20
-rw-r--r--lib/rbcodec/codecs/wav.c20
-rw-r--r--lib/rbcodec/codecs/wav64.c19
-rw-r--r--lib/rbcodec/codecs/wavpack.c14
-rwxr-xr-xlib/rbcodec/codecs/wma.c28
-rw-r--r--lib/rbcodec/codecs/wmapro.c17
-rw-r--r--lib/rbcodec/codecs/wmavoice.c24
36 files changed, 487 insertions, 192 deletions
diff --git a/lib/rbcodec/codecs/a52.c b/lib/rbcodec/codecs/a52.c
index 77caaf87c1..da670308b8 100644
--- a/lib/rbcodec/codecs/a52.c
+++ b/lib/rbcodec/codecs/a52.c
@@ -150,19 +150,28 @@ enum codec_status codec_run(void)
150 150
151 samplesdone = 0; 151 samplesdone = 0;
152 152
153 /* The main decoding loop */
154 if (ci->id3->offset) { 153 if (ci->id3->offset) {
155 if (ci->seek_buffer(ci->id3->offset)) { 154 sample_loc = (ci->id3->offset / ci->id3->bytesperframe) *
156 samplesdone = (ci->id3->offset / ci->id3->bytesperframe) * 155 A52_SAMPLESPERFRAME;
157 A52_SAMPLESPERFRAME; 156 param = ci->id3->offset;
158 ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000)); 157 }
159 } 158 else if (ci->id3->elapsed) {
159 sample_loc = ci->id3->elapsed/1000 * ci->id3->frequency;
160 param = sample_loc/A52_SAMPLESPERFRAME*ci->id3->bytesperframe;
160 } 161 }
161 else { 162 else {
162 ci->seek_buffer(ci->id3->first_frame_offset); 163 sample_loc = 0;
163 ci->set_elapsed(0); 164 param = ci->id3->first_frame_offset;
165 }
166
167 if (ci->seek_buffer(param)) {
168 samplesdone = sample_loc;
164 } 169 }
165 170
171 ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
172
173 /* The main decoding loop */
174
166 while (1) { 175 while (1) {
167 enum codec_command_action action = ci->get_command(&param); 176 enum codec_command_action action = ci->get_command(&param);
168 177
@@ -172,7 +181,8 @@ enum codec_status codec_run(void)
172 if (action == CODEC_ACTION_SEEK_TIME) { 181 if (action == CODEC_ACTION_SEEK_TIME) {
173 sample_loc = param/1000 * ci->id3->frequency; 182 sample_loc = param/1000 * ci->id3->frequency;
174 183
175 if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) { 184 if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*
185 ci->id3->bytesperframe)) {
176 samplesdone = sample_loc; 186 samplesdone = sample_loc;
177 ci->set_elapsed(samplesdone/(ci->id3->frequency/1000)); 187 ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
178 } 188 }
diff --git a/lib/rbcodec/codecs/a52_rm.c b/lib/rbcodec/codecs/a52_rm.c
index 42868437d8..3f07a43ce9 100644
--- a/lib/rbcodec/codecs/a52_rm.c
+++ b/lib/rbcodec/codecs/a52_rm.c
@@ -148,13 +148,15 @@ enum codec_status codec_run(void)
148 int consumed, packet_offset; 148 int consumed, packet_offset;
149 int playback_on = -1; 149 int playback_on = -1;
150 size_t resume_offset; 150 size_t resume_offset;
151 enum codec_command_action action;
151 intptr_t param; 152 intptr_t param;
152 enum codec_command_action action = CODEC_ACTION_NULL;
153 153
154 if (codec_init()) { 154 if (codec_init()) {
155 return CODEC_ERROR; 155 return CODEC_ERROR;
156 } 156 }
157 157
158 action = CODEC_ACTION_NULL;
159 param = ci->id3->elapsed;
158 resume_offset = ci->id3->offset; 160 resume_offset = ci->id3->offset;
159 161
160 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); 162 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
@@ -171,11 +173,14 @@ enum codec_status codec_run(void)
171 samplesdone = 0; 173 samplesdone = 0;
172 174
173 /* check for a mid-track resume and force a seek time accordingly */ 175 /* check for a mid-track resume and force a seek time accordingly */
174 if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { 176 if (resume_offset) {
175 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; 177 resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
176 /* put number of subpackets to skip in resume_offset */ 178 /* put number of subpackets to skip in resume_offset */
177 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); 179 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
178 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); 180 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
181 }
182
183 if (param > 0) {
179 action = CODEC_ACTION_SEEK_TIME; 184 action = CODEC_ACTION_SEEK_TIME;
180 } 185 }
181 else { 186 else {
diff --git a/lib/rbcodec/codecs/aac.c b/lib/rbcodec/codecs/aac.c
index c9cf737b48..015e332be2 100644
--- a/lib/rbcodec/codecs/aac.c
+++ b/lib/rbcodec/codecs/aac.c
@@ -72,6 +72,7 @@ enum codec_status codec_run(void)
72 uint32_t sbr_fac = 1; 72 uint32_t sbr_fac = 1;
73 unsigned char c = 0; 73 unsigned char c = 0;
74 void *ret; 74 void *ret;
75 enum codec_command_action action;
75 intptr_t param; 76 intptr_t param;
76 bool empty_first_frame = false; 77 bool empty_first_frame = false;
77 78
@@ -82,6 +83,8 @@ enum codec_status codec_run(void)
82 return CODEC_ERROR; 83 return CODEC_ERROR;
83 } 84 }
84 85
86 action = CODEC_ACTION_NULL;
87 param = ci->id3->elapsed;
85 file_offset = ci->id3->offset; 88 file_offset = ci->id3->offset;
86 89
87 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); 90 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
@@ -138,11 +141,16 @@ enum codec_status codec_run(void)
138 sound_samples_done = 0; 141 sound_samples_done = 0;
139 } 142 }
140 NeAACDecPostSeekReset(decoder, i); 143 NeAACDecPostSeekReset(decoder, i);
144 elapsed_time = (sound_samples_done * 10) /
145 (ci->id3->frequency / 100);
146 } else if (param) {
147 elapsed_time = param;
148 action = CODEC_ACTION_SEEK_TIME;
141 } else { 149 } else {
150 elapsed_time = 0;
142 sound_samples_done = 0; 151 sound_samples_done = 0;
143 } 152 }
144 153
145 elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
146 ci->set_elapsed(elapsed_time); 154 ci->set_elapsed(elapsed_time);
147 155
148 if (i == 0) 156 if (i == 0)
@@ -152,7 +160,8 @@ enum codec_status codec_run(void)
152 160
153 /* The main decoding loop */ 161 /* The main decoding loop */
154 while (i < demux_res.num_sample_byte_sizes) { 162 while (i < demux_res.num_sample_byte_sizes) {
155 enum codec_command_action action = ci->get_command(&param); 163 if (action == CODEC_ACTION_NULL)
164 action = ci->get_command(&param);
156 165
157 if (action == CODEC_ACTION_HALT) 166 if (action == CODEC_ACTION_HALT)
158 break; 167 break;
@@ -180,6 +189,8 @@ enum codec_status codec_run(void)
180 ci->seek_complete(); 189 ci->seek_complete();
181 } 190 }
182 191
192 action = CODEC_ACTION_NULL;
193
183 /* There can be gaps between chunks, so skip ahead if needed. It 194 /* There can be gaps between chunks, so skip ahead if needed. It
184 * doesn't seem to happen much, but it probably means that a 195 * doesn't seem to happen much, but it probably means that a
185 * "proper" file can have chunks out of order. Why one would want 196 * "proper" file can have chunks out of order. Why one would want
diff --git a/lib/rbcodec/codecs/aiff.c b/lib/rbcodec/codecs/aiff.c
index 3bedfa5760..9fee781c03 100644
--- a/lib/rbcodec/codecs/aiff.c
+++ b/lib/rbcodec/codecs/aiff.c
@@ -99,6 +99,7 @@ enum codec_status codec_run(void)
99 codec_set_replaygain(ci->id3); 99 codec_set_replaygain(ci->id3);
100 100
101 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 101 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
102 param = ci->id3->elapsed;
102 bytesdone = ci->id3->offset; 103 bytesdone = ci->id3->offset;
103 104
104 /* assume the AIFF header is less than 1024 bytes */ 105 /* assume the AIFF header is less than 1024 bytes */
@@ -270,10 +271,20 @@ enum codec_status codec_run(void)
270 ci->advance_buffer(firstblockposn); 271 ci->advance_buffer(firstblockposn);
271 272
272 /* make sure we're at the correct offset */ 273 /* make sure we're at the correct offset */
273 if (bytesdone > (uint32_t) firstblockposn) { 274 if (bytesdone > (uint32_t) firstblockposn || param) {
275 uint32_t seek_val;
276 int seek_mode;
277
278 if (bytesdone) {
279 seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone);
280 seek_mode = PCM_SEEK_POS;
281 } else {
282 seek_val = param;
283 seek_mode = PCM_SEEK_TIME;
284 }
285
274 /* Round down to previous block */ 286 /* Round down to previous block */
275 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, 287 struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, NULL);
276 PCM_SEEK_POS, NULL);
277 288
278 if (newpos->pos > format.numbytes) 289 if (newpos->pos > format.numbytes)
279 return CODEC_OK; 290 return CODEC_OK;
diff --git a/lib/rbcodec/codecs/alac.c b/lib/rbcodec/codecs/alac.c
index 5eb6e001f7..a3a5ad43b8 100644
--- a/lib/rbcodec/codecs/alac.c
+++ b/lib/rbcodec/codecs/alac.c
@@ -50,7 +50,7 @@ enum codec_status codec_run(void)
50 demux_res_t demux_res; 50 demux_res_t demux_res;
51 stream_t input_stream; 51 stream_t input_stream;
52 uint32_t samplesdone; 52 uint32_t samplesdone;
53 uint32_t elapsedtime = 0; 53 uint32_t elapsedtime;
54 int samplesdecoded; 54 int samplesdecoded;
55 unsigned int i; 55 unsigned int i;
56 unsigned char* buffer; 56 unsigned char* buffer;
@@ -71,9 +71,9 @@ enum codec_status codec_run(void)
71 71
72 stream_create(&input_stream,ci); 72 stream_create(&input_stream,ci);
73 73
74 /* Read from ci->id3->offset before calling qtmovie_read. */ 74 /* Read resume info before calling qtmovie_read. */
75 samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) / 75 elapsedtime = ci->id3->elapsed;
76 (ci->id3->bitrate*128)); 76 samplesdone = ci->id3->offset;
77 77
78 /* if qtmovie_read returns successfully, the stream is up to 78 /* if qtmovie_read returns successfully, the stream is up to
79 * the movie data, which can be used directly by the decoder */ 79 * the movie data, which can be used directly by the decoder */
@@ -87,16 +87,24 @@ enum codec_status codec_run(void)
87 87
88 /* Set i for first frame, seek to desired sample position for resuming. */ 88 /* Set i for first frame, seek to desired sample position for resuming. */
89 i=0; 89 i=0;
90 if (samplesdone > 0) { 90
91 if (m4a_seek(&demux_res, &input_stream, samplesdone, 91 if (elapsedtime || samplesdone) {
92 if (samplesdone) {
93 samplesdone =
94 (uint32_t)((uint64_t)samplesdone*ci->id3->frequency /
95 (ci->id3->bitrate*128));
96 }
97 else {
98 samplesdone = (elapsedtime/10) * (ci->id3->frequency/100);
99 }
100
101 if (!m4a_seek(&demux_res, &input_stream, samplesdone,
92 &samplesdone, (int*) &i)) { 102 &samplesdone, (int*) &i)) {
93 elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100);
94 ci->set_elapsed(elapsedtime);
95 } else {
96 samplesdone = 0; 103 samplesdone = 0;
97 } 104 }
98 } 105 }
99 106
107 elapsedtime = (samplesdone*10)/(ci->id3->frequency/100);
100 ci->set_elapsed(elapsedtime); 108 ci->set_elapsed(elapsedtime);
101 109
102 /* The main decoding loop */ 110 /* The main decoding loop */
@@ -106,9 +114,6 @@ enum codec_status codec_run(void)
106 if (action == CODEC_ACTION_HALT) 114 if (action == CODEC_ACTION_HALT)
107 break; 115 break;
108 116
109 /* Request the required number of bytes from the input buffer */
110 buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE);
111
112 /* Deal with any pending seek requests */ 117 /* Deal with any pending seek requests */
113 if (action == CODEC_ACTION_SEEK_TIME) { 118 if (action == CODEC_ACTION_SEEK_TIME) {
114 if (m4a_seek(&demux_res, &input_stream, 119 if (m4a_seek(&demux_res, &input_stream,
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 &currentframe, &samplesdone, &samplestoskip, &firstbyte); 220 &currentframe, &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(&param); 262 if (action == CODEC_ACTION_NULL)
263 action = ci->get_command(&param);
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 &currentframe,
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 &currentframe,
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);
diff --git a/lib/rbcodec/codecs/asap.c b/lib/rbcodec/codecs/asap.c
index 19b39a44c4..2c350ba450 100644
--- a/lib/rbcodec/codecs/asap.c
+++ b/lib/rbcodec/codecs/asap.c
@@ -52,6 +52,8 @@ enum codec_status codec_run(void)
52 return CODEC_ERROR; 52 return CODEC_ERROR;
53 } 53 }
54 54
55 param = ci->id3->elapsed;
56
55 codec_set_replaygain(ci->id3); 57 codec_set_replaygain(ci->id3);
56 58
57 int bytes_done =0; 59 int bytes_done =0;
@@ -86,8 +88,6 @@ enum codec_status codec_run(void)
86 ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); 88 ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
87 bytesPerSample = 4; 89 bytesPerSample = 4;
88 } 90 }
89 /* reset eleapsed */
90 ci->set_elapsed(0);
91 91
92 song = asap.module_info->default_song; 92 song = asap.module_info->default_song;
93 duration = asap.module_info->durations[song]; 93 duration = asap.module_info->durations[song];
@@ -100,6 +100,11 @@ enum codec_status codec_run(void)
100 ASAP_PlaySong(&asap, song, duration); 100 ASAP_PlaySong(&asap, song, duration);
101 ASAP_MutePokeyChannels(&asap, 0); 101 ASAP_MutePokeyChannels(&asap, 0);
102 102
103 if (param)
104 goto resume_start;
105
106 ci->set_elapsed(0);
107
103 /* The main decoder loop */ 108 /* The main decoder loop */
104 while (1) { 109 while (1) {
105 enum codec_command_action action = ci->get_command(&param); 110 enum codec_command_action action = ci->get_command(&param);
@@ -108,6 +113,7 @@ enum codec_status codec_run(void)
108 break; 113 break;
109 114
110 if (action == CODEC_ACTION_SEEK_TIME) { 115 if (action == CODEC_ACTION_SEEK_TIME) {
116 resume_start:
111 /* New time is ready in param */ 117 /* New time is ready in param */
112 118
113 /* seek to pos */ 119 /* seek to pos */
diff --git a/lib/rbcodec/codecs/atrac3_oma.c b/lib/rbcodec/codecs/atrac3_oma.c
index 50f7c8f163..65d9ed8b38 100644
--- a/lib/rbcodec/codecs/atrac3_oma.c
+++ b/lib/rbcodec/codecs/atrac3_oma.c
@@ -50,13 +50,15 @@ enum codec_status codec_run(void)
50 int elapsed = 0; 50 int elapsed = 0;
51 size_t resume_offset; 51 size_t resume_offset;
52 intptr_t param; 52 intptr_t param;
53 enum codec_command_action action = CODEC_ACTION_NULL; 53 enum codec_command_action action;
54 54
55 if (codec_init()) { 55 if (codec_init()) {
56 DEBUGF("codec init failed\n"); 56 DEBUGF("codec init failed\n");
57 return CODEC_ERROR; 57 return CODEC_ERROR;
58 } 58 }
59 59
60 action = CODEC_ACTION_NULL;
61 param = ci->id3->elapsed;
60 resume_offset = ci->id3->offset; 62 resume_offset = ci->id3->offset;
61 63
62 codec_set_replaygain(ci->id3); 64 codec_set_replaygain(ci->id3);
@@ -79,11 +81,13 @@ enum codec_status codec_run(void)
79 frame_counter = 0; 81 frame_counter = 0;
80 82
81 /* check for a mid-track resume and force a seek time accordingly */ 83 /* check for a mid-track resume and force a seek time accordingly */
82 if(resume_offset > ci->id3->first_frame_offset) { 84 if (resume_offset) {
83 resume_offset -= ci->id3->first_frame_offset; 85 resume_offset -= MIN(resume_offset, ci->id3->first_frame_offset);
84 /* calculate resume_offset in frames */ 86 /* calculate resume_offset in frames */
85 resume_offset = (int)resume_offset / FRAMESIZE; 87 param = (resume_offset/FRAMESIZE) * ((FRAMESIZE * 8)/BITRATE);
86 param = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE); 88 }
89
90 if ((unsigned long)param) {
87 action = CODEC_ACTION_SEEK_TIME; 91 action = CODEC_ACTION_SEEK_TIME;
88 } 92 }
89 else { 93 else {
@@ -100,11 +104,9 @@ enum codec_status codec_run(void)
100 if (action == CODEC_ACTION_HALT) 104 if (action == CODEC_ACTION_HALT)
101 break; 105 break;
102 106
103 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
104
105 if (action == CODEC_ACTION_SEEK_TIME) { 107 if (action == CODEC_ACTION_SEEK_TIME) {
106 /* Do not allow seeking beyond the file's length */ 108 /* Do not allow seeking beyond the file's length */
107 if ((unsigned) param > ci->id3->length) { 109 if ((unsigned long) param > ci->id3->length) {
108 ci->set_elapsed(ci->id3->length); 110 ci->set_elapsed(ci->id3->length);
109 ci->seek_complete(); 111 ci->seek_complete();
110 break; 112 break;
@@ -123,7 +125,6 @@ enum codec_status codec_run(void)
123 seek_frame_offset = (param * BITRATE) / (8 * FRAMESIZE); 125 seek_frame_offset = (param * BITRATE) / (8 * FRAMESIZE);
124 frame_counter = seek_frame_offset; 126 frame_counter = seek_frame_offset;
125 ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE); 127 ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE);
126 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
127 elapsed = param; 128 elapsed = param;
128 ci->set_elapsed(elapsed); 129 ci->set_elapsed(elapsed);
129 ci->seek_complete(); 130 ci->seek_complete();
@@ -131,6 +132,8 @@ enum codec_status codec_run(void)
131 132
132 action = CODEC_ACTION_NULL; 133 action = CODEC_ACTION_NULL;
133 134
135 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
136
134 res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE); 137 res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE);
135 138
136 if(res != (int)FRAMESIZE) { 139 if(res != (int)FRAMESIZE) {
diff --git a/lib/rbcodec/codecs/atrac3_rm.c b/lib/rbcodec/codecs/atrac3_rm.c
index 997507425e..4b528c0a8d 100644
--- a/lib/rbcodec/codecs/atrac3_rm.c
+++ b/lib/rbcodec/codecs/atrac3_rm.c
@@ -57,17 +57,19 @@ enum codec_status codec_run(void)
57 uint8_t *bit_buffer; 57 uint8_t *bit_buffer;
58 uint16_t fs,sps,h; 58 uint16_t fs,sps,h;
59 uint32_t packet_count; 59 uint32_t packet_count;
60 int scrambling_unit_size, num_units, elapsed = 0; 60 int scrambling_unit_size, num_units, elapsed;
61 int playback_on = -1; 61 int playback_on = -1;
62 size_t resume_offset; 62 size_t resume_offset;
63 intptr_t param; 63 intptr_t param;
64 enum codec_command_action action = CODEC_ACTION_NULL; 64 enum codec_command_action action;
65 65
66 if (codec_init()) { 66 if (codec_init()) {
67 DEBUGF("codec init failed\n"); 67 DEBUGF("codec init failed\n");
68 return CODEC_ERROR; 68 return CODEC_ERROR;
69 } 69 }
70 70
71 action = CODEC_ACTION_NULL;
72 elapsed = ci->id3->elapsed;
71 resume_offset = ci->id3->offset; 73 resume_offset = ci->id3->offset;
72 74
73 codec_set_replaygain(ci->id3); 75 codec_set_replaygain(ci->id3);
@@ -98,15 +100,20 @@ enum codec_status codec_run(void)
98 } 100 }
99 101
100 /* check for a mid-track resume and force a seek time accordingly */ 102 /* check for a mid-track resume and force a seek time accordingly */
101 if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { 103 if(resume_offset) {
102 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; 104 resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
103 num_units = (int)resume_offset / scrambling_unit_size; 105 num_units = (int)resume_offset / scrambling_unit_size;
104 /* put number of subpackets to skip in resume_offset */ 106 /* put number of subpackets to skip in resume_offset */
105 resume_offset /= (sps + PACKET_HEADER_SIZE); 107 resume_offset /= (sps + PACKET_HEADER_SIZE);
106 param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); 108 elapsed = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);
109 }
110
111 if (elapsed > 0) {
112 param = elapsed;
107 action = CODEC_ACTION_SEEK_TIME; 113 action = CODEC_ACTION_SEEK_TIME;
108 } 114 }
109 else { 115 else {
116 elapsed = 0;
110 ci->set_elapsed(0); 117 ci->set_elapsed(0);
111 } 118 }
112 119
@@ -151,6 +158,7 @@ seek_start :
151 158
152 /* Seek to the start of the track */ 159 /* Seek to the start of the track */
153 if (param == 0) { 160 if (param == 0) {
161 elapsed = 0;
154 ci->set_elapsed(0); 162 ci->set_elapsed(0);
155 ci->seek_complete(); 163 ci->seek_complete();
156 action = CODEC_ACTION_NULL; 164 action = CODEC_ACTION_NULL;
diff --git a/lib/rbcodec/codecs/au.c b/lib/rbcodec/codecs/au.c
index 7ae7fe3e94..18d4296125 100644
--- a/lib/rbcodec/codecs/au.c
+++ b/lib/rbcodec/codecs/au.c
@@ -139,6 +139,7 @@ enum codec_status codec_run(void)
139 codec_set_replaygain(ci->id3); 139 codec_set_replaygain(ci->id3);
140 140
141 /* 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) */
142 param = ci->id3->elapsed;
142 bytesdone = ci->id3->offset; 143 bytesdone = ci->id3->offset;
143 144
144 ci->memset(&format, 0, sizeof(struct pcm_format)); 145 ci->memset(&format, 0, sizeof(struct pcm_format));
@@ -236,10 +237,20 @@ enum codec_status codec_run(void)
236 } 237 }
237 238
238 /* make sure we're at the correct offset */ 239 /* make sure we're at the correct offset */
239 if (bytesdone > (uint32_t) firstblockposn) { 240 if (bytesdone > (uint32_t) firstblockposn || param) {
241 uint32_t seek_val;
242 int seek_mode;
243
244 if (bytesdone) {
245 seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone);
246 seek_mode = PCM_SEEK_POS;
247 } else {
248 seek_val = param;
249 seek_mode = PCM_SEEK_TIME;
250 }
251
240 /* Round down to previous block */ 252 /* Round down to previous block */
241 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, 253 struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode, NULL);
242 PCM_SEEK_POS, NULL);
243 254
244 if (newpos->pos > format.numbytes) 255 if (newpos->pos > format.numbytes)
245 goto done; 256 goto done;
diff --git a/lib/rbcodec/codecs/ay.c b/lib/rbcodec/codecs/ay.c
index b11ad84294..88936df131 100644
--- a/lib/rbcodec/codecs/ay.c
+++ b/lib/rbcodec/codecs/ay.c
@@ -56,6 +56,7 @@ enum codec_status codec_run(void)
56 /* reset values */ 56 /* reset values */
57 track = is_multitrack = 0; 57 track = is_multitrack = 0;
58 elapsed_time = 0; 58 elapsed_time = 0;
59 param = ci->id3->elapsed;
59 60
60 DEBUGF("AY: next_track\n"); 61 DEBUGF("AY: next_track\n");
61 if (codec_init()) { 62 if (codec_init()) {
@@ -87,6 +88,10 @@ enum codec_status codec_run(void)
87 is_multitrack = 1; 88 is_multitrack = 1;
88 } 89 }
89 90
91 if (param) {
92 goto resume_start;
93 }
94
90next_track: 95next_track:
91 set_codec_track(track, is_multitrack); 96 set_codec_track(track, is_multitrack);
92 97
@@ -98,6 +103,7 @@ next_track:
98 break; 103 break;
99 104
100 if (action == CODEC_ACTION_SEEK_TIME) { 105 if (action == CODEC_ACTION_SEEK_TIME) {
106 resume_start:
101 if (is_multitrack) { 107 if (is_multitrack) {
102 track = param/1000; 108 track = param/1000;
103 ci->seek_complete(); 109 ci->seek_complete();
diff --git a/lib/rbcodec/codecs/cook.c b/lib/rbcodec/codecs/cook.c
index 55188aad36..402d1d3fa6 100644
--- a/lib/rbcodec/codecs/cook.c
+++ b/lib/rbcodec/codecs/cook.c
@@ -56,14 +56,16 @@ enum codec_status codec_run(void)
56 uint32_t packet_count; 56 uint32_t packet_count;
57 int scrambling_unit_size, num_units; 57 int scrambling_unit_size, num_units;
58 size_t resume_offset; 58 size_t resume_offset;
59 intptr_t param = 0; 59 intptr_t param;
60 enum codec_command_action action = CODEC_ACTION_NULL; 60 enum codec_command_action action;
61 61
62 if (codec_init()) { 62 if (codec_init()) {
63 DEBUGF("codec init failed\n"); 63 DEBUGF("codec init failed\n");
64 return CODEC_ERROR; 64 return CODEC_ERROR;
65 } 65 }
66 66
67 action = CODEC_ACTION_NULL;
68 param = ci->id3->elapsed;
67 resume_offset = ci->id3->offset; 69 resume_offset = ci->id3->offset;
68 70
69 codec_set_replaygain(ci->id3); 71 codec_set_replaygain(ci->id3);
@@ -97,12 +99,15 @@ enum codec_status codec_run(void)
97 } 99 }
98 100
99 /* check for a mid-track resume and force a seek time accordingly */ 101 /* check for a mid-track resume and force a seek time accordingly */
100 if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { 102 if(resume_offset) {
101 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; 103 resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
102 num_units = (int)resume_offset / scrambling_unit_size; 104 num_units = (int)resume_offset / scrambling_unit_size;
103 /* put number of subpackets to skip in resume_offset */ 105 /* put number of subpackets to skip in resume_offset */
104 resume_offset /= (sps + PACKET_HEADER_SIZE); 106 resume_offset /= (sps + PACKET_HEADER_SIZE);
105 param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); 107 param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);
108 }
109
110 if (param) {
106 action = CODEC_ACTION_SEEK_TIME; 111 action = CODEC_ACTION_SEEK_TIME;
107 } 112 }
108 else { 113 else {
diff --git a/lib/rbcodec/codecs/flac.c b/lib/rbcodec/codecs/flac.c
index 3390c24a2c..eab6e7c2bc 100644
--- a/lib/rbcodec/codecs/flac.c
+++ b/lib/rbcodec/codecs/flac.c
@@ -468,7 +468,8 @@ enum codec_status codec_run(void)
468 return CODEC_ERROR; 468 return CODEC_ERROR;
469 } 469 }
470 470
471 /* Need to save offset for later use (cleared indirectly by flac_init) */ 471 /* Need to save resume for later use (cleared indirectly by flac_init) */
472 elapsedtime = ci->id3->elapsed;
472 samplesdone = ci->id3->offset; 473 samplesdone = ci->id3->offset;
473 474
474 if (!flac_init(&fc,ci->id3->first_frame_offset)) { 475 if (!flac_init(&fc,ci->id3->first_frame_offset)) {
@@ -481,9 +482,16 @@ enum codec_status codec_run(void)
481 STEREO_MONO : STEREO_NONINTERLEAVED); 482 STEREO_MONO : STEREO_NONINTERLEAVED);
482 codec_set_replaygain(ci->id3); 483 codec_set_replaygain(ci->id3);
483 484
484 flac_seek_offset(&fc, samplesdone); 485 if (samplesdone || !elapsedtime) {
485 samplesdone=fc.samplenumber+fc.blocksize; 486 flac_seek_offset(&fc, samplesdone);
486 elapsedtime=((uint64_t)samplesdone*1000)/(ci->id3->frequency); 487 samplesdone=fc.samplenumber+fc.blocksize;
488 elapsedtime=((uint64_t)samplesdone*1000)/(ci->id3->frequency);
489 }
490 else if (!flac_seek(&fc,(uint32_t)((uint64_t)elapsedtime
491 *ci->id3->frequency/1000))) {
492 elapsedtime = 0;
493 }
494
487 ci->set_elapsed(elapsedtime); 495 ci->set_elapsed(elapsedtime);
488 496
489 /* The main decoding loop */ 497 /* The main decoding loop */
diff --git a/lib/rbcodec/codecs/gbs.c b/lib/rbcodec/codecs/gbs.c
index def05ed351..717f56c82f 100644
--- a/lib/rbcodec/codecs/gbs.c
+++ b/lib/rbcodec/codecs/gbs.c
@@ -76,6 +76,11 @@ enum codec_status codec_run(void)
76 if (gbs_emu.m3u.size > 0) 76 if (gbs_emu.m3u.size > 0)
77 gbs_emu.track_count = gbs_emu.m3u.size; 77 gbs_emu.track_count = gbs_emu.m3u.size;
78 78
79 if (ci->id3->elapsed) {
80 track = ci->id3->elapsed/1000;
81 if (track >= gbs_emu.track_count) return CODEC_OK;
82 }
83
79next_track: 84next_track:
80 set_codec_track(track); 85 set_codec_track(track);
81 86
diff --git a/lib/rbcodec/codecs/hes.c b/lib/rbcodec/codecs/hes.c
index 849fd88f12..56f49621c6 100644
--- a/lib/rbcodec/codecs/hes.c
+++ b/lib/rbcodec/codecs/hes.c
@@ -76,6 +76,11 @@ enum codec_status codec_run(void)
76 if (hes_emu.m3u.size > 0) 76 if (hes_emu.m3u.size > 0)
77 hes_emu.track_count = hes_emu.m3u.size; 77 hes_emu.track_count = hes_emu.m3u.size;
78 78
79 if (ci->id3->elapsed) {
80 track = ci->id3->elapsed/1000;
81 if (track >= hes_emu.track_count) return CODEC_OK;
82 }
83
79next_track: 84next_track:
80 set_codec_track(track); 85 set_codec_track(track);
81 86
diff --git a/lib/rbcodec/codecs/kss.c b/lib/rbcodec/codecs/kss.c
index 92efcd4e5f..e6cf866cdd 100644
--- a/lib/rbcodec/codecs/kss.c
+++ b/lib/rbcodec/codecs/kss.c
@@ -79,6 +79,11 @@ enum codec_status codec_run(void)
79 if (kss_emu.m3u.size > 0) 79 if (kss_emu.m3u.size > 0)
80 kss_emu.track_count = kss_emu.m3u.size; 80 kss_emu.track_count = kss_emu.m3u.size;
81 81
82 if (ci->id3->elapsed) {
83 track = ci->id3->elapsed/1000;
84 if (track >= kss_emu.track_count) return CODEC_OK;
85 }
86
82next_track: 87next_track:
83 set_codec_track(track); 88 set_codec_track(track);
84 89
diff --git a/lib/rbcodec/codecs/mod.c b/lib/rbcodec/codecs/mod.c
index 8bb2dc5163..4dd0cde6e5 100644
--- a/lib/rbcodec/codecs/mod.c
+++ b/lib/rbcodec/codecs/mod.c
@@ -1319,7 +1319,16 @@ enum codec_status codec_run(void)
1319 loadmod(modfile); 1319 loadmod(modfile);
1320 1320
1321 /* The main decoder loop */ 1321 /* The main decoder loop */
1322 ci->set_elapsed(0); 1322#if 0
1323 /* Needs to be a bit more elaborate or critical stuff is missed */
1324 if (ci->id3->elapsed) {
1325 modplayer.patterntableposition = ci->id3->elapsed/1000;
1326 modplayer.currentline = 0;
1327 }
1328#endif
1329
1330 ci->set_elapsed(modplayer.patterntableposition*1000);
1331
1323 bytesdone = 0; 1332 bytesdone = 0;
1324 old_patterntableposition = 0; 1333 old_patterntableposition = 0;
1325 1334
diff --git a/lib/rbcodec/codecs/mpa.c b/lib/rbcodec/codecs/mpa.c
index 07db248099..ca12087e87 100644
--- a/lib/rbcodec/codecs/mpa.c
+++ b/lib/rbcodec/codecs/mpa.c
@@ -346,6 +346,11 @@ enum codec_status codec_run(void)
346 current_frequency = ci->id3->frequency; 346 current_frequency = ci->id3->frequency;
347 codec_set_replaygain(ci->id3); 347 codec_set_replaygain(ci->id3);
348 348
349 if (!ci->id3->offset && ci->id3->elapsed) {
350 /* Have elapsed time but not offset */
351 ci->id3->offset = get_file_pos(ci->id3->elapsed);
352 }
353
349 if (ci->id3->offset) { 354 if (ci->id3->offset) {
350 ci->seek_buffer(ci->id3->offset); 355 ci->seek_buffer(ci->id3->offset);
351 set_elapsed(ci->id3); 356 set_elapsed(ci->id3);
diff --git a/lib/rbcodec/codecs/mpc.c b/lib/rbcodec/codecs/mpc.c
index 9db40242dc..79f2aa22db 100644
--- a/lib/rbcodec/codecs/mpc.c
+++ b/lib/rbcodec/codecs/mpc.c
@@ -108,6 +108,7 @@ enum codec_status codec_run(void)
108 * sample seek position from the file offset, the sampling frequency and 108 * sample seek position from the file offset, the sampling frequency and
109 * the bitrate. As the saved position is exactly calculated the reverse way 109 * the bitrate. As the saved position is exactly calculated the reverse way
110 * there is no loss of information except rounding. */ 110 * there is no loss of information except rounding. */
111 elapsed_time = ci->id3->elapsed;
111 samplesdone = 100 * (((mpc_uint64_t)ci->id3->offset * frequency) / byterate); 112 samplesdone = 100 * (((mpc_uint64_t)ci->id3->offset * frequency) / byterate);
112 113
113 /* Set up digital signal processing for correct number of channels */ 114 /* Set up digital signal processing for correct number of channels */
@@ -122,19 +123,24 @@ enum codec_status codec_run(void)
122 123
123 codec_set_replaygain(ci->id3); 124 codec_set_replaygain(ci->id3);
124 125
125 /* Resume to saved sample offset. */ 126 if (samplesdone > 0 || elapsed_time)
126 elapsed_time = 0;
127
128 if (samplesdone > 0)
129 { 127 {
130 if (mpc_demux_seek_sample(demux, samplesdone) == MPC_STATUS_OK) 128 mpc_int64_t new_offset = samplesdone;
129
130 if (new_offset <= 0)
131 new_offset = (elapsed_time/10)*frequency; /* by time */
132
133 /* Resume to sample offset. */
134 if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK)
131 { 135 {
132 elapsed_time = (samplesdone*10)/frequency; 136 samplesdone = new_offset;
133 } 137 }
134 else 138 else
135 { 139 {
136 samplesdone = 0; 140 samplesdone = 0;
137 } 141 }
142
143 elapsed_time = (samplesdone*10)/frequency;
138 } 144 }
139 145
140 ci->set_elapsed(elapsed_time); 146 ci->set_elapsed(elapsed_time);
diff --git a/lib/rbcodec/codecs/nsf.c b/lib/rbcodec/codecs/nsf.c
index 4c5b37c3fa..cbdf8e3ec5 100644
--- a/lib/rbcodec/codecs/nsf.c
+++ b/lib/rbcodec/codecs/nsf.c
@@ -57,6 +57,7 @@ enum codec_status codec_run(void)
57 57
58 track = is_multitrack = 0; 58 track = is_multitrack = 0;
59 elapsed_time = 0; 59 elapsed_time = 0;
60 param = ci->id3->elapsed;
60 61
61 DEBUGF("NSF: next_track\n"); 62 DEBUGF("NSF: next_track\n");
62 if (codec_init()) { 63 if (codec_init()) {
@@ -85,6 +86,10 @@ enum codec_status codec_run(void)
85 86
86 if (nsf_emu.track_count > 1) is_multitrack = 1; 87 if (nsf_emu.track_count > 1) is_multitrack = 1;
87 88
89 if (param) {
90 goto resume_start;
91 }
92
88next_track: 93next_track:
89 set_codec_track(track, is_multitrack); 94 set_codec_track(track, is_multitrack);
90 95
@@ -96,6 +101,7 @@ next_track:
96 break; 101 break;
97 102
98 if (action == CODEC_ACTION_SEEK_TIME) { 103 if (action == CODEC_ACTION_SEEK_TIME) {
104 resume_start:
99 if (is_multitrack) { 105 if (is_multitrack) {
100 track = param/1000; 106 track = param/1000;
101 ci->seek_complete(); 107 ci->seek_complete();
diff --git a/lib/rbcodec/codecs/opus.c b/lib/rbcodec/codecs/opus.c
index 15d96ff6fe..2c495aa8d0 100644
--- a/lib/rbcodec/codecs/opus.c
+++ b/lib/rbcodec/codecs/opus.c
@@ -314,6 +314,7 @@ enum codec_status codec_main(enum codec_entry_call_reason reason)
314enum codec_status codec_run(void) 314enum codec_status codec_run(void)
315{ 315{
316 int error = CODEC_ERROR; 316 int error = CODEC_ERROR;
317 enum codec_command_action action;
317 intptr_t param; 318 intptr_t param;
318 ogg_sync_state oy; 319 ogg_sync_state oy;
319 ogg_page og; 320 ogg_page og;
@@ -325,13 +326,17 @@ enum codec_status codec_run(void)
325 OpusDecoder *st = NULL; 326 OpusDecoder *st = NULL;
326 OpusHeader header; 327 OpusHeader header;
327 int ret; 328 int ret;
328 unsigned long strtoffset = ci->id3->offset; 329 unsigned long strtoffset;
329 int skip = 0; 330 int skip = 0;
330 int64_t seek_target; 331 int64_t seek_target;
331 uint64_t granule_pos; 332 uint64_t granule_pos;
332 333
333 ogg_malloc_init(); 334 ogg_malloc_init();
334 335
336 action = CODEC_ACTION_NULL;
337 param = ci->id3->elapsed;
338 strtoffset = ci->id3->offset;
339
335 global_stack = 0; 340 global_stack = 0;
336 341
337#if defined(CPU_COLDFIRE) 342#if defined(CPU_COLDFIRE)
@@ -351,28 +356,40 @@ enum codec_status codec_run(void)
351 ci->seek_buffer(0); 356 ci->seek_buffer(0);
352 ci->set_elapsed(0); 357 ci->set_elapsed(0);
353 358
359 if (!strtoffset && param) {
360 action = CODEC_ACTION_SEEK_TIME;
361 }
362
363 goto next_page;
364
354 while (1) { 365 while (1) {
355 enum codec_command_action action = ci->get_command(&param); 366 if (action == CODEC_ACTION_NULL)
367 action = ci->get_command(&param);
356 368
357 if (action == CODEC_ACTION_HALT) 369 if (action != CODEC_ACTION_NULL) {
358 break; 370 if (action == CODEC_ACTION_HALT)
371 break;
372
373 if (action == CODEC_ACTION_SEEK_TIME) {
374 if (st != NULL) {
375 /* calculate granule to seek to (including seek rewind) */
376 seek_target = (48LL * param) + header.preskip;
377 skip = MIN(seek_target, SEEK_REWIND);
378 seek_target -= skip;
359 379
360 if (action == CODEC_ACTION_SEEK_TIME) { 380 LOGF("Opus seek page:%lld,%lld,%ld\n",
361 if (st != NULL) { 381 seek_target, page_granule, (long)param);
362 /* calculate granule to seek to (including seek rewind) */ 382 speex_seek_page_granule(seek_target, page_granule, &oy, &os);
363 seek_target = (48LL * param) + header.preskip; 383 }
364 skip = MIN(seek_target, SEEK_REWIND);
365 seek_target -= skip;
366 384
367 LOGF("Opus seek page:%lld,%lld,%ld\n", 385 ci->set_elapsed(param);
368 seek_target, page_granule, (long)param); 386 ci->seek_complete();
369 speex_seek_page_granule(seek_target, page_granule, &oy, &os);
370 } 387 }
371 388
372 ci->set_elapsed(param); 389 action = CODEC_ACTION_NULL;
373 ci->seek_complete();
374 } 390 }
375 391
392 next_page:
376 /*Get the ogg buffer for writing*/ 393 /*Get the ogg buffer for writing*/
377 if (get_more_data(&oy) < 1) { 394 if (get_more_data(&oy) < 1) {
378 goto done; 395 goto done;
diff --git a/lib/rbcodec/codecs/raac.c b/lib/rbcodec/codecs/raac.c
index 523560b63e..d2d3531028 100644
--- a/lib/rbcodec/codecs/raac.c
+++ b/lib/rbcodec/codecs/raac.c
@@ -63,14 +63,16 @@ enum codec_status codec_run(void)
63 unsigned char c = 0; /* channels */ 63 unsigned char c = 0; /* channels */
64 int playback_on = -1; 64 int playback_on = -1;
65 size_t resume_offset; 65 size_t resume_offset;
66 enum codec_command_action action;
66 intptr_t param; 67 intptr_t param;
67 enum codec_command_action action = CODEC_ACTION_NULL;
68 68
69 if (codec_init()) { 69 if (codec_init()) {
70 DEBUGF("FAAD: Codec init error\n"); 70 DEBUGF("FAAD: Codec init error\n");
71 return CODEC_ERROR; 71 return CODEC_ERROR;
72 } 72 }
73 73
74 action = CODEC_ACTION_NULL;
75 param = ci->id3->elapsed;
74 resume_offset = ci->id3->offset; 76 resume_offset = ci->id3->offset;
75 77
76 ci->memset(&rmctx,0,sizeof(RMContext)); 78 ci->memset(&rmctx,0,sizeof(RMContext));
@@ -104,15 +106,21 @@ enum codec_status codec_run(void)
104 } 106 }
105 107
106 /* check for a mid-track resume and force a seek time accordingly */ 108 /* check for a mid-track resume and force a seek time accordingly */
107 if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { 109 if (resume_offset) {
108 resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; 110 resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
109 /* put number of subpackets to skip in resume_offset */ 111 /* put number of subpackets to skip in resume_offset */
110 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); 112 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
111 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); 113 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
114 }
115
116 if (param > 0) {
112 action = CODEC_ACTION_SEEK_TIME; 117 action = CODEC_ACTION_SEEK_TIME;
113 } 118 }
114 ci->set_elapsed(0); 119 else {
115 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); 120 /* Seek to the first packet */
121 ci->set_elapsed(0);
122 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
123 }
116 124
117 /* The main decoding loop */ 125 /* The main decoding loop */
118 while (1) { 126 while (1) {
@@ -124,7 +132,7 @@ enum codec_status codec_run(void)
124 132
125 if (action == CODEC_ACTION_SEEK_TIME) { 133 if (action == CODEC_ACTION_SEEK_TIME) {
126 /* Do not allow seeking beyond the file's length */ 134 /* Do not allow seeking beyond the file's length */
127 if ((unsigned) param > ci->id3->length) { 135 if ((unsigned long)param > ci->id3->length) {
128 ci->set_elapsed(ci->id3->length); 136 ci->set_elapsed(ci->id3->length);
129 ci->seek_complete(); 137 ci->seek_complete();
130 break; 138 break;
@@ -164,6 +172,7 @@ enum codec_status codec_run(void)
164 172
165 ci->advance_buffer(pkt.length); 173 ci->advance_buffer(pkt.length);
166 } 174 }
175
167 ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE); 176 ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE);
168 buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000); 177 buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000);
169 NeAACDecPostSeekReset(decoder, decoder->frame); 178 NeAACDecPostSeekReset(decoder, decoder->frame);
diff --git a/lib/rbcodec/codecs/sgc.c b/lib/rbcodec/codecs/sgc.c
index 348a54a2d3..eb260975c5 100644
--- a/lib/rbcodec/codecs/sgc.c
+++ b/lib/rbcodec/codecs/sgc.c
@@ -91,6 +91,11 @@ enum codec_status codec_run(void)
91 if (sgc_emu.m3u.size > 0) 91 if (sgc_emu.m3u.size > 0)
92 sgc_emu.track_count = sgc_emu.m3u.size; 92 sgc_emu.track_count = sgc_emu.m3u.size;
93 93
94 if (ci->id3->elapsed) {
95 track = ci->id3->elapsed/1000;
96 if (track >= sgc_emu.track_count) return CODEC_OK;
97 }
98
94next_track: 99next_track:
95 set_codec_track(track); 100 set_codec_track(track);
96 101
diff --git a/lib/rbcodec/codecs/sid.c b/lib/rbcodec/codecs/sid.c
index 1a6d04155d..6e39d3f759 100644
--- a/lib/rbcodec/codecs/sid.c
+++ b/lib/rbcodec/codecs/sid.c
@@ -1253,6 +1253,7 @@ enum codec_status codec_run(void)
1253 unsigned char subSongsMax, subSong, song_speed; 1253 unsigned char subSongsMax, subSong, song_speed;
1254 unsigned char *sidfile = NULL; 1254 unsigned char *sidfile = NULL;
1255 intptr_t param; 1255 intptr_t param;
1256 bool resume;
1256 1257
1257 if (codec_init()) { 1258 if (codec_init()) {
1258 return CODEC_ERROR; 1259 return CODEC_ERROR;
@@ -1269,15 +1270,10 @@ enum codec_status codec_run(void)
1269 return CODEC_ERROR; 1270 return CODEC_ERROR;
1270 } 1271 }
1271 1272
1272 c64Init(SAMPLE_RATE); 1273 param = ci->id3->elapsed;
1273 LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, 1274 resume = param != 0;
1274 &subSongsMax, &subSong, &song_speed, (unsigned short)filesize);
1275 sidPoke(24, 15); /* Turn on full volume */
1276 cpuJSR(init_addr, subSong); /* Start the song initialize */
1277 1275
1278 1276 goto sid_start;
1279 /* Set the elapsed time to the current subsong (in seconds) */
1280 ci->set_elapsed(subSong*1000);
1281 1277
1282 /* The main decoder loop */ 1278 /* The main decoder loop */
1283 while (1) { 1279 while (1) {
@@ -1287,20 +1283,26 @@ enum codec_status codec_run(void)
1287 break; 1283 break;
1288 1284
1289 if (action == CODEC_ACTION_SEEK_TIME) { 1285 if (action == CODEC_ACTION_SEEK_TIME) {
1286 sid_start:
1290 /* New time is ready in param */ 1287 /* New time is ready in param */
1291 1288
1292 /* Start playing from scratch */ 1289 /* Start playing from scratch */
1293 c64Init(SAMPLE_RATE); 1290 c64Init(SAMPLE_RATE);
1294 LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, 1291 LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr,
1295 &subSongsMax, &subSong, &song_speed, (unsigned short)filesize); 1292 &subSongsMax, &subSong, &song_speed,
1293 (unsigned short)filesize);
1296 sidPoke(24, 15); /* Turn on full volume */ 1294 sidPoke(24, 15); /* Turn on full volume */
1297 subSong = param / 1000; /* Now use the current seek time in seconds as subsong */ 1295 if (!resume || (resume && param))
1296 subSong = param / 1000; /* Now use the current seek time in
1297 seconds as subsong */
1298 cpuJSR(init_addr, subSong); /* Start the song initialize */ 1298 cpuJSR(init_addr, subSong); /* Start the song initialize */
1299 nSamplesToRender = 0; /* Start the rendering from scratch */ 1299 nSamplesToRender = 0; /* Start the rendering from scratch */
1300 1300
1301 /* Set the elapsed time to the current subsong (in seconds) */ 1301 /* Set the elapsed time to the current subsong (in seconds) */
1302 ci->set_elapsed(subSong*1000); 1302 ci->set_elapsed(subSong*1000);
1303 ci->seek_complete(); 1303 ci->seek_complete();
1304
1305 resume = false;
1304 } 1306 }
1305 1307
1306 nSamplesRendered = 0; 1308 nSamplesRendered = 0;
diff --git a/lib/rbcodec/codecs/smaf.c b/lib/rbcodec/codecs/smaf.c
index d56aa0a860..e4ec6342b2 100644
--- a/lib/rbcodec/codecs/smaf.c
+++ b/lib/rbcodec/codecs/smaf.c
@@ -360,7 +360,8 @@ enum codec_status codec_run(void)
360 360
361 codec_set_replaygain(ci->id3); 361 codec_set_replaygain(ci->id3);
362 362
363 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 363 /* Need to save resume for later use (cleared indirectly by advance_buffer) */
364 param = ci->id3->elapsed;
364 bytesdone = ci->id3->offset; 365 bytesdone = ci->id3->offset;
365 366
366 decodedsamples = 0; 367 decodedsamples = 0;
@@ -408,11 +409,21 @@ enum codec_status codec_run(void)
408 ci->seek_buffer(firstblockposn); 409 ci->seek_buffer(firstblockposn);
409 410
410 /* make sure we're at the correct offset */ 411 /* make sure we're at the correct offset */
411 if (bytesdone > (uint32_t) firstblockposn) 412 if (bytesdone > (uint32_t) firstblockposn || param) {
412 { 413 uint32_t seek_val;
414 int seek_mode;
415
416 if (bytesdone) {
417 seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone);
418 seek_mode = PCM_SEEK_POS;
419 } else {
420 seek_val = param;
421 seek_mode = PCM_SEEK_TIME;
422 }
423
413 /* Round down to previous block */ 424 /* Round down to previous block */
414 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, 425 struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode,
415 PCM_SEEK_POS, &read_buffer); 426 &read_buffer);
416 427
417 if (newpos->pos > format.numbytes) 428 if (newpos->pos > format.numbytes)
418 return CODEC_OK; 429 return CODEC_OK;
diff --git a/lib/rbcodec/codecs/speex.c b/lib/rbcodec/codecs/speex.c
index ac3bc963b1..a073151ee2 100644
--- a/lib/rbcodec/codecs/speex.c
+++ b/lib/rbcodec/codecs/speex.c
@@ -381,7 +381,6 @@ enum codec_status codec_run(void)
381 int error = CODEC_ERROR; 381 int error = CODEC_ERROR;
382 382
383 SpeexBits bits; 383 SpeexBits bits;
384 int eof = 0;
385 spx_ogg_sync_state oy; 384 spx_ogg_sync_state oy;
386 spx_ogg_page og; 385 spx_ogg_page og;
387 spx_ogg_packet op; 386 spx_ogg_packet op;
@@ -403,9 +402,10 @@ enum codec_status codec_run(void)
403 int packet_count = 0; 402 int packet_count = 0;
404 int lookahead; 403 int lookahead;
405 int headerssize = 0; 404 int headerssize = 0;
406 unsigned long strtoffset = ci->id3->offset; 405 unsigned long strtoffset;
407 void *st = NULL; 406 void *st = NULL;
408 int j = 0; 407 int j = 0;
408 enum codec_command_action action;
409 intptr_t param; 409 intptr_t param;
410 410
411 memset(&bits, 0, sizeof(bits)); 411 memset(&bits, 0, sizeof(bits));
@@ -416,6 +416,10 @@ enum codec_status codec_run(void)
416 goto exit; 416 goto exit;
417 } 417 }
418 418
419 action = CODEC_ACTION_NULL;
420 param = ci->id3->elapsed;
421 strtoffset = ci->id3->offset;
422
419 ci->seek_buffer(0); 423 ci->seek_buffer(0);
420 ci->set_elapsed(0); 424 ci->set_elapsed(0);
421 425
@@ -425,29 +429,39 @@ enum codec_status codec_run(void)
425 429
426 codec_set_replaygain(ci->id3); 430 codec_set_replaygain(ci->id3);
427 431
428 eof = 0; 432 if (!strtoffset && param) {
429 while (!eof) { 433 action = CODEC_ACTION_SEEK_TIME;
430 enum codec_command_action action = ci->get_command(&param); 434 }
431 435
432 if (action == CODEC_ACTION_HALT) 436 goto next_page;
433 break; 437
434 438 while (1) {
435 /*seek (seeks to the page before the position) */ 439 if (action == CODEC_ACTION_NULL)
436 if (action == CODEC_ACTION_SEEK_TIME) { 440 action = ci->get_command(&param);
437 if(samplerate!=0&&packet_count>1){ 441
438 LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n", 442 if (action != CODEC_ACTION_NULL) {
439 ((spx_int64_t)param/1000) * 443 if (action == CODEC_ACTION_HALT)
440 (spx_int64_t)samplerate, 444 break;
441 page_granule, (long)param, 445
442 (page_granule/samplerate)*1000, samplerate); 446 /*seek (seeks to the page before the position) */
443 447 if (action == CODEC_ACTION_SEEK_TIME) {
444 speex_seek_page_granule(((spx_int64_t)param/1000) * 448 if(samplerate!=0&&packet_count>1){
445 (spx_int64_t)samplerate, 449 LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n",
446 page_granule, &oy, headerssize); 450 ((spx_int64_t)param/1000) *
451 (spx_int64_t)samplerate,
452 page_granule, (long)param,
453 (page_granule/samplerate)*1000, samplerate);
454
455 speex_seek_page_granule(((spx_int64_t)param/1000) *
456 (spx_int64_t)samplerate,
457 page_granule, &oy, headerssize);
458 }
459
460 ci->set_elapsed(param);
461 ci->seek_complete();
447 } 462 }
448 463
449 ci->set_elapsed(param); 464 action = CODEC_ACTION_NULL;
450 ci->seek_complete();
451 } 465 }
452 466
453next_page: 467next_page:
diff --git a/lib/rbcodec/codecs/tta.c b/lib/rbcodec/codecs/tta.c
index 564496a14e..b7660a920f 100644
--- a/lib/rbcodec/codecs/tta.c
+++ b/lib/rbcodec/codecs/tta.c
@@ -82,10 +82,20 @@ enum codec_status codec_run(void)
82 decodedsamples = 0; 82 decodedsamples = 0;
83 endofstream = 0; 83 endofstream = 0;
84 84
85 if (ci->id3->offset > 0) 85 if (ci->id3->offset || ci->id3->elapsed)
86 { 86 {
87 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 87 /* Need to save offset for later use (cleared indirectly by
88 new_pos = set_position(ci->id3->offset, TTA_SEEK_POS); 88 advance_buffer) */
89 unsigned int pos = ci->id3->offset;
90 enum tta_seek_type type = TTA_SEEK_POS;
91
92 if (!pos) {
93 pos = ci->id3->elapsed / SEEK_STEP;
94 type = TTA_SEEK_TIME;
95 }
96
97 new_pos = set_position(pos, type);
98
89 if (new_pos >= 0) 99 if (new_pos >= 0)
90 decodedsamples = new_pos; 100 decodedsamples = new_pos;
91 } 101 }
diff --git a/lib/rbcodec/codecs/vgm.c b/lib/rbcodec/codecs/vgm.c
index 9f2f1b9c5e..126305944f 100644
--- a/lib/rbcodec/codecs/vgm.c
+++ b/lib/rbcodec/codecs/vgm.c
@@ -127,7 +127,10 @@ enum codec_status codec_run(void)
127 127
128 Vgm_start_track(&vgm_emu); 128 Vgm_start_track(&vgm_emu);
129 129
130 ci->set_elapsed(0); 130 if (ci->id3->elapsed != 0)
131 Track_seek(&vgm_emu, ci->id3->elapsed);
132
133 codec_update_elapsed();
131 codec_update_fade(); 134 codec_update_fade();
132 135
133 /* The main decoder loop */ 136 /* The main decoder loop */
diff --git a/lib/rbcodec/codecs/vorbis.c b/lib/rbcodec/codecs/vorbis.c
index c09d2cea6d..ca9db9b802 100644
--- a/lib/rbcodec/codecs/vorbis.c
+++ b/lib/rbcodec/codecs/vorbis.c
@@ -126,7 +126,6 @@ enum codec_status codec_run(void)
126 long n; 126 long n;
127 int current_section; 127 int current_section;
128 int previous_section; 128 int previous_section;
129 int eof;
130 ogg_int64_t vf_offsets[2]; 129 ogg_int64_t vf_offsets[2];
131 ogg_int64_t vf_dataoffsets; 130 ogg_int64_t vf_dataoffsets;
132 ogg_uint32_t vf_serialnos; 131 ogg_uint32_t vf_serialnos;
@@ -193,16 +192,17 @@ enum codec_status codec_run(void)
193 if (ci->id3->offset) { 192 if (ci->id3->offset) {
194 ci->seek_buffer(ci->id3->offset); 193 ci->seek_buffer(ci->id3->offset);
195 ov_raw_seek(&vf, ci->id3->offset); 194 ov_raw_seek(&vf, ci->id3->offset);
196 ci->set_elapsed(ov_time_tell(&vf));
197 ci->set_offset(ov_raw_tell(&vf)); 195 ci->set_offset(ov_raw_tell(&vf));
198 } 196 }
199 else { 197 else if (ci->id3->elapsed) {
200 ci->set_elapsed(0); 198 ov_time_seek(&vf, ci->id3->elapsed);
201 } 199 }
202 200
201 ci->set_elapsed(ov_time_tell(&vf));
202
203 previous_section = -1; 203 previous_section = -1;
204 eof = 0; 204
205 while (!eof) { 205 while (1) {
206 enum codec_command_action action = ci->get_command(&param); 206 enum codec_command_action action = ci->get_command(&param);
207 207
208 if (action == CODEC_ACTION_HALT) 208 if (action == CODEC_ACTION_HALT)
@@ -230,7 +230,7 @@ enum codec_status codec_run(void)
230 } 230 }
231 231
232 if (n == 0) { 232 if (n == 0) {
233 eof = 1; 233 break;
234 } else if (n < 0) { 234 } else if (n < 0) {
235 DEBUGF("Vorbis: Error decoding frame\n"); 235 DEBUGF("Vorbis: Error decoding frame\n");
236 } else { 236 } else {
diff --git a/lib/rbcodec/codecs/vox.c b/lib/rbcodec/codecs/vox.c
index 66979e2911..d84af24cfc 100644
--- a/lib/rbcodec/codecs/vox.c
+++ b/lib/rbcodec/codecs/vox.c
@@ -73,7 +73,8 @@ enum codec_status codec_run(void)
73 73
74 codec_set_replaygain(ci->id3); 74 codec_set_replaygain(ci->id3);
75 75
76 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 76 /* Need to save resume for later use (cleared indirectly by advance_buffer) */
77 param = ci->id3->elapsed;
77 bytesdone = ci->id3->offset; 78 bytesdone = ci->id3->offset;
78 ci->seek_buffer(0); 79 ci->seek_buffer(0);
79 80
@@ -123,10 +124,21 @@ enum codec_status codec_run(void)
123 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); 124 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
124 125
125 /* make sure we're at the correct offset */ 126 /* make sure we're at the correct offset */
126 if (bytesdone > (uint32_t) firstblockposn) { 127 if (bytesdone > (uint32_t) firstblockposn || param) {
128 uint32_t seek_val;
129 int seek_mode;
130
131 if (bytesdone) {
132 seek_val = bytesdone - MIN((uint32_t )firstblockposn, bytesdone);
133 seek_mode = PCM_SEEK_POS;
134 } else {
135 seek_val = param;
136 seek_mode = PCM_SEEK_TIME;
137 }
138
127 /* Round down to previous block */ 139 /* Round down to previous block */
128 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, 140 struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode,
129 PCM_SEEK_POS, &read_buffer); 141 &read_buffer);
130 142
131 if (newpos->pos > format.numbytes) { 143 if (newpos->pos > format.numbytes) {
132 return CODEC_OK; 144 return CODEC_OK;
diff --git a/lib/rbcodec/codecs/wav.c b/lib/rbcodec/codecs/wav.c
index cc65ab83b2..3208e2b5b8 100644
--- a/lib/rbcodec/codecs/wav.c
+++ b/lib/rbcodec/codecs/wav.c
@@ -182,7 +182,8 @@ enum codec_status codec_run(void)
182 182
183 codec_set_replaygain(ci->id3); 183 codec_set_replaygain(ci->id3);
184 184
185 /* Need to save offset for later use (cleared indirectly by advance_buffer) */ 185 /* Need to save resume for later use (cleared indirectly by advance_buffer) */
186 param = ci->id3->elapsed;
186 bytesdone = ci->id3->offset; 187 bytesdone = ci->id3->offset;
187 188
188 /* get RIFF chunk header */ 189 /* get RIFF chunk header */
@@ -361,10 +362,21 @@ enum codec_status codec_run(void)
361 } 362 }
362 363
363 /* make sure we're at the correct offset */ 364 /* make sure we're at the correct offset */
364 if (bytesdone > (uint32_t) firstblockposn) { 365 if (bytesdone > (uint32_t) firstblockposn || param) {
366 uint32_t seek_val;
367 int seek_mode;
368
369 if (bytesdone) {
370 seek_val = bytesdone - MIN((uint32_t) firstblockposn, bytesdone);
371 seek_mode = PCM_SEEK_POS;
372 } else {
373 seek_val = param;
374 seek_mode = PCM_SEEK_TIME;
375 }
376
365 /* Round down to previous block */ 377 /* Round down to previous block */
366 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, 378 struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode,
367 PCM_SEEK_POS, &read_buffer); 379 &read_buffer);
368 380
369 if (newpos->pos > format.numbytes) 381 if (newpos->pos > format.numbytes)
370 return CODEC_OK; 382 return CODEC_OK;
diff --git a/lib/rbcodec/codecs/wav64.c b/lib/rbcodec/codecs/wav64.c
index 9b3b2d38e4..96e605faad 100644
--- a/lib/rbcodec/codecs/wav64.c
+++ b/lib/rbcodec/codecs/wav64.c
@@ -191,6 +191,7 @@ enum codec_status codec_run(void)
191 codec_set_replaygain(ci->id3); 191 codec_set_replaygain(ci->id3);
192 192
193 /* 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) */
194 param = ci->id3->elapsed;
194 bytesdone = ci->id3->offset; 195 bytesdone = ci->id3->offset;
195 196
196 /* get RIFF chunk header */ 197 /* get RIFF chunk header */
@@ -363,10 +364,22 @@ enum codec_status codec_run(void)
363 } 364 }
364 365
365 /* make sure we're at the correct offset */ 366 /* make sure we're at the correct offset */
366 if (bytesdone > (uint32_t) firstblockposn) { 367 if (bytesdone > (uint32_t) firstblockposn || param) {
368 uint32_t seek_val;
369 int seek_mode;
370
371 /* we prefer offset resume */
372 if (bytesdone > (uint32_t) firstblockposn) {
373 seek_val = bytesdone - firstblockposn;
374 seek_mode = PCM_SEEK_POS;
375 } else {
376 seek_val = param;
377 seek_mode = PCM_SEEK_TIME;
378 }
379
367 /* Round down to previous block */ 380 /* Round down to previous block */
368 struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, 381 struct pcm_pos *newpos = codec->get_seek_pos(seek_val, seek_mode,
369 PCM_SEEK_POS, &read_buffer); 382 &read_buffer);
370 383
371 if (newpos->pos > format.numbytes) { 384 if (newpos->pos > format.numbytes) {
372 return CODEC_OK; 385 return CODEC_OK;
diff --git a/lib/rbcodec/codecs/wavpack.c b/lib/rbcodec/codecs/wavpack.c
index c0cdafabac..d9c294397c 100644
--- a/lib/rbcodec/codecs/wavpack.c
+++ b/lib/rbcodec/codecs/wavpack.c
@@ -55,12 +55,16 @@ enum codec_status codec_run(void)
55 int bps; 55 int bps;
56 */ 56 */
57 int nchans, sr_100; 57 int nchans, sr_100;
58 unsigned long offset;
58 intptr_t param; 59 intptr_t param;
59 60
60 if (codec_init()) 61 if (codec_init())
61 return CODEC_ERROR; 62 return CODEC_ERROR;
62 63
63 ci->seek_buffer (ci->id3->offset); 64 param = ci->id3->elapsed;
65 offset = ci->id3->offset;
66
67 ci->seek_buffer (offset);
64 68
65 /* Create a decoder instance */ 69 /* Create a decoder instance */
66 wpc = WavpackOpenFileInput (read_callback, error); 70 wpc = WavpackOpenFileInput (read_callback, error);
@@ -75,7 +79,12 @@ enum codec_status codec_run(void)
75 ci->configure(DSP_SET_STEREO_MODE, nchans == 2 ? STEREO_INTERLEAVED : STEREO_MONO); 79 ci->configure(DSP_SET_STEREO_MODE, nchans == 2 ? STEREO_INTERLEAVED : STEREO_MONO);
76 sr_100 = ci->id3->frequency / 100; 80 sr_100 = ci->id3->frequency / 100;
77 81
78 ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); 82 if (!offset && param) {
83 goto resume_start; /* resume by elapsed */
84 }
85 else {
86 ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10);
87 }
79 88
80 /* The main decoder loop */ 89 /* The main decoder loop */
81 90
@@ -87,6 +96,7 @@ enum codec_status codec_run(void)
87 break; 96 break;
88 97
89 if (action == CODEC_ACTION_SEEK_TIME) { 98 if (action == CODEC_ACTION_SEEK_TIME) {
99 resume_start:;
90 int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10; 100 int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10;
91 int n, d, skip; 101 int n, d, skip;
92 102
diff --git a/lib/rbcodec/codecs/wma.c b/lib/rbcodec/codecs/wma.c
index 9039f81429..9a5e0c71fa 100755
--- a/lib/rbcodec/codecs/wma.c
+++ b/lib/rbcodec/codecs/wma.c
@@ -52,13 +52,16 @@ enum codec_status codec_run(void)
52 int audiobufsize; 52 int audiobufsize;
53 int packetlength = 0; 53 int packetlength = 0;
54 int errcount = 0; 54 int errcount = 0;
55 enum codec_command_action action;
55 intptr_t param; 56 intptr_t param;
56 57
57 /* Remember the resume position - when the codec is opened, the 58 /* Remember the resume position - when the codec is opened, the
58 playback engine will reset it. */ 59 playback engine will reset it. */
60 elapsedtime = ci->id3->elapsed;
59 resume_offset = ci->id3->offset; 61 resume_offset = ci->id3->offset;
60 62
61restart_track: 63restart_track:
64 action = CODEC_ACTION_NULL;
62 65
63 /* Proper reset of the decoder context. */ 66 /* Proper reset of the decoder context. */
64 memset(&wmadec, 0, sizeof(wmadec)); 67 memset(&wmadec, 0, sizeof(wmadec));
@@ -78,13 +81,20 @@ restart_track:
78 return CODEC_ERROR; 81 return CODEC_ERROR;
79 } 82 }
80 83
81 if (resume_offset > ci->id3->first_frame_offset) 84 if (resume_offset > ci->id3->first_frame_offset || elapsedtime)
82 { 85 {
83 /* Get start of current packet */ 86 if (resume_offset) {
84 int packet_offset = (resume_offset - ci->id3->first_frame_offset) 87 /* Get start of current packet */
85 % wfx.packet_size; 88 int packet_offset = (resume_offset -
86 ci->seek_buffer(resume_offset - packet_offset); 89 MIN(resume_offset, ci->id3->first_frame_offset))
87 elapsedtime = asf_get_timestamp(&i); 90 % wfx.packet_size;
91 ci->seek_buffer(resume_offset - packet_offset);
92 elapsedtime = asf_get_timestamp(&i);
93 }
94 else {
95 param = elapsedtime;
96 action = CODEC_ACTION_SEEK_TIME;
97 }
88 } 98 }
89 else 99 else
90 { 100 {
@@ -104,7 +114,8 @@ restart_track:
104 /* The main decoding loop */ 114 /* The main decoding loop */
105 while (res >= 0) 115 while (res >= 0)
106 { 116 {
107 enum codec_command_action action = ci->get_command(&param); 117 if (action == CODEC_ACTION_NULL)
118 action = ci->get_command(&param);
108 119
109 if (action != CODEC_ACTION_NULL) { 120 if (action != CODEC_ACTION_NULL) {
110 121
@@ -126,6 +137,7 @@ restart_track:
126 if (param == 0) { 137 if (param == 0) {
127 ci->set_elapsed(0); 138 ci->set_elapsed(0);
128 ci->seek_complete(); 139 ci->seek_complete();
140 elapsedtime = 0;
129 goto restart_track; /* Pretend you never saw this... */ 141 goto restart_track; /* Pretend you never saw this... */
130 } 142 }
131 143
@@ -140,6 +152,8 @@ restart_track:
140 ci->set_elapsed(elapsedtime); 152 ci->set_elapsed(elapsedtime);
141 ci->seek_complete(); 153 ci->seek_complete();
142 } 154 }
155
156 action = CODEC_ACTION_NULL;
143 } 157 }
144 158
145 errcount = 0; 159 errcount = 0;
diff --git a/lib/rbcodec/codecs/wmapro.c b/lib/rbcodec/codecs/wmapro.c
index d99ca1aa9e..f15f36813d 100644
--- a/lib/rbcodec/codecs/wmapro.c
+++ b/lib/rbcodec/codecs/wmapro.c
@@ -55,6 +55,8 @@ enum codec_status codec_run(void)
55 int size; /* Size of the input frame to the decoder */ 55 int size; /* Size of the input frame to the decoder */
56 intptr_t param; 56 intptr_t param;
57 57
58 elapsedtime = ci->id3->elapsed;
59
58restart_track: 60restart_track:
59 if (codec_init()) { 61 if (codec_init()) {
60 LOGF("(WMA PRO) Error: Error initialising codec\n"); 62 LOGF("(WMA PRO) Error: Error initialising codec\n");
@@ -75,11 +77,17 @@ restart_track:
75 return CODEC_ERROR; 77 return CODEC_ERROR;
76 } 78 }
77 79
78 /* Now advance the file position to the first frame */ 80 if (elapsedtime) {
79 ci->seek_buffer(ci->id3->first_frame_offset); 81 elapsedtime = asf_seek(elapsedtime, &wfx);
82 if (elapsedtime < 1)
83 return CODEC_OK;
84 }
85 else {
86 /* Now advance the file position to the first frame */
87 ci->seek_buffer(ci->id3->first_frame_offset);
88 }
80 89
81 elapsedtime = 0; 90 ci->set_elapsed(elapsedtime);
82 ci->set_elapsed(0);
83 91
84 /* The main decoding loop */ 92 /* The main decoding loop */
85 93
@@ -95,6 +103,7 @@ restart_track:
95 if (param == 0) { 103 if (param == 0) {
96 ci->set_elapsed(0); 104 ci->set_elapsed(0);
97 ci->seek_complete(); 105 ci->seek_complete();
106 elapsedtime = 0;
98 goto restart_track; /* Pretend you never saw this... */ 107 goto restart_track; /* Pretend you never saw this... */
99 } 108 }
100 109
diff --git a/lib/rbcodec/codecs/wmavoice.c b/lib/rbcodec/codecs/wmavoice.c
index 214e0737e7..4c89c6dc96 100644
--- a/lib/rbcodec/codecs/wmavoice.c
+++ b/lib/rbcodec/codecs/wmavoice.c
@@ -67,7 +67,6 @@ enum codec_status codec_run(void)
67{ 67{
68 uint32_t elapsedtime; 68 uint32_t elapsedtime;
69 asf_waveformatex_t wfx; /* Holds the stream properties */ 69 asf_waveformatex_t wfx; /* Holds the stream properties */
70 size_t resume_offset;
71 int res; /* Return values from asf_read_packet() and decode_packet() */ 70 int res; /* Return values from asf_read_packet() and decode_packet() */
72 uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */ 71 uint8_t* audiobuf; /* Pointer to the payload of one wma pro packet */
73 int audiobufsize; /* Payload size */ 72 int audiobufsize; /* Payload size */
@@ -76,8 +75,8 @@ enum codec_status codec_run(void)
76 int pktcnt = 0; /* Count of the packets played */ 75 int pktcnt = 0; /* Count of the packets played */
77 intptr_t param; 76 intptr_t param;
78 77
79 /* Remember the resume position */ 78 elapsedtime = ci->id3->elapsed;
80 resume_offset = ci->id3->offset; 79
81restart_track: 80restart_track:
82 if (codec_init()) { 81 if (codec_init()) {
83 LOGF("(WMA Voice) Error: Error initialising codec\n"); 82 LOGF("(WMA Voice) Error: Error initialising codec\n");
@@ -105,13 +104,17 @@ restart_track:
105 return CODEC_ERROR; 104 return CODEC_ERROR;
106 } 105 }
107 106
108 /* Now advance the file position to the first frame */ 107 if (elapsedtime) {
109 ci->seek_buffer(ci->id3->first_frame_offset); 108 elapsedtime = asf_seek(elapsedtime, &wfx);
110 109 if (elapsedtime < 1)
111 elapsedtime = 0; 110 return CODEC_OK;
112 ci->set_elapsed(0); 111 }
112 else {
113 /* Now advance the file position to the first frame */
114 ci->seek_buffer(ci->id3->first_frame_offset);
115 }
113 116
114 resume_offset = 0; 117 ci->set_elapsed(elapsedtime);
115 118
116 /* The main decoding loop */ 119 /* The main decoding loop */
117 120
@@ -129,6 +132,7 @@ restart_track:
129 if (param == 0) { 132 if (param == 0) {
130 ci->set_elapsed(0); 133 ci->set_elapsed(0);
131 ci->seek_complete(); 134 ci->seek_complete();
135 elapsedtime = 0;
132 goto restart_track; /* Pretend you never saw this... */ 136 goto restart_track; /* Pretend you never saw this... */
133 } 137 }
134 138
@@ -136,7 +140,7 @@ restart_track:
136 if (elapsedtime < 1){ 140 if (elapsedtime < 1){
137 ci->set_elapsed(0); 141 ci->set_elapsed(0);
138 ci->seek_complete(); 142 ci->seek_complete();
139 goto next_track; 143 break;
140 } 144 }
141 145
142 ci->set_elapsed(elapsedtime); 146 ci->set_elapsed(elapsedtime);