diff --git a/src/sound/mad.cpp b/src/sound/mad.cpp
index 1934719e7..d8a6e3a18 100644
--- a/src/sound/mad.cpp
+++ b/src/sound/mad.cpp
@@ -23,6 +23,8 @@
 //
 //	$Id$
 
+//	FIXME: JOHNS: MP3 streaming did not yet work.
+
 //@{
 
 /*----------------------------------------------------------------------------
@@ -55,6 +57,17 @@ typedef struct _mad_user_ {
     unsigned char Buffer[4096];		// Decoded buffer
 } MyUser;
 
+/**
+**	Private mp3 data structure to handle mp3 streaming.
+*/
+typedef struct _mp3_data_ {
+    char*		PointerInBuffer;	/// Pointer into buffer
+    struct mad_decoder	Decoder[1];		/// Mad decoder handle
+    MyUser		User[1];		/// Decoder user data
+} Mp3Data;
+
+#define MP3_BUFFER_SIZE  (12 * 1024)		/// Buffer size to fill
+
 /*----------------------------------------------------------------------------
 --	Functions
 ----------------------------------------------------------------------------*/
@@ -181,39 +194,113 @@ local enum mad_flow MAD_error(void *user __attribute__((unused)),
 
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
+/**
+**	Read one frame from mad decoder.
+**
+**	@param decoder	Decoder
+**	@param buf	Buffer to write data to
+**	@param len	Length of the buffer
+**
+**	@return		Number of bytes read
+*/
+local int MadRead(struct mad_decoder* decoder, unsigned char* buf, int len)
+{
+    struct mad_stream *stream;
+    struct mad_frame *frame;
+    struct mad_synth *synth;
+
+    DebugLevel0Fn("%p %p %d\n" _C_ decoder _C_ buf _C_ len);
+
+    stream = &decoder->sync->stream;
+    frame = &decoder->sync->frame;
+    synth = &decoder->sync->synth;
+    DebugLevel0Fn("Error: %d\n" _C_ stream->error);
+    do {
+	DebugLevel0Fn("Read stream\n");
+	switch (MAD_read(decoder->cb_data, stream)) {
+	    case MAD_FLOW_STOP:
+		return 0;
+	    case MAD_FLOW_BREAK:
+		return -1;
+	    case MAD_FLOW_IGNORE:
+		continue;
+	    case MAD_FLOW_CONTINUE:
+		break;
+	}
+
+	while (1) {
+	    if (mad_frame_decode(frame, stream) == -1) {
+		if (!MAD_RECOVERABLE(stream->error)) {
+		    break;
+		}
+
+		switch (MAD_error(decoder->cb_data, stream, frame)) {
+		    case MAD_FLOW_STOP:
+			return 0;
+		    case MAD_FLOW_BREAK:
+			return -1;
+		    case MAD_FLOW_IGNORE:
+			break;
+		    case MAD_FLOW_CONTINUE:
+		    default:
+			continue;
+		}
+	    }
+
+	    mad_synth_frame(synth, frame);
+
 #if 0
+	    // FIXME: write out the frame buffer!
+	    switch (decoder->output_func(decoder->cb_data, &frame->header,
+		    &synth->pcm)) {
+		case MAD_FLOW_STOP:
+		    return 0;
+		case MAD_FLOW_BREAK:
+		    return -1;
+		case MAD_FLOW_IGNORE:
+		case MAD_FLOW_CONTINUE:
+		    break;
+	    }
+#endif
+
+	}
+	// Should stop here!
+    } while (stream->error == MAD_ERROR_BUFLEN);
+
+    return -1;
+}
 
 /**
-**	Type member function to read from the Mp3 file
+**	Type member function to read from the mp3 file
 **
-**	@param sample	    Sample reading from
-**	@param buf	    Buffer to write data to
-**	@param len	    Length of the buffer
+**	@param sample	Sample reading from
+**	@param buf	Buffer to write data to
+**	@param len	Length of the buffer
 **
-**	@return		    Number of bytes read
+**	@return		Number of bytes read
 */
 local int Mp3ReadStream(Sample* sample, void* buf, int len)
 {
     Mp3Data* data;
     int i;
     int n;
-    int bitstream;
 
-    data = (Mp3Data*) sample->User;
+    DebugLevel0Fn("%p %d\n" _C_ buf _C_ len);
+
+    data = sample->User;
 
     // see if we have enough read already
-    if (data->PointerInBuffer + len - sample->Data > sample->Length) {
+    if (data->PointerInBuffer - sample->Data + len > sample->Length) {
 	// not enough in buffer, read more
 	n = sample->Length - (data->PointerInBuffer - sample->Data);
 	memcpy(sample->Data, data->PointerInBuffer, n);
 	sample->Length = n;
 	data->PointerInBuffer = sample->Data;
 
-	n = OGG_BUFFER_SIZE - n;
+	n = MP3_BUFFER_SIZE - n;
 	for (;;) {
-	    i = ov_read(data->VorbisFile,
-		    data->PointerInBuffer + sample->Length, n, 0, 2, 1,
-		    &bitstream);
+	    i = MadRead(data->Decoder, data->PointerInBuffer + sample->Length,
+		    n);
 	    if (i <= 0) {
 		break;
 	    }
@@ -234,18 +321,30 @@ local int Mp3ReadStream(Sample* sample, void* buf, int len)
 }
 
 /**
-**	Type member function to free an Mp3 file
+**	Type member function to free an mp3 file
 **
-**	@param sample	    Sample to free
+**	@param sample	Sample to free
 */
 local void Mp3FreeStream(Sample* sample)
 {
     Mp3Data* data;
 
-    IfDebug( AllocatedSoundMemory -= sizeof(*sample) + OGG_BUFFER_SIZE);
+    IfDebug( AllocatedSoundMemory -= sizeof(*sample) + MP3_BUFFER_SIZE);
+
+    data = sample->User;
+
+    // release the decoder
+
+    mad_synth_finish(data->Decoder->sync->synth);
+    mad_frame_finish(&data->Decoder->sync->frame);
+    mad_stream_finish(&data->Decoder->sync->stream);
+
+    free(data->Decoder->sync);
+    data->Decoder->sync = NULL;
+    mad_decoder_finish(data->Decoder);
+
+    CLclose(data->User->File);
 
-    data = (Mp3Data*)sample->User;
-    ov_clear(data->VorbisFile);
     free(data);
     free(sample);
 }
@@ -257,16 +356,15 @@ local const SampleType Mp3StreamSampleType = {
     Mp3ReadStream,
     Mp3FreeStream,
 };
-#endif
 
 /**
-**	Type member function to read from the Mp3 file
+**	Type member function to read from the mp3 file
 **
-**	@param sample	    Sample reading from
-**	@param buf	    Buffer to write data to
-**	@param len	    Length of the buffer
+**	@param sample	Sample reading from
+**	@param buf	Buffer to write data to
+**	@param len	Length of the buffer
 **
-**	@return		    Number of bytes read
+**	@return		Number of bytes read
 */
 local int Mp3Read(Sample* sample, void* buf, int len)
 {
@@ -284,9 +382,9 @@ local int Mp3Read(Sample* sample, void* buf, int len)
 }
 
 /**
-**	Type member function to free an Mp3 file
+**	Type member function to free an mp3 file
 **
-**	@param sample	    Sample to free
+**	@param sample	Sample to free
 */
 local void Mp3Free(Sample* sample)
 {
@@ -303,121 +401,6 @@ local const SampleType Mp3SampleType = {
     Mp3Free,
 };
 
-/**
-**	Test code.
-*/
-static int run_sync(struct mad_decoder *decoder)
-{
-    enum mad_flow (*error_func) (void *, struct mad_stream *,
-	struct mad_frame *);
-    void *error_data;
-    int bad_last_frame = 0;
-    struct mad_stream *stream;
-    struct mad_frame *frame;
-    struct mad_synth *synth;
-    int result = 0;
-
-    error_func = decoder->error_func;
-    error_data = decoder->cb_data;
-
-    stream = &decoder->sync->stream;
-    frame = &decoder->sync->frame;
-    synth = &decoder->sync->synth;
-
-    mad_stream_init(stream);
-    mad_frame_init(frame);
-    mad_synth_init(synth);
-
-    mad_stream_options(stream, decoder->options);
-
-    do {
-	switch (decoder->input_func(decoder->cb_data, stream)) {
-	    case MAD_FLOW_STOP:
-		goto done;
-	    case MAD_FLOW_BREAK:
-		goto fail;
-	    case MAD_FLOW_IGNORE:
-		continue;
-	    case MAD_FLOW_CONTINUE:
-		break;
-	}
-
-	while (1) {
-	    if (decoder->header_func) {
-		if (mad_header_decode(&frame->header, stream) == -1) {
-		    if (!MAD_RECOVERABLE(stream->error))
-			break;
-
-		    switch (error_func(error_data, stream, frame)) {
-			case MAD_FLOW_STOP:
-			    goto done;
-			case MAD_FLOW_BREAK:
-			    goto fail;
-			case MAD_FLOW_IGNORE:
-			case MAD_FLOW_CONTINUE:
-			default:
-			    continue;
-		    }
-		}
-
-		switch (decoder->header_func(decoder->cb_data, &frame->header)) {
-		    case MAD_FLOW_STOP:
-			goto done;
-		    case MAD_FLOW_BREAK:
-			goto fail;
-		    case MAD_FLOW_IGNORE:
-			continue;
-		    case MAD_FLOW_CONTINUE:
-			break;
-		}
-	    }
-
-	    if (mad_frame_decode(frame, stream) == -1) {
-		if (!MAD_RECOVERABLE(stream->error))
-		    break;
-
-		switch (error_func(error_data, stream, frame)) {
-		    case MAD_FLOW_STOP:
-			goto done;
-		    case MAD_FLOW_BREAK:
-			goto fail;
-		    case MAD_FLOW_IGNORE:
-			break;
-		    case MAD_FLOW_CONTINUE:
-		    default:
-			continue;
-		}
-	    } else
-		bad_last_frame = 0;
-
-	    mad_synth_frame(synth, frame);
-
-	    if (decoder->output_func) {
-		switch (decoder->output_func(decoder->cb_data, &frame->header,
-			&synth->pcm)) {
-		    case MAD_FLOW_STOP:
-			goto done;
-		    case MAD_FLOW_BREAK:
-			goto fail;
-		    case MAD_FLOW_IGNORE:
-		    case MAD_FLOW_CONTINUE:
-			break;
-		}
-	    }
-	}
-    } while (stream->error == MAD_ERROR_BUFLEN);
-
-fail:
-    result = -1;
-
-done:
-    mad_synth_finish(synth);
-    mad_frame_finish(frame);
-    mad_stream_finish(stream);
-
-    return result;
-}
-
 /**
 **	Load mp3.
 **
@@ -425,13 +408,13 @@ done:
 **	@param flags	Load flags.
 **
 **	@return		Returns the loaded sample.
+**
+**	@todo		Support more flags, LoadOnDemand.
 */
-global Sample *LoadMp3(const char* name, int flags __attribute__((unused)))
+global Sample *LoadMp3(const char* name, int flags)
 {
-    MyUser user;
     CLFile* f;
     unsigned char magic[2];
-    struct mad_decoder decoder;
     Sample* sample;
 
     if (!(f = CLopen(name))) {
@@ -454,47 +437,95 @@ global Sample *LoadMp3(const char* name, int flags __attribute__((unused)))
 
     DebugLevel2Fn("Have mp3 file %s\n" _C_ name);
 
-    sample = malloc(sizeof(*sample));
-    sample->Channels = 0;
-    sample->SampleSize = 0;
-    sample->Frequency = 0;
-    sample->Length = 0;
+#ifdef MP3_STREAM_WORKS
+    if (flags & PlayAudioStream)
+#else
+    if (0 && (flags & PlayAudioStream))
+#endif
+    {
+	Mp3Data* data;
 
-    // configure input, output, and error functions
-    user.File = f;
-    user.Sample = sample;
+	sample = malloc(sizeof(*sample) + MP3_BUFFER_SIZE);
+	if (!sample) {
+	    fprintf(stderr, "Out of memory\n");
+	    CLclose(f);
+	    return NULL;
+	}
+	data = malloc(sizeof(*data));
+	if (!data) {
+	    fprintf(stderr, "Out of memory\n");
+	    free(sample);
+	    CLclose(f);
+	    return NULL;
+	}
+	sample->User = data;
+	sample->Channels = 0;
+	sample->SampleSize = 0;
+	sample->Frequency = 0;
+	sample->Length = 0;
+	sample->Type = &Mp3StreamSampleType;
 
-    mad_decoder_init(&decoder, &user,
-	MAD_read, 0 /* header */, 0 /* filter */, MAD_write,
-	MAD_error, 0 /* message */);
+	data->User->File = f;
+	data->User->Sample = sample;
 
-    // start decoding
-    // mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
+	// configure input, output, and error functions
 
-    decoder.sync = malloc(sizeof(*decoder.sync));
-    if (!decoder.sync) {
+	mad_decoder_init(data->Decoder, data->User,
+	    MAD_read, NULL /* header */, NULL /* filter */, MAD_write,
+	    MAD_error, NULL /* message */);
+
+	data->Decoder->sync = malloc(sizeof(*data->Decoder->sync));
+	if (!data->Decoder->sync) {
+	    fprintf(stderr, "Out of memory\n");
+	    mad_decoder_finish(data->Decoder);
+	    free(data);
+	    free(sample);
+	    CLclose(f);
+	    return NULL;
+	}
+
+	mad_stream_init(&data->Decoder->sync->stream);
+	mad_frame_init(&data->Decoder->sync->frame);
+	mad_synth_init(&data->Decoder->sync->synth);
+	mad_stream_options(&data->Decoder->sync->stream,
+		data->Decoder->options);
+
+	// Read first frame for channels, ...
+	data->PointerInBuffer = sample->Data;
+	sample->Length = MadRead(data->Decoder, sample->Data, MP3_BUFFER_SIZE);
+
+	DebugLevel0Fn(" %d\n" _C_ sizeof(*sample) + MP3_BUFFER_SIZE);
+	IfDebug( AllocatedSoundMemory += sizeof(*sample) + MP3_BUFFER_SIZE);
+
+	return sample;
+    } else {
+	MyUser user;
+	struct mad_decoder decoder;
+
+	sample = calloc(1, sizeof(*sample));
+	user.File = f;
+	user.Sample = sample;
+
+	// configure input, output, and error functions
+
+	mad_decoder_init(&decoder, &user,
+	    MAD_read, NULL /* header */, NULL /* filter */, MAD_write,
+	    MAD_error, NULL /* message */);
+
+	mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
+
+	// release the decoder
 	mad_decoder_finish(&decoder);
 	CLclose(f);
-	return NULL;
+
+	user.Sample->Type = &Mp3SampleType;
+	user.Sample->User = 0;
+
+	DebugLevel0Fn(" %d\n" _C_ user.Sample->Length);
+	IfDebug( AllocatedSoundMemory += user.Sample->Length; );
+
+	return user.Sample;
     }
-
-    run_sync(&decoder);
-
-    free(decoder.sync);
-    decoder.sync = 0;
-
-    // release the decoder
-
-    mad_decoder_finish(&decoder);
-    CLclose(f);
-
-    user.Sample->Type = &Mp3SampleType;
-    user.Sample->User = 0;
-
-    DebugLevel0Fn(" %d\n" _C_ user.Sample->Length);
-    IfDebug( AllocatedSoundMemory += user.Sample->Length; );
-
-    return user.Sample;
 }
 
 #endif	// } WITH_SOUND && USE_MAD