Index: libmpcdec/branches/zorg/src/mpc_reader.c
===================================================================
--- libmpcdec/branches/zorg/src/mpc_reader.c	(revision 63)
+++ libmpcdec/branches/zorg/src/mpc_reader.c	(revision 68)
@@ -32,65 +32,148 @@
   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
-
 /// \file mpc_reader.c
 /// Contains implementations for simple file-based mpc_reader
+#include <mpcdec/reader.h>
+#include "internal.h"
+#include <stdio.h>
 
-#include <mpcdec/mpcdec.h>
+#define STDIO_MAGIC 0xF34B963C ///< Just a random safe-check value...
+typedef struct mpc_reader_stdio_t {
+    FILE       *p_file;
+    int         file_size;
+    mpc_bool_t  is_seekable;
+    mpc_int32_t magic;
+} mpc_reader_stdio;
 
 /// mpc_reader callback implementations
 static mpc_int32_t
-read_impl(void *data, void *ptr, mpc_int32_t size)
+read_stdio(mpc_reader *p_reader, void *ptr, mpc_int32_t size)
 {
-    mpc_reader_file *d = (mpc_reader_file *) data;
-
-    return (mpc_int32_t) fread(ptr, 1, size, d->file);
+    mpc_reader_stdio *p_stdio = (mpc_reader_stdio*) p_reader->data;
+    if(p_stdio->magic != STDIO_MAGIC) return MPC_STATUS_FILE;
+    return (mpc_int32_t) fread(ptr, 1, size, p_stdio->p_file);
 }
 
 static mpc_bool_t
-seek_impl(void *data, mpc_int32_t offset)
+seek_stdio(mpc_reader *p_reader, mpc_int32_t offset)
 {
-    mpc_reader_file *d = (mpc_reader_file *) data;
-
-    return d->is_seekable ? fseek(d->file, offset, SEEK_SET) == 0 : FALSE;
+    mpc_reader_stdio *p_stdio = (mpc_reader_stdio*) p_reader->data;
+    if(p_stdio->magic != STDIO_MAGIC) return FALSE;
+    return p_stdio->is_seekable ? fseek(p_stdio->p_file, offset, SEEK_SET) == 0 : FALSE;
 }
 
 static mpc_int32_t
-tell_impl(void *data)
+tell_stdio(mpc_reader *p_reader)
 {
-    mpc_reader_file *d = (mpc_reader_file *) data;
-
-    return ftell(d->file);
+    mpc_reader_stdio *p_stdio = (mpc_reader_stdio*) p_reader->data;
+    if(p_stdio->magic != STDIO_MAGIC) return MPC_STATUS_FILE;
+    return ftell(p_stdio->p_file);
 }
 
 static mpc_int32_t
-get_size_impl(void *data)
+get_size_stdio(mpc_reader *p_reader)
 {
-    mpc_reader_file *d = (mpc_reader_file *) data;
-
-    return d->file_size;
+    mpc_reader_stdio *p_stdio = (mpc_reader_stdio*) p_reader->data;
+    if(p_stdio->magic != STDIO_MAGIC) return MPC_STATUS_FILE;
+    return p_stdio->file_size;
 }
 
 static mpc_bool_t
-canseek_impl(void *data)
+canseek_stdio(mpc_reader *p_reader)
 {
-    mpc_reader_file *d = (mpc_reader_file *) data;
+    mpc_reader_stdio *p_stdio = (mpc_reader_stdio*) p_reader->data;
+    if(p_stdio->magic != STDIO_MAGIC) return FALSE;
+    return p_stdio->is_seekable;
+}
 
-    return d->is_seekable;
+mpc_status
+mpc_reader_setup_file_reader(mpc_reader *p_reader, char *filename)
+{
+    mpc_reader tmp_reader; mpc_reader_stdio *p_stdio; int err;
+
+    p_stdio = NULL;
+    memset(&tmp_reader, 0, sizeof tmp_reader);
+    p_stdio = malloc(sizeof *p_stdio);
+    if(!p_stdio) return MPC_STATUS_FILE;
+    memset(p_stdio, 0, sizeof *p_stdio);
+
+    p_stdio->magic  = STDIO_MAGIC;
+    p_stdio->p_file = fopen(filename, "rb");
+    if(!p_stdio->p_file) goto clean;
+    p_stdio->is_seekable = TRUE;
+    err = fseek(p_stdio->p_file, 0, SEEK_END);
+    if(err < 0) goto clean;
+    err = ftell(p_stdio->p_file);
+    if(err < 0) goto clean;
+    p_stdio->file_size = err;
+    err = fseek(p_stdio->p_file, 0, SEEK_SET);
+    if(err < 0) goto clean;
+
+    tmp_reader.data     = p_stdio;
+    tmp_reader.canseek  = canseek_stdio;
+    tmp_reader.get_size = get_size_stdio;
+    tmp_reader.read     = read_stdio;
+    tmp_reader.seek     = seek_stdio;
+    tmp_reader.tell     = tell_stdio;
+
+    *p_reader = tmp_reader;
+    return MPC_STATUS_OK;
+clean:
+    if(p_stdio && p_stdio->p_file)
+        fclose(p_stdio->p_file);
+    free(p_stdio);
+    return MPC_STATUS_FILE;
 }
 
 void
-mpc_reader_setup_file_reader(mpc_reader_file *p_reader, FILE *input)
+mpc_exit_stdio_reader(mpc_reader *p_reader)
 {
-    p_reader->reader.seek = seek_impl;
-    p_reader->reader.read = read_impl;
-    p_reader->reader.tell = tell_impl;
-    p_reader->reader.get_size = get_size_impl;
-    p_reader->reader.canseek = canseek_impl;
-    p_reader->reader.data = p_reader; // point back to ourselves
+    mpc_reader_stdio *p_stdio = (mpc_reader_stdio*) p_reader->data;
+    if(p_stdio->magic != STDIO_MAGIC) return;
+    fclose(p_stdio->p_file);
+    free(p_stdio);
+    p_reader->data = NULL;
+}
 
-    p_reader->file = input;
-    p_reader->is_seekable = TRUE;
-    fseek(input, 0, SEEK_END);
-    p_reader->file_size = ftell(input);
-    fseek(input, 0, SEEK_SET);
+mpc_int32_t
+mpc_skip_id3v2(mpc_reader* p_reader)
+{
+    mpc_uint8_t  tmp [10];
+    mpc_uint32_t unsynchronisation; // ID3v2.4-flag
+    mpc_uint32_t extHeaderPresent;  // ID3v2.4-flag
+    mpc_uint32_t experimentalFlag;  // ID3v2.4-flag
+    mpc_uint32_t footerPresent;     // ID3v2.4-flag
+    mpc_int32_t  ret;
+
+    // seek to first byte of mpc data
+    ret = p_reader->seek(p_reader, 0);
+    if(!ret) return 0;
+    
+    p_reader->read(p_reader, tmp, sizeof tmp);
+
+    // check id3-tag
+    if ( 0 != memcmp( tmp, "ID3", 3 ) )
+        return 0;
+
+    // read flags
+    unsynchronisation = tmp[5] & 0x80;
+    extHeaderPresent  = tmp[5] & 0x40;
+    experimentalFlag  = tmp[5] & 0x20;
+    footerPresent     = tmp[5] & 0x10;
+
+    if ( tmp[5] & 0x0F )
+        return MPC_STATUS_FILE; // not (yet???) allowed
+    if ( (tmp[6] | tmp[7] | tmp[8] | tmp[9]) & 0x80 )
+        return MPC_STATUS_FILE; // not allowed
+
+    // read headerSize (syncsave: 4 * $0xxxxxxx = 28 significant bits)
+    ret  = tmp[6] << 21;
+    ret += tmp[7] << 14;
+    ret += tmp[8] <<  7;
+    ret += tmp[9];
+    ret += 10;
+    if ( footerPresent )
+        ret += 10;
+
+    return ret;
 }
