[libdvdnav-devel] [Git][videolan/libdvdnav][master] 8 commits: rename callback stream as priv

Jean-Baptiste Kempf gitlab at videolan.org
Wed Mar 4 15:19:54 CET 2020



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


Commits:
0326c25d by Francois Cartegnie at 2020-03-04T14:11:27+01:00
rename callback stream as priv

- - - - -
9ae56e85 by Francois Cartegnie at 2020-03-04T14:11:27+01:00
add open2 to pass private context

- - - - -
462a1e45 by Francois Cartegnie at 2020-03-04T14:11:27+01:00
Add logger context to open2

- - - - -
fa3b325d by Francois Cartegnie at 2020-03-04T14:11:27+01:00
add logger

- - - - -
56f71ea2 by Francois Cartegnie at 2020-03-04T14:11:27+01:00
use logger

- - - - -
7dc0c0cd by Francois Cartegnie at 2020-03-04T14:11:27+01:00
getset.c use logger

- - - - -
6f6d27c8 by Francois Cartegnie at 2020-03-04T14:11:27+01:00
vmget: use logger

- - - - -
ac7327d2 by Francois Cartegnie at 2020-03-04T14:11:27+01:00
searching.c: use logger

- - - - -


12 changed files:

- Makefile.am
- src/dvdnav.c
- src/dvdnav/dvdnav.h
- src/dvdnav_internal.h
- + src/logger.c
- + src/logger.h
- src/searching.c
- src/vm/getset.c
- src/vm/play.c
- src/vm/vm.c
- src/vm/vm.h
- src/vm/vmget.c


Changes:

=====================================
Makefile.am
=====================================
@@ -18,6 +18,8 @@ libdvdnav_la_SOURCES = \
 	src/read_cache.c \
 	src/navigation.c \
 	src/highlight.c \
+        src/logger.c \
+        src/logger.h \
 	src/searching.c \
 	src/settings.c \
 	src/dvdnav_internal.h \


=====================================
src/dvdnav.c
=====================================
@@ -41,6 +41,7 @@
 #include "vm/vm.h"
 #include "vm/getset.h"
 #include "dvdnav_internal.h"
+#include "logger.h"
 #include "read_cache.h"
 #include <dvdread/nav_read.h>
 
@@ -114,14 +115,14 @@ fail:
 dvdnav_status_t dvdnav_free_dup(dvdnav_t *this) {
 
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: free_dup:called\n");
+  Log3(this, "free_dup:called");
 #endif
 
   if (this->file) {
     pthread_mutex_lock(&this->vm_lock);
     DVDCloseFile(this->file);
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: close:file closing\n");
+    Log3(this, "close:file closing");
 #endif
     this->file = NULL;
     pthread_mutex_unlock(&this->vm_lock);
@@ -146,8 +147,9 @@ dvdnav_status_t dvdnav_free_dup(dvdnav_t *this) {
   return DVDNAV_STATUS_OK;
 }
 
-static dvdnav_status_t dvdnav_open_common(dvdnav_t** dest, const char *path,
-                                          void *stream,
+static dvdnav_status_t dvdnav_open_common(dvdnav_t** dest,
+                                          void *priv, const dvdnav_logger_cb *logcb,
+                                          const char *path,
                                           dvdnav_stream_cb *stream_cb) {
   dvdnav_t *this;
   struct timeval time;
@@ -158,16 +160,20 @@ static dvdnav_status_t dvdnav_open_common(dvdnav_t** dest, const char *path,
   if(!this)
     return DVDNAV_STATUS_ERR;
 
+  this->priv = priv;
+  if(logcb)
+    this->logcb = *logcb;
+
   pthread_mutex_init(&this->vm_lock, NULL);
   /* Initialise the error string */
   printerr("");
 
   /* Initialise the VM */
-  this->vm = vm_new_vm();
+  this->vm = vm_new_vm(priv, logcb);
   if(!this->vm) {
     goto fail;
   }
-  if(!vm_reset(this->vm, path, stream, stream_cb)) {
+  if(!vm_reset(this->vm, path, priv, stream_cb)) {
     goto fail;
   }
 
@@ -206,25 +212,37 @@ fail:
 }
 
 dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) {
-  return dvdnav_open_common(dest, path, NULL, NULL);
+  return dvdnav_open_common(dest, NULL, NULL, path, NULL);
+}
+
+dvdnav_status_t dvdnav_open2(dvdnav_t** dest,
+                             void *priv,const dvdnav_logger_cb *logcb,
+                             const char *path) {
+  return dvdnav_open_common(dest, priv, logcb, path, NULL);
 }
 
 dvdnav_status_t dvdnav_open_stream(dvdnav_t** dest,
-                                   void *stream, dvdnav_stream_cb *stream_cb) {
-  return dvdnav_open_common(dest, NULL, stream, stream_cb);
+                                   void *priv, dvdnav_stream_cb *stream_cb) {
+  return dvdnav_open_common(dest, priv, NULL, NULL, stream_cb);
+}
+
+dvdnav_status_t dvdnav_open_stream2(dvdnav_t** dest,
+                                    void *priv,const dvdnav_logger_cb *logcb,
+                                    dvdnav_stream_cb *stream_cb) {
+  return dvdnav_open_common(dest, priv, logcb, NULL, stream_cb);
 }
 
 dvdnav_status_t dvdnav_close(dvdnav_t *this) {
 
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: close:called\n");
+  Log3(this, "close:called");
 #endif
 
   if (this->file) {
     pthread_mutex_lock(&this->vm_lock);
     DVDCloseFile(this->file);
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: close:file closing\n");
+    Log3(this, "close:file closing");
 #endif
     this->file = NULL;
     pthread_mutex_unlock(&this->vm_lock);
@@ -253,13 +271,13 @@ dvdnav_status_t dvdnav_reset(dvdnav_t *this) {
   dvdnav_status_t result;
 
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: reset:called\n");
+  Log3(this, "reset:called");
 #endif
 
   pthread_mutex_lock(&this->vm_lock);
 
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: reseting vm\n");
+  Log3(this, "reseting vm");
 #endif
   if(!vm_reset(this->vm, NULL, NULL, NULL)) {
     printerr("Error restarting the VM.");
@@ -267,7 +285,7 @@ dvdnav_status_t dvdnav_reset(dvdnav_t *this) {
     return DVDNAV_STATUS_ERR;
   }
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: clearing dvdnav\n");
+  Log3(this, "clearing dvdnav");
 #endif
   pthread_mutex_unlock(&this->vm_lock);
   result = dvdnav_clear(this);
@@ -319,7 +337,8 @@ int64_t dvdnav_convert_time(dvd_time_t *time) {
  * Most of the code in here is copied from xine's MPEG demuxer
  * so any bugs which are found in that should be corrected here also.
  */
-static int32_t dvdnav_decode_packet(uint8_t *p, dsi_t *nav_dsi, pci_t *nav_pci) {
+static int32_t dvdnav_decode_packet(dvdnav_t *this, uint8_t *p,
+                                    dsi_t *nav_dsi, pci_t *nav_pci) {
   int32_t        bMpeg1 = 0;
   uint32_t       nHeaderLen;
   uint32_t       nPacketLen;
@@ -345,7 +364,7 @@ static int32_t dvdnav_decode_packet(uint8_t *p, dsi_t *nav_dsi, pci_t *nav_pci)
 
   /* we should now have a PES packet here */
   if (p[0] || p[1] || (p[2] != 1)) {
-    fprintf(MSG_OUT, "libdvdnav: demux error! %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]);
+    Log1(this, "demux error! %02x %02x %02x (should be 0x000001)",p[0],p[1],p[2]);
     return 0;
   }
 
@@ -357,11 +376,11 @@ static int32_t dvdnav_decode_packet(uint8_t *p, dsi_t *nav_dsi, pci_t *nav_pci)
 
   if (nStreamID == 0xbf) { /* Private stream 2 */
 #if 0
+    char buffer[80 * 3 + 1];
     int32_t i;
-    fprintf(MSG_OUT, "libdvdnav: nav packet=%u\n",p-p_start-6);
     for(i=0;i<80;i++)
-      fprintf(MSG_OUT, "%02x ",p[i-6]);
-    fprintf(MSG_OUT, "\n");
+      sprintf(&buffer[i*3], "%02x ",p[i-6]);
+    Log3(this, "nav packet=%u %s",p-p_start-6, buffer);
 #endif
 
     if(p[0] == 0x00) {
@@ -420,7 +439,7 @@ static int32_t dvdnav_get_vobu(dvdnav_t *this, dsi_t *nav_dsi, pci_t *nav_pci, d
   /* FIMXE: The angle reset doesn't work for some reason for the moment */
 #if 0
   if((num_angle < angle) && (angle != 1)) {
-    fprintf(MSG_OUT, "libdvdnav: angle ends!\n");
+    Log3(this, "angle ends!");
 
     /* This is to switch back to angle one when we
      * finish with angles. */
@@ -539,9 +558,9 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
   vm_position_get(this->vm, &this->position_next);
 
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: POS-NEXT ");
+  Log3(vm, "POS-NEXT ");
   vm_position_print(this->vm, &this->position_next);
-  fprintf(MSG_OUT, "libdvdnav: POS-CUR  ");
+  Log3(vm, "POS-CUR  ");
   vm_position_print(this->vm, &this->position_current);
 #endif
 
@@ -549,7 +568,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
   if(this->position_current.hop_channel != this->position_next.hop_channel) {
     (*event) = DVDNAV_HOP_CHANNEL;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: HOP_CHANNEL\n");
+    Log3(vm, "HOP_CHANNEL");
 #endif
     if (this->position_next.hop_channel - this->position_current.hop_channel >= HOP_SEEK) {
       int32_t num_angles = 0, current;
@@ -568,7 +587,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
           return DVDNAV_STATUS_ERR;
         }
         /* Decode nav into pci and dsi. Then get next VOBU info. */
-        if(!dvdnav_decode_packet(*buf, &this->dsi, &this->pci)) {
+        if(!dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci)) {
           printerr("Expected NAV packet but none found.");
           pthread_mutex_unlock(&this->vm_lock);
           return DVDNAV_STATUS_ERR;
@@ -601,7 +620,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
 
     (*event) = DVDNAV_HIGHLIGHT;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: HIGHLIGHT\n");
+    Log3(this, "HIGHLIGHT");
 #endif
     (*len) = sizeof(dvdnav_highlight_event_t);
     hevent->display = 1;
@@ -615,7 +634,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
   if(this->sync_wait) {
     (*event) = DVDNAV_WAIT;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: WAIT\n");
+    Log3(this, "WAIT");
 #endif
     (*len) = 0;
     pthread_mutex_unlock(&this->vm_lock);
@@ -677,7 +696,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
     /* File opened successfully so return a VTS change event */
     (*event) = DVDNAV_VTS_CHANGE;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: VTS_CHANGE\n");
+    Log3(this, "VTS_CHANGE");
 #endif
     (*len) = sizeof(dvdnav_vts_change_event_t);
 
@@ -701,7 +720,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
     this->cur_cell_time = 0;
     (*event) = DVDNAV_CELL_CHANGE;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: CELL_CHANGE\n");
+    Log3(this, "CELL_CHANGE");
 #endif
     (*len) = sizeof(dvdnav_cell_change_event_t);
 
@@ -759,7 +778,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
   if(this->spu_clut_changed) {
     (*event) = DVDNAV_SPU_CLUT_CHANGE;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: SPU_CLUT_CHANGE\n");
+    Log3(this, "SPU_CLUT_CHANGE");
 #endif
     (*len) = 16 * sizeof(uint32_t);
     memcpy(*buf, state->pgc->palette, sizeof(state->pgc->palette));
@@ -774,7 +793,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
 
     (*event) = DVDNAV_SPU_STREAM_CHANGE;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE\n");
+    Log3(this, "SPU_STREAM_CHANGE");
 #endif
     (*len) = sizeof(dvdnav_spu_stream_change_event_t);
     stream_change->physical_wide      = vm_get_subp_active_stream(this->vm, 0);
@@ -782,10 +801,10 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
     stream_change->physical_pan_scan  = vm_get_subp_active_stream(this->vm, 2);
     this->position_current.spu_channel = this->position_next.spu_channel;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_wide=%d\n",stream_change->physical_wide);
-    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_letterbox=%d\n",stream_change->physical_letterbox);
-    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_pan_scan=%d\n",stream_change->physical_pan_scan);
-    fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE returning DVDNAV_STATUS_OK\n");
+    Log3(this, "SPU_STREAM_CHANGE stream_id_wide=%d",stream_change->physical_wide);
+    Log3(this, "SPU_STREAM_CHANGE stream_id_letterbox=%d",stream_change->physical_letterbox);
+    Log3(this, "SPU_STREAM_CHANGE stream_id_pan_scan=%d",stream_change->physical_pan_scan);
+    Log3(this, "SPU_STREAM_CHANGE returning DVDNAV_STATUS_OK");
 #endif
     /* This is not realy the right place to do this. FOSL_BTNN should set the register
      * at HLI_S_PTM rather than when we enter the SPU. As well we should activate FOAC_BTNN
@@ -805,14 +824,14 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
 
     (*event) = DVDNAV_AUDIO_STREAM_CHANGE;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: AUDIO_STREAM_CHANGE\n");
+    Log3(this, "AUDIO_STREAM_CHANGE");
 #endif
     (*len) = sizeof(dvdnav_audio_stream_change_event_t);
     stream_change->physical = vm_get_audio_active_stream( this->vm );
     stream_change->logical = this->position_next.audio_channel;
     this->position_current.audio_channel = this->position_next.audio_channel;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: AUDIO_STREAM_CHANGE stream_id=%d returning DVDNAV_STATUS_OK\n",stream_change->physical);
+    Log3(this, "AUDIO_STREAM_CHANGE stream_id=%d returning DVDNAV_STATUS_OK",stream_change->physical);
 #endif
     pthread_mutex_unlock(&this->vm_lock);
     return DVDNAV_STATUS_OK;
@@ -824,7 +843,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
 
     (*event) = DVDNAV_STILL_FRAME;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: STILL_FRAME\n");
+    Log3(this, "STILL_FRAME");
 #endif
     (*len) = sizeof(dvdnav_still_event_t);
     still_event->length = this->position_current.still;
@@ -839,7 +858,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
     if(this->vobu.vobu_next == SRI_END_OF_CELL) {
       /* End of Cell from NAV DSI info */
 #ifdef LOG_DEBUG
-      fprintf(MSG_OUT, "libdvdnav: Still set to %x\n", this->position_next.still);
+      Log3(this, "Still set to %x", this->position_next.still);
 #endif
       this->position_current.still = this->position_next.still;
 
@@ -872,7 +891,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
       return DVDNAV_STATUS_ERR;
     }
     /* Decode nav into pci and dsi. Then get next VOBU info. */
-    if(!dvdnav_decode_packet(*buf, &this->dsi, &this->pci)) {
+    if(!dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci)) {
       printerr("Expected NAV packet but none found.");
       pthread_mutex_unlock(&this->vm_lock);
       return DVDNAV_STATUS_ERR;
@@ -896,7 +915,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, uint8_t **buf,
     /* Successfully got a NAV packet */
     (*event) = DVDNAV_NAV_PACKET;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: NAV_PACKET\n");
+    Log3(this, "NAV_PACKET");
 #endif
     (*len) = 2048;
     this->cur_cell_time = dvdnav_convert_time(&this->dsi.dsi_gi.c_eltm);


=====================================
src/dvdnav/dvdnav.h
=====================================
@@ -38,7 +38,7 @@ extern "C" {
 #include <dvdread/ifo_types.h> /* For vm_cmd_t */
 #include <dvdnav/dvdnav_events.h>
 
-
+#include <stdarg.h>
 
 /*********************************************************************
  * dvdnav data types                                                 *
@@ -69,6 +69,22 @@ typedef dvd_reader_stream_cb dvdnav_stream_cb;
  * initialisation & housekeeping functions                           *
  *********************************************************************/
 
+/*
+ * Logger callback definition
+ */
+typedef enum
+{
+    DVDNAV_LOGGER_LEVEL_INFO,
+    DVDNAV_LOGGER_LEVEL_ERROR,
+    DVDNAV_LOGGER_LEVEL_WARN,
+    DVDNAV_LOGGER_LEVEL_DEBUG,
+} dvdnav_logger_level_t;
+
+typedef struct
+{
+  void ( *pf_log )  ( void *, dvdnav_logger_level_t, const char *, va_list );
+} dvdnav_logger_cb;
+
 /*
  * These functions allow you to open a DVD device and associate it
  * with a dvdnav_t.
@@ -87,7 +103,14 @@ typedef dvd_reader_stream_cb dvdnav_stream_cb;
  */
 dvdnav_status_t dvdnav_open(dvdnav_t **dest, const char *path);
 dvdnav_status_t
-dvdnav_open_stream(dvdnav_t **dest, void *stream, dvdnav_stream_cb *stream_cb);
+dvdnav_open_stream(dvdnav_t **dest, void *priv, dvdnav_stream_cb *stream_cb);
+
+dvdnav_status_t dvdnav_open2(dvdnav_t **dest,
+                             void *, const dvdnav_logger_cb *,
+                             const char *path);
+dvdnav_status_t dvdnav_open_stream2(dvdnav_t **dest,
+                                    void *priv, const dvdnav_logger_cb *,
+                                    dvdnav_stream_cb *stream_cb);
 
 dvdnav_status_t dvdnav_dup(dvdnav_t **dest, dvdnav_t *src);
 dvdnav_status_t dvdnav_free_dup(dvdnav_t * _this);


=====================================
src/dvdnav_internal.h
=====================================
@@ -210,6 +210,10 @@ struct dvdnav_s {
   vm_t *vm;
   pthread_mutex_t vm_lock;
 
+  /* private context and logger*/
+  void *priv;
+  dvdnav_logger_cb logcb;
+
   /* Read-ahead cache */
   read_cache_t *cache;
 


=====================================
src/logger.c
=====================================
@@ -0,0 +1,41 @@
+/*
+* This file is part of libdvdnav, a DVD navigation library.
+*
+ * 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 "dvdnav/dvdnav.h"
+#include "logger.h"
+
+void dvdnav_log( void *priv, const dvdnav_logger_cb *logcb,
+                 dvdnav_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 == DVDNAV_LOGGER_LEVEL_ERROR) ? stderr : stdout;
+        fprintf(stream, "libdvdnav: ");
+        vfprintf(stream, fmt, list);
+        fprintf(stream, "\n");
+    }
+    va_end(list);
+}


=====================================
src/logger.h
=====================================
@@ -0,0 +1,32 @@
+/*
+* This file is part of libdvdnav, a DVD navigation library.
+*
+ * 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 LIBDVDNAV_LOGGER_H
+#define LIBDVDNAV_LOGGER_H
+
+void dvdnav_log( void *priv, const dvdnav_logger_cb *logcb,
+                 dvdnav_logger_level_t level, const char *fmt, ... );
+
+#define LOG(ctx, level, ...) \
+  dvdnav_log(ctx->priv, &ctx->logcb, level, __VA_ARGS__)
+#define Log0(ctx, ...) LOG(ctx, DVDNAV_LOGGER_LEVEL_ERROR, __VA_ARGS__)
+#define Log1(ctx, ...) LOG(ctx, DVDNAV_LOGGER_LEVEL_WARN,  __VA_ARGS__)
+#define Log2(ctx, ...) LOG(ctx, DVDNAV_LOGGER_LEVEL_INFO,  __VA_ARGS__)
+#define Log3(ctx, ...) LOG(ctx, DVDNAV_LOGGER_LEVEL_DEBUG, __VA_ARGS__)
+
+#endif


=====================================
src/searching.c
=====================================
@@ -35,6 +35,7 @@
 #include "vm/decoder.h"
 #include "vm/vm.h"
 #include "dvdnav_internal.h"
+#include "logger.h"
 #include <dvdread/ifo_read.h>
 
 /*
@@ -51,7 +52,7 @@ static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_
   vobu_admap_t *admap = NULL;
 
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: Seeking to target %u ...\n", seekto_block);
+  Log3(this, "Seeking to target %u ...", seekto_block);
 #endif
   *vobu = -1;
 
@@ -69,7 +70,7 @@ static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_
     admap = this->vm->vtsi->vts_vobu_admap;
     break;
   default:
-    fprintf(MSG_OUT, "libdvdnav: Error: Unknown domain for seeking.\n");
+    Log0(this, "Error: Unknown domain for seeking.");
   }
   if(admap) {
     uint32_t address = 0;
@@ -118,7 +119,7 @@ static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_
     *vobu = next ? next_vobu : vobu_start;
     return DVDNAV_STATUS_OK;
   }
-  fprintf(MSG_OUT, "libdvdnav: admap not located\n");
+  Log0(this, "admap not located");
   return DVDNAV_STATUS_ERR;
 }
 
@@ -183,7 +184,7 @@ dvdnav_status_t dvdnav_time_search(dvdnav_t *this,
   if(found) {
     uint32_t vobu;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n",
+    Log3(this, "Seeking to cell %i from choice of %i to %i",
             cell_nr, first_cell_nr, last_cell_nr);
 #endif
     if (dvdnav_scan_admap(this, state->domain, target, 0, &vobu) == DVDNAV_STATUS_OK) {
@@ -191,7 +192,7 @@ dvdnav_status_t dvdnav_time_search(dvdnav_t *this,
 
       if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) {
 #ifdef LOG_DEBUG
-        fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" ,
+        Log3(this, "After cellN=%u blockN=%u target=%x vobu=%x start=%x" ,
           state->cellN, state->blockN, target, vobu, start);
 #endif
         this->vm->hop_channel += HOP_SEEK;
@@ -201,7 +202,7 @@ dvdnav_status_t dvdnav_time_search(dvdnav_t *this,
     }
   }
 
-  fprintf(MSG_OUT, "libdvdnav: Error when seeking\n");
+  Log0(this, "Error when seeking");
   printerr("Error when seeking.");
   pthread_mutex_unlock(&this->vm_lock);
   return DVDNAV_STATUS_ERR;
@@ -239,8 +240,8 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
     return DVDNAV_STATUS_ERR;
   }
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: seeking to offset=%lld pos=%u length=%u\n", offset, target, length);
-  fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN);
+  Log3(this, "seeking to offset=%lld pos=%u length=%u", offset, target, length);
+  Log3(this, "Before cellN=%u blockN=%u", state->cellN, state->blockN);
 #endif
 
   current_pos = target;
@@ -339,7 +340,7 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
   if(found) {
     uint32_t vobu;
 #ifdef LOG_DEBUG
-    fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n",
+    Log3(this, "Seeking to cell %i from choice of %i to %i",
             cell_nr, first_cell_nr, last_cell_nr);
 #endif
     if (dvdnav_scan_admap(this, state->domain, target, 0, &vobu) == DVDNAV_STATUS_OK) {
@@ -347,7 +348,7 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
 
       if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) {
 #ifdef LOG_DEBUG
-        fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" ,
+        Log3(this, "After cellN=%u blockN=%u target=%x vobu=%x start=%x" ,
           state->cellN, state->blockN, target, vobu, start);
 #endif
         this->vm->hop_channel += HOP_SEEK;
@@ -357,8 +358,8 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
     }
   }
 
-  fprintf(MSG_OUT, "libdvdnav: Error when seeking\n");
-  fprintf(MSG_OUT, "libdvdnav: FIXME: Implement seeking to location %u\n", target);
+  Log0(this, "Error when seeking");
+  Log1(this, "FIXME: Implement seeking to location %u", target);
   printerr("Error when seeking.");
   pthread_mutex_unlock(&this->vm_lock);
   return DVDNAV_STATUS_ERR;
@@ -381,10 +382,10 @@ dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) {
   }
 
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: previous chapter\n");
+  Log3(this, "previous chapter");
 #endif
   if (!vm_jump_prev_pg(this->vm)) {
-    fprintf(MSG_OUT, "libdvdnav: previous chapter failed.\n");
+    Log0(this, "previous chapter failed.");
     printerr("Skip to previous chapter failed.");
     pthread_mutex_unlock(&this->vm_lock);
     return DVDNAV_STATUS_ERR;
@@ -393,7 +394,7 @@ dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) {
   this->position_current.still = 0;
   this->vm->hop_channel++;
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: previous chapter done\n");
+  Log3(this, "previous chapter done");
 #endif
   pthread_mutex_unlock(&this->vm_lock);
 
@@ -409,10 +410,10 @@ dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) {
   }
 
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: top chapter\n");
+  Log3(this, "top chapter");
 #endif
   if (!vm_jump_top_pg(this->vm)) {
-    fprintf(MSG_OUT, "libdvdnav: top chapter failed.\n");
+    Log0(this, "top chapter failed.");
     printerr("Skip to top chapter failed.");
     pthread_mutex_unlock(&this->vm_lock);
     return DVDNAV_STATUS_ERR;
@@ -421,7 +422,7 @@ dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) {
   this->position_current.still = 0;
   this->vm->hop_channel++;
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: top chapter done\n");
+  Log3(this, "top chapter done");
 #endif
   pthread_mutex_unlock(&this->vm_lock);
 
@@ -438,7 +439,7 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) {
   }
 
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: next chapter\n");
+  Log3(this, "next chapter");
 #endif
   /* make a copy of current VM and try to navigate the copy to the next PG */
   try_vm = vm_new_copy(this->vm);
@@ -458,7 +459,7 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) {
     vm_get_next_cell(try_vm);
     if (try_vm->stopped) {
       vm_free_copy(try_vm);
-      fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n");
+      Log0(this, "next chapter failed.");
       printerr("Skip to next chapter failed.");
       goto fail;
     }
@@ -470,7 +471,7 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) {
   this->position_current.still = 0;
   this->vm->hop_channel++;
 #ifdef LOG_DEBUG
-  fprintf(MSG_OUT, "libdvdnav: next chapter done\n");
+  Log3(this, "next chapter done");
 #endif
   pthread_mutex_unlock(&this->vm_lock);
 
@@ -775,7 +776,7 @@ static vobu_admap_t* dvdnav_admap_get(dvdnav_t *this, dvd_state_t *state,
     admap = this->vm->vtsi->vts_vobu_admap;
     break;
   default: {
-    fprintf(MSG_OUT, "Unknown domain");
+    Log1(this, "Unknown domain");
     return NULL;
   }
   }
@@ -783,7 +784,7 @@ static vobu_admap_t* dvdnav_admap_get(dvdnav_t *this, dvd_state_t *state,
 
   *admap_len = (admap->last_byte + 1 - VOBU_ADMAP_SIZE) / VOBU_ADMAP_SIZE;
   if (*admap_len <= 0) {
-    fprintf(MSG_OUT, "admap_len <= 0");
+    Log1(this, "admap_len <= 0");
     return NULL;
   }
   return admap;
@@ -813,7 +814,7 @@ static vts_tmap_t* dvdnav_tmap_get(dvdnav_t *this, dvd_state_t *state,
     break;
   }
   default: {
-    fprintf(MSG_OUT, "unknown domain for tmap");
+    Log1(this, "unknown domain for tmap");
     return NULL;
   }
   }
@@ -833,7 +834,7 @@ static vts_tmap_t* dvdnav_tmap_get(dvdnav_t *this, dvd_state_t *state,
   tmap_count = tmapt->nr_of_tmaps;
   pgcN = state->pgcN - 1; /* -1 b/c pgcN is base1 */
   if (pgcN < 0) {
-    fprintf(MSG_OUT, "pgcN < 0");
+    Log1(this, "pgcN < 0");
     return NULL;
   }
 
@@ -843,7 +844,7 @@ static vts_tmap_t* dvdnav_tmap_get(dvdnav_t *this, dvd_state_t *state,
   case DVD_DOMAIN_VMGM:
   case DVD_DOMAIN_VTSMenu: {
     if (tmap_count == 0) {
-      fprintf(MSG_OUT, "tmap_count == 0");
+      Log1(this, "tmap_count == 0");
       return NULL;
     }
     tmap = &tmapt->tmap[0]; /* ASSUME: vmgi only has one time map */
@@ -851,7 +852,7 @@ static vts_tmap_t* dvdnav_tmap_get(dvdnav_t *this, dvd_state_t *state,
   }
   case DVD_DOMAIN_VTSTitle: {
     if (pgcN >= tmap_count) {
-      fprintf(MSG_OUT, "pgcN >= tmap_count; pgcN=%i tmap_count=%i",
+      Log1(this, "pgcN >= tmap_count; pgcN=%i tmap_count=%i",
           pgcN, tmap_count);
       return NULL;
     }
@@ -864,20 +865,21 @@ static vts_tmap_t* dvdnav_tmap_get(dvdnav_t *this, dvd_state_t *state,
   /* tmap->tmu is in seconds; convert to millisecs */
   *tmap_interval = tmap->tmu * 1000;
   if (*tmap_interval == 0) {
-    fprintf(MSG_OUT, "tmap_interval == 0");
+    Log1(this, "tmap_interval == 0");
     return NULL;
   }
   *tmap_len = tmap->nr_of_entries;
   if (*tmap_len == 0) {
-    fprintf(MSG_OUT, "tmap_len == 0");
+    Log1(this, "tmap_len == 0");
     return NULL;
   }
   return tmap;
 }
 
 /* Get a sector from a tmap */
-static int32_t dvdnav_tmap_get_entry(vts_tmap_t *tmap, uint16_t tmap_len,
-            int32_t idx, uint32_t *sector) {
+static int32_t dvdnav_tmap_get_entry(dvdnav_t *this,
+                                     vts_tmap_t *tmap, uint16_t tmap_len,
+                                     int32_t idx, uint32_t *sector) {
   /* tmaps start at idx 0 which represents a sector at time 1 * tmap_interval
    * this creates a "fake" tmap index at idx -1 for sector 0 */
   if (idx == TMAP_IDX_EDGE_BGN) {
@@ -885,7 +887,7 @@ static int32_t dvdnav_tmap_get_entry(vts_tmap_t *tmap, uint16_t tmap_len,
     return 1;
   }
   if (idx < TMAP_IDX_EDGE_BGN || idx >= tmap_len) {
-    fprintf(MSG_OUT, "idx out of bounds idx=%i %i", idx, tmap_len);
+    Log1(this, "idx out of bounds idx=%i %i", idx, tmap_len);
     return 0;
   }
   /* 0x7fffffff unsets discontinuity bit if present */
@@ -933,7 +935,8 @@ static int32_t dvdnav_admap_search(vobu_admap_t *admap, uint32_t admap_len,
 }
 
 /* Do a binary search for the earlier tmap entry near find_sector */
-static int32_t dvdnav_tmap_search(vts_tmap_t *tmap, uint32_t tmap_len,
+static int32_t dvdnav_tmap_search(dvdnav_t *this,
+                                  vts_tmap_t *tmap, uint32_t tmap_len,
             uint32_t find_sector, int32_t *tmap_idx, uint32_t *sector) {
   int32_t adj = 1;
   int32_t prv_pos = 0;
@@ -952,7 +955,7 @@ static int32_t dvdnav_tmap_search(vts_tmap_t *tmap, uint32_t tmap_len,
     else if (cur_idx >= (int32_t)tmap_len)
       cur_idx = tmap_len - 1;
     cur_sector = 0;
-    result = dvdnav_tmap_get_entry(tmap, tmap_len, cur_idx, &cur_sector);
+    result = dvdnav_tmap_get_entry(this, tmap, tmap_len, cur_idx, &cur_sector);
     if (!result) return 0;
     if      (find_sector <  cur_sector) adj = -1;
     else if (find_sector >  cur_sector) adj =  1;
@@ -969,7 +972,7 @@ static int32_t dvdnav_tmap_search(vts_tmap_t *tmap, uint32_t tmap_len,
         }
         else {
           cur_idx -= 1;
-          result = dvdnav_tmap_get_entry(tmap, tmap_len, cur_idx, &cur_sector);
+          result = dvdnav_tmap_get_entry(this, tmap, tmap_len, cur_idx, &cur_sector);
           if (!result) return 0;
         }
       }
@@ -998,7 +1001,7 @@ static int32_t dvdnav_cell_find(dvdnav_t *this, dvd_state_t *state,
   if (pgc == NULL) return 0;
   cells_len = pgc->nr_of_cells;
   if (cells_len == 0) {
-    fprintf(MSG_OUT, "cells_len == 0");
+    Log1(this, "cells_len == 0");
     return 0;
   }
 
@@ -1045,12 +1048,13 @@ static int32_t dvdnav_cell_find(dvdnav_t *this, dvd_state_t *state,
     cell_data->idx = cell_idx;
   }
   else
-    fprintf(MSG_OUT, "cell not found; find=%"PRId64"", find_val);
+    Log1(this, "cell not found; find=%"PRId64, find_val);
   return found;
 }
 
 /* Given two sectors and a fraction, calc the corresponding vobu */
-static int32_t dvdnav_admap_interpolate_vobu(dvdnav_jump_args_t *args,
+static int32_t dvdnav_admap_interpolate_vobu(dvdnav_t *this,
+                                             dvdnav_jump_args_t *args,
             dvdnav_pos_data_t *bgn, dvdnav_pos_data_t *end, uint32_t fraction,
             uint32_t *jump_sector) {
   int32_t result = 0;
@@ -1062,7 +1066,7 @@ static int32_t dvdnav_admap_interpolate_vobu(dvdnav_jump_args_t *args,
   result = dvdnav_admap_search(args->admap, args->admap_len,
       bgn->sector, &bgn->vobu_idx);
   if (!result) {
-    fprintf(MSG_OUT, "admap_interpolate: could not find sector_bgn");
+    Log1(this, "admap_interpolate: could not find sector_bgn");
     return 0;
   }
 
@@ -1070,7 +1074,7 @@ static int32_t dvdnav_admap_interpolate_vobu(dvdnav_jump_args_t *args,
   result = dvdnav_admap_search(args->admap, args->admap_len,
       end->sector, &end->vobu_idx);
   if (!result) {
-    fprintf(MSG_OUT, "admap_interpolate: could not find sector_end");
+    Log1(this, "admap_interpolate: could not find sector_end");
     return 0;
   }
 
@@ -1081,7 +1085,7 @@ static int32_t dvdnav_admap_interpolate_vobu(dvdnav_jump_args_t *args,
   vobu_adj++;
   vobu_idx = bgn->vobu_idx + vobu_adj;
   if ((int32_t)vobu_idx >= args->admap_len) {
-    fprintf(MSG_OUT, "admap_interpolate: vobu_idx >= admap_len");
+    Log1(this, "admap_interpolate: vobu_idx >= admap_len");
     return 0;
   }
   *jump_sector = args->admap->vobu_start_sectors[vobu_idx];
@@ -1089,7 +1093,8 @@ static int32_t dvdnav_admap_interpolate_vobu(dvdnav_jump_args_t *args,
 }
 
 /* Given two tmap entries and a time, calc the time for the lo tmap entry */
-static int32_t dvdnav_tmap_calc_time_for_tmap_entry(dvdnav_jump_args_t *args,
+static int32_t dvdnav_tmap_calc_time_for_tmap_entry(dvdnav_t *this,
+                                                    dvdnav_jump_args_t *args,
             dvdnav_pos_data_t *lo, dvdnav_pos_data_t *hi,
             dvdnav_pos_data_t *pos, uint64_t *out_time) {
   int32_t result = 0;
@@ -1097,7 +1102,7 @@ static int32_t dvdnav_tmap_calc_time_for_tmap_entry(dvdnav_jump_args_t *args,
   uint64_t time_adj = 0;
 
   if (lo->sector == hi->sector) {
-    fprintf(MSG_OUT, "lo->sector == hi->sector: %i", lo->sector);
+    Log1(this, "lo->sector == hi->sector: %i", lo->sector);
     return 0;
   }
 
@@ -1105,19 +1110,19 @@ static int32_t dvdnav_tmap_calc_time_for_tmap_entry(dvdnav_jump_args_t *args,
   result = dvdnav_admap_search(args->admap, args->admap_len,
       lo->sector, &lo->vobu_idx);
   if (!result) {
-    fprintf(MSG_OUT, "lo->vobu: lo->sector=%i", lo->sector);
+    Log1(this, "lo->vobu: lo->sector=%i", lo->sector);
     return 0;
   }
   result = dvdnav_admap_search(args->admap, args->admap_len,
       hi->sector, &hi->vobu_idx);
   if (!result) {
-    fprintf(MSG_OUT, "hi->vobu: hi->sector=%i", hi->sector);
+    Log1(this, "hi->vobu: hi->sector=%i", hi->sector);
     return 0;
   }
   result = dvdnav_admap_search(args->admap, args->admap_len,
       pos->sector, &pos->vobu_idx);
   if (!result) {
-    fprintf(MSG_OUT, "pos->vobu: pos->sector=%i", pos->sector);
+    Log1(this, "pos->vobu: pos->sector=%i", pos->sector);
     return 0;
   }
 
@@ -1131,7 +1136,7 @@ static int32_t dvdnav_tmap_calc_time_for_tmap_entry(dvdnav_jump_args_t *args,
       / ( hi->vobu_idx - lo->vobu_idx);
   }
   if (vobu_pct < 0 || vobu_pct > 1000) {
-    fprintf(MSG_OUT, "vobu_pct must be between 0 and 1000");
+    Log1(this, "vobu_pct must be between 0 and 1000");
     return 0;
   }
 
@@ -1143,15 +1148,17 @@ static int32_t dvdnav_tmap_calc_time_for_tmap_entry(dvdnav_jump_args_t *args,
 
 /* Find the tmap entries on either side of a given sector */
 static int32_t dvdnav_tmap_get_entries_for_sector(
+            dvdnav_t *this,
             dvdnav_jump_args_t *args,
             dvdnav_cell_data_t *cell_data, uint32_t find_sector,
             dvdnav_pos_data_t *lo, dvdnav_pos_data_t *hi) {
   int32_t result = 0;
 
-  result = dvdnav_tmap_search(args->tmap, args->tmap_len, find_sector,
+  result = dvdnav_tmap_search(this,
+      args->tmap, args->tmap_len, find_sector,
       &lo->tmap_idx, &lo->sector);
   if (!result) {
-    fprintf(MSG_OUT, "could not find lo idx: %i", find_sector);
+    Log1(this, "could not find lo idx: %i", find_sector);
     return 0;
   }
 
@@ -1175,10 +1182,10 @@ static int32_t dvdnav_tmap_get_entries_for_sector(
   }
   else {
     hi->tmap_idx = lo->tmap_idx + 1;
-    result = dvdnav_tmap_get_entry(args->tmap, args->tmap_len,
+    result = dvdnav_tmap_get_entry(this, args->tmap, args->tmap_len,
         hi->tmap_idx, &hi->sector);
     if (!result) {
-      fprintf(MSG_OUT, "could not find hi idx: %i", find_sector);
+      Log1(this, "could not find hi idx: %i", find_sector);
       return 0;
     }
   }
@@ -1205,12 +1212,13 @@ static int32_t dvdnav_find_vobu_by_tmap(dvdnav_t *this, dvd_state_t *state,
   /* get tmap entries on either side of cell_bgn */
   cell_bgn_lo = &(dvdnav_pos_data_t){0};
   cell_bgn_hi = &(dvdnav_pos_data_t){0};
-  result = dvdnav_tmap_get_entries_for_sector(args, cell_data,
+  result = dvdnav_tmap_get_entries_for_sector(this, args, cell_data,
       cell_data->bgn->sector, cell_bgn_lo, cell_bgn_hi);
   if (!result) return 0;
 
   /* calc time of cell_bgn_lo */
-  result = dvdnav_tmap_calc_time_for_tmap_entry(args, cell_bgn_lo, cell_bgn_hi,
+  result = dvdnav_tmap_calc_time_for_tmap_entry(this,
+      args, cell_bgn_lo, cell_bgn_hi,
       cell_data->bgn, &cell_bgn_lo->time);
   if (!result) return 0;
 
@@ -1232,26 +1240,26 @@ static int32_t dvdnav_find_vobu_by_tmap(dvdnav_t *this, dvd_state_t *state,
   }
   else {
     jump_lo->tmap_idx = (uint32_t)(cell_bgn_lo->tmap_idx + seek_idx);
-    result = dvdnav_tmap_get_entry(args->tmap, args->tmap_len,
+    result = dvdnav_tmap_get_entry(this, args->tmap, args->tmap_len,
         jump_lo->tmap_idx, &jump_lo->sector);
     if (!result) return 0;
 
     /* +1 handled by dvdnav_tmap_get_entry */
     jump_hi->tmap_idx = jump_lo->tmap_idx + 1;
-    result = dvdnav_tmap_get_entry(args->tmap, args->tmap_len,
+    result = dvdnav_tmap_get_entry(this, args->tmap, args->tmap_len,
         jump_hi->tmap_idx, &jump_hi->sector);
     if (!result) return 0;
   }
 
   /* interpolate sector */
-  result = dvdnav_admap_interpolate_vobu(args, jump_lo, jump_hi,
+  result = dvdnav_admap_interpolate_vobu(this, args, jump_lo, jump_hi,
       seek_pct, &jump->sector);
 
   return result;
 }
 
 /* Find the nearest vobu by using the cell boundaries */
-static int32_t dvdnav_find_vobu_by_cell_boundaries(
+static int32_t dvdnav_find_vobu_by_cell_boundaries(dvdnav_t *this,
             dvdnav_jump_args_t *args, dvdnav_cell_data_t *cell_data,
             dvdnav_pos_data_t *jump) {
   int64_t jump_offset = 0;
@@ -1262,12 +1270,12 @@ static int32_t dvdnav_find_vobu_by_cell_boundaries(
   /* get jump_offset */
   jump_offset = jump->time - cell_data->bgn->time;
   if (jump_offset < 0) {
-    fprintf(MSG_OUT, "jump_offset < 0");
+    Log1(this, "jump_offset < 0");
     return 0;
   }
   cell_len = cell_data->end->time - cell_data->bgn->time;
   if (cell_len < 0) {
-    fprintf(MSG_OUT, "cell_len < 0");
+    Log1(this, "cell_len < 0");
     return 0;
   }
   jump_pct = (jump_offset * 1000) / cell_len;
@@ -1278,10 +1286,10 @@ static int32_t dvdnav_find_vobu_by_cell_boundaries(
    * +1 to get sector that is the start of a VOBU
    * start of a VOBU is needed in order to index into admap */
   cell_data->end->sector += 1;
-  result = dvdnav_admap_interpolate_vobu(args,
+  result = dvdnav_admap_interpolate_vobu(this, args,
       cell_data->bgn, cell_data->end, jump_pct, &jump->sector);
   if (!result) {
-    fprintf(MSG_OUT, "find_by_admap.interpolate");
+    Log1(this, "find_by_admap.interpolate");
     return 0;
   }
   return 1;
@@ -1326,7 +1334,7 @@ dvdnav_status_t dvdnav_jump_to_sector_by_time(dvdnav_t *this,
   /* find sector */
   result = dvdnav_find_vobu_by_tmap(this, state, args, cell_data, jump);
   if (!result) {/* bad tmap; interpolate over cell */
-    result = dvdnav_find_vobu_by_cell_boundaries(args, cell_data, jump);
+    result = dvdnav_find_vobu_by_cell_boundaries(this, args, cell_data, jump);
     if (!result) {
       goto exit;
     }


=====================================
src/vm/getset.c
=====================================
@@ -39,6 +39,7 @@
 #include "vm.h"
 #include "getset.h"
 #include "dvdnav_internal.h"
+#include "logger.h"
 
 #include "getset.h"
 /* Set functions */
@@ -152,7 +153,7 @@ int set_PGCN(vm_t *vm, int pgcN) {
 
   if(pgcN < 1 || pgcN > pgcit->nr_of_pgci_srp) {
 #ifdef TRACE
-    fprintf(MSG_OUT, "libdvdnav:  ** No such pgcN = %d\n", pgcN);
+    Log3(vm, "** No such pgcN = %d", pgcN);
 #endif
     return 0;
   }
@@ -253,11 +254,11 @@ int get_ID(vm_t *vm, int id) {
   /* Relies on state to get the correct pgcit. */
   pgcit = get_PGCIT(vm);
   if(pgcit == NULL) {
-    fprintf(MSG_OUT, "libdvdnav: PGCIT null!\n");
+    Log1(vm, "PGCIT null!");
     return 0;
   }
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: ** Searching for menu (0x%x) entry PGC\n", id);
+  Log3(vm, "** Searching for menu (0x%x) entry PGC", id);
 #endif
 
   /* Force high bit set. */
@@ -268,16 +269,16 @@ int get_ID(vm_t *vm, int id) {
     if( (pgcit->pgci_srp[i].entry_id) == id) {
       pgcN = i + 1;
 #ifdef TRACE
-      fprintf(MSG_OUT, "libdvdnav: Found menu.\n");
+      Log3(vm, "Found menu.");
 #endif
       return pgcN;
     }
   }
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: ** No such id/menu (0x%02x) entry PGC\n", id & 0x7f);
+  Log3(vm, "** No such id/menu (0x%02x) entry PGC", id & 0x7f);
   for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
     if ( (pgcit->pgci_srp[i].entry_id & 0x80) == 0x80) {
-      fprintf(MSG_OUT, "libdvdnav: Available menus: 0x%x\n",
+      Log3(vm, "Available menus: 0x%x",
                      pgcit->pgci_srp[i].entry_id & 0x7f);
     }
   }
@@ -305,7 +306,7 @@ int get_PGCN(vm_t *vm) {
       pgcN++;
     }
   }
-  fprintf(MSG_OUT, "libdvdnav: get_PGCN failed. Was trying to find pgcN in domain %d\n",
+  Log0(vm, "get_PGCN failed. Was trying to find pgcN in domain %d",
          (vm->state).domain);
   return 0; /*  error */
 }
@@ -314,7 +315,7 @@ pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang) {
   int i;
 
   if(h == NULL || h->pgci_ut == NULL) {
-    fprintf(MSG_OUT, "libdvdnav: *** pgci_ut handle is NULL ***\n");
+    Log0(vm, "*** pgci_ut handle is NULL ***");
     return NULL; /*  error? */
   }
 
@@ -323,17 +324,22 @@ pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang) {
         && h->pgci_ut->lu[i].lang_code != lang)
     i++;
   if(i == h->pgci_ut->nr_of_lus) {
-    fprintf(MSG_OUT, "libdvdnav: Language '%c%c' not found, using '%c%c' instead\n",
+    Log1(vm, "Language '%c%c' not found, using '%c%c' instead",
             (char)(lang >> 8), (char)(lang & 0xff),
              (char)(h->pgci_ut->lu[0].lang_code >> 8),
             (char)(h->pgci_ut->lu[0].lang_code & 0xff));
-    fprintf(MSG_OUT, "libdvdnav: Menu Languages available: ");
-    for(i = 0; i < h->pgci_ut->nr_of_lus; i++) {
-      fprintf(MSG_OUT, "%c%c ",
-             (char)(h->pgci_ut->lu[i].lang_code >> 8),
-            (char)(h->pgci_ut->lu[i].lang_code & 0xff));
+    char *buffer = malloc(3 * h->pgci_ut->nr_of_lus + 1);
+    if(buffer)
+    {
+        buffer[3 * h->pgci_ut->nr_of_lus] = 0;
+        for(i = 0; i < h->pgci_ut->nr_of_lus; i++) {
+        sprintf(&buffer[3*i], "%c%c ",
+                 (char)(h->pgci_ut->lu[i].lang_code >> 8),
+                (char)(h->pgci_ut->lu[i].lang_code & 0xff));
+        }
+        Log2(vm, "Menu Languages available: %s", buffer);
+        free(buffer);
     }
-    fprintf(MSG_OUT, "\n");
     i = 0; /*  error? */
   }
 


=====================================
src/vm/play.c
=====================================
@@ -40,6 +40,7 @@
 #include "vm/getset.h"
 
 #include "dvdnav_internal.h"
+#include "logger.h"
 
 /* Playback control */
 
@@ -47,11 +48,10 @@ link_t play_PGC(vm_t *vm) {
   link_t link_values;
 
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: play_PGC:");
   if((vm->state).domain != DVD_DOMAIN_FirstPlay) {
-    fprintf(MSG_OUT, " (vm->state).pgcN (%i)\n", get_PGCN(vm));
+    Log3(vm, "play_PGC: (vm->state).pgcN (%i)", get_PGCN(vm));
   } else {
-    fprintf(MSG_OUT, " first_play_pgc\n");
+    Log3(vm, "play_PGC: first_play_pgc");
   }
 #endif
 
@@ -91,7 +91,7 @@ link_t play_PGC(vm_t *vm) {
       return link_values;
     } else {
 #ifdef TRACE
-      fprintf(MSG_OUT, "libdvdnav: PGC pre commands didn't do a Jump, Link or Call\n");
+      Log3(vm, "PGC pre commands didn't do a Jump, Link or Call");
 #endif
     }
   }
@@ -102,11 +102,10 @@ link_t play_PGC_PG(vm_t *vm, int pgN) {
   link_t link_values;
 
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: play_PGC_PG:");
   if((vm->state).domain != DVD_DOMAIN_FirstPlay) {
-    fprintf(MSG_OUT, " (vm->state).pgcN (%i)\n", get_PGCN(vm));
+    Log3(vm, "play_PGC_PG: (vm->state).pgcN (%i)", get_PGCN(vm));
   } else {
-    fprintf(MSG_OUT, " first_play_pgc\n");
+    Log3(vm, "play_PGC_PG: first_play_pgc");
   }
 #endif
 
@@ -131,7 +130,7 @@ link_t play_PGC_PG(vm_t *vm, int pgN) {
       return link_values;
     } else {
 #ifdef TRACE
-      fprintf(MSG_OUT, "libdvdnav: PGC pre commands didn't do a Jump, Link or Call\n");
+      Log3(vm, "PGC pre commands didn't do a Jump, Link or Call");
 #endif
     }
   }
@@ -142,7 +141,7 @@ link_t play_PGC_post(vm_t *vm) {
   link_t link_values = { LinkNoLink, 0, 0, 0 };
 
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: play_PGC_post:\n");
+  Log3(vm, "play_PGC_post:");
 #endif
 
   /* eval -> updates the state and returns either
@@ -158,7 +157,7 @@ link_t play_PGC_post(vm_t *vm) {
   }
 
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: ** Fell of the end of the pgc, continuing in NextPGC\n");
+  Log3(vm, "** Fell of the end of the pgc, continuing in NextPGC");
 #endif
   /* Should end up in the STOP_DOMAIN if next_pgc is 0. */
   if(!set_PGCN(vm, (vm->state).pgc->next_pgc_nr)) {
@@ -170,13 +169,13 @@ link_t play_PGC_post(vm_t *vm) {
 
 link_t play_PG(vm_t *vm) {
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: play_PG: (vm->state).pgN (%i)\n", (vm->state).pgN);
+  Log3(vm, "play_PG: (vm->state).pgN (%i)", (vm->state).pgN);
 #endif
 
   assert((vm->state).pgN > 0);
   if((vm->state).pgN > (vm->state).pgc->nr_of_programs) {
 #ifdef TRACE
-    fprintf(MSG_OUT, "libdvdnav: play_PG: (vm->state).pgN (%i) > pgc->nr_of_programs (%i)\n",
+    Log3(vm, "play_PG: (vm->state).pgN (%i) > pgc->nr_of_programs (%i)",
             (vm->state).pgN, (vm->state).pgc->nr_of_programs );
 #endif
     assert((vm->state).pgN == (vm->state).pgc->nr_of_programs + 1);
@@ -192,13 +191,13 @@ link_t play_Cell(vm_t *vm) {
   static const link_t play_this = {PlayThis, /* Block in Cell */ 0, 0, 0};
 
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: play_Cell: (vm->state).cellN (%i)\n", (vm->state).cellN);
+  Log3(vm, "play_Cell: (vm->state).cellN (%i)", (vm->state).cellN);
 #endif
 
   assert((vm->state).cellN > 0);
   if((vm->state).cellN > (vm->state).pgc->nr_of_cells) {
 #ifdef TRACE
-    fprintf(MSG_OUT, "libdvdnav: (vm->state).cellN (%i) > pgc->nr_of_cells (%i)\n",
+    Log3(vm, "(vm->state).cellN (%i) > pgc->nr_of_cells (%i)",
             (vm->state).cellN, (vm->state).pgc->nr_of_cells );
 #endif
     assert((vm->state).cellN == (vm->state).pgc->nr_of_cells + 1);
@@ -226,7 +225,7 @@ link_t play_Cell(vm_t *vm) {
       if (!((vm->state).cellN <= (vm->state).pgc->nr_of_cells) ||
           !((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode != 0) ||
           !((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 1)) {
-        fprintf(MSG_OUT, "libdvdnav: Invalid angle block\n");
+        Log1(vm, "Invalid angle block");
         (vm->state).cellN -= (vm->state).AGL_REG - 1;
       }
 #endif
@@ -234,7 +233,7 @@ link_t play_Cell(vm_t *vm) {
     case 2: /*  reserved */
     case 3: /*  reserved */
     default:
-      fprintf(MSG_OUT, "libdvdnav: Invalid? Cell block_mode (%d), block_type (%d)\n",
+      Log1(vm, "Invalid? Cell block_mode (%d), block_type (%d)",
               (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode,
               (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type);
       assert(0);
@@ -244,7 +243,7 @@ link_t play_Cell(vm_t *vm) {
   case 3: /*  Last cell in the block */
   /* These might perhaps happen for RSM or LinkC commands? */
   default:
-    fprintf(MSG_OUT, "libdvdnav: Cell is in block but did not enter at first cell!\n");
+    Log1(vm, "Cell is in block but did not enter at first cell!");
   }
 
   /* Updates (vm->state).pgN and PTTN_REG */
@@ -256,7 +255,7 @@ link_t play_Cell(vm_t *vm) {
   (vm->state).cell_restart++;
   (vm->state).blockN = 0;
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: Cell should restart here\n");
+  Log3(vm, "Cell should restart here");
 #endif
   return play_this;
 }
@@ -265,7 +264,7 @@ link_t play_Cell_post(vm_t *vm) {
   cell_playback_t *cell;
 
 #ifdef TRACE
-  fprintf(MSG_OUT, "libdvdnav: play_Cell_post: (vm->state).cellN (%i)\n", (vm->state).cellN);
+  Log3(vm, "play_Cell_post: (vm->state).cellN (%i)", (vm->state).cellN);
 #endif
 
   cell = &(vm->state).pgc->cell_playback[(vm->state).cellN - 1];
@@ -279,19 +278,19 @@ link_t play_Cell_post(vm_t *vm) {
     if ((vm->state).pgc->command_tbl != NULL &&
         (vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr) {
 #ifdef TRACE
-      fprintf(MSG_OUT, "libdvdnav: Cell command present, executing\n");
+      Log3(vm, "Cell command present, executing");
 #endif
       if(vmEval_CMD(&(vm->state).pgc->command_tbl->cell_cmds[cell->cell_cmd_nr - 1], 1,
                     &(vm->state).registers, &link_values)) {
         return link_values;
       } else {
 #ifdef TRACE
-        fprintf(MSG_OUT, "libdvdnav: Cell command didn't do a Jump, Link or Call\n");
+        Log3(vm, "Cell command didn't do a Jump, Link or Call");
 #endif
       }
     } else {
 #ifdef TRACE
-      fprintf(MSG_OUT, "libdvdnav: Invalid Cell command\n");
+      Log3(vm, "Invalid Cell command");
 #endif
     }
   }
@@ -322,7 +321,7 @@ link_t play_Cell_post(vm_t *vm) {
     case 2: /*  reserved */
     case 3: /*  reserved */
     default:
-      fprintf(MSG_OUT, "libdvdnav: Invalid? Cell block_mode (%d), block_type (%d)\n",
+      Log1(vm, "Invalid? Cell block_mode (%d), block_type (%d)",
               (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode,
               (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type);
       assert(0);
@@ -333,7 +332,7 @@ link_t play_Cell_post(vm_t *vm) {
   /* Figure out the correct pgN for the new cell */
   if(!set_PGN(vm)) {
 #ifdef TRACE
-    fprintf(MSG_OUT, "libdvdnav: last cell in this PGC\n");
+    Log3(vm, "last cell in this PGC");
 #endif
     return play_PGC_post(vm);
   }


=====================================
src/vm/vm.c
=====================================
@@ -36,6 +36,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <fcntl.h>
+#include <ctype.h>
 
 #include <dvdread/nav_types.h>
 #include <dvdread/ifo_types.h>
@@ -47,6 +48,7 @@
 #include "play.h"
 #include "getset.h"
 #include "dvdnav_internal.h"
+#include "logger.h"
 
 #ifdef _MSC_VER
 #include <io.h>   /* read() */
@@ -76,7 +78,7 @@ static void vm_close(vm_t *vm);
 
 #ifdef TRACE
 void vm_position_print(vm_t *vm, vm_position_t *position) {
-  fprintf(MSG_OUT, "libdvdnav: But=%x Spu=%x Aud=%x Ang=%x Hop=%x vts=%x dom=%x cell=%x cell_restart=%x cell_start=%x still=%x block=%x\n",
+  Log3(vm, "But=%x Spu=%x Aud=%x Ang=%x Hop=%x vts=%x dom=%x cell=%x cell_restart=%x cell_start=%x still=%x block=%x",
   position->button,
   position->spu_channel,
   position->audio_channel,
@@ -101,7 +103,7 @@ static void vm_print_current_domain_state(vm_t *vm) {
     case DVD_DOMAIN_FirstPlay:   domain = "First Play";         break;
     default:          domain = "Unknown";            break;
   }
-  fprintf(MSG_OUT, "libdvdnav: %s Domain: VTS:%d PGC:%d PG:%u CELL:%u BLOCK:%u VTS_TTN:%u TTN:%u TT_PGCN:%u\n",
+  Log3(vm, "%s Domain: VTS:%d PGC:%d PG:%u CELL:%u BLOCK:%u VTS_TTN:%u TTN:%u TT_PGCN:%u",
                    domain,
                    vm->state.vtsN,
                    get_PGCN(vm),
@@ -137,79 +139,79 @@ static int os2_open(const char *name, int oflag)
 }
 #endif
 
-static int dvd_read_name(char *name, char *serial, const char *device) {
+static void escaped_strcpy(char *dst, const char *src, size_t len)
+{
+    for(size_t i=0; i < len; i++ )
+    {
+      if(src[i] == 0)
+      {
+          dst[i] = 0;
+          break;
+      }
+      else if(isprint(src[i]))
+      {
+        dst[i] = src[i];
+      } else {
+        dst[i] = ' ';
+      }
+    }
+}
+
+static int dvd_read_name(const vm_t *vm, char *name, char *serial, const char *device) {
   /* Because we are compiling with _FILE_OFFSET_BITS=64
    * all off_t are 64bit.
    */
   off_t off;
   ssize_t read_size = 0;
-  int fd = -1, i;
+  int fd = -1;
   uint8_t data[DVD_VIDEO_LB_LEN];
 
   /* Read DVD name */
   if (device == NULL) {
-    fprintf(MSG_OUT, "libdvdnav: Device name string NULL\n");
+    Log0(vm, "Device name string NULL");
     goto fail;
   }
   if ((fd = open(device, O_RDONLY)) == -1) {
-    fprintf(MSG_OUT, "libdvdnav: Unable to open device file %s.\n", device);
+    Log0(vm, "Unable to open device file %s.", device);
     goto fail;
   }
 
   if ((off = lseek( fd, 32 * (off_t) DVD_VIDEO_LB_LEN, SEEK_SET )) == (off_t) - 1) {
-    fprintf(MSG_OUT, "libdvdnav: Unable to seek to the title block %u.\n", 32);
+    Log0(vm, "Unable to seek to the title block %u.", 32);
     goto fail;
   }
 
   if( off != ( 32 * (off_t) DVD_VIDEO_LB_LEN ) ) {
-    fprintf(MSG_OUT, "libdvdnav: Can't seek to block %u\n", 32 );
+    Log0(vm, "Can't seek to block %u", 32 );
     goto fail;
   }
 
   if ((read_size = read( fd, data, DVD_VIDEO_LB_LEN )) == -1) {
-    fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n");
+    Log0(vm, "Can't read name block. Probably not a DVD-ROM device.");
     goto fail;
   }
 
   close(fd);
   fd = -1;
   if (read_size != DVD_VIDEO_LB_LEN) {
-    fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n");
+    Log0(vm, "Can't read name block. Probably not a DVD-ROM device.");
     goto fail;
   }
 
-  fprintf(MSG_OUT, "libdvdnav: DVD Title: ");
-  for(i=25; i < 73; i++ ) {
-    if(data[i] == 0) break;
-    if((data[i] > 32) && (data[i] < 127)) {
-      fprintf(MSG_OUT, "%c", data[i]);
-    } else {
-      fprintf(MSG_OUT, " ");
-    }
-  }
-  strncpy(name, (char*) &data[25], 48);
+  char buffer[49] = {0};
+  strncpy(name, (const char*) &data[25], 48);
   name[48] = 0;
-  fprintf(MSG_OUT, "\nlibdvdnav: DVD Serial Number: ");
-  for(i=73; i < 89; i++ ) {
-    if(data[i] == 0) break;
-    if((data[i] > 32) && (data[i] < 127)) {
-      fprintf(MSG_OUT, "%c", data[i]);
-    } else {
-      fprintf(MSG_OUT, " ");
-    }
-  }
-  strncpy(serial, (char*) &data[73], 14);
+  escaped_strcpy(buffer, name, 48);
+  Log2(vm, "DVD Title: %s", buffer);
+
+  strncpy(serial, (const char*) &data[73], 14);
   serial[14] = 0;
-  fprintf(MSG_OUT, "\nlibdvdnav: DVD Title (Alternative): ");
-  for(i=89; i < 128; i++ ) {
-    if(data[i] == 0) break;
-    if((data[i] > 32) && (data[i] < 127)) {
-      fprintf(MSG_OUT, "%c", data[i]);
-    } else {
-      fprintf(MSG_OUT, " ");
-    }
-  }
-  fprintf(MSG_OUT, "\n");
+  escaped_strcpy(buffer, serial, 14);
+  Log2(vm, "DVD Serial Number: %s", buffer);
+
+  escaped_strcpy(buffer, (const char *) &data[89], 128 - 89);
+  Log2(vm, "DVD Title (Alternative): %s", buffer);
+
   return 1;
 
 fail:
@@ -229,27 +231,27 @@ int ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN) {
 
   vm->vtsi = ifoOpenVTSI(dvd, vtsN);
   if(vm->vtsi == NULL) {
-    fprintf(MSG_OUT, "libdvdnav: ifoOpenVTSI failed\n");
+    Log0(vm, "ifoOpenVTSI failed");
     return 0;
   }
   if(!ifoRead_VTS_PTT_SRPT(vm->vtsi)) {
-    fprintf(MSG_OUT, "libdvdnav: ifoRead_VTS_PTT_SRPT failed\n");
+    Log0(vm, "ifoRead_VTS_PTT_SRPT failed");
     return 0;
   }
   if(!ifoRead_PGCIT(vm->vtsi)) {
-    fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCIT failed\n");
+    Log0(vm, "ifoRead_PGCIT failed");
     return 0;
   }
   if(!ifoRead_PGCI_UT(vm->vtsi)) {
-    fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCI_UT failed\n");
+    Log0(vm, "ifoRead_PGCI_UT failed");
     return 0;
   }
   if(!ifoRead_VOBU_ADMAP(vm->vtsi)) {
-    fprintf(MSG_OUT, "libdvdnav: ifoRead_VOBU_ADMAP vtsi failed\n");
+    Log0(vm, "ifoRead_VOBU_ADMAP vtsi failed");
     return 0;
   }
   if(!ifoRead_TITLE_VOBU_ADMAP(vm->vtsi)) {
-    fprintf(MSG_OUT, "libdvdnav: ifoRead_TITLE_VOBU_ADMAP vtsi failed\n");
+    Log0(vm, "ifoRead_TITLE_VOBU_ADMAP vtsi failed");
     return 0;
   }
   vm->state.vtsN = vtsN;
@@ -260,8 +262,15 @@ int ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN) {
 
 /* Initialisation & Destruction */
 
-vm_t* vm_new_vm() {
-  return (vm_t*)calloc(1, sizeof(vm_t));
+vm_t* vm_new_vm(void *priv, const dvdnav_logger_cb *logcb) {
+  vm_t *vm = calloc(1, sizeof(vm_t));
+  if(vm)
+  {
+    vm->priv = priv;
+    if(logcb)
+        vm->logcb = *logcb;
+  }
+  return vm;
 }
 
 void vm_free_vm(vm_t *vm) {
@@ -326,7 +335,7 @@ static void vm_close(vm_t *vm) {
 }
 
 int vm_reset(vm_t *vm, const char *dvdroot,
-             void *stream, dvdnav_stream_cb *stream_cb) {
+             void *priv, dvdnav_stream_cb *stream_cb) {
   /*  Setup State */
   memset(vm->state.registers.SPRM, 0, sizeof(vm->state.registers.SPRM));
   memset(vm->state.registers.GPRM, 0, sizeof(vm->state.registers.GPRM));
@@ -363,61 +372,68 @@ int vm_reset(vm_t *vm, const char *dvdroot,
 
   vm->hop_channel                = 0;
 
-  if (vm->dvd && (dvdroot || (stream && stream_cb))) {
+  if (vm->dvd && (dvdroot || (priv && stream_cb))) {
     /* a new dvd device has been requested */
     vm_close(vm);
   }
   if (!vm->dvd) {
     if(dvdroot)
         vm->dvd = DVDOpen(dvdroot);
-    else if(stream && stream_cb)
-        vm->dvd = DVDOpenStream(stream, (dvd_reader_stream_cb *)stream_cb);
+    else if(priv && stream_cb)
+        vm->dvd = DVDOpenStream(priv, (dvd_reader_stream_cb *)stream_cb);
     if(!vm->dvd) {
-      fprintf(MSG_OUT, "libdvdnav: vm: failed to open/read the DVD\n");
+      Log0(vm, "vm: failed to open/read the DVD");
       return 0;
     }
     vm->vmgi = ifoOpenVMGI(vm->dvd);
     if(!vm->vmgi) {
-      fprintf(MSG_OUT, "libdvdnav: vm: failed to read VIDEO_TS.IFO\n");
+      Log0(vm, "vm: vm: failed to read VIDEO_TS.IFO");
       return 0;
     }
     if(!ifoRead_FP_PGC(vm->vmgi)) {
-      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_FP_PGC failed\n");
+      Log0(vm, "vm: vm: ifoRead_FP_PGC failed");
       return 0;
     }
     if(!ifoRead_TT_SRPT(vm->vmgi)) {
-      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_TT_SRPT failed\n");
+      Log0(vm, "vm: vm: ifoRead_TT_SRPT failed");
       return 0;
     }
     if(!ifoRead_PGCI_UT(vm->vmgi)) {
-      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PGCI_UT failed\n");
+      Log0(vm, "vm: vm: ifoRead_PGCI_UT failed");
       return 0;
     }
     if(!ifoRead_PTL_MAIT(vm->vmgi)) {
-      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PTL_MAIT failed\n");
+      Log0(vm, "vm: ifoRead_PTL_MAIT failed");
       /* return 0; Not really used for now.. */
     }
     if(!ifoRead_VTS_ATRT(vm->vmgi)) {
-      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VTS_ATRT failed\n");
+      Log0(vm, "vm: ifoRead_VTS_ATRT failed");
       /* return 0; Not really used for now.. */
     }
     if(!ifoRead_VOBU_ADMAP(vm->vmgi)) {
-      fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VOBU_ADMAP vgmi failed\n");
+      Log0(vm, "vm: ifoRead_VOBU_ADMAP vgmi failed");
       /* return 0; Not really used for now.. */
     }
     /* ifoRead_TXTDT_MGI(vmgi); Not implemented yet */
-    if(dvd_read_name(vm->dvd_name, vm->dvd_serial, dvdroot) != 1) {
-      fprintf(MSG_OUT, "libdvdnav: vm: dvd_read_name failed\n");
+    if(dvd_read_name(vm, vm->dvd_name, vm->dvd_serial, dvdroot) != 1) {
+      Log1(vm, "vm: dvd_read_name failed");
     }
   }
   if (vm->vmgi) {
     int i, mask;
-    fprintf(MSG_OUT, "libdvdnav: DVD disk reports itself with Region mask 0x%08x. Regions:",
-      vm->vmgi->vmgi_mat->vmg_category);
+    char buffer[8 * 3 + 1];
+    char *p = buffer;
     for (i = 1, mask = 1; i <= 8; i++, mask <<= 1)
+    {
       if (((vm->vmgi->vmgi_mat->vmg_category >> 16) & mask) == 0)
-        fprintf(MSG_OUT, " %d", i);
-    fprintf(MSG_OUT, "\n");
+      {
+        sprintf(p, " %02d", i);
+        p +=3;
+      }
+    }
+    *p = 0;
+    Log2(vm, "DVD disk reports itself with Region mask 0x%08x. Regions:%s",
+      vm->vmgi->vmgi_mat->vmg_category, buffer);
   }
   return 1;
 }
@@ -426,7 +442,7 @@ int vm_reset(vm_t *vm, const char *dvdroot,
 /* copying and merging */
 
 vm_t *vm_new_copy(vm_t *source) {
-  vm_t *target = vm_new_vm();
+  vm_t *target = vm_new_vm(source->priv, &source->logcb);
   int vtsN;
   int pgcN = get_PGCN(source);
   int pgN  = (source->state).pgN;
@@ -685,12 +701,12 @@ static int process_command(vm_t *vm, link_t link_values) {
   while(link_values.command != PlayThis) {
 
 #ifdef TRACE
-    fprintf(MSG_OUT, "libdvdnav: Before printout starts:\n");
+    Log3(vm, "Before printout starts:");
     vm_print_link(link_values);
-    fprintf(MSG_OUT, "libdvdnav: Link values %i %i %i %i\n", link_values.command,
+    Log3(vm, "Link values %i %i %i %i", link_values.command,
             link_values.data1, link_values.data2, link_values.data3);
     vm_print_current_domain_state(vm);
-    fprintf(MSG_OUT, "libdvdnav: Before printout ends.\n");
+    Log3(vm, "Before printout ends.");
 #endif
 
     switch(link_values.command) {
@@ -810,7 +826,7 @@ static int process_command(vm_t *vm, link_t link_values) {
     case LinkRSM:
         /* Check and see if there is any rsm info!! */
         if (!vm->state.rsm_vtsN) {
-          fprintf(MSG_OUT, "libdvdnav: trying to resume without any resume info set\n");
+          Log2(vm, "trying to resume without any resume info set");
           link_values.command = Exit;
           break;
         }
@@ -1078,9 +1094,9 @@ static int process_command(vm_t *vm, link_t link_values) {
     }
 
 #ifdef TRACE
-    fprintf(MSG_OUT, "libdvdnav: After printout starts:\n");
+    Log3(vm, "After printout starts:");
     vm_print_current_domain_state(vm);
-    fprintf(MSG_OUT, "libdvdnav: After printout ends.\n");
+    Log3(vm, "After printout ends.");
 #endif
 
   }


=====================================
src/vm/vm.h
=====================================
@@ -67,6 +67,8 @@ typedef struct vm_position_s {
 } vm_position_t;
 
 typedef struct {
+  void *priv;
+  dvdnav_logger_cb logcb;
   dvd_reader_t *dvd;
   ifo_handle_t *vmgi;
   ifo_handle_t *vtsi;
@@ -101,7 +103,7 @@ typedef struct {
 #define PTL_REG      registers.SPRM[13]
 
 /* Initialisation & destruction */
-vm_t *vm_new_vm(void);
+vm_t *vm_new_vm(void *, const dvdnav_logger_cb *);
 void  vm_free_vm(vm_t *vm);
 
 /* IFO access */
@@ -114,7 +116,7 @@ dvd_reader_t *vm_get_dvd_reader(vm_t *vm);
 /* Basic Handling */
 int  vm_start(vm_t *vm);
 void vm_stop(vm_t *vm);
-int  vm_reset(vm_t *vm, const char *dvdroot, void *stream,
+int  vm_reset(vm_t *vm, const char *dvdroot, void *priv,
               dvdnav_stream_cb *stream_cb);
 
 /* copying and merging  - useful for try-running an operation */


=====================================
src/vm/vmget.c
=====================================
@@ -40,6 +40,7 @@
 #include "vm.h"
 #include "getset.h"
 #include "dvdnav_internal.h"
+#include "logger.h"
 
 /* getting information */
 
@@ -85,7 +86,7 @@ int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result) {
   part++;
 
   if (!found) {
-    fprintf(MSG_OUT, "libdvdnav: chapter NOT FOUND!\n");
+    Log1(vm, "chapter NOT FOUND!");
     return 0;
   }
 
@@ -93,8 +94,8 @@ int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result) {
 
 #ifdef TRACE
   if (title) {
-    fprintf(MSG_OUT, "libdvdnav: ************ this chapter FOUND!\n");
-    fprintf(MSG_OUT, "libdvdnav: VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n",
+    Log3(vm, "************ this chapter FOUND!");
+    Log3(vm, "VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i",
              title, part,
              vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgcn ,
              vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgn );
@@ -296,7 +297,7 @@ int vm_get_video_aspect(vm_t *vm) {
   int aspect = vm_get_video_attr(vm).display_aspect_ratio;
 
   if(aspect != 0 && aspect != 3) {
-    fprintf(MSG_OUT, "libdvdnav: display aspect ratio is unexpected: %d!\n", aspect);
+    Log1(vm, "display aspect ratio is unexpected: %d!", aspect);
     return -1;
   }
 



View it on GitLab: https://code.videolan.org/videolan/libdvdnav/-/compare/fccdbe0b3ebc501d3798ad83308830b7352331dc...ac7327d23e67d6358a34b39af0a71ffa6c915520

-- 
View it on GitLab: https://code.videolan.org/videolan/libdvdnav/-/compare/fccdbe0b3ebc501d3798ad83308830b7352331dc...ac7327d23e67d6358a34b39af0a71ffa6c915520
You're receiving this email because of your account on code.videolan.org.




More information about the libdvdnav-devel mailing list