Index: libmpc/branches/r2d/libmpcdec/mpc_demux.c
===================================================================
--- libmpc/branches/r2d/libmpcdec/mpc_demux.c	(revision 139)
+++ libmpc/branches/r2d/libmpcdec/mpc_demux.c	(revision 143)
@@ -53,8 +53,16 @@
 
 enum {
-	MPC_BUFFER_CLEAR = 1,
-	MPC_BUFFER_SWAP = 2,
-	MPC_BUFFER_FULL = 4,
+	MPC_BUFFER_SWAP = 1,
+	MPC_BUFFER_FULL = 2,
 };
+
+static void mpc_demux_clear_buff(mpc_demux * d)
+{
+	d->bytes_total = 0;
+	d->bits_reader.buff = d->buffer;
+	d->bits_reader.count = 8;
+	d->block_bits = 0;
+	d->end = MPC_FALSE;
+}
 
 static mpc_uint32_t
@@ -95,4 +103,34 @@
 
 	return 0;
+}
+
+/**
+ * seek to a bit position in the stream
+ * @param d
+ * @param fpos position in the stream in bits from the beginning of mpc datas
+ * @param min_bytes number of bytes to load after seeking
+ */
+static void
+mpc_demux_seek(mpc_demux * d, mpc_uint32_t fpos, mpc_uint32_t min_bytes) {
+// 	mpc_uint32_t cur_pos = d->r->tell(d->r);
+	mpc_uint32_t next_pos;
+	mpc_int_t bit_offset;
+
+	// FIXME : do not flush the buffer if fpos is in the current buffer
+
+	next_pos = fpos >> 3;
+	if (d->si.stream_version == 7)
+		next_pos &= (-1u << 2);
+	bit_offset = fpos - (next_pos << 3);
+	next_pos += d->si.header_position; // add id3 offset
+
+	d->r->seek(d->r, next_pos);
+	mpc_demux_clear_buff(d);
+	if (d->si.stream_version == 7)
+		mpc_demux_fill(d, (min_bytes + ((bit_offset + 7) >> 3) + 3) & (-1 << 2), MPC_BUFFER_SWAP);
+	else
+		mpc_demux_fill(d, min_bytes + ((bit_offset + 7) >> 3), 0);
+	d->bits_reader.buff += bit_offset >> 3;
+	d->bits_reader.count = 8 - (bit_offset & 7);
 }
 
@@ -159,9 +197,5 @@
 	if (p_tmp != 0) {
 		p_tmp->r = p_reader;
-		p_tmp->bytes_total = 0;
-		p_tmp->bits_reader.buff = p_tmp->buffer;
-		p_tmp->bits_reader.count = 8;
-		p_tmp->block_bits = 0;
-		p_tmp->end = MPC_FALSE;
+		mpc_demux_clear_buff(p_tmp);
 		// lire entÃªte
 		if (mpc_demux_header(p_tmp) == MPC_STATUS_OK) {
@@ -190,14 +224,16 @@
 void mpc_demux_decode(mpc_demux * d, mpc_frame_info * i)
 {
-	if (d->si.stream_version == 8) {
+	if (d->si.stream_version >= 8) {
 		mpc_bits_reader r;
-		if (d->block_bits < 8 && d->end == MPC_FALSE){
+		if (d->block_bits < 8 && d->end == MPC_FALSE) {
 			mpc_block b;
 			d->bits_reader.count &= -8;
 			mpc_demux_fill(d, 11, 0); // max header block size
 			mpc_bits_get_block(&d->bits_reader, &b);
-			while( memcmp(b.key, "AD", 2) != 0 ){ // scan all blocks until audio
-				if (memcmp(b.key, "SE", 2) == 0) // end block
+			while( memcmp(b.key, "AD", 2) != 0 ) { // scan all blocks until audio
+				if (memcmp(b.key, "SE", 2) == 0) { // end block
 					d->end = MPC_TRUE;
+					break;
+				}
 				mpc_demux_fill(d, 11 + b.size, 0);
 				d->bits_reader.buff += b.size;
@@ -206,5 +242,5 @@
 			d->block_bits = b.size * 8;
 		}
-
+		// FIXME : this is not good if block size > buffer size
 		mpc_demux_fill(d, (d->block_bits >> 3) + 1, 0);
 		r = d->bits_reader;
@@ -220,2 +256,54 @@
 }
 
+mpc_status mpc_demux_seek_second(mpc_demux * d, double seconds)
+{
+	return mpc_demux_seek_sample(d, (mpc_int64_t)(seconds * (double)d->si.sample_freq + 0.5));
+}
+
+mpc_status mpc_demux_seek_sample(mpc_demux * d, mpc_int64_t destsample)
+{
+	mpc_uint32_t fwd, samples_to_skip, fpos = 32, i;
+
+	if (destsample > d->si.samples) destsample = d->si.samples;
+	fwd = (mpc_uint32_t) (destsample / (MPC_FRAME_LENGTH * d->si.frames_per_block));
+	samples_to_skip = MPC_DECODER_SYNTH_DELAY + (mpc_uint32_t)
+			(destsample % (MPC_FRAME_LENGTH * d->si.frames_per_block));
+
+	// FIXME : we start seeking from the beginning of the file, easier but not optimal
+	d->d->decoded_samples = 0;
+
+	if (d->si.stream_version >= 8) {
+		mpc_block b;
+		int size;
+		mpc_demux_seek(d, fpos, 11);
+		size = mpc_bits_get_block(&d->bits_reader, &b);
+		for( i = 0; i < fwd; ){
+			if (memcmp(b.key, "AD", 2) == 0){
+				i++;
+				d->d->decoded_samples += MPC_FRAME_LENGTH * d->si.frames_per_block;
+			}
+			fpos += (b.size + size) * 8;
+			mpc_demux_seek(d, fpos, 11);
+			size = mpc_bits_get_block(&d->bits_reader, &b);
+		}
+		d->bits_reader.buff -= size;
+	} else {
+		if (fwd > 32) {
+			fwd -= 32;
+			samples_to_skip += MPC_FRAME_LENGTH * 32;
+		} else {
+			samples_to_skip += MPC_FRAME_LENGTH * fwd;
+			fwd = 0;
+		}
+		mpc_decoder_reset_scf(d->d);
+		fpos += 21 * 8;
+		mpc_demux_seek(d, fpos, 4);
+		for( i = 0; i < fwd; i++){
+			fpos += mpc_bits_read(&d->bits_reader, 20) + 20;
+			mpc_demux_seek(d, fpos, 4);
+			d->d->decoded_samples += MPC_FRAME_LENGTH;
+		}
+	}
+	d->d->samples_to_skip = samples_to_skip;
+	return MPC_STATUS_OK;
+}
