[libdvdnav-devel] [Git][videolan/libdvdread][master] 10 commits: Add new versions of DVDOpen to provide context

Jean-Baptiste Kempf gitlab at videolan.org
Wed Mar 4 13:57:21 CET 2020



Jean-Baptiste Kempf pushed to branch master at VideoLAN / libdvdread


Commits:
3e4519df by Francois Cartegnie at 2020-03-04T11:44:11+01:00
Add new versions of DVDOpen to provide context

- - - - -
c2e322ae by Francois Cartegnie at 2020-03-04T11:44:11+01:00
add logger parameters in new Open2

- - - - -
5ef1a395 by Francois Cartegnie at 2020-03-04T11:44:11+01:00
Add internal logger functions

- - - - -
bde28bce by Francois Cartegnie at 2020-03-04T11:44:11+01:00
dvd_reader: use logger

- - - - -
cabd80c8 by Francois Cartegnie at 2020-03-04T11:44:11+01:00
ifo_handle: create real priv data, unexpose dvd_file_t pointer

- - - - -
d9cd1b5f by Francois Cartegnie at 2020-03-04T11:44:11+01:00
ifo_handle: store main context in priv

- - - - -
5ebbd78d by Francois Cartegnie at 2020-03-04T11:44:11+01:00
ifo_read: use logger

- - - - -
7ec273dd by Francois Cartegnie at 2020-03-04T11:44:11+01:00
dvd_udf: replace log occurrences

- - - - -
33e674e4 by Francois Cartegnie at 2020-03-04T11:44:11+01:00
dvd_input: use logger

- - - - -
42374932 by Francois Cartegnie at 2020-03-04T11:44:11+01:00
ifo_print: use logger

- - - - -


14 changed files:

- Makefile.am
- configure.ac
- src/dvd_input.c
- src/dvd_input.h
- src/dvd_reader.c
- src/dvd_udf.c
- src/dvdread/dvd_reader.h
- src/dvdread/ifo_types.h
- src/dvdread_internal.h
- src/ifo_print.c
- src/ifo_read.c
- + src/logger.c
- + src/logger.h
- src/nav_read.c


Changes:

=====================================
Makefile.am
=====================================
@@ -26,6 +26,8 @@ libdvdread_la_SOURCES = \
 	src/dvdread_internal.h \
 	src/ifo_print.c \
 	src/ifo_read.c \
+	src/logger.c \
+	src/logger.h \
 	src/md5.c \
 	src/md5.h \
 	src/nav_print.c \


=====================================
configure.ac
=====================================
@@ -1,7 +1,7 @@
 dnl library version number
 m4_define([dvdread_major], 6)
-m4_define([dvdread_minor], 0)
-m4_define([dvdread_micro], 3)
+m4_define([dvdread_minor], 1)
+m4_define([dvdread_micro], 0)
 m4_define([dvdread_version],[dvdread_major.dvdread_minor.dvdread_micro])
 
 AC_INIT(libdvdread, dvdread_version)
@@ -46,8 +46,8 @@ dnl    are platform dependent
 dnl  * in Linux, the library will be named
 dnl    libname.so.(DVDREAD_LT_CURRENT - DVDREAD_LT_AGE).DVDREAD_LT_REVISION.DVDREAD_LT_AGE
 
-DVDREAD_LT_CURRENT=7
-DVDREAD_LT_AGE=0
+DVDREAD_LT_CURRENT=8
+DVDREAD_LT_AGE=1
 DVDREAD_LT_REVISION=0
 
 AC_SUBST([DVDREAD_LTVERSION], [$DVDREAD_LT_CURRENT:$DVDREAD_LT_REVISION:$DVDREAD_LT_AGE])


=====================================
src/dvd_input.c
=====================================
@@ -24,13 +24,18 @@
 #include <stdlib.h>                              /* free */
 #include <fcntl.h>                               /* open */
 #include <unistd.h>                              /* lseek */
+#include <string.h>                  /* strerror */
+#include <errno.h>
 
 #include "dvdread/dvd_reader.h"      /* DVD_VIDEO_LB_LEN */
+#include "dvdread_internal.h"
 #include "dvd_input.h"
+#include "logger.h"
 
 
 /* The function pointers that is the exported interface of this file. */
-dvd_input_t (*dvdinput_open)  (const char *, void *, dvd_reader_stream_cb *);
+dvd_input_t (*dvdinput_open)  (void *, dvd_logger_cb *,
+                               const char *,dvd_reader_stream_cb *);
 int         (*dvdinput_close) (dvd_input_t);
 int         (*dvdinput_seek)  (dvd_input_t, int);
 int         (*dvdinput_title) (dvd_input_t, int);
@@ -71,41 +76,57 @@ static int      (*DVDcss_read)  (dvdcss_t, void *, int, int);
 struct dvd_input_s {
   /* libdvdcss handle */
   dvdcss_t dvdcss;
+  /* */
+  void *priv;
+  dvd_logger_cb *logcb;
 
   /* dummy file input */
   int fd;
 };
 
+static dvd_input_t dvd_input_New(void *priv, dvd_logger_cb *logcb)
+{
+  dvd_input_t dev = calloc(1, sizeof(*dev));
+  if(dev)
+  {
+      dev->priv = priv;
+      dev->logcb = logcb;
+  }
+  return dev;
+}
 
 /**
  * initialize and open a DVD (device or file or stream_cb)
  */
-static dvd_input_t css_open(const char *target,
-                            void *stream, dvd_reader_stream_cb *stream_cb)
+static dvd_input_t css_open(void *priv, dvd_logger_cb *logcb,
+                            const char *target,
+                            dvd_reader_stream_cb *stream_cb)
 {
   dvd_input_t dev;
 
   /* Allocate the handle structure */
-  dev = malloc(sizeof(*dev));
+  dev = dvd_input_New(priv, logcb);
   if(dev == NULL) {
-    fprintf(stderr, "libdvdread: Could not allocate memory.\n");
+    DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR,
+               "Could not allocate memory.");
     return NULL;
   }
 
   /* Really open it with libdvdcss */
   if(target)
       dev->dvdcss = DVDcss_open(target);
-  else if(stream && stream_cb) {
+  else if(priv && stream_cb) {
 #ifdef HAVE_DVDCSS_DVDCSS_H
-      dev->dvdcss = DVDcss_open_stream(stream, (dvdcss_stream_cb *)stream_cb);
+      dev->dvdcss = DVDcss_open_stream(priv, (dvdcss_stream_cb *)stream_cb);
 #else
       dev->dvdcss = DVDcss_open_stream ?
-                    DVDcss_open_stream(stream, (dvdcss_stream_cb *)stream_cb) :
+                    DVDcss_open_stream(priv, (dvdcss_stream_cb *)stream_cb) :
                     NULL;
 #endif
   }
   if(dev->dvdcss == NULL) {
-    fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target);
+    DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR,
+               "Could not open %s with libdvdcss.", target);
     free(dev);
     return NULL;
   }
@@ -155,8 +176,8 @@ static int css_close(dvd_input_t dev)
 /**
  * initialize and open a DVD device or file.
  */
-static dvd_input_t file_open(const char *target,
-                             void *stream UNUSED,
+static dvd_input_t file_open(void *priv, dvd_logger_cb *logcb,
+                             const char *target,
                              dvd_reader_stream_cb *stream_cb UNUSED)
 {
   dvd_input_t dev;
@@ -164,9 +185,10 @@ static dvd_input_t file_open(const char *target,
   if(target == NULL)
     return NULL;
   /* Allocate the library structure */
-  dev = malloc(sizeof(*dev));
+  dev = dvd_input_New(priv, logcb);
   if(dev == NULL) {
-    fprintf(stderr, "libdvdread: Could not allocate memory.\n");
+    DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR,
+               "Could not allocate memory.");
     return NULL;
   }
 
@@ -177,7 +199,11 @@ static dvd_input_t file_open(const char *target,
   dev->fd = open(target, O_RDONLY | O_BINARY);
 #endif
   if(dev->fd < 0) {
-    perror("libdvdread: Could not open input");
+    char buf[256];
+    if(strerror_r(errno, buf, 256) != 0)
+        *buf=0;
+    DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR,
+               "Could not open input: %s", buf);
     free(dev);
     return NULL;
   }
@@ -235,7 +261,8 @@ static int file_read(dvd_input_t dev, void *buffer, int blocks,
       off_t over_read = -(bytes % DVD_VIDEO_LB_LEN);
       off_t pos = lseek(dev->fd, over_read, SEEK_CUR);
       if(pos % 2048 != 0)
-        fprintf( stderr, "libdvdread: lseek not multiple of 2048! Something is wrong!\n" );
+          DVDReadLog(dev->priv, dev->logcb, DVD_LOGGER_LEVEL_WARN,
+                     "lseek not multiple of 2048! Something is wrong!");
       return (int) (bytes / DVD_VIDEO_LB_LEN);
     }
 
@@ -264,7 +291,7 @@ static int file_close(dvd_input_t dev)
 /**
  * Setup read functions with either libdvdcss or minimal DVD access.
  */
-int dvdinput_setup(void)
+int dvdinput_setup(void *priv, dvd_logger_cb *logcb)
 {
   void *dvdcss_library = NULL;
 
@@ -304,16 +331,17 @@ int dvdinput_setup(void)
       dlsym(dvdcss_library, U_S "dvdcss_read");
 
     if(dlsym(dvdcss_library, U_S "dvdcss_crack")) {
-      fprintf(stderr,
-              "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n"
-              "libdvdread: You should get the latest version from "
-              "http://www.videolan.org/\n" );
+      DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR,
+                 "Old (pre-0.0.2) version of libdvdcss found. "
+                "libdvdread: You should get the latest version from "
+                "http://www.videolan.org/" );
       dlclose(dvdcss_library);
       dvdcss_library = NULL;
     } else if(!DVDcss_open || !DVDcss_close || !DVDcss_seek
               || !DVDcss_read) {
-      fprintf(stderr,  "libdvdread: Missing symbols in %s, "
-              "this shouldn't happen !\n", CSS_LIB);
+      DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_ERROR,
+                 "Missing symbols in %s, "
+                "this shouldn't happen !", CSS_LIB);
       dlclose(dvdcss_library);
       dvdcss_library = NULL;
     }
@@ -337,7 +365,8 @@ int dvdinput_setup(void)
     return 1;
 
   } else {
-    fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n");
+    DVDReadLog(priv, logcb, DVD_LOGGER_LEVEL_WARN,
+               "Encrypted DVD support unavailable.");
 
     /* libdvdcss replacement functions */
     dvdinput_open  = file_open;


=====================================
src/dvd_input.h
=====================================
@@ -55,8 +55,9 @@ typedef struct dvd_input_s *dvd_input_t;
  * Function pointers that will be filled in by the input implementation.
  * These functions provide the main API.
  */
-extern dvd_input_t (*dvdinput_open)  (const char *,
-                                      void *, dvd_reader_stream_cb *);
+extern dvd_input_t (*dvdinput_open)  (void *, dvd_logger_cb *,
+                                      const char *,
+                                      dvd_reader_stream_cb *);
 extern int         (*dvdinput_close) (dvd_input_t);
 extern int         (*dvdinput_seek)  (dvd_input_t, int);
 extern int         (*dvdinput_title) (dvd_input_t, int);
@@ -65,6 +66,6 @@ extern int         (*dvdinput_read)  (dvd_input_t, void *, int, int);
 /**
  * Setup function accessed by dvd_reader.c.  Returns 1 if there is CSS support.
  */
-int dvdinput_setup(void);
+int dvdinput_setup(void *, dvd_logger_cb *);
 
 #endif /* LIBDVDREAD_DVD_INPUT_H */


=====================================
src/dvd_reader.c
=====================================
@@ -174,10 +174,8 @@ static int initAllCSSKeys( dvd_reader_t *ctx )
   if(nokeys_str != NULL)
     return 0;
 
-  fprintf( stderr, "\n" );
-  fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" );
-  fprintf( stderr, "libdvdread: This can take a _long_ time, "
-           "please be patient\n\n" );
+  Log2(ctx,"Attempting to retrieve all CSS keys" );
+  Log2(ctx,"This can take a _long_ time, please be patient" );
   gettimeofday(&all_s, NULL);
 
   for( title = 0; title < 100; title++ ) {
@@ -190,14 +188,12 @@ static int initAllCSSKeys( dvd_reader_t *ctx )
     start = UDFFindFile( ctx, filename, &len );
     if( start != 0 && len != 0 ) {
       /* Perform CSS key cracking for this title. */
-      fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
-               filename, start );
+      Log3(ctx,"Get key for %s at 0x%08x",filename, start );
       if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
-        fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)\n", filename, start);
+        Log1(ctx,"Error cracking CSS key for %s (0x%08x)", filename, start);
       }
       gettimeofday( &t_e, NULL );
-      fprintf( stderr, "libdvdread: Elapsed time %ld\n",
-               (long int) t_e.tv_sec - t_s.tv_sec );
+      Log3(ctx,"Elapsed time %ld", (long int) t_e.tv_sec - t_s.tv_sec );
     }
 
     if( title == 0 ) continue;
@@ -208,21 +204,18 @@ static int initAllCSSKeys( dvd_reader_t *ctx )
     if( start == 0 || len == 0 ) break;
 
     /* Perform CSS key cracking for this title. */
-    fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
-             filename, start );
+    Log3(ctx,"Get key for %s at 0x%08x",filename, start );
     if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
-      fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)!!\n", filename, start);
+      Log1(ctx,"Error cracking CSS key for %s (0x%08x)", filename, start);
     }
     gettimeofday( &t_e, NULL );
-    fprintf( stderr, "libdvdread: Elapsed time %ld\n",
-             (long int) t_e.tv_sec - t_s.tv_sec );
+    Log3(ctx,"Elapsed time %ld", (long int) t_e.tv_sec - t_s.tv_sec );
   }
   title--;
 
-  fprintf( stderr, "libdvdread: Found %d VTS's\n", title );
+  Log3(ctx,"Found %d VTS's", title );
   gettimeofday(&all_e, NULL);
-  fprintf( stderr, "libdvdread: Elapsed time %ld\n",
-           (long int) all_e.tv_sec - all_s.tv_sec );
+  Log3(ctx,"Elapsed time %ld", (long int) all_e.tv_sec - all_s.tv_sec );
 
   return 0;
 }
@@ -232,17 +225,17 @@ static int initAllCSSKeys( dvd_reader_t *ctx )
 /**
  * Open a DVD image or block device file or use stream_cb functions.
  */
-static dvd_reader_device_t *DVDOpenImageFile( const char *location,
-                                       void *stream,
-                                       dvd_reader_stream_cb *stream_cb,
+static dvd_reader_device_t *DVDOpenImageFile( dvd_reader_t *ctx,
+                                              const char *location,
+                                        dvd_reader_stream_cb *stream_cb,
                                        int have_css )
 {
   dvd_reader_device_t *dvd;
   dvd_input_t dev;
 
-  dev = dvdinput_open( location, stream, stream_cb );
+  dev = dvdinput_open( ctx->priv, &ctx->logcb, location, stream_cb );
   if( !dev ) {
-    fprintf( stderr, "libdvdread: Can't open %s for reading\n", location );
+    Log0(ctx,"Can't open %s for reading", location );
     return NULL;
   }
 
@@ -337,8 +330,9 @@ static char *bsd_block2char( const char *path )
 }
 #endif
 
-static dvd_reader_t *DVDOpenCommon( const char *ppath,
-                                    void *stream,
+static dvd_reader_t *DVDOpenCommon( void *priv,
+                                    const dvd_logger_cb *logcb,
+                                    const char *ppath,
                                     dvd_reader_stream_cb *stream_cb )
 {
   struct stat fileinfo;
@@ -349,15 +343,19 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
   if(!ctx)
       return NULL;
 
+  ctx->priv = priv;
+  if(logcb)
+    ctx->logcb = *logcb;
+
 #if defined(_WIN32) || defined(__OS2__)
       int len;
 #endif
 
   /* Try to open DVD using stream_cb functions */
-  if( stream != NULL && stream_cb != NULL )
+  if( priv != NULL && stream_cb != NULL )
   {
-    have_css = dvdinput_setup();
-    ctx->rd = DVDOpenImageFile( NULL, stream, stream_cb, have_css );
+    have_css = dvdinput_setup( ctx->priv, &ctx->logcb );
+    ctx->rd = DVDOpenImageFile( ctx, NULL, stream_cb, have_css );
     if(!ctx->rd)
     {
         free(ctx);
@@ -374,7 +372,7 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
     goto DVDOpen_error;
 
   /* Try to open libdvdcss or fall back to standard functions */
-  have_css = dvdinput_setup();
+  have_css = dvdinput_setup( ctx->priv, &ctx->logcb );
 
 #if defined(_WIN32) || defined(__OS2__)
   /* Strip off the trailing \ if it is not a drive */
@@ -393,7 +391,7 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
 
     /* maybe "host:port" url? try opening it with acCeSS library */
     if( strchr(path,':') ) {
-      ctx->rd = DVDOpenImageFile( path, NULL, NULL, have_css );
+      ctx->rd = DVDOpenImageFile( ctx, path, NULL, have_css );
       free(path);
       if(!ctx->rd)
       {
@@ -404,7 +402,7 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
     }
 
     /* If we can't stat the file, give up */
-    fprintf( stderr, "libdvdread: Can't stat %s\n", path );
+    Log0(ctx, "Can't stat %s", path );
     perror("");
     goto DVDOpen_error;
   }
@@ -426,7 +424,7 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
 #endif
     if(!dev_name)
         goto DVDOpen_error;
-    ctx->rd = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
+    ctx->rd = DVDOpenImageFile( ctx, dev_name, NULL, have_css );
     free( dev_name );
     free(path);
     if(!ctx->rd)
@@ -517,12 +515,11 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
         for (i=0; i<r; i++) {
             if (!strcmp(path_copy, s[i].f_mntonname)) {
                 dev_name = bsd_block2char(s[i].f_mntfromname);
-                fprintf( stderr,
-                        "libdvdread: Attempting to use device %s"
-                        " mounted on %s for CSS authentication\n",
+                Log3(ctx, "Attempting to use device %s"
+                          " mounted on %s for CSS authentication",
                         dev_name,
                         s[i].f_mntonname);
-                ctx->rd = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
+                ctx->rd = DVDOpenImageFile( ctx, dev_name, NULL, have_css );
                 break;
             }
         }
@@ -530,12 +527,11 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
 #elif defined(SYS_BSD)
     if( ( fe = getfsfile( path_copy ) ) ) {
       dev_name = bsd_block2char( fe->fs_spec );
-      fprintf( stderr,
-               "libdvdread: Attempting to use device %s"
-               " mounted on %s for CSS authentication\n",
+      Log3(ctx, "Attempting to use device %s"
+               " mounted on %s for CSS authentication",
                dev_name,
                fe->fs_file );
-      ctx->rd = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
+      ctx->rd = DVDOpenImageFile( ctx, dev_name, NULL, have_css );
     }
 #elif defined(__sun)
     mntfile = fopen( MNTTAB, "r" );
@@ -546,12 +542,11 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
       while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
         if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
           dev_name = sun_block2char( mp.mnt_special );
-          fprintf( stderr,
-                   "libdvdread: Attempting to use device %s"
-                   " mounted on %s for CSS authentication\n",
+          Log3(ctx, "Attempting to use device %s"
+                   " mounted on %s for CSS authentication",
                    dev_name,
                    mp.mnt_mountp );
-          ctx->rd = DVDOpenImageFile( dev_name, NULL, NULL, have_css );
+          ctx->rd = DVDOpenImageFile( ctx, dev_name, NULL, have_css );
           break;
         }
       }
@@ -570,12 +565,11 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
       while( ( me = getmntent( mntfile ) ) ) {
 #endif
         if( !strcmp( me->mnt_dir, path_copy ) ) {
-          fprintf( stderr,
-                   "libdvdread: Attempting to use device %s"
-                   " mounted on %s for CSS authentication\n",
+          Log3(ctx, "Attempting to use device %s"
+                   " mounted on %s for CSS authentication",
                    me->mnt_fsname,
                    me->mnt_dir );
-          ctx->rd = DVDOpenImageFile( me->mnt_fsname, NULL, NULL, have_css );
+          ctx->rd = DVDOpenImageFile( ctx, me->mnt_fsname, NULL, have_css );
           dev_name = strdup(me->mnt_fsname);
           break;
         }
@@ -589,20 +583,20 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
         ( !path[2] ||
           ((path[2] == '\\' || path[2] == '/') && !path[3])))
 #endif
-    ctx->rd = DVDOpenImageFile( path, NULL, NULL, have_css );
+    ctx->rd = DVDOpenImageFile( ctx, path, NULL, have_css );
 #endif
 
 #if !defined(_WIN32) && !defined(__OS2__)
     if( !dev_name ) {
-      fprintf( stderr, "libdvdread: Couldn't find device name.\n" );
+      Log0(ctx, "Couldn't find device name." );
     } else if( !ctx->rd ) {
-      fprintf( stderr, "libdvdread: Device %s inaccessible, "
-               "CSS authentication not available.\n", dev_name );
+      Log0(ctx, "Device %s inaccessible, "
+                "CSS authentication not available.", dev_name );
     }
 #else
     if( !ctx->rd ) {
-        fprintf( stderr, "libdvdread: Device %s inaccessible, "
-                 "CSS authentication not available.\n", path );
+        Log0(ctx, "Device %s inaccessible, "
+                 "CSS authentication not available.", path );
     }
 #endif
 
@@ -634,7 +628,7 @@ static dvd_reader_t *DVDOpenCommon( const char *ppath,
 
 DVDOpen_error:
   /* If it's none of the above, screw it. */
-  fprintf( stderr, "libdvdread: Could not open %s\n", path );
+  Log0(ctx, "Could not open %s", path );
   free( path );
   free( path_copy );
   if ( cdir >= 0 )
@@ -645,13 +639,25 @@ DVDOpen_error:
 
 dvd_reader_t *DVDOpen( const char *ppath )
 {
-    return DVDOpenCommon( ppath, NULL, NULL );
+    return DVDOpenCommon( NULL, NULL, ppath, NULL );
 }
 
 dvd_reader_t *DVDOpenStream( void *stream,
                              dvd_reader_stream_cb *stream_cb )
 {
-    return DVDOpenCommon( NULL, stream, stream_cb );
+    return DVDOpenCommon( stream, NULL, NULL, stream_cb );
+}
+
+dvd_reader_t *DVDOpen2( void *priv, const dvd_logger_cb *logcb,
+                        const char *ppath )
+{
+    return DVDOpenCommon( priv, logcb, ppath, NULL );
+}
+
+dvd_reader_t *DVDOpenStream2( void *priv, const dvd_logger_cb *logcb,
+                              dvd_reader_stream_cb *stream_cb )
+{
+    return DVDOpenCommon( priv, logcb, NULL, stream_cb );
 }
 
 void DVDClose( dvd_reader_t *dvd )
@@ -676,13 +682,13 @@ static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *ctx, const char *filename,
 
   start = UDFFindFile( ctx, filename, &len );
   if( !start ) {
-    fprintf( stderr, "libdvdread:DVDOpenFileUDF:UDFFindFile %s failed\n", filename );
+    Log0(ctx, "DVDOpenFileUDF:UDFFindFile %s failed", filename );
     return NULL;
   }
 
   dvd_file = calloc( 1, sizeof( dvd_file_t ) );
   if( !dvd_file ) {
-    fprintf( stderr, "libdvdread:DVDOpenFileUDF:malloc failed\n" );
+    Log0(ctx, "DVDOpenFileUDF:malloc failed" );
     return NULL;
   }
   dvd_file->ctx = ctx;
@@ -781,26 +787,26 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *ctx, const char *filename )
 
   /* Get the full path of the file. */
   if( !findDVDFile( ctx, filename, full_path ) ) {
-    fprintf( stderr, "libdvdread:DVDOpenFilePath:findDVDFile %s failed\n", filename );
+    Log0(ctx, "DVDOpenFilePath:findDVDFile %s failed", filename );
     return NULL;
   }
 
-  dev = dvdinput_open( full_path, NULL, NULL );
+  dev = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL );
   if( !dev ) {
-    fprintf( stderr, "libdvdread:DVDOpenFilePath:dvdinput_open %s failed\n", full_path );
+    Log0(ctx, "DVDOpenFilePath:dvdinput_open %s failed", full_path );
     return NULL;
   }
 
   dvd_file = calloc( 1, sizeof( dvd_file_t ) );
   if( !dvd_file ) {
-    fprintf( stderr, "libdvdread:DVDOpenFilePath:dvd_file malloc failed\n" );
+    Log0(ctx, "DVDOpenFilePath:dvd_file malloc failed" );
     dvdinput_close(dev);
     return NULL;
   }
   dvd_file->ctx = ctx;
 
   if( stat( full_path, &fileinfo ) < 0 ) {
-    fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+    Log0(ctx, "Can't stat() %s.", filename );
     free( dvd_file );
     dvdinput_close( dev );
     return NULL;
@@ -850,8 +856,7 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *ctx, int title, int menu )
   }
   /*
   if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) {
-      fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
-               filename );
+      Log0(ctx, "Error cracking CSS key for %s", filename );
   }
   */
 
@@ -883,14 +888,14 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *ctx, int title, int menu )
       return NULL;
     }
 
-    dev = dvdinput_open( full_path, NULL, NULL );
+    dev = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL );
     if( dev == NULL ) {
       free( dvd_file );
       return NULL;
     }
 
     if( stat( full_path, &fileinfo ) < 0 ) {
-      fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+      Log0(ctx, "Can't stat() %s.", filename );
       dvdinput_close(dev);
       free( dvd_file );
       return NULL;
@@ -911,12 +916,12 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *ctx, int title, int menu )
       }
 
       if( stat( full_path, &fileinfo ) < 0 ) {
-        fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+        Log0(ctx, "Can't stat() %s.", filename );
         break;
       }
 
       dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
-      dvd_file->title_devs[ i ] = dvdinput_open( full_path, NULL, NULL );
+      dvd_file->title_devs[ i ] = dvdinput_open( ctx->priv, &ctx->logcb, full_path, NULL );
       dvdinput_title( dvd_file->title_devs[ i ], 0 );
       dvd_file->filesize += dvd_file->title_sizes[ i ];
     }
@@ -973,7 +978,7 @@ dvd_file_t *DVDOpenFile( dvd_reader_t *ctx, int titlenum,
     }
     break;
   default:
-    fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
+    Log1(ctx, "Invalid domain for file open." );
     return NULL;
   }
 
@@ -1069,7 +1074,7 @@ static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title,
     return -1;
 
   if( stat( full_path, &fileinfo ) < 0 ) {
-    fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+    Log1(dvd, "Can't stat() %s.", filename );
     return -1;
   }
 
@@ -1085,7 +1090,7 @@ static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title,
         break;
 
       if( stat( full_path, &fileinfo ) < 0 ) {
-        fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+        Log1(dvd, "Can't stat() %s.", filename );
         break;
       }
 
@@ -1151,7 +1156,7 @@ int DVDFileStat( dvd_reader_t *reader, int titlenum,
 
     break;
   default:
-    fprintf( stderr, "libdvdread: Invalid domain for file stat.\n" );
+    Log1(reader, "Invalid domain for file stat." );
     errno = EINVAL;
     return -1;
   }
@@ -1168,7 +1173,7 @@ int DVDFileStat( dvd_reader_t *reader, int titlenum,
 
     if( findDVDFile( reader, filename, full_path ) ) {
       if( stat( full_path, &fileinfo ) < 0 )
-        fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+        Log1(reader, "Can't stat() %s.", filename );
       else {
         statbuf->size = fileinfo.st_size;
         statbuf->nr_parts = 1;
@@ -1188,13 +1193,13 @@ int InternalUDFReadBlocksRaw( const dvd_reader_t *ctx, uint32_t lb_number,
   int ret;
 
   if( !ctx->rd->dev ) {
-    fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
+    Log0(ctx, "Fatal error in block read." );
     return -1;
   }
 
   ret = dvdinput_seek( ctx->rd->dev, (int) lb_number );
   if( ret != (int) lb_number ) {
-    fprintf( stderr, "libdvdread: Can't seek to block %u\n", lb_number );
+    Log1(ctx, "Can't seek to block %u", lb_number );
     return ret;
   }
 
@@ -1244,6 +1249,7 @@ static int DVDReadBlocksPath( const dvd_file_t *dvd_file, unsigned int offset,
                               size_t block_count, unsigned char *data,
                               int encrypted )
 {
+  const dvd_reader_t *ctx = dvd_file->ctx;
   int i;
   int ret, ret2, off;
 
@@ -1256,8 +1262,7 @@ static int DVDReadBlocksPath( const dvd_file_t *dvd_file, unsigned int offset,
       if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
         off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
         if( off < 0 || off != (int)offset ) {
-          fprintf( stderr, "libdvdread: Can't seek to block %u\n",
-                   offset );
+          Log1(ctx, "Can't seek to block %u", offset );
           return off < 0 ? off : 0;
         }
         ret = dvdinput_read( dvd_file->title_devs[ i ], data,
@@ -1271,8 +1276,7 @@ static int DVDReadBlocksPath( const dvd_file_t *dvd_file, unsigned int offset,
         /* Read part 1 */
         off = dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
         if( off < 0 || off != (int)offset ) {
-          fprintf( stderr, "libdvdread: Can't seek to block %u\n",
-                   offset );
+          Log1(ctx, "Can't seek to block %u", offset );
           return off < 0 ? off : 0;
         }
         ret = dvdinput_read( dvd_file->title_devs[ i ], data,
@@ -1288,8 +1292,7 @@ static int DVDReadBlocksPath( const dvd_file_t *dvd_file, unsigned int offset,
         /* Read part 2 */
         off = dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 );
         if( off < 0 || off != 0 ) {
-          fprintf( stderr, "libdvdread: Can't seek to block %d\n",
-                   0 );
+          Log1(ctx, "Can't seek to block %d", 0 );
           return off < 0 ? off : 0;
         }
         ret2 = dvdinput_read( dvd_file->title_devs[ i + 1 ],
@@ -1371,7 +1374,7 @@ int DVDFileSeekForce(dvd_file_t *dvd_file, int offset, int force_size)
       dvd_file->filesize = force_size;
       free(dvd_file->cache);
       dvd_file->cache = NULL;
-      fprintf(stderr, "libdvdread: Ignored size of file indicated in UDF.\n");
+      Log2(ctx, "Ignored size of file indicated in UDF.");
     }
   }
 
@@ -1402,8 +1405,7 @@ ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
 
   secbuf_base = malloc( numsec * DVD_VIDEO_LB_LEN + 2048 );
   if( !secbuf_base ) {
-    fprintf( stderr, "libdvdread: Can't allocate memory "
-             "for file read!\n" );
+    Log0(ctx, "Can't allocate memory for file read" );
     return 0;
   }
   secbuf = (unsigned char *)(((uintptr_t)secbuf_base & ~((uintptr_t)2047)) + 2048);
@@ -1451,8 +1453,7 @@ int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
 
   vmg_ifo = ifoOpen( dvd, 0 );
   if( !vmg_ifo ) {
-    fprintf( stderr, "libdvdread: DVDDiscId, failed to "
-      "open VMG IFO!\n" );
+    Log0(dvd, "DVDDiscId, failed to open VMG IFO" );
     return -1;
   }
 
@@ -1474,8 +1475,7 @@ int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
 
       if( buffer_base == NULL ) {
           DVDCloseFile( dvd_file );
-          fprintf( stderr, "libdvdread: DVDDiscId, failed to "
-                   "allocate memory for file read!\n" );
+          Log0(dvd, "DVDDiscId, failed to allocate memory for file read" );
           return -1;
       }
 
@@ -1483,8 +1483,8 @@ int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
 
       bytes_read = DVDReadBytes( dvd_file, buffer, file_size );
       if( bytes_read != file_size ) {
-          fprintf( stderr, "libdvdread: DVDDiscId read returned %zd bytes"
-                   ", wanted %zd\n", bytes_read, file_size );
+          Log1(dvd, "DVDDiscId read returned %zd bytes"
+                   ", wanted %zd", bytes_read, file_size );
           DVDCloseFile( dvd_file );
           free( buffer_base );
           return -1;
@@ -1526,8 +1526,8 @@ int DVDISOVolumeInfo( dvd_reader_t *ctx,
   buffer_base = malloc( DVD_VIDEO_LB_LEN + 2048 );
 
   if( buffer_base == NULL ) {
-    fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
-             "allocate memory for file read!\n" );
+    Log0(ctx, "DVDISOVolumeInfo, failed to "
+             "allocate memory for file read" );
     return -1;
   }
 
@@ -1535,8 +1535,8 @@ int DVDISOVolumeInfo( dvd_reader_t *ctx,
 
   ret = InternalUDFReadBlocksRaw( ctx, 16, 1, buffer, 0 );
   if( ret != 1 ) {
-    fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
-             "read ISO9660 Primary Volume Descriptor!\n" );
+    Log0(ctx, "DVDISOVolumeInfo, failed to "
+             "read ISO9660 Primary Volume Descriptor" );
     free( buffer_base );
     return -1;
   }


=====================================
src/dvd_udf.c
=====================================
@@ -232,7 +232,7 @@ static int SetUDFCache(dvd_reader_t *ctx, UDFCacheType type,
 
   if(c == NULL) {
     c = calloc(1, sizeof(struct udf_cache));
-    /* fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); */
+    /* Log3(ctx, "calloc: %d", sizeof(struct udf_cache)); */
     if(c == NULL)
       return 0;
     SetUDFCacheHandle(ctx, c);
@@ -269,7 +269,7 @@ static int SetUDFCache(dvd_reader_t *ctx, UDFCacheType type,
     c->lb_num++;
     tmp = realloc(c->lbs, c->lb_num * sizeof(struct lbudf));
     /*
-    fprintf(stderr, "realloc lb: %d * %d = %d\n",
+    Log3(ctx, "realloc lb: %d * %d = %d",
     c->lb_num, sizeof(struct lbudf),
     c->lb_num * sizeof(struct lbudf));
     */
@@ -295,7 +295,7 @@ static int SetUDFCache(dvd_reader_t *ctx, UDFCacheType type,
     c->map_num++;
     tmp = realloc(c->maps, c->map_num * sizeof(struct icbmap));
     /*
-    fprintf(stderr, "realloc maps: %d * %d = %d\n",
+    Log3(ctx, "realloc maps: %d * %d = %d\n",
       c->map_num, sizeof(struct icbmap),
       c->map_num * sizeof(struct icbmap));
     */
@@ -600,7 +600,7 @@ static int UDFScanDir( dvd_reader_t *ctx, struct AD Dir, char *FileName,
       }
       /*
       if(cached_dir) {
-        fprintf(stderr, "malloc dir: %d\n",  dir_lba * DVD_VIDEO_LB_LEN);
+        Log3(ctx, "malloc dir: %d",  dir_lba * DVD_VIDEO_LB_LEN);
       }
       */
       {


=====================================
src/dvdread/dvd_reader.h
=====================================
@@ -32,6 +32,7 @@
 
 #include <sys/types.h>
 #include <inttypes.h>
+#include <stdarg.h>
 
 /**
  * The DVD access interface.
@@ -78,6 +79,27 @@ struct dvd_reader_stream_cb
 };
 typedef struct dvd_reader_stream_cb dvd_reader_stream_cb;
 
+/**
+ * Custom logger callback for DVDOpen[Stream]2
+ * @param private Handle as provided in Open functions
+ * @param level Log level
+ * @param fmt Format string
+ * @param args Arguments list
+ * pf_log(priv, level, fmt, args);
+ */
+typedef enum
+{
+    DVD_LOGGER_LEVEL_INFO,
+    DVD_LOGGER_LEVEL_ERROR,
+    DVD_LOGGER_LEVEL_WARN,
+    DVD_LOGGER_LEVEL_DEBUG,
+} dvd_logger_level_t;
+
+typedef struct
+{
+  void ( *pf_log )  ( void *, dvd_logger_level_t, const char *, va_list );
+} dvd_logger_cb;
+
 /**
  * Public type that is used to provide statistics on a handle.
  */
@@ -117,6 +139,21 @@ typedef struct {
 dvd_reader_t *DVDOpen( const char * );
 dvd_reader_t *DVDOpenStream( void *, dvd_reader_stream_cb * );
 
+/**
+ * Same as DVDOpen, but with private handle to be passed back on callbacks
+ *
+ * @param path Specifies the the device, file or directory to be used.
+ * @param priv is a private handle
+ * @param logcb is a custom logger callback struct, or NULL if none needed
+ * @param stream_cb is a struct containing seek and read functions
+ * @return If successful a a read handle is returned. Otherwise 0 is returned.
+ *
+ * dvd = DVDOpen2(priv, logcb, path);
+ * dvd = DVDOpenStream2(priv, logcb, &stream_cb);
+ */
+dvd_reader_t *DVDOpen2( void *, const dvd_logger_cb *, const char * );
+dvd_reader_t *DVDOpenStream2( void *, const dvd_logger_cb *, dvd_reader_stream_cb * );
+
 /**
  * Closes and cleans up the DVD reader object.
  *


=====================================
src/dvdread/ifo_types.h
=====================================
@@ -732,8 +732,6 @@ typedef struct {
  * is read in from the VTS_XX_0.[IFO,BUP] files.
  */
 typedef struct {
-  dvd_file_t *file;
-
   /* VMGI */
   vmgi_mat_t     *vmgi_mat;
   tt_srpt_t      *tt_srpt;


=====================================
src/dvdread_internal.h
=====================================
@@ -20,6 +20,7 @@
 #define LIBDVDREAD_DVDREAD_INTERNAL_H
 
 #include <stdint.h>
+#include <stddef.h>
 #include <sys/types.h>
 
 #ifdef _WIN32
@@ -27,22 +28,29 @@
 #endif /* _WIN32 */
 
 #include "dvdread/dvd_reader.h"
+#include "dvdread/ifo_types.h"
+#include "logger.h"
 
-#define CHECK_VALUE(arg)                                                \
-  if(!(arg)) {                                                          \
-    fprintf(stderr, "\n*** libdvdread: CHECK_VALUE failed in %s:%i ***" \
-                    "\n*** for %s ***\n\n",                             \
-            __FILE__, __LINE__, # arg );                                \
-  }
+#define container_of(ptr, type, member) \
+    ((type *)(((char *)(ptr)) - offsetof(type, member)))
 
 struct dvd_reader_s
 {
     dvd_reader_device_t *rd;
+    void *priv; /* User provided context */
+    dvd_logger_cb logcb;
     /* Set 100 flags for BUP fallback, most signifiant left
        [0] for upper remaining VTS, [1] for the first Main + 63 VTS */
     uint64_t ifoBUPflags[2];
 };
 
+struct ifo_handle_private_s
+{
+    ifo_handle_t handle;
+    dvd_reader_t *ctx;
+    dvd_file_t *file;
+};
+
 enum TagIdentifier {
   /* ECMA 167 3/7.2.1 */
   PrimaryVolumeDescriptor           = 1,


=====================================
src/ifo_print.c
=====================================
@@ -28,6 +28,8 @@
 #include "dvdread/ifo_types.h"
 #include "dvdread/ifo_read.h"
 #include "dvdread/ifo_print.h"
+#include "dvdread_internal.h"
+#include "logger.h"
 
 /* Put this in some other file / package?  It's used in nav_print too. */
 static void ifo_print_time(dvd_time_t *dtime) {
@@ -1083,7 +1085,7 @@ void ifo_print(dvd_reader_t *dvd, int title) {
   printf("Local ifo_print\n");
   ifohandle = ifoOpen(dvd, title);
   if(!ifohandle) {
-    fprintf(stderr, "Can't open info file for title %d\n", title);
+    Log0(dvd,  "Can't open info file for title %d", title);
     return;
   }
 


=====================================
src/ifo_read.c
=====================================
@@ -38,20 +38,37 @@
 #define DVD_BLOCK_LEN 2048
 #endif
 
+#define PRIV(a) container_of(a, struct ifo_handle_private_s, handle)
+
+#define CHECK_VALUE(arg)\
+  if(!(arg)) {\
+    Log1(ifop->ctx, "CHECK_VALUE failed in %s:%i for %s",\
+                __FILE__, __LINE__, # arg );\
+  }
+
 #ifndef NDEBUG
+static inline char * makehexdump(const uint8_t *p_CZ, size_t i_CZ)
+{
+  char *alloc = malloc(i_CZ * 2 + 1);
+  if(alloc)
+  {
+    *alloc = 0;
+    for(size_t i = 0; i < i_CZ; i++)
+        sprintf(&alloc[i*2], "%02x", *((uint8_t*)&p_CZ[i]));
+  }
+  return alloc;
+}
 #define CHECK_ZERO0(arg)                                                \
   if(arg != 0) {                                                        \
-    fprintf(stderr, "*** Zero check failed in %s:%i\n    for %s = 0x%x\n", \
+    Log1(ifop->ctx, "Zero check failed in %s:%i\n    for %s = 0x%x",    \
             __FILE__, __LINE__, # arg, arg);                            \
   }
 #define CHECK_ZERO(arg)                                                 \
   if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) {                    \
-    unsigned int i_CZ;                                                  \
-    fprintf(stderr, "*** Zero check failed in %s:%i\n    for %s = 0x",  \
-            __FILE__, __LINE__, # arg );                                \
-    for(i_CZ = 0; i_CZ < sizeof(arg); i_CZ++)                           \
-      fprintf(stderr, "%02x", *((uint8_t *)&arg + i_CZ));               \
-    fprintf(stderr, "\n");                                              \
+    char *dump = makehexdump((const uint8_t *)&arg, sizeof(arg));       \
+    Log0(ifop->ctx, "Zero check failed in %s:%i for %s : 0x%s",         \
+            __FILE__, __LINE__, # arg, dump );                          \
+    free(dump);                                                         \
   }
 static const uint8_t my_friendly_zeros[2048];
 #else
@@ -290,19 +307,20 @@ static void free_ptl_mait(ptl_mait_t* ptl_mait, int num_entries) {
 
 static ifo_handle_t *ifoOpenFileOrBackup(dvd_reader_t *ctx, int title,
                                          int backup) {
-  ifo_handle_t *ifofile;
+  struct ifo_handle_private_s *ifop;
   dvd_read_domain_t domain = backup ? DVD_READ_INFO_BACKUP_FILE
                                     : DVD_READ_INFO_FILE;
   char ifo_filename[13];
 
-  ifofile = calloc(1, sizeof(ifo_handle_t));
-  if(!ifofile)
+  ifop = calloc(1, sizeof(*ifop));
+  if(!ifop)
     return NULL;
 
-  ifofile->file = DVDOpenFile(ctx, title, domain);
-  if(!ifofile->file)
+  ifop->ctx = ctx;
+  ifop->file = DVDOpenFile(ctx, title, domain);
+  if(!ifop->file)
   {
-      free(ifofile);
+      free(ifop);
       return NULL;
   }
 
@@ -311,12 +329,13 @@ static ifo_handle_t *ifoOpenFileOrBackup(dvd_reader_t *ctx, int title,
   else
     snprintf(ifo_filename, 13, "VIDEO_TS.%s", backup ? "BUP" : "IFO");
 
-  if(!ifofile->file) {
-    fprintf(stderr, "libdvdread: Can't open file %s.\n", ifo_filename);
-    free(ifofile);
+  if(!ifop->file) {
+    Log1(ctx, "Can't open file %s.", ifo_filename);
+    free(ifop);
     return NULL;
   }
 
+  ifo_handle_t *ifofile = &ifop->handle;
   /* First check if this is a VMGI file. */
   if(ifoRead_VMG(ifofile)) {
 
@@ -355,7 +374,7 @@ static ifo_handle_t *ifoOpenFileOrBackup(dvd_reader_t *ctx, int title,
   }
 
 ifoOpen_fail:
-  fprintf(stderr, "libdvdread: Invalid IFO for title %d (%s).\n", title, ifo_filename);
+  Log1(ctx, "Invalid IFO for title %d (%s).", title, ifo_filename);
   ifoClose(ifofile);
   return NULL;
 }
@@ -393,66 +412,68 @@ ifo_handle_t *ifoOpen(dvd_reader_t *ctx, int title) {
 }
 
 ifo_handle_t *ifoOpenVMGI(dvd_reader_t *ctx) {
-  ifo_handle_t *ifofile;
+  struct ifo_handle_private_s *ifop;
 
   for(int backup = ifoGetBupFlag(ctx, 0); backup <= 1; backup++)
   {
-    ifofile = calloc(1, sizeof(ifo_handle_t));
-    if(!ifofile)
+    ifop = calloc(1, sizeof(*ifop));
+    if(!ifop)
       return NULL;
 
     const dvd_read_domain_t domain = backup ? DVD_READ_INFO_BACKUP_FILE
                                             : DVD_READ_INFO_FILE;
     const char *ext = backup ? "BUP" : "IFO";
 
-    ifofile->file = DVDOpenFile(ctx, 0, domain);
-    if(!ifofile->file) { /* Should really catch any error */
-      fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.%s.\n", ext);
-      free(ifofile);
+    ifop->ctx = ctx;
+    ifop->file = DVDOpenFile(ctx, 0, domain);
+    if(!ifop->file) { /* Should really catch any error */
+      Log1(ctx, "Can't open file VIDEO_TS.%s.", ext);
+      free(ifop);
       return NULL;
     }
 
-    if(ifoRead_VMG(ifofile))
-      return ifofile;
+    if(ifoRead_VMG(&ifop->handle))
+      return &ifop->handle;
 
-    fprintf(stderr, "libdvdread,ifoOpenVMGI(): Invalid main menu IFO (VIDEO_TS.%s).\n", ext);
-    ifoClose(ifofile);
+    Log1(ctx, "ifoOpenVMGI(): Invalid main menu IFO (VIDEO_TS.%s).", ext);
+    ifoClose(&ifop->handle);
   }
   return NULL;
 }
 
 
 ifo_handle_t *ifoOpenVTSI(dvd_reader_t *ctx, int title) {
-  ifo_handle_t *ifofile;
+  struct ifo_handle_private_s *ifop;
 
   if(title <= 0 || title > 99) {
-    fprintf(stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", title);
+    Log1(ctx, "ifoOpenVTSI invalid title (%d).", title);
     return NULL;
   }
 
   for(int backup = ifoGetBupFlag(ctx, title); backup <= 1; backup++)
   {
-    ifofile = calloc(1, sizeof(ifo_handle_t));
-    if(!ifofile)
+    ifop = calloc(1, sizeof(*ifop));
+    if(!ifop)
       return NULL;
 
     const dvd_read_domain_t domain = backup ? DVD_READ_INFO_BACKUP_FILE
                                             : DVD_READ_INFO_FILE;
     const char *ext = backup ? "BUP" : "IFO";
-    ifofile->file = DVDOpenFile(ctx, title, domain);
+    ifop->ctx = ctx;
+    ifop->file = DVDOpenFile(ctx, title, domain);
     /* Should really catch any error */
-    if(!ifofile->file) {
-      fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n", title, ext);
-      free(ifofile);
+    if(!ifop->file) {
+      Log1(ctx, "Can't open file VTS_%02d_0.%s.", title, ext);
+      free(ifop);
       continue;
     }
 
-    if(ifoRead_VTS(ifofile) && ifofile->vtsi_mat)
-      return ifofile;
+    if(ifoRead_VTS(&ifop->handle) && ifop->handle.vtsi_mat)
+      return &ifop->handle;
 
-    fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.%s).\n",
+    Log1(ctx, "Invalid IFO for title %d (VTS_%02d_0.%s).",
             title, title, ext);
-    ifoClose(ifofile);
+    ifoClose(&ifop->handle);
   }
 
   return NULL;
@@ -483,14 +504,14 @@ void ifoClose(ifo_handle_t *ifofile) {
   if(ifofile->vtsi_mat)
     free(ifofile->vtsi_mat);
 
-  DVDCloseFile(ifofile->file);
-  ifofile->file = 0;
-  free(ifofile);
-  ifofile = 0;
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
+  DVDCloseFile(ifop->file);
+  free(ifop);
 }
 
 
 static int ifoRead_VMG(ifo_handle_t *ifofile) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   vmgi_mat_t *vmgi_mat;
 
   vmgi_mat = calloc(1, sizeof(vmgi_mat_t));
@@ -499,13 +520,13 @@ static int ifoRead_VMG(ifo_handle_t *ifofile) {
 
   ifofile->vmgi_mat = vmgi_mat;
 
-  if(!DVDFileSeek_(ifofile->file, 0)) {
+  if(!DVDFileSeek_(ifop->file, 0)) {
     free(ifofile->vmgi_mat);
     ifofile->vmgi_mat = NULL;
     return 0;
   }
 
-  if(!DVDReadBytes(ifofile->file, vmgi_mat, sizeof(vmgi_mat_t))) {
+  if(!DVDReadBytes(ifop->file, vmgi_mat, sizeof(vmgi_mat_t))) {
     free(ifofile->vmgi_mat);
     ifofile->vmgi_mat = NULL;
     return 0;
@@ -584,6 +605,7 @@ static int ifoRead_VMG(ifo_handle_t *ifofile) {
 
 
 static int ifoRead_VTS(ifo_handle_t *ifofile) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   vtsi_mat_t *vtsi_mat;
   int i;
 
@@ -593,13 +615,13 @@ static int ifoRead_VTS(ifo_handle_t *ifofile) {
 
   ifofile->vtsi_mat = vtsi_mat;
 
-  if(!DVDFileSeek_(ifofile->file, 0)) {
+  if(!DVDFileSeek_(ifop->file, 0)) {
     free(ifofile->vtsi_mat);
     ifofile->vtsi_mat = NULL;
     return 0;
   }
 
-  if(!(DVDReadBytes(ifofile->file, vtsi_mat, sizeof(vtsi_mat_t)))) {
+  if(!(DVDReadBytes(ifop->file, vtsi_mat, sizeof(vtsi_mat_t)))) {
     free(ifofile->vtsi_mat);
     ifofile->vtsi_mat = NULL;
     return 0;
@@ -701,11 +723,11 @@ static int ifoRead_VTS(ifo_handle_t *ifofile) {
 static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
                                    pgc_command_tbl_t *cmd_tbl,
                                    unsigned int offset) {
-
-  if(!DVDFileSeek_(ifofile->file, offset))
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
+  if(!DVDFileSeek_(ifop->file, offset))
     return 0;
 
-  if(!(DVDReadBytes(ifofile->file, cmd_tbl, PGC_COMMAND_TBL_SIZE)))
+  if(!(DVDReadBytes(ifop->file, cmd_tbl, PGC_COMMAND_TBL_SIZE)))
     return 0;
 
   B2N_16(cmd_tbl->nr_of_pre);
@@ -720,7 +742,7 @@ static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
     if(!cmd_tbl->pre_cmds)
       return 0;
 
-    if(!(DVDReadBytes(ifofile->file, cmd_tbl->pre_cmds, pre_cmds_size))) {
+    if(!(DVDReadBytes(ifop->file, cmd_tbl->pre_cmds, pre_cmds_size))) {
       free(cmd_tbl->pre_cmds);
       return 0;
     }
@@ -734,7 +756,7 @@ static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
         free(cmd_tbl->pre_cmds);
       return 0;
     }
-    if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size))) {
+    if(!(DVDReadBytes(ifop->file, cmd_tbl->post_cmds, post_cmds_size))) {
       if(cmd_tbl->pre_cmds)
         free(cmd_tbl->pre_cmds);
       free(cmd_tbl->post_cmds);
@@ -752,7 +774,7 @@ static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,
         free(cmd_tbl->post_cmds);
       return 0;
     }
-    if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size))) {
+    if(!(DVDReadBytes(ifop->file, cmd_tbl->cell_cmds, cell_cmds_size))) {
       if(cmd_tbl->pre_cmds)
         free(cmd_tbl->pre_cmds);
       if(cmd_tbl->post_cmds)
@@ -784,12 +806,13 @@ static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl) {
 static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,
                                    pgc_program_map_t *program_map,
                                    unsigned int nr, unsigned int offset) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   unsigned int size = nr * sizeof(pgc_program_map_t);
 
-  if(!DVDFileSeek_(ifofile->file, offset))
+  if(!DVDFileSeek_(ifop->file, offset))
     return 0;
 
-  if(!(DVDReadBytes(ifofile->file, program_map, size)))
+  if(!(DVDReadBytes(ifop->file, program_map, size)))
     return 0;
 
   return 1;
@@ -798,13 +821,14 @@ static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,
 static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile,
                                      cell_playback_t *cell_playback,
                                      unsigned int nr, unsigned int offset) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   unsigned int i;
   unsigned int size = nr * sizeof(cell_playback_t);
 
-  if(!DVDFileSeek_(ifofile->file, offset))
+  if(!DVDFileSeek_(ifop->file, offset))
     return 0;
 
-  if(!(DVDReadBytes(ifofile->file, cell_playback, size)))
+  if(!(DVDReadBytes(ifop->file, cell_playback, size)))
     return 0;
 
   for(i = 0; i < nr; i++) {
@@ -823,13 +847,14 @@ static int ifoRead_CELL_PLAYBACK_TBL(ifo_handle_t *ifofile,
 static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile,
                                      cell_position_t *cell_position,
                                      unsigned int nr, unsigned int offset) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   unsigned int i;
   unsigned int size = nr * sizeof(cell_position_t);
 
-  if(!DVDFileSeek_(ifofile->file, offset))
+  if(!DVDFileSeek_(ifop->file, offset))
     return 0;
 
-  if(!(DVDReadBytes(ifofile->file, cell_position, size)))
+  if(!(DVDReadBytes(ifop->file, cell_position, size)))
     return 0;
 
   for(i = 0; i < nr; i++) {
@@ -841,12 +866,13 @@ static int ifoRead_CELL_POSITION_TBL(ifo_handle_t *ifofile,
 }
 
 static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int offset) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   unsigned int i;
 
-  if(!DVDFileSeek_(ifofile->file, offset))
+  if(!DVDFileSeek_(ifop->file, offset))
     return 0;
 
-  if(!(DVDReadBytes(ifofile->file, pgc, PGC_SIZE)))
+  if(!(DVDReadBytes(ifop->file, pgc, PGC_SIZE)))
     return 0;
 
   read_user_ops(&pgc->prohibited_ops);
@@ -1000,6 +1026,7 @@ void ifoFree_FP_PGC(ifo_handle_t *ifofile) {
 
 
 int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   tt_srpt_t *tt_srpt;
   unsigned int i;
   size_t info_length;
@@ -1013,7 +1040,7 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
   if(ifofile->vmgi_mat->tt_srpt == 0) /* mandatory */
     return 0;
 
-  if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN))
+  if(!DVDFileSeek_(ifop->file, ifofile->vmgi_mat->tt_srpt * DVD_BLOCK_LEN))
     return 0;
 
   tt_srpt = calloc(1, sizeof(tt_srpt_t));
@@ -1022,8 +1049,8 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
 
   ifofile->tt_srpt = tt_srpt;
 
-  if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) {
-    fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
+  if(!(DVDReadBytes(ifop->file, tt_srpt, TT_SRPT_SIZE))) {
+    Log0(ifop->ctx, "Unable to read read TT_SRPT.");
     free(tt_srpt);
     return 0;
   }
@@ -1043,14 +1070,14 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
     ifofile->tt_srpt = NULL;
     return 0;
   }
-  if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) {
-    fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
+  if(!(DVDReadBytes(ifop->file, tt_srpt->title, info_length))) {
+    Log0(ifop->ctx, "libdvdread: Unable to read read TT_SRPT.");
     ifoFree_TT_SRPT(ifofile);
     return 0;
   }
 
   if(tt_srpt->nr_of_srpts>info_length/sizeof(title_info_t)){
-    fprintf(stderr,"libdvdread: data mismatch: info_length (%zd)!= nr_of_srpts (%d). Truncating.\n",
+    Log1(ifop->ctx, "data mismatch: info_length (%zd)!= nr_of_srpts (%d). Truncating.",
             info_length/sizeof(title_info_t),tt_srpt->nr_of_srpts);
     tt_srpt->nr_of_srpts=info_length/sizeof(title_info_t);
   }
@@ -1088,7 +1115,7 @@ int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
             tt_srpt->nr_of_srpts * sizeof(title_info_t),
             my_friendly_zeros,
             info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) {
-    fprintf(stderr, "VMG_PTT_SRPT slack is != 0, ");
+    Log1(ifop->ctx, "VMG_PTT_SRPT slack is != 0, ");
     hexdump((uint8_t *)tt_srpt->title +
             tt_srpt->nr_of_srpts * sizeof(title_info_t),
             info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t));
@@ -1113,6 +1140,7 @@ void ifoFree_TT_SRPT(ifo_handle_t *ifofile) {
 
 
 int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   vts_ptt_srpt_t *vts_ptt_srpt = NULL;
   int info_length, i, j;
   uint32_t *data = NULL;
@@ -1126,7 +1154,7 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
   if(ifofile->vtsi_mat->vts_ptt_srpt == 0) /* mandatory */
     return 0;
 
-  if(!DVDFileSeek_(ifofile->file,
+  if(!DVDFileSeek_(ifop->file,
                    ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN))
     return 0;
 
@@ -1137,8 +1165,8 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
   vts_ptt_srpt->title = NULL;
   ifofile->vts_ptt_srpt = vts_ptt_srpt;
 
-  if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) {
-    fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
+  if(!(DVDReadBytes(ifop->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) {
+    Log0(ifop->ctx, "Unable to read PTT search table.");
     goto fail;
   }
 
@@ -1158,18 +1186,18 @@ int ifoRead_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
   if(!data)
     goto fail;
 
-  if(!(DVDReadBytes(ifofile->file, data, info_length))) {
-    fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
+  if(!(DVDReadBytes(ifop->file, data, info_length))) {
+    Log0(ifop->ctx, "Unable to read PTT search table.");
     goto fail;
   }
 
   if(vts_ptt_srpt->nr_of_srpts > info_length / sizeof(*data)) {
-    fprintf(stderr, "libdvdread: PTT search table too small.\n");
+    Log0(ifop->ctx, "PTT search table too small.");
     goto fail;
   }
 
   if(vts_ptt_srpt->nr_of_srpts == 0) {
-    fprintf(stderr, "libdvdread: Zero entries in PTT search table.\n");
+    Log0(ifop->ctx, "Zero entries in PTT search table.");
     goto fail;
   }
 
@@ -1275,6 +1303,7 @@ void ifoFree_VTS_PTT_SRPT(ifo_handle_t *ifofile) {
 
 
 int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   ptl_mait_t *ptl_mait;
   int info_length;
   unsigned int i, j;
@@ -1288,7 +1317,7 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
   if(!ifofile->vmgi_mat->ptl_mait)
     return 1;
 
-  if(!DVDFileSeek_(ifofile->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN))
+  if(!DVDFileSeek_(ifop->file, ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN))
     return 0;
 
   ptl_mait = calloc(1, sizeof(ptl_mait_t));
@@ -1297,7 +1326,7 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
 
   ifofile->ptl_mait = ptl_mait;
 
-  if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) {
+  if(!(DVDReadBytes(ifop->file, ptl_mait, PTL_MAIT_SIZE))) {
     free(ptl_mait);
     ifofile->ptl_mait = NULL;
     return 0;
@@ -1326,8 +1355,8 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
   }
 
   for(i = 0; i < ptl_mait->nr_of_countries; i++) {
-    if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) {
-      fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n");
+    if(!(DVDReadBytes(ifop->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) {
+      Log0(ifop->ctx, "Unable to read PTL_MAIT.");
       free(ptl_mait->countries);
       free(ptl_mait);
       ifofile->ptl_mait = NULL;
@@ -1350,10 +1379,10 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
   for(i = 0; i < ptl_mait->nr_of_countries; i++) {
     uint16_t *pf_temp;
 
-    if(!DVDFileSeek_(ifofile->file,
+    if(!DVDFileSeek_(ifop->file,
                      ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN
                      + ptl_mait->countries[i].pf_ptl_mai_start_byte)) {
-      fprintf(stderr, "libdvdread: Unable to seek PTL_MAIT table at index %d.\n",i);
+      Log0(ifop->ctx, "Unable to seek PTL_MAIT table at index %d.",i);
       free(ptl_mait->countries);
       free(ptl_mait);
       ifofile->ptl_mait = NULL;
@@ -1366,8 +1395,8 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
       ifofile->ptl_mait = NULL;
       return 0;
     }
-    if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) {
-      fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table at index %d.\n",i);
+    if(!(DVDReadBytes(ifop->file, pf_temp, info_length))) {
+      Log0(ifop->ctx, "Unable to read PTL_MAIT table at index %d.",i);
       free(pf_temp);
       free_ptl_mait(ptl_mait, i);
       ifofile->ptl_mait = NULL;
@@ -1414,6 +1443,7 @@ void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) {
 }
 
 int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   vts_tmapt_t *vts_tmapt;
   uint32_t *vts_tmap_srp;
   unsigned int offset;
@@ -1433,7 +1463,7 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
 
   offset = ifofile->vtsi_mat->vts_tmapt * DVD_BLOCK_LEN;
 
-  if(!DVDFileSeek_(ifofile->file, offset))
+  if(!DVDFileSeek_(ifop->file, offset))
     return 0;
 
   vts_tmapt = calloc(1, sizeof(vts_tmapt_t));
@@ -1442,8 +1472,8 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
 
   ifofile->vts_tmapt = vts_tmapt;
 
-  if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) {
-    fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
+  if(!(DVDReadBytes(ifop->file, vts_tmapt, VTS_TMAPT_SIZE))) {
+    Log0(ifop->ctx, "Unable to read VTS_TMAPT.");
     free(vts_tmapt);
     ifofile->vts_tmapt = NULL;
     return 0;
@@ -1465,8 +1495,8 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
 
   vts_tmapt->tmap_offset = vts_tmap_srp;
 
-  if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) {
-    fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
+  if(!(DVDReadBytes(ifop->file, vts_tmap_srp, info_length))) {
+    Log0(ifop->ctx, "Unable to read VTS_TMAPT.");
     free(vts_tmap_srp);
     free(vts_tmapt);
     ifofile->vts_tmapt = NULL;
@@ -1489,13 +1519,13 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
   }
 
   for(i = 0; i < vts_tmapt->nr_of_tmaps; i++) {
-    if(!DVDFileSeek_(ifofile->file, offset + vts_tmap_srp[i])) {
+    if(!DVDFileSeek_(ifop->file, offset + vts_tmap_srp[i])) {
       ifoFree_VTS_TMAPT(ifofile);
       return 0;
     }
 
-    if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) {
-      fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n");
+    if(!(DVDReadBytes(ifop->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE))) {
+      Log0(ifop->ctx, "Unable to read VTS_TMAP.");
       ifoFree_VTS_TMAPT(ifofile);
       return 0;
     }
@@ -1516,8 +1546,8 @@ int ifoRead_VTS_TMAPT(ifo_handle_t *ifofile) {
       return 0;
     }
 
-    if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_length))) {
-      fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n");
+    if(!(DVDReadBytes(ifop->file, vts_tmapt->tmap[i].map_ent, info_length))) {
+      Log0(ifop->ctx, "Unable to read VTS_TMAP_ENT.");
       ifoFree_VTS_TMAPT(ifofile);
       return 0;
     }
@@ -1605,12 +1635,13 @@ int ifoRead_C_ADT(ifo_handle_t *ifofile) {
 
 static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
                                   c_adt_t *c_adt, unsigned int sector) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   size_t i, info_length;
 
-  if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
+  if(!DVDFileSeek_(ifop->file, sector * DVD_BLOCK_LEN))
     return 0;
 
-  if(!(DVDReadBytes(ifofile->file, c_adt, C_ADT_SIZE)))
+  if(!(DVDReadBytes(ifop->file, c_adt, C_ADT_SIZE)))
     return 0;
 
   B2N_16(c_adt->nr_of_vobs);
@@ -1631,7 +1662,7 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
      Enemy of the State region 2 (de) has Titles where nr_of_vobs field
      is to high, they high ones are never referenced though. */
   if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) {
-    fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > available info entries\n");
+    Log1(ifop->ctx, "C_ADT nr_of_vobs > available info entries");
     c_adt->nr_of_vobs = info_length / sizeof(cell_adr_t);
   }
 
@@ -1640,7 +1671,7 @@ static int ifoRead_C_ADT_internal(ifo_handle_t *ifofile,
     return 0;
 
   if(info_length &&
-     !(DVDReadBytes(ifofile->file, c_adt->cell_adr_table, info_length))) {
+     !(DVDReadBytes(ifop->file, c_adt->cell_adr_table, info_length))) {
     free(c_adt->cell_adr_table);
     return 0;
   }
@@ -1743,13 +1774,14 @@ int ifoRead_VOBU_ADMAP(ifo_handle_t *ifofile) {
 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
                                        vobu_admap_t *vobu_admap,
                                        unsigned int sector) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   unsigned int i;
   int info_length;
 
-  if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector))
+  if(!DVDFileSeekForce_(ifop->file, sector * DVD_BLOCK_LEN, sector))
     return 0;
 
-  if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE)))
+  if(!(DVDReadBytes(ifop->file, vobu_admap, VOBU_ADMAP_SIZE)))
     return 0;
 
   B2N_32(vobu_admap->last_byte);
@@ -1765,7 +1797,7 @@ static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,
     return 0;
   }
   if(info_length &&
-     !(DVDReadBytes(ifofile->file,
+     !(DVDReadBytes(ifop->file,
                     vobu_admap->vobu_start_sectors, info_length))) {
     free(vobu_admap->vobu_start_sectors);
     return 0;
@@ -1840,13 +1872,14 @@ static int find_dup_pgc(pgci_srp_t *pgci_srp, uint32_t start_byte, int count) {
 
 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
                                   unsigned int offset) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   int i, info_length;
   uint8_t *data, *ptr;
 
-  if(!DVDFileSeek_(ifofile->file, offset))
+  if(!DVDFileSeek_(ifop->file, offset))
     return 0;
 
-  if(!(DVDReadBytes(ifofile->file, pgcit, PGCIT_SIZE)))
+  if(!(DVDReadBytes(ifop->file, pgcit, PGCIT_SIZE)))
     return 0;
 
   B2N_16(pgcit->nr_of_pgci_srp);
@@ -1863,7 +1896,7 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
   if(!data)
     return 0;
 
-  if(info_length && !(DVDReadBytes(ifofile->file, data, info_length))) {
+  if(info_length && !(DVDReadBytes(ifop->file, data, info_length))) {
     free(data);
     return 0;
   }
@@ -1903,7 +1936,7 @@ static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,
     pgcit->pgci_srp[i].pgc->ref_count = 1;
     if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc,
                     offset + pgcit->pgci_srp[i].pgc_start_byte)) {
-      fprintf(stderr, "libdvdread: Unable to read invalid PCG\n");
+      Log0(ifop->ctx, "Unable to read invalid PCG");
       //E-One releases provide boggus PGC, ie: out of bound start_byte
       free(pgcit->pgci_srp[i].pgc);
       pgcit->pgci_srp[i].pgc = NULL;
@@ -1952,6 +1985,7 @@ static int find_dup_lut(pgci_lu_t *lu, uint32_t start_byte, int count) {
 }
 
 int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   pgci_ut_t *pgci_ut;
   unsigned int sector;
   unsigned int i;
@@ -1977,13 +2011,13 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
   if(!ifofile->pgci_ut)
     return 0;
 
-  if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) {
+  if(!DVDFileSeek_(ifop->file, sector * DVD_BLOCK_LEN)) {
     free(ifofile->pgci_ut);
     ifofile->pgci_ut = NULL;
     return 0;
   }
 
-  if(!(DVDReadBytes(ifofile->file, ifofile->pgci_ut, PGCI_UT_SIZE))) {
+  if(!(DVDReadBytes(ifop->file, ifofile->pgci_ut, PGCI_UT_SIZE))) {
     free(ifofile->pgci_ut);
     ifofile->pgci_ut = NULL;
     return 0;
@@ -2006,7 +2040,7 @@ int ifoRead_PGCI_UT(ifo_handle_t *ifofile) {
     ifofile->pgci_ut = NULL;
     return 0;
   }
-  if(!(DVDReadBytes(ifofile->file, data, info_length))) {
+  if(!(DVDReadBytes(ifop->file, data, info_length))) {
     free(data);
     free(pgci_ut);
     ifofile->pgci_ut = NULL;
@@ -2100,12 +2134,13 @@ void ifoFree_PGCI_UT(ifo_handle_t *ifofile) {
 static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
                                   vts_attributes_t *vts_attributes,
                                   unsigned int offset) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   unsigned int i;
 
-  if(!DVDFileSeek_(ifofile->file, offset))
+  if(!DVDFileSeek_(ifop->file, offset))
     return 0;
 
-  if(!(DVDReadBytes(ifofile->file, vts_attributes, sizeof(vts_attributes_t))))
+  if(!(DVDReadBytes(ifop->file, vts_attributes, sizeof(vts_attributes_t))))
     return 0;
 
   read_video_attr(&vts_attributes->vtsm_vobs_attr);
@@ -2151,6 +2186,7 @@ static int ifoRead_VTS_ATTRIBUTES(ifo_handle_t *ifofile,
 
 
 int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   vts_atrt_t *vts_atrt;
   unsigned int i, info_length, sector;
   uint32_t *data;
@@ -2165,7 +2201,7 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
     return 0;
 
   sector = ifofile->vmgi_mat->vts_atrt;
-  if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN))
+  if(!DVDFileSeek_(ifop->file, sector * DVD_BLOCK_LEN))
     return 0;
 
   vts_atrt = calloc(1, sizeof(vts_atrt_t));
@@ -2174,7 +2210,7 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
 
   ifofile->vts_atrt = vts_atrt;
 
-  if(!(DVDReadBytes(ifofile->file, vts_atrt, VTS_ATRT_SIZE))) {
+  if(!(DVDReadBytes(ifop->file, vts_atrt, VTS_ATRT_SIZE))) {
     free(vts_atrt);
     ifofile->vts_atrt = NULL;
     return 0;
@@ -2199,7 +2235,7 @@ int ifoRead_VTS_ATRT(ifo_handle_t *ifofile) {
 
   vts_atrt->vts_atrt_offsets = data;
 
-  if(!(DVDReadBytes(ifofile->file, data, info_length))) {
+  if(!(DVDReadBytes(ifop->file, data, info_length))) {
     free(data);
     free(vts_atrt);
     ifofile->vts_atrt = NULL;
@@ -2252,6 +2288,7 @@ void ifoFree_VTS_ATRT(ifo_handle_t *ifofile) {
 
 
 int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
+  struct ifo_handle_private_s *ifop = PRIV(ifofile);
   txtdt_mgi_t *txtdt_mgi;
 
   if(!ifofile)
@@ -2264,7 +2301,7 @@ int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
   if(ifofile->vmgi_mat->txtdt_mgi == 0)
     return 1;
 
-  if(!DVDFileSeek_(ifofile->file,
+  if(!DVDFileSeek_(ifop->file,
                    ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN))
     return 0;
 
@@ -2274,14 +2311,14 @@ int ifoRead_TXTDT_MGI(ifo_handle_t *ifofile) {
   }
   ifofile->txtdt_mgi = txtdt_mgi;
 
-  if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) {
-    fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n");
+  if(!(DVDReadBytes(ifop->file, txtdt_mgi, TXTDT_MGI_SIZE))) {
+    Log0(ifop->ctx, "Unable to read TXTDT_MGI.");
     free(txtdt_mgi);
     ifofile->txtdt_mgi = NULL;
     return 0;
   }
 
-  /* fprintf(stderr, "-- Not done yet --\n"); */
+  /* Log1(ifop->ctx, "-- Not done yet --\n"); */
   return 1;
 }
 


=====================================
src/logger.c
=====================================
@@ -0,0 +1,41 @@
+/*
+ * This file is part of libdvdread.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "dvdread/dvd_reader.h"
+#include "logger.h"
+
+void DVDReadLog( void *priv, const dvd_logger_cb *logcb,
+                 dvd_logger_level_t level, const char *fmt, ... )
+{
+    va_list list;
+    va_start(list, fmt);
+    if(logcb && logcb->pf_log)
+        logcb->pf_log(priv, level, fmt, list);
+    else
+    {
+        FILE *stream = (level == DVD_LOGGER_LEVEL_ERROR) ? stderr : stdout;
+        fprintf(stream, "libdvdread: ");
+        vfprintf(stream, fmt, list);
+        fprintf(stream, "\n");
+    }
+    va_end(list);
+}


=====================================
src/logger.h
=====================================
@@ -0,0 +1,32 @@
+/*
+ * This file is part of libdvdread.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ */
+
+#ifndef LIBDVDREAD_LOGGER_H
+#define LIBDVDREAD_LOGGER_H
+
+void DVDReadLog( void *priv, const dvd_logger_cb *logcb,
+                 dvd_logger_level_t level, const char *fmt, ... );
+
+#define LOG(ctx, level, ...) \
+  DVDReadLog(ctx->priv, &ctx->logcb, level, __VA_ARGS__)
+#define Log0(ctx, ...) LOG(ctx, DVD_LOGGER_LEVEL_ERROR, __VA_ARGS__)
+#define Log1(ctx, ...) LOG(ctx, DVD_LOGGER_LEVEL_WARN,  __VA_ARGS__)
+#define Log2(ctx, ...) LOG(ctx, DVD_LOGGER_LEVEL_INFO,  __VA_ARGS__)
+#define Log3(ctx, ...) LOG(ctx, DVD_LOGGER_LEVEL_DEBUG, __VA_ARGS__)
+
+#endif


=====================================
src/nav_read.c
=====================================
@@ -34,6 +34,13 @@
 #define getbits_init dvdread_getbits_init
 #define getbits dvdread_getbits
 
+#define CHECK_VALUE(arg)\
+  if(!(arg)) {\
+    DVDReadLog(NULL, NULL, DVD_LOGGER_LEVEL_WARN,\
+                "CHECK_VALUE failed in %s:%i for %s",\
+                __FILE__, __LINE__, # arg );\
+  }
+
 void navRead_PCI(pci_t *pci, unsigned char *buffer) {
   int32_t i, j;
   getbits_state_t state;



View it on GitLab: https://code.videolan.org/videolan/libdvdread/-/compare/6c463b78201e2af6a5191c1d4c2272ef5711c45b...42374932bebd4f9e67f8cd0db46c792038e69df1

-- 
View it on GitLab: https://code.videolan.org/videolan/libdvdread/-/compare/6c463b78201e2af6a5191c1d4c2272ef5711c45b...42374932bebd4f9e67f8cd0db46c792038e69df1
You're receiving this email because of your account on code.videolan.org.




More information about the libdvdnav-devel mailing list