]> git.sesse.net Git - vlc/blobdiff - modules/access/vcdx/access.c
vcdx: Fix memleaks.
[vlc] / modules / access / vcdx / access.c
index 0c377fe3fe0591d249cd2c3833b000b20bcacdf6..279c34a1fdc98beb17b1783c4cb25b6ee9685add 100644 (file)
@@ -2,7 +2,7 @@
  * vcd.c : VCD input module for vlc using libcdio, libvcd and libvcdinfo.
  *         vlc-specific things tend to go here.
  *****************************************************************************
- * Copyright (C) 2000, 2003, 2004 VideoLAN
+ * Copyright (C) 2000, 2003, 2004, 2005 the VideoLAN team
  * $Id$
  *
  * Authors: Rocky Bernstein <rocky@panix.com>
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
 
-#include <vlc/vlc.h>
-#include <vlc/intf.h>
-#include <vlc/input.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_interface.h>
+#include <vlc_input.h>
+#include <vlc_access.h>
+#include <vlc_charset.h>
 #include "vlc_keys.h"
 
 #include <cdio/cdio.h>
@@ -44,8 +50,6 @@
 #include "info.h"
 #include "intf.h"
 
-#define FREE_AND_NULL(ptr) if (NULL != ptr) free(ptr); ptr = NULL;
-
 extern void VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track,
                           const vcdinfo_itemid_t *p_itemid );
 
@@ -60,13 +64,13 @@ static int      VCDControl      ( access_t *p_access, int i_query,
                                   va_list args );
 
 /* Now those which are strictly internal */
-static vlc_bool_t  VCDEntryPoints  ( access_t * );
-static vlc_bool_t  VCDLIDs         ( access_t * );
-static vlc_bool_t  VCDSegments     ( access_t * );
+static bool  VCDEntryPoints  ( access_t * );
+static bool  VCDLIDs         ( access_t * );
+static bool  VCDSegments     ( access_t * );
 static int  VCDTitles       ( access_t * );
 static char *VCDParse       ( access_t *,
                               /*out*/ vcdinfo_itemid_t * p_itemid ,
-                              /*out*/ vlc_bool_t *play_single_item );
+                              /*out*/ bool *play_single_item );
 
 static void VCDUpdateVar( access_t *p_access, int i_entry, int i_action,
                           const char *p_varname, char *p_label,
@@ -92,17 +96,17 @@ cdio_log_handler (cdio_log_level_t level, const char message[])
   case CDIO_LOG_DEBUG:
   case CDIO_LOG_INFO:
     if (p_vcdplayer->i_debug & INPUT_DBG_CDIO)
-      msg_Dbg( p_vcd_access, message);
+      msg_Dbg( p_vcd_access, "%s", message);
     break;
   case CDIO_LOG_WARN:
-    msg_Warn( p_vcd_access, message);
+    msg_Warn( p_vcd_access, "%s", message);
     break;
   case CDIO_LOG_ERROR:
   case CDIO_LOG_ASSERT:
-    msg_Err( p_vcd_access, message);
+    msg_Err( p_vcd_access, "%s", message);
     break;
   default:
-    msg_Warn( p_vcd_access, message,
+    msg_Warn( p_vcd_access, "%s\n%s %d", message,
             _("The above message had unknown log level"),
             level);
   }
@@ -118,14 +122,14 @@ vcd_log_handler (vcd_log_level_t level, const char message[])
   case VCD_LOG_DEBUG:
   case VCD_LOG_INFO:
     if (p_vcdplayer->i_debug & INPUT_DBG_VCDINFO)
-      msg_Dbg( p_vcd_access, message);
+      msg_Dbg( p_vcd_access, "%s", message);
     break;
   case VCD_LOG_WARN:
-    msg_Warn( p_vcd_access, message);
+    msg_Warn( p_vcd_access, "%s", message);
     break;
   case VCD_LOG_ERROR:
   case VCD_LOG_ASSERT:
-    msg_Err( p_vcd_access, message);
+    msg_Err( p_vcd_access, "%s", message);
     break;
   default:
     msg_Warn( p_vcd_access, "%s\n%s %d", message,
@@ -185,18 +189,8 @@ VCDReadBlock( access_t * p_access )
         }
 #endif
 
-#if 1
         block_Release( p_block );
         return NULL;
-#else
-        {
-          memset(p_buf, 0, M2F2_SECTOR_SIZE);
-          p_buf += 2;
-          *p_buf = 0x01;
-          printf("++++hacked\n");
-          return p_block;
-        }
-#endif
 
       case READ_ERROR:
         /* Some sort of error. Should we increment lsn? to skip block?
@@ -208,23 +202,18 @@ VCDReadBlock( access_t * p_access )
           /* FIXME The below should be done in an event thread.
              Until then...
            */
-#if 0
+#if 1
           msleep( MILLISECONDS_PER_SEC * *p_buf );
-          p_vcd->in_still = VLC_FALSE;
+      VCDSetOrigin(p_access, p_vcdplayer->origin_lsn, p_vcdplayer->i_track,
+               &(p_vcdplayer->play_item));
+          // p_vcd->in_still = false;
           dbg_print(INPUT_DBG_STILL, "still wait time done");
 #else
           vcdIntfStillTime(p_vcdplayer->p_intf, *p_buf);
 #endif
 
-#if 1
           block_Release( p_block );
           return NULL;
-#else
-          memset(p_buf, 0, M2F2_SECTOR_SIZE);
-          p_buf += 2;
-          *p_buf = 0x01;
-          return p_block;
-#endif
         }
 
       default:
@@ -242,8 +231,13 @@ VCDReadBlock( access_t * p_access )
         if ( p_vcdplayer->i_lsn >= i_lsn && i_lsn != VCDINFO_NULL_LSN )
         {
             const track_t i_track = p_vcdplayer->i_track;
+
+        dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
+               "entry change to %d, current LSN %u >= end %u",
+               i_entry, p_vcdplayer->i_lsn, i_lsn);
+
             p_vcdplayer->play_item.num = i_entry;
-            dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "entry change" );
+
             VCDSetOrigin( p_access,  i_lsn, i_track,
                           &(p_vcdplayer->play_item) );
         }
@@ -270,15 +264,15 @@ VCDSeek( access_t * p_access, int64_t i_pos )
 
       /* Next sector to read */
       p_access->info.i_pos = i_pos;
-      p_vcdplayer->i_lsn = (i_pos / (int64_t)M2F2_SECTOR_SIZE) +
-                                p_vcdplayer->track_lsn;
+      p_vcdplayer->i_lsn = (i_pos / (int64_t) M2F2_SECTOR_SIZE) +
+    p_vcdplayer->origin_lsn;
 
       switch (p_vcdplayer->play_item.type) {
       case VCDINFO_ITEM_TYPE_TRACK:
       case VCDINFO_ITEM_TYPE_ENTRY:
         break ;
       default:
-        p_vcdplayer->b_valid_ep = VLC_FALSE;
+        p_vcdplayer->b_valid_ep = false;
       }
 
       /* Find entry */
@@ -305,29 +299,30 @@ VCDSeek( access_t * p_access, int64_t i_pos )
 
       dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
                  "orig %lu, cur: %lu, offset: %lld, entry %d",
-                 (long unsigned int) p_vcdplayer->origin_lsn, 
+                 (long unsigned int) p_vcdplayer->origin_lsn,
                  (long unsigned int) p_vcdplayer->i_lsn, i_pos,
                  i_entry );
  
       /* Find seekpoint */
       for( i_seekpoint = 0; i_seekpoint < t->i_seekpoint; i_seekpoint++ )
-       {
-         if( i_seekpoint + 1 >= t->i_seekpoint ) break;
-         if( i_pos < t->seekpoint[i_seekpoint + 1]->i_byte_offset ) break;
-       }
-      
+    {
+      if( i_seekpoint + 1 >= t->i_seekpoint ) break;
+      if( i_pos < t->seekpoint[i_seekpoint + 1]->i_byte_offset ) break;
+    }
       /* Update current seekpoint */
       if( i_seekpoint != p_access->info.i_seekpoint )
-       {
-         dbg_print( (INPUT_DBG_SEEK), "seekpoint change %lu", 
-                    (long unsigned int) i_seekpoint );
-         p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;
-         p_access->info.i_seekpoint = i_seekpoint;
-       }
+    {
+      dbg_print( (INPUT_DBG_SEEK), "seekpoint change %lu",
+             (long unsigned int) i_seekpoint );
+      p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;
+      p_access->info.i_seekpoint = i_seekpoint;
+    }
 
     }
+    p_access->info.b_eof = false;
     return VLC_SUCCESS;
-    
 }
 
 /*****************************************************************************
@@ -335,70 +330,70 @@ VCDSeek( access_t * p_access, int64_t i_pos )
   and initializes area information with that.
   Before calling this track information should have been read in.
  *****************************************************************************/
-static vlc_bool_t
+static bool
 VCDEntryPoints( access_t * p_access )
 {
-  if (!p_access || !p_access->p_sys) return VLC_FALSE;
-  
+  if (!p_access || !p_access->p_sys) return false;
   {
     vcdplayer_t       *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
-    const unsigned int i_entries   = 
+    const unsigned int i_entries   =
       vcdinfo_get_num_entries(p_vcdplayer->vcd);
-    const track_t      i_last_track 
+    const track_t      i_last_track
       = cdio_get_num_tracks(vcdinfo_get_cd_image(p_vcdplayer->vcd))
       + cdio_get_first_track_num(vcdinfo_get_cd_image(p_vcdplayer->vcd));
     unsigned int i;
-   
     if (0 == i_entries) {
       LOG_ERR ("no entires found -- something is wrong" );
-      return VLC_FALSE;
+      return false;
     }
-    
     p_vcdplayer->p_entries  = malloc( sizeof( lsn_t ) * i_entries );
-    
     if( p_vcdplayer->p_entries == NULL )
       {
-       LOG_ERR ("not enough memory for entry points treatment" );
-       return VLC_FALSE;
+    LOG_ERR ("not enough memory for entry points treatment" );
+    return false;
       }
-    
     p_vcdplayer->i_entries = i_entries;
-    
     for( i = 0 ; i < i_entries ; i++ )
     {
-       const track_t i_track = vcdinfo_get_track(p_vcdplayer->vcd, i);
-       if( i_track <= i_last_track ) {
-         seekpoint_t *s = vlc_seekpoint_New();
-         char psz_entry[100];
-         
-         snprintf(psz_entry, sizeof(psz_entry), "%s%02d", _("Entry "), i );
-
-         p_vcdplayer->p_entries[i] = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i);
-         
-         s->psz_name      = strdup(psz_entry);
-         s->i_byte_offset = 
-           (p_vcdplayer->p_entries[i] - vcdinfo_get_track_lsn(p_vcdplayer->vcd, i_track))
-           * M2F2_SECTOR_SIZE;
-         
-         dbg_print( INPUT_DBG_MRL, 
-                    "%s, lsn %d,  byte_offset %ld",
-                    s->psz_name, p_vcdplayer->p_entries[i], 
-                    (unsigned long int) s->i_byte_offset);
+    const track_t i_track = vcdinfo_get_track(p_vcdplayer->vcd, i);
+    if( i_track <= i_last_track ) {
+      seekpoint_t *s = vlc_seekpoint_New();
+      char psz_entry[100];
+    
+      snprintf(psz_entry, sizeof(psz_entry), "%s %02d", _("Entry"), i );
+
+      p_vcdplayer->p_entries[i] = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i);
+    
+      s->psz_name      = strdup(psz_entry);
+      s->i_byte_offset =
+        (p_vcdplayer->p_entries[i] - vcdinfo_get_track_lsn(p_vcdplayer->vcd, i_track))
+        * M2F2_SECTOR_SIZE;
+    
+      dbg_print( INPUT_DBG_MRL,
+             "%s, lsn %d,  byte_offset %ld",
+             s->psz_name, p_vcdplayer->p_entries[i],
+             (unsigned long int) s->i_byte_offset);
           TAB_APPEND( p_vcdplayer->p_title[i_track-1]->i_seekpoint,
                       p_vcdplayer->p_title[i_track-1]->seekpoint, s );
 
         } else
           msg_Warn( p_access, "wrong track number found in entry points" );
     }
-    p_vcdplayer->b_valid_ep = VLC_TRUE;
-    return VLC_TRUE;
+    p_vcdplayer->b_valid_ep = true;
+    return true;
   }
 }
 
 /*****************************************************************************
  * VCDSegments: Reads the information about the segments the disc.
  *****************************************************************************/
-static vlc_bool_t
+static bool
 VCDSegments( access_t * p_access )
 {
     vcdplayer_t   *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
@@ -410,7 +405,7 @@ VCDSegments( access_t * p_access )
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),
                "Segments: %d", p_vcdplayer->i_segments);
 
-    if ( 0 == p_vcdplayer->i_segments ) return VLC_FALSE;
+    if ( 0 == p_vcdplayer->i_segments ) return false;
 
     t = p_vcdplayer->p_title[p_vcdplayer->i_titles] = vlc_input_title_New();
     p_vcdplayer->i_titles++;
@@ -426,7 +421,7 @@ VCDSegments( access_t * p_access )
     if( p_vcdplayer->p_segments == NULL )
     {
         LOG_ERR ("not enough memory for segment treatment" );
-        return VLC_FALSE;
+        return false;
     }
 
     for( i = 0 ; i < p_vcdplayer->i_segments ; i++ )
@@ -435,7 +430,7 @@ VCDSegments( access_t * p_access )
         seekpoint_t *s = vlc_seekpoint_New();
         p_vcdplayer->p_segments[i] = vcdinfo_get_seg_lsn(p_vcdplayer->vcd, i);
 
-        snprintf( psz_segment, sizeof(psz_segment), "%s%02d", _("Segment "),
+        snprintf( psz_segment, sizeof(psz_segment), "%s %02d", _("Segment"),
                   i );
 
         s->i_byte_offset = 0; /* Not sure what this would mean here */
@@ -448,14 +443,14 @@ VCDSegments( access_t * p_access )
       vcdinfo_get_seg_sector_count(p_vcdplayer->vcd,
                                    p_vcdplayer->i_segments-1);
 
-    return VLC_TRUE;
+    return true;
 }
 
 /*****************************************************************************
  Build title table which will be returned via ACCESS_GET_TITLE_INFO.
 
  We start area addressing for tracks at 1 since the default area 0
- is reserved for segments. 
+ is reserved for segments.
  *****************************************************************************/
 static int
 VCDTitles( access_t * p_access )
@@ -465,7 +460,7 @@ VCDTitles( access_t * p_access )
        very careful about this. Note: cdio_get_first_track() will give the
        ISO-9660 track before the MPEG tracks.
      */
-  
     if (!p_access || !p_access->p_sys) return VLC_EGENERIC;
 
     {
@@ -477,18 +472,16 @@ VCDTitles( access_t * p_access )
         {
             input_title_t *t = p_vcdplayer->p_title[i-1] =
               vlc_input_title_New();
-            char psz_track[100];
-            uint32_t i_secsize =
-              vcdinfo_get_track_sect_count( p_vcdplayer->vcd, i );
+            char psz_track[80];
 
-            snprintf( psz_track, sizeof(psz_track), "%s%02d", _("Track "),
+            snprintf( psz_track, sizeof(psz_track), "%s %02d", _("Track"),
                                                     i );
-
-            t->i_size    = (i_secsize) * (int64_t) M2F2_SECTOR_SIZE;
+            t->i_size    = (int64_t) vcdinfo_get_track_size( p_vcdplayer->vcd,
+                                 i )
+          * M2F2_SECTOR_SIZE / CDIO_CD_FRAMESIZE ;
             t->psz_name  = strdup(psz_track);
 
-            dbg_print( INPUT_DBG_MRL, "track[%d] i_size: %lld",
-                       i, t->i_size );
+        dbg_print( INPUT_DBG_MRL, "track[%d] i_size: %lld", i, t->i_size );
 
             p_vcdplayer->i_titles++;
         }
@@ -500,7 +493,7 @@ VCDTitles( access_t * p_access )
 /*****************************************************************************
   VCDLIDs: Reads the LIST IDs from the LOT.
  *****************************************************************************/
-static vlc_bool_t
+static bool
 VCDLIDs( access_t * p_access )
 {
     vcdplayer_t   *p_vcdplayer = (vcdplayer_t *) p_access->p_sys;
@@ -513,11 +506,11 @@ VCDLIDs( access_t * p_access )
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),
                "LIDs: %d", p_vcdplayer->i_lids);
 
-    if ( 0 == p_vcdplayer->i_lids ) return VLC_FALSE;
+    if ( 0 == p_vcdplayer->i_lids ) return false;
 
     if (vcdinfo_read_psd (p_vcdplayer->vcd)) {
 
-      vcdinfo_visit_lot (p_vcdplayer->vcd, VLC_FALSE);
+      vcdinfo_visit_lot (p_vcdplayer->vcd, false);
 
 #if FIXED
     /*
@@ -527,13 +520,13 @@ VCDLIDs( access_t * p_access )
        it's best then to not try to read this at all.
      */
       if (vcdinfo_get_psd_x_size(p_vcdplayer->vcd))
-        vcdinfo_visit_lot (p_vcdplayer->vcd, VLC_TRUE);
+        vcdinfo_visit_lot (p_vcdplayer->vcd, true);
 #endif
     }
 
     /* Set up LIDs Navigation Menu */
     t = vlc_input_title_New();
-    t->b_menu = VLC_TRUE;
+    t->b_menu = true;
     t->psz_name = strdup( "LIDs" );
 
     i_title = p_vcdplayer->i_tracks;
@@ -542,7 +535,7 @@ VCDLIDs( access_t * p_access )
         char psz_lid[100];
         seekpoint_t *s = vlc_seekpoint_New();
 
-        snprintf( psz_lid, sizeof(psz_lid), "%s%02d", _("LID "),
+        snprintf( psz_lid, sizeof(psz_lid), "%s %02d", _("LID"),
                   i_lid );
 
         s->i_byte_offset = 0; /*  A lid doesn't have an offset
@@ -558,7 +551,7 @@ VCDLIDs( access_t * p_access )
     p_vcdplayer->i_titles++;
 #endif
 
-    return VLC_TRUE;
+    return true;
 }
 
 /*****************************************************************************
@@ -566,7 +559,7 @@ VCDLIDs( access_t * p_access )
  *****************************************************************************/
 static char *
 VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid,
-          /*out*/ vlc_bool_t *play_single_item )
+          /*out*/ bool *play_single_item )
 {
     vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
     char        *psz_parser;
@@ -576,7 +569,7 @@ VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid,
     if( config_GetInt( p_access, MODULE_STRING "-PBC" ) ) {
       p_itemid->type = VCDINFO_ITEM_TYPE_LID;
       p_itemid->num = 1;
-      *play_single_item = VLC_FALSE;
+      *play_single_item = false;
     }
     else
     {
@@ -618,22 +611,22 @@ VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid,
           case 'E':
             p_itemid->type = VCDINFO_ITEM_TYPE_ENTRY;
             ++psz_parser;
-            *play_single_item = VLC_TRUE;
+            *play_single_item = true;
             break;
           case 'P':
             p_itemid->type = VCDINFO_ITEM_TYPE_LID;
             ++psz_parser;
-            *play_single_item = VLC_FALSE;
+            *play_single_item = false;
             break;
           case 'S':
             p_itemid->type = VCDINFO_ITEM_TYPE_SEGMENT;
             ++psz_parser;
-            *play_single_item = VLC_TRUE;
+            *play_single_item = true;
             break;
           case 'T':
             p_itemid->type = VCDINFO_ITEM_TYPE_TRACK;
             ++psz_parser;
-            *play_single_item = VLC_TRUE;
+            *play_single_item = true;
             break;
           default: ;
           }
@@ -658,11 +651,12 @@ VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid,
       psz_source = config_GetPsz( p_access, "vcd" );
 
       if( !psz_source || 0==strlen(psz_source) ) {
+        free( psz_source );
         /* Scan for a CD-ROM drive with a VCD in it. */
         char **cd_drives = cdio_get_devices_with_cap( NULL,
                             ( CDIO_FS_ANAL_SVCD | CDIO_FS_ANAL_CVD
                               |CDIO_FS_ANAL_VIDEOCD | CDIO_FS_UNKNOWN ),
-                                                     VLC_TRUE );
+                                                     true );
         if( NULL == cd_drives ) return NULL;
         if( cd_drives[0] == NULL )
         {
@@ -682,7 +676,7 @@ VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid,
 }
 
 /*
-   Set's start origin subsequent seeks/reads
+   Sets start origin for subsequent seeks/reads
 */
 void
 VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track,
@@ -696,18 +690,23 @@ VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track,
 
   vcdplayer_set_origin(p_access, i_lsn, i_track, p_itemid);
 
-  p_access->info.i_pos     = ( i_lsn - p_vcdplayer->track_lsn )
-                             * M2F2_SECTOR_SIZE;
-  p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE
-                          |  INPUT_UPDATE_SEEKPOINT;
-
-
   switch (p_vcdplayer->play_item.type) {
   case VCDINFO_ITEM_TYPE_ENTRY:
       VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE,
                     "chapter", _("Entry"), "Setting entry/segment");
       p_access->info.i_title     = i_track-1;
-      p_access->info.i_size      = p_vcdplayer->p_title[i_track-1]->i_size;
+      if (p_vcdplayer->b_track_length)
+      {
+    p_access->info.i_size = p_vcdplayer->p_title[i_track-1]->i_size;
+    p_access->info.i_pos  = (int64_t) M2F2_SECTOR_SIZE *
+      (vcdinfo_get_track_lsn(p_vcdplayer->vcd, i_track) - i_lsn) ;
+      } else {
+    p_access->info.i_size = M2F2_SECTOR_SIZE * (int64_t)
+      vcdinfo_get_entry_sect_count(p_vcdplayer->vcd, p_itemid->num);
+    p_access->info.i_pos = 0;
+      }
+      dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "size: %llu, pos: %llu",
+         p_access->info.i_size, p_access->info.i_pos );
       p_access->info.i_seekpoint = p_itemid->num;
       break;
 
@@ -719,7 +718,8 @@ VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track,
          the entry seekpoints and (zeroed) lid seekpoints.
       */
       p_access->info.i_title     = p_vcdplayer->i_titles - 1;
-      p_access->info.i_size      = 150 * M2F2_SECTOR_SIZE;
+      p_access->info.i_size      = 0; /* No seeking on stills, please. */
+      p_access->info.i_pos       = 0;
       p_access->info.i_seekpoint = p_vcdplayer->i_entries
         + p_vcdplayer->i_lids + p_itemid->num;
       break;
@@ -727,14 +727,18 @@ VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track,
   case VCDINFO_ITEM_TYPE_TRACK:
       p_access->info.i_title     = i_track-1;
       p_access->info.i_size      = p_vcdplayer->p_title[i_track-1]->i_size;
+      p_access->info.i_pos       = 0;
       p_access->info.i_seekpoint = vcdinfo_track_get_entry(p_vcdplayer->vcd,
                                                            i_track);
       break;
+
   default:
       msg_Warn( p_access, "can't set origin for play type %d",
                 p_vcdplayer->play_item.type );
   }
 
+  p_access->info.i_update = INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE
+    |  INPUT_UPDATE_SEEKPOINT;
 
   VCDUpdateTitle( p_access );
 
@@ -757,7 +761,7 @@ vcd_Open( vlc_object_t *p_this, const char *psz_dev )
 
     if( !psz_dev ) return NULL;
 
-    actual_dev=strdup(psz_dev);
+    actual_dev= ToLocaleDup(psz_dev);
     if ( vcdinfo_open(&p_vcdobj, &actual_dev, DRIVER_UNKNOWN, NULL) !=
          VCDINFO_OPEN_VCD) {
       free(actual_dev);
@@ -853,17 +857,17 @@ VCDOpen ( vlc_object_t *p_this )
     vcdplayer_t      *p_vcdplayer;
     char             *psz_source;
     vcdinfo_itemid_t  itemid;
-    vlc_bool_t        play_single_item = VLC_FALSE;
+    bool        play_single_item = false;
 
     p_access->pf_read          = NULL;
-    p_access->pf_block         = VCDReadBlock; 
+    p_access->pf_block         = VCDReadBlock;
     p_access->pf_control       = VCDControl;
     p_access->pf_seek          = VCDSeek;
 
     p_access->info.i_update    = 0;
     p_access->info.i_size      = 0;
     p_access->info.i_pos       = 0;
-    p_access->info.b_eof       = VLC_FALSE;
+    p_access->info.b_eof       = false;
     p_access->info.i_title     = 0;
     p_access->info.i_seekpoint = 0;
 
@@ -875,6 +879,7 @@ VCDOpen ( vlc_object_t *p_this )
         return VLC_ENOMEM;
     }
 
+    p_vcdplayer->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
     p_access->p_sys = (access_sys_t *) p_vcdplayer;
 
     /* Set where to log errors messages from libcdio. */
@@ -894,19 +899,16 @@ VCDOpen ( vlc_object_t *p_this )
                psz_source, p_access->psz_path );
 
     p_vcdplayer->psz_source        = strdup(psz_source);
-    p_vcdplayer->i_debug           = config_GetInt( p_this,
-                                                  MODULE_STRING "-debug" );
     p_vcdplayer->i_blocks_per_read = config_GetInt( p_this, MODULE_STRING
                                                     "-blocks-per-read" );
-    p_vcdplayer->in_still          = VLC_FALSE;
+    p_vcdplayer->b_track_length    = config_GetInt( p_this, MODULE_STRING
+                                                    "-track-length" );
+    p_vcdplayer->in_still          = false;
     p_vcdplayer->play_item.type    = VCDINFO_ITEM_TYPE_NOTFOUND;
     p_vcdplayer->p_input           = vlc_object_find( p_access,
                                                       VLC_OBJECT_INPUT,
                                                       FIND_PARENT );
-    p_vcdplayer->p_demux           = vlc_object_find( p_access,
-                                                      VLC_OBJECT_DEMUX,
-                                                      FIND_PARENT );
-    p_vcdplayer->p_meta            = vlc_meta_New();
+//    p_vcdplayer->p_meta            = vlc_meta_New();
     p_vcdplayer->p_segments        = NULL;
     p_vcdplayer->p_entries         = NULL;
 
@@ -917,7 +919,7 @@ VCDOpen ( vlc_object_t *p_this )
         goto err_exit;
     }
 
-    p_vcdplayer->b_svd= (vlc_bool_t) vcdinfo_get_tracksSVD(p_vcdplayer->vcd);;
+    p_vcdplayer->b_svd= (bool) vcdinfo_get_tracksSVD(p_vcdplayer->vcd);;
 
     /* Get track information. */
     p_vcdplayer->i_tracks = vcdinfo_get_num_tracks(p_vcdplayer->vcd);
@@ -935,7 +937,7 @@ VCDOpen ( vlc_object_t *p_this )
     if( ! VCDEntryPoints( p_access ) )
     {
         msg_Warn( p_access, "could not read entry points, will not use them" );
-        p_vcdplayer->b_valid_ep = VLC_FALSE;
+        p_vcdplayer->b_valid_ep = false;
     }
 
     /* Initialize LID info and add that as a menu item */
@@ -956,6 +958,7 @@ VCDOpen ( vlc_object_t *p_this )
 
     vcdplayer_play( p_access, itemid );
 
+    free( p_access->psz_demux );
     p_access->psz_demux = strdup( "ps" );
 
 #if FIXED
@@ -964,8 +967,10 @@ VCDOpen ( vlc_object_t *p_this )
                         play_single_item );
 #endif
 
+#if FIXED
     p_vcdplayer->p_intf = intf_Create( p_access, "vcdx" );
-    p_vcdplayer->p_intf->b_block = VLC_FALSE;
+    p_vcdplayer->p_intf->b_block = false;
+#endif
     p_vcdplayer->p_access = p_access;
 
 #ifdef FIXED
@@ -977,7 +982,6 @@ VCDOpen ( vlc_object_t *p_this )
     return VLC_SUCCESS;
  err_exit:
     if( p_vcdplayer->p_input ) vlc_object_release( p_vcdplayer->p_input );
-    if( p_vcdplayer->p_demux ) vlc_object_release( p_vcdplayer->p_demux );
     free( psz_source );
     free( p_vcdplayer );
     return VLC_EGENERIC;
@@ -994,21 +998,25 @@ VCDClose ( vlc_object_t *p_this )
 
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "VCDClose" );
 
+    {
+      unsigned int i;
+      for (i=0 ; i<p_vcdplayer->i_titles; i++)
+    if (p_vcdplayer->p_title[i])
+      free(p_vcdplayer->p_title[i]->psz_name);
+    }
     vcdinfo_close( p_vcdplayer->vcd );
 
     if( p_vcdplayer->p_input ) vlc_object_release( p_vcdplayer->p_input );
-    if( p_vcdplayer->p_demux ) vlc_object_release( p_vcdplayer->p_demux );
-
 
-    FREE_AND_NULL( p_vcdplayer->p_entries );
-    FREE_AND_NULL( p_vcdplayer->p_segments );
-    FREE_AND_NULL( p_vcdplayer->psz_source );
-    FREE_AND_NULL( p_vcdplayer->track );
-    FREE_AND_NULL( p_vcdplayer->segment );
-    FREE_AND_NULL( p_vcdplayer->entry );
-
-    free( p_vcdplayer );
-    p_access->p_sys = NULL;
+    FREENULL( p_vcdplayer->p_entries );
+    FREENULL( p_vcdplayer->p_segments );
+    FREENULL( p_vcdplayer->psz_source );
+    FREENULL( p_vcdplayer->track );
+    FREENULL( p_vcdplayer->segment );
+    FREENULL( p_vcdplayer->entry );
+    FREENULL( p_access->psz_demux );
+    FREENULL( p_vcdplayer );
     p_vcd_access    = NULL;
 }
 
@@ -1036,11 +1044,14 @@ static int VCDControl( access_t *p_access, int i_query, va_list args )
             vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
 
             dbg_print( INPUT_DBG_EVENT, "get meta info" );
-
-            if ( p_vcdplayer->p_meta ) {
-              *pp_meta = vlc_meta_Duplicate( p_vcdplayer->p_meta );
-              dbg_print( INPUT_DBG_META, "%s", "Meta copied" );
-            } else
+#if 0
+            if( p_vcdplayer->p_meta )
+            {
+                *pp_meta = vlc_meta_Duplicate( p_vcdplayer->p_meta );
+                dbg_print( INPUT_DBG_META, "%s", "Meta copied" );
+            }
+            else
+#endif
               msg_Warn( p_access, "tried to copy NULL meta info" );
 
             return VLC_SUCCESS;
@@ -1052,11 +1063,11 @@ static int VCDControl( access_t *p_access, int i_query, va_list args )
         case ACCESS_CAN_PAUSE:
         case ACCESS_CAN_CONTROL_PACE:
         {
-            vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
+            bool *pb_bool = (bool*)va_arg( args, bool* );
 
             dbg_print( INPUT_DBG_EVENT,
                        "seek/fastseek/pause/can_control_pace" );
-            *pb_bool = VLC_TRUE;
+            *pb_bool = true;
             return VLC_SUCCESS;
             break;
           }
@@ -1139,11 +1150,26 @@ static int VCDControl( access_t *p_access, int i_query, va_list args )
                 unsigned int     i_entry =
                   vcdinfo_track_get_entry( p_vcdplayer->vcd, i_track);
 
-                /* FIXME! For now we are assuming titles are only
-                 tracks and that track == title+1 */
-                itemid.num = i_track;
-                itemid.type = VCDINFO_ITEM_TYPE_TRACK;
-
+        if( i < p_vcdplayer->i_tracks )
+        {
+            /* FIXME! For now we are assuming titles are only
+               tracks and that track == title+1 */
+            itemid.num = i_track;
+            itemid.type = VCDINFO_ITEM_TYPE_TRACK;
+        }
+        else
+        {
+            /* FIXME! i_tracks+2 are Segments, but we need to
+               be able to figure out which segment of that.
+                       i_tracks+1 is either Segments (if no LIDs) or
+               LIDs otherwise. Again need a way to get the LID
+               number. */
+            msg_Warn( p_access,
+                    "Trying to set track (%u) beyond end of last track (%u).",
+                  i+1, p_vcdplayer->i_tracks );
+            return VLC_EGENERIC;
+        }
+        
                 VCDSetOrigin(p_access,
                      vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i_entry),
                              i_track, &itemid );