summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2013-07-14 07:59:39 -0400
committerMichael Sevakis <jethead71@rockbox.org>2014-03-10 04:12:30 +0100
commit31b712286721dd606940c7b557d03e3f714b9604 (patch)
tree8c4a4cc32e9000ea721ebb23aa3c0129ca97bf53 /lib
parentdda54b85daa83b7803b4fb189ab45859f96ff3f9 (diff)
downloadrockbox-31b712286721dd606940c7b557d03e3f714b9604.tar.gz
rockbox-31b712286721dd606940c7b557d03e3f714b9604.zip
Implement time-based resume and playback start.
This complements offset-based resume and playback start funcionality. The implementation is global on both HWCODEC and SWCODEC. Basically, if either the specified elapsed or offset are non-zero, it indicates a mid-track resume. To resume by time only, set elapsed to nonzero and offset to zero. To resume by offset only, set offset to nonzero and elapsed to zero. Which one the codec uses and which has priority is up to the codec; however, using an elapsed time covers more cases: * Codecs not able to use an offset such as VGM or other atomic formats * Starting playback at a nonzero elapsed time from a source that contains no offset, such as a cuesheet The change re-versions pretty much everything from tagcache to nvram. Change-Id: Ic7aebb24e99a03ae99585c5e236eba960d163f38 Reviewed-on: http://gerrit.rockbox.org/516 Reviewed-by: Michael Sevakis <jethead71@rockbox.org> Tested: Michael Sevakis <jethead71@rockbox.org>
Diffstat (limited to 'lib')
-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);