]> git.sesse.net Git - vlc/commitdiff
First attempt to libcdio VCD working under new regime. It is still
authorRocky Bernstein <rocky@videolan.org>
Sun, 19 Dec 2004 13:58:38 +0000 (13:58 +0000)
committerRocky Bernstein <rocky@videolan.org>
Sun, 19 Dec 2004 13:58:38 +0000 (13:58 +0000)
mostly disabled or broken.

12 files changed:
modules/access/vcdx/Modules.am
modules/access/vcdx/access.c
modules/access/vcdx/cdrom.c
modules/access/vcdx/cdrom.h
modules/access/vcdx/demux.c
modules/access/vcdx/info.c [new file with mode: 0644]
modules/access/vcdx/info.h [new file with mode: 0644]
modules/access/vcdx/intf.h
modules/access/vcdx/vcd.c
modules/access/vcdx/vcd.h
modules/access/vcdx/vcdplayer.c
modules/access/vcdx/vcdplayer.h

index 58af28076f1235cf01e5ac4f0639b6fa72c16a2f..02bbe8ddc6987f5b315e83cd7cf533cee0687884 100644 (file)
@@ -2,11 +2,11 @@ SOURCES_vcdx = \
        access.c \
        cdrom.c \
        cdrom.h \
-       demux.c \
-       intf.c \
        intf.h \
        vcd.c \
        vcd.h \
        vcdplayer.h \
        vcdplayer.c \
+       info.c \
+       info.h \
        $(NULL)
index 0664238502b24bac20117b7af875ce68f6388ed9..9e03318955461d31b55c63b7e93cf28162b3109f 100644 (file)
@@ -7,7 +7,8 @@
  * $Id$
  *
  * Authors: Rocky Bernstein <rocky@panix.com>
- *          Johan Bilien <jobi@via.ecp.fr>
+ *   Some code is based on the non-libcdio VCD plugin (as there really
+ *   isn't real documentation yet.)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *****************************************************************************/
 
 #include <vlc/vlc.h>
-#include <vlc/input.h>
 #include <vlc/intf.h>
+#include <vlc/input.h>
 
-#include "../../demux/mpeg/system.h"
 #include "vcd.h"
 #include "vcdplayer.h"
 #include "intf.h"
+#include "info.h"
+#include "vlc_keys.h"
 
 #include <cdio/cdio.h>
 #include <cdio/cd_types.h>
 
 /* how many blocks VCDRead will read in each loop */
 #define VCD_BLOCKS_ONCE 20
-#define VCD_DATA_ONCE   (VCD_BLOCKS_ONCE * M2F2_SECTOR_SIZE)
-
-#define VCD_MRL_PREFIX "vcdx://"
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
 
 /* First those which are accessed from outside (via pointers). */
-static int  VCDRead         ( input_thread_t *, byte_t *, size_t );
-static int  VCDSetProgram   ( input_thread_t *, pgrm_descriptor_t * );
+static block_t *VCDReadBlock    ( access_t * );
+
+static int      VCDControl      ( access_t *p_access, int i_query, 
+                                 va_list args );
 
 /* Now those which are strictly internal */
-static void VCDSetOrigin    ( input_thread_t *, lsn_t origin_lsn,
-                              lsn_t cur_lsn, lsn_t end_lsn,
-                              int cur_entry, track_t track );
-static int  VCDEntryPoints  ( input_thread_t * );
-static int  VCDLIDs         ( input_thread_t * );
-static int  VCDSegments     ( input_thread_t * );
-static void VCDTracks       ( input_thread_t * );
+static void VCDSetOrigin    ( access_t *p_access,
+                             lsn_t origin_lsn,
+                              lsn_t i_lsn, lsn_t end_lsn,
+                              track_t track, 
+                             const vcdinfo_itemid_t * p_itemid );
+static int  VCDEntryPoints  ( access_t * );
+static int  VCDLIDs         ( access_t * );
+#ifdef FIXED
+static int  VCDSegments     ( access_t * );
+#endif
+static int  VCDTitles       ( access_t * );
 static int  VCDReadSector   ( vlc_object_t *p_this,
-                              const vcdinfo_obj_t *p_vcd, lsn_t cur_lsn,
+                              const vcdinfo_obj_t *p_vcd, lsn_t i_lsn,
                               byte_t * p_buffer );
-static char *VCDParse       ( input_thread_t *,
+static char *VCDParse       ( access_t *,
                               /*out*/ vcdinfo_itemid_t * p_itemid ,
                               /*out*/ vlc_bool_t *play_single_item );
 
-static void VCDUpdateVar( input_thread_t *p_input, int i_entry, int i_action,
+static void VCDUpdateVar( access_t *p_access, int i_entry, int i_action,
                           const char *p_varname, char *p_label,
                          const char *p_debug_label );
 
@@ -88,28 +93,28 @@ static vcdinfo_obj_t *vcd_Open   ( vlc_object_t *p_this, const char *psz_dev );
 /* FIXME: This variable is a hack. Would be nice to eliminate the
    global-ness. */
 
-static input_thread_t *p_vcd_input = NULL;
+static access_t *p_vcd_access = NULL;
 
 /* process messages that originate from libcdio. */
 static void
 cdio_log_handler (cdio_log_level_t level, const char message[])
 {
-  thread_vcd_data_t *p_vcd = (thread_vcd_data_t *)p_vcd_input->p_access_data;
+  const access_vcd_data_t *p_vcd = (access_vcd_data_t *)p_vcd_access->p_sys;
   switch (level) {
   case CDIO_LOG_DEBUG:
   case CDIO_LOG_INFO:
     if (p_vcd->i_debug & INPUT_DBG_CDIO)
-      msg_Dbg( p_vcd_input, message);
+      msg_Dbg( p_vcd_access, message);
     break;
   case CDIO_LOG_WARN:
-    msg_Warn( p_vcd_input, message);
+    msg_Warn( p_vcd_access, message);
     break;
   case CDIO_LOG_ERROR:
   case CDIO_LOG_ASSERT:
-    msg_Err( p_vcd_input, message);
+    msg_Err( p_vcd_access, message);
     break;
   default:
-    msg_Warn( p_vcd_input, message,
+    msg_Warn( p_vcd_access, message,
             _("The above message had unknown log level"),
             level);
   }
@@ -120,22 +125,22 @@ cdio_log_handler (cdio_log_level_t level, const char message[])
 static void
 vcd_log_handler (vcd_log_level_t level, const char message[])
 {
-  thread_vcd_data_t *p_vcd = (thread_vcd_data_t *)p_vcd_input->p_access_data;
+  access_vcd_data_t *p_vcd = (access_vcd_data_t *)p_vcd_access->p_sys;
   switch (level) {
   case VCD_LOG_DEBUG:
   case VCD_LOG_INFO:
     if (p_vcd->i_debug & INPUT_DBG_VCDINFO)
-      msg_Dbg( p_vcd_input, message);
+      msg_Dbg( p_vcd_access, message);
     break;
   case VCD_LOG_WARN:
-    msg_Warn( p_vcd_input, message);
+    msg_Warn( p_vcd_access, message);
     break;
   case VCD_LOG_ERROR:
   case VCD_LOG_ASSERT:
-    msg_Err( p_vcd_input, message);
+    msg_Err( p_vcd_access, message);
     break;
   default:
-    msg_Warn( p_vcd_input, "%s\n%s %d", message,
+    msg_Warn( p_vcd_access, "%s\n%s %d", message,
             _("The above message had unknown vcdimager log level"),
             level);
   }
@@ -143,16 +148,15 @@ vcd_log_handler (vcd_log_level_t level, const char message[])
 }
 
 /*****************************************************************************
- * VCDRead: reads i_len bytes from the VCD into p_buffer.
- *****************************************************************************
- * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
- * bytes.
+  VCDRead: reads VCD_BLOCKS_ONCE from the VCD and returns that.
+  NULL is returned if something went wrong.
  *****************************************************************************/
-static int
-VCDRead( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
+static block_t *
+VCDReadBlock( access_t * p_access )
 {
-    thread_vcd_data_t *     p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
-    int                     i_blocks;
+    access_vcd_data_t *     p_vcd= (access_vcd_data_t *)p_access->p_sys;
+    block_t                *p_block;
+    int                     i_blocks = VCD_BLOCKS_ONCE;
     int                     i_index;
     int                     i_read;
     byte_t                  p_last_sector[ M2F2_SECTOR_SIZE ];
@@ -160,40 +164,47 @@ VCDRead( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
     i_read = 0;
 
     dbg_print( (INPUT_DBG_CALL), "lsn: %lu", 
-              (long unsigned int) p_vcd->cur_lsn );
+              (long unsigned int) p_vcd->i_lsn );
 
     /* Compute the number of blocks we have to read */
 
-    i_blocks = i_len / M2F2_SECTOR_SIZE;
+    i_blocks = VCD_BLOCKS_ONCE ;
+
+    /* Allocate a block for the reading */
+    if( !( p_block = block_New( p_access, i_blocks * M2F2_SECTOR_SIZE ) ) )
+    {
+        msg_Err( p_access, "cannot get a new block of size: %i",
+                 i_blocks * M2F2_SECTOR_SIZE );
+       block_Release( p_block );
+        return NULL;
+    }
 
     for ( i_index = 0 ; i_index < i_blocks ; i_index++ )
     {
 
-      if ( p_vcd->cur_lsn == p_vcd->end_lsn ) {
+      if ( p_vcd->i_lsn == p_vcd->end_lsn ) {
         vcdplayer_read_status_t read_status;
 
         /* We've run off of the end of this entry. Do we continue or stop? */
         dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
                    "end reached, cur: %lu", 
-                  (long unsigned int) p_vcd->cur_lsn );
+                  (long unsigned int) p_vcd->i_lsn );
 
         read_status = vcdplayer_pbc_is_on( p_vcd )
-          ? vcdplayer_pbc_nav( p_input )
-          : vcdplayer_non_pbc_nav( p_input );
+          ? vcdplayer_pbc_nav( p_access )
+          : vcdplayer_non_pbc_nav( p_access );
 
         switch (read_status) {
         case READ_END:
           /* End reached. Return NULL to indicated this. */
         case READ_ERROR:
           /* Some sort of error. */
-          return i_read;
+          return NULL;
 
         case READ_STILL_FRAME:
           {
             /* Reached the end of a still frame. */
-
-            byte_t * p_buf = p_buffer;
-            pgrm_descriptor_t * p_pgrm = p_input->stream.p_selected_program;;
+            byte_t * p_buf = (byte_t *) p_block->p_buffer;
 
             p_buf += (i_index*M2F2_SECTOR_SIZE);
             memset(p_buf, 0, M2F2_SECTOR_SIZE);
@@ -201,24 +212,10 @@ VCDRead( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
             *p_buf = 0x01;
             dbg_print(INPUT_DBG_STILL, "Handled still event");
 
-#if 1
-            p_vcd->p_intf->p_sys->b_still = 1;
-            var_SetInteger( p_input, "state", PAUSE_S );
-#endif
-
-            vlc_mutex_lock( &p_input->stream.stream_lock );
-
-            p_pgrm = p_input->stream.p_selected_program;
-            p_pgrm->i_synchro_state = SYNCHRO_REINIT;
-
-            vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-            input_ClockManageControl( p_input, p_pgrm, 0 );
+            p_vcd->p_intf->p_sys->b_still = VLC_TRUE;
+            var_SetInteger( p_access, "state", PAUSE_S );
 
-            p_vcd->p_intf->p_sys->b_still = 1;
-            var_SetInteger( p_input, "state", PAUSE_S );
-
-            return i_read + M2F2_SECTOR_SIZE;
+            return p_block;
           }
         default:
         case READ_BLOCK:
@@ -226,206 +223,115 @@ VCDRead( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
         }
       }
 
-      if ( VCDReadSector( VLC_OBJECT(p_input), p_vcd->vcd,
-                          p_vcd->cur_lsn,
-                          p_buffer + (i_index*M2F2_SECTOR_SIZE) ) < 0 )
+      if ( VCDReadSector( VLC_OBJECT(p_access), p_vcd->vcd,
+                          p_vcd->i_lsn,
+                          (byte_t *) p_block->p_buffer + (i_index*M2F2_SECTOR_SIZE) ) < 0 )
         {
           LOG_ERR ("could not read sector %lu", 
-                  (long unsigned int) p_vcd->cur_lsn );
-          return -1;
+                  (long unsigned int) p_vcd->i_lsn );
+          return NULL;
         }
 
-      p_vcd->cur_lsn ++;
-
-      /* Update chapter */
-      if( p_vcd->b_valid_ep &&
-          /* FIXME kludge so that read does not update chapter
-           * when a manual chapter change was requested and not
-           * yet accomplished */
-          !p_input->stream.p_new_area )
-        {
-          unsigned int i_entry = p_input->stream.p_selected_area->i_part;
-
-          vlc_mutex_lock( &p_input->stream.stream_lock );
+      p_vcd->i_lsn ++;
 
-          if( i_entry < p_vcd->num_entries &&
-              p_vcd->cur_lsn >= p_vcd->p_entries[i_entry+1] )
-            {
-              dbg_print( INPUT_DBG_PBC,
-                         "new entry, i_entry %d, sector %lu, es %u",
-                         i_entry, (long unsigned int) p_vcd->cur_lsn,
-                         p_vcd->p_entries[i_entry] );
-              p_vcd->play_item.num =
-                ++ p_input->stream.p_selected_area->i_part;
-              p_vcd->play_item.type = VCDINFO_ITEM_TYPE_ENTRY;
-              VCDUpdateVar( p_input, p_vcd->play_item.num, VLC_VAR_SETVALUE,
-                            "chapter", _("Entry"), "Setting entry" );
-            }
-          vlc_mutex_unlock( &p_input->stream.stream_lock );
-        }
-
-        i_read += M2F2_SECTOR_SIZE;
     }
 
-    if ( i_len % M2F2_SECTOR_SIZE ) /* this should not happen */
+    if ( i_index != i_blocks ) /* this should not happen */
     {
-        if ( VCDReadSector( VLC_OBJECT(p_input), p_vcd->vcd,
-                            p_vcd->cur_lsn, p_last_sector ) < 0 )
+        if ( VCDReadSector( VLC_OBJECT(p_access), p_vcd->vcd,
+                            p_vcd->i_lsn, p_last_sector ) < 0 )
         {
             LOG_ERR ("could not read sector %lu", 
-                    (long unsigned int) p_vcd->cur_lsn );
-            return -1;
+                    (long unsigned int) p_vcd->i_lsn );
         }
-
-        p_input->p_vlc->pf_memcpy( p_buffer + i_blocks * M2F2_SECTOR_SIZE,
-                                   p_last_sector, i_len % M2F2_SECTOR_SIZE );
-        i_read += i_len % M2F2_SECTOR_SIZE;
+       
+       return NULL;
     }
 
-    return i_read;
-}
-
-
-/*****************************************************************************
- * VCDSetProgram: Does nothing since a VCD is mono_program
- *****************************************************************************/
-static int
-VCDSetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_program)
-{
-    thread_vcd_data_t *     p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
-    dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "VCDSetProgram" );
-    return 0;
-}
-
-
-/*****************************************************************************
- * VCDSetArea: initialize internal data structures and input stream data
-   so set subsequent reading and seeking to reflect that we are
-   at track x, entry or segment y.
-   This is called for each user navigation request, e.g. the GUI
-   Chapter/Title selections or in initial MRL parsing.
- ****************************************************************************/
-int
-VCDSetArea( input_thread_t * p_input, input_area_t * p_area )
-{
-    thread_vcd_data_t *p_vcd = (thread_vcd_data_t*)p_input->p_access_data;
-    unsigned int i_entry = p_area->i_part;
-    track_t i_track      = p_area->i_id;
-    int old_seekable     = p_input->stream.b_seekable;
-    unsigned int i_nb    = p_area->i_plugin_data + p_area->i_part_nb;
-
-    dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT),
-               "track: %d, entry %d, seekable %d, area %lx, select area %lx ",
-               i_track, i_entry, old_seekable,
-               (long unsigned int) p_area,
-               (long unsigned int) p_input->stream.p_selected_area );
-
-    /* we can't use the interface slider until initilization is complete */
-    p_input->stream.b_seekable = 0;
-
-    if( p_area != p_input->stream.p_selected_area )
+    /* Update seekpoints */
+    for( i_read = 0; i_read < i_blocks; i_read++ )
     {
-        unsigned int i;
-
-        /* If is the result of a track change, make the entry valid. */
-        if (i_entry < p_area->i_plugin_data || i_entry >= i_nb)
-          i_entry = p_area->i_plugin_data;
-
-        /* Change the default area */
-        p_input->stream.p_selected_area = p_area;
+        input_title_t *t = p_vcd->p_title[p_access->info.i_title];
 
-        /* Update the navigation variables without triggering a callback */
-
-        VCDUpdateVar( p_input, i_track, VLC_VAR_SETVALUE, "title",
-                      _("Track"), "Setting track");
-
-        var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL );
-        for( i = p_area->i_plugin_data; i < i_nb; i++ )
+        if( t->i_seekpoint > 0 &&
+            p_access->info.i_seekpoint + 1 < t->i_seekpoint &&
+            p_access->info.i_pos + i_read * M2F2_SECTOR_SIZE >=
+            t->seekpoint[p_access->info.i_seekpoint+1]->i_byte_offset )
         {
-          VCDUpdateVar( p_input, i , VLC_VAR_ADDCHOICE,
-                        "chapter",  
-                       p_vcd->play_item.type == VCDINFO_ITEM_TYPE_SEGMENT ?
-                       _("Segment"): _("Entry"),
-                       "Adding entry choice");
+            msg_Dbg( p_access, "seekpoint change" );
+            p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;
+            p_access->info.i_seekpoint++;
         }
-
-       if (p_vcd->b_svd) {
-         unsigned int audio_type = 
-           vcdinfo_get_track_audio_type(p_vcd->vcd, i_track);
-         unsigned int i_channels = 
-           vcdinfo_audio_type_num_channels(p_vcd->vcd, audio_type);
-         
-         var_Change( p_input, "audio_channels", VLC_VAR_CLEARCHOICES, NULL, 
-                     NULL );
-         
-         for( i = 0;  i < i_channels; i++ )
-           {
-             VCDUpdateVar( p_input, i , VLC_VAR_ADDCHOICE,
-                           "audio_channels",  NULL, "Adding audio choice");
-           }
-       }
-
     }
 
-    if (i_track == 0)
-      VCDSetOrigin( p_input, p_vcd->p_segments[i_entry],
-                    p_vcd->p_segments[i_entry], p_vcd->p_segments[i_entry+1],
-                    i_entry, 0 );
-    else
-      VCDSetOrigin( p_input, p_vcd->p_sectors[i_track],
-                    vcdinfo_get_entry_lsn(p_vcd->vcd, i_entry),
-                    p_vcd->p_sectors[i_track+1],
-                    i_entry, i_track );
+    /* Update a few values */
+    p_vcd->i_lsn += i_blocks;
+    p_access->info.i_pos += p_block->i_buffer;
 
-    p_input->stream.b_seekable = old_seekable;
-    /* warn interface that something has changed */
-    p_input->stream.b_changed = 1;
-
-    return VLC_SUCCESS;
+    return p_block;
 }
 
 
 /****************************************************************************
  * VCDSeek
  ****************************************************************************/
-void
-VCDSeek( input_thread_t * p_input, off_t i_off )
+int
+VCDSeek( access_t * p_access, int64_t i_pos )
 {
-    thread_vcd_data_t * p_vcd;
-    unsigned int i_entry=0; /* invalid entry */
-
-    p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-
-    p_vcd->cur_lsn = p_vcd->origin_lsn + (i_off / (off_t)M2F2_SECTOR_SIZE);
-
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-#define p_area p_input->stream.p_selected_area
-    /* Find entry */
-    if( p_vcd->b_valid_ep )
+    if (!p_access || !p_access->p_sys) return VLC_EGENERIC;
+    
     {
-        for( i_entry = 0 ; i_entry < p_vcd->num_entries ; i_entry ++ )
-        {
-            if( p_vcd->cur_lsn < p_vcd->p_entries[i_entry] )
-            {
-              VCDUpdateVar( p_input, i_entry, VLC_VAR_SETVALUE,
-                            "chapter", _("Entry"), "Setting entry" );
-              break;
-            }
-        }
-        p_vcd->play_item.num  = p_area->i_part = i_entry;
-        p_vcd->play_item.type = VCDINFO_ITEM_TYPE_ENTRY;
-    }
-#undef p_area
-
-    p_input->stream.p_selected_area->i_tell = i_off;
-
-    dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
-               "orig %lu, cur: %lu, offset: %lld, start: %lld, entry %d",
-               (long unsigned int) p_vcd->origin_lsn, 
-              (long unsigned int) p_vcd->cur_lsn, i_off,
-               p_input->stream.p_selected_area->i_start, i_entry );
+      access_vcd_data_t *p_vcd = 
+       (access_vcd_data_t *)p_vcd_access->p_sys;
+      const input_title_t *t = p_vcd->p_title[p_access->info.i_title];
+      int i_seekpoint;
+      unsigned int i_entry=VCDINFO_INVALID_ENTRY; 
+      
+      /* Next sector to read */
+      p_access->info.i_pos = i_pos;
+      p_vcd->i_lsn = (i_pos / (int64_t)M2F2_SECTOR_SIZE) +
+       p_vcd->origin_lsn;
+      
+      /* Find entry */
+      if( p_vcd->b_valid_ep )
+       {
+         for( i_entry = 0 ; i_entry < p_vcd->i_entries ; i_entry ++ )
+           {
+             if( p_vcd->i_lsn < p_vcd->p_entries[i_entry] )
+               {
+                 VCDUpdateVar( p_access, i_entry, VLC_VAR_SETVALUE,
+                               "chapter", _("Entry"), "Setting entry" );
+                 break;
+               }
+           }
+         p_vcd->play_item.num  = i_entry;
+         p_vcd->play_item.type = VCDINFO_ITEM_TYPE_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;
+       }
+      
+      /* Update current seekpoint */
+      if( i_seekpoint != p_access->info.i_seekpoint )
+       {
+         msg_Dbg( p_access, "seekpoint change" );
+         p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;
+         p_access->info.i_seekpoint = i_seekpoint;
+       }
 
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
+      dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
+                "orig %lu, cur: %lu, offset: %lld, entry %d",
+                (long unsigned int) p_vcd->origin_lsn, 
+                (long unsigned int) p_vcd->i_lsn, i_pos,
+                i_entry );
+      
+    }
+    return VLC_SUCCESS;
+    
 }
 
 /*****************************************************************************
@@ -436,147 +342,149 @@ VCDSeek( input_thread_t * p_input, off_t i_off )
   for differences in numbering.
  *****************************************************************************/
 int
-VCDPlay( input_thread_t *p_input, vcdinfo_itemid_t itemid )
+VCDPlay( access_t *p_access, vcdinfo_itemid_t itemid )
 {
-    thread_vcd_data_t *     p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
-    input_area_t *          p_area;
-    vlc_bool_t              b_was_still;
-
-    dbg_print(INPUT_DBG_CALL, "itemid.num: %d, itemid.type: %d\n",
-              itemid.num, itemid.type);
-
-    if (!p_input->p_access_data) return VLC_EGENERIC;
+    if (!p_access || !p_access->p_sys) return VLC_EGENERIC;
     
-    b_was_still = p_vcd->in_still;
-
-#define area p_input->stream.pp_areas
-
-    switch (itemid.type) {
-    case VCDINFO_ITEM_TYPE_TRACK:
-
-      /* Valid tracks go from 1...num_tracks-1, because track 0 is unplayable.
-       */
-
-      if (itemid.num == 0 || itemid.num >= p_vcd->num_tracks) {
-        LOG_ERR ("Invalid track number %d", itemid.num );
-        return VLC_EGENERIC;
-      }
-      p_vcd->in_still  = VLC_FALSE;
-      p_area           = area[itemid.num];
-      p_area->i_part   = p_area->i_plugin_data;
-      p_input->stream.b_seekable = 1;
-      break;
-    case VCDINFO_ITEM_TYPE_SEGMENT:
-      /* Valid segments go from 0...num_segments-1. */
-      if (itemid.num >= p_vcd->num_segments) {
-        LOG_ERR ( "Invalid segment number: %d", itemid.num );
-        return VLC_EGENERIC;
-      } else {
-        vcdinfo_video_segment_type_t segtype =
-          vcdinfo_get_video_type(p_vcd->vcd, itemid.num);
-
-        dbg_print(INPUT_DBG_PBC, "%s (%d), seg_num: %d",
-                  vcdinfo_video_type2str(p_vcd->vcd, itemid.num),
-                  (int) segtype, itemid.num);
-
-        p_area           = area[0];
-        p_area->i_part   = itemid.num;
-
-        switch (segtype)
-          {
-          case VCDINFO_FILES_VIDEO_NTSC_STILL:
-          case VCDINFO_FILES_VIDEO_NTSC_STILL2:
-          case VCDINFO_FILES_VIDEO_PAL_STILL:
-          case VCDINFO_FILES_VIDEO_PAL_STILL2:
-            p_input->stream.b_seekable = 0;
-            p_vcd->in_still = VLC_TRUE;
-            break;
-          default:
-            p_input->stream.b_seekable = 1;
-            p_vcd->in_still = VLC_FALSE;
-          }
-      }
-      break;
-
-    case VCDINFO_ITEM_TYPE_LID:
-      /* LIDs go from 1..num_lids. */
-      if (itemid.num == 0 || itemid.num > p_vcd->num_lids) {
-        LOG_ERR ( "Invalid LID number: %d", itemid.num );
-        return VLC_EGENERIC;
-      } else {
-        p_vcd->cur_lid = itemid.num;
-        vcdinfo_lid_get_pxd(p_vcd->vcd, &(p_vcd->pxd), itemid.num);
-
-        switch (p_vcd->pxd.descriptor_type) {
-
-        case PSD_TYPE_SELECTION_LIST:
-        case PSD_TYPE_EXT_SELECTION_LIST: {
-          vcdinfo_itemid_t trans_itemid;
-          uint16_t trans_itemid_num;
-
-          if (p_vcd->pxd.psd == NULL) return VLC_EGENERIC;
-          trans_itemid_num  = vcdinf_psd_get_itemid(p_vcd->pxd.psd);
-          vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
-          p_vcd->loop_count = 1;
-          p_vcd->loop_item  = trans_itemid;
-          return VCDPlay( p_input, trans_itemid );
-          break;
-        }
-
-        case PSD_TYPE_PLAY_LIST: {
-          if (p_vcd->pxd.pld == NULL) return VLC_EGENERIC;
-          p_vcd->pdi = -1;
-          return vcdplayer_inc_play_item(p_input)
-            ? VLC_SUCCESS : VLC_EGENERIC;
-          break;
-        }
+    {
+      
+      access_vcd_data_t *p_vcd= (access_vcd_data_t *)p_access->p_sys;
+#if 0
+      const vlc_bool_t   b_was_still = p_vcd->in_still;
+#endif
+      
+      dbg_print(INPUT_DBG_CALL, "itemid.num: %d, itemid.type: %d\n",
+               itemid.num, itemid.type);
 
-        case PSD_TYPE_END_LIST:
-        case PSD_TYPE_COMMAND_LIST:
+      switch (itemid.type) {
+      case VCDINFO_ITEM_TYPE_TRACK:
+       
+       {
+         track_t i_track = itemid.num;
+         unsigned int i_entry = 
+           vcdinfo_track_get_entry( p_vcd->vcd, i_track);
+         
+         /* Valid tracks go from 1...i_tracks-1, because track 0 is
+            unplayable. */
+       
+         if (i_track == 0 || i_track >= p_vcd->i_tracks) {
+           LOG_ERR ("Invalid track number %d", i_track );
+           return VLC_EGENERIC;
+         }
+         p_vcd->in_still  = VLC_FALSE;
+         VCDSetOrigin( p_access, p_vcd->p_sectors[i_track],
+                       vcdinfo_get_entry_lsn(p_vcd->vcd, i_entry),
+                       p_vcd->p_sectors[i_track+1],
+                       i_track, &itemid );
+         break;
+       }
+       
+      case VCDINFO_ITEM_TYPE_SEGMENT:
+       {
+         int i_seg = itemid.num;
+         
+         /* Valid segments go from 0...i_segments-1. */
+         if (itemid.num >= p_vcd->i_segments) {
+           LOG_ERR ( "Invalid segment number: %d", i_seg );
+           return VLC_EGENERIC;
+         } else {
+           vcdinfo_video_segment_type_t segtype =
+             vcdinfo_get_video_type(p_vcd->vcd, i_seg);
+         
+           dbg_print(INPUT_DBG_PBC, "%s (%d), seg_num: %d",
+                     vcdinfo_video_type2str(p_vcd->vcd, i_seg),
+                     (int) segtype, itemid.num);
+           
+           switch (segtype)
+             {
+             case VCDINFO_FILES_VIDEO_NTSC_STILL:
+             case VCDINFO_FILES_VIDEO_NTSC_STILL2:
+             case VCDINFO_FILES_VIDEO_PAL_STILL:
+             case VCDINFO_FILES_VIDEO_PAL_STILL2:
+               p_vcd->in_still = VLC_TRUE;
+               break;
+             default:
+               p_vcd->in_still = VLC_FALSE;
+             }
+           VCDSetOrigin( p_access, p_vcd->p_segments[i_seg],
+                         p_vcd->p_segments[i_seg], 
+                         p_vcd->p_segments[i_seg+1],
+                         0, &itemid );
+         }
 
-        default:
-          ;
-        }
-      }
-      return VLC_EGENERIC;
-    case VCDINFO_ITEM_TYPE_ENTRY:
-      /* Entries go from 0..num_entries-1. */
-      if (itemid.num >= p_vcd->num_entries) {
-        LOG_ERR ("Invalid entry number: %d", itemid.num );
-        return VLC_EGENERIC;
-      } else {
-        track_t cur_track  = vcdinfo_get_track(p_vcd->vcd,  itemid.num);
-        p_vcd->in_still    = VLC_FALSE;
-        p_area             = area[cur_track];
-        p_area->i_part     = itemid.num;
-        p_input->stream.b_seekable = 1;
+       }
+       break;
+       
+      case VCDINFO_ITEM_TYPE_LID:
+       /* LIDs go from 1..i_lids. */
+       if (itemid.num == 0 || itemid.num > p_vcd->i_lids) {
+         LOG_ERR ( "Invalid LID number: %d", itemid.num );
+         return VLC_EGENERIC;
+       } else {
+         p_vcd->i_lid = itemid.num;
+         vcdinfo_lid_get_pxd(p_vcd->vcd, &(p_vcd->pxd), itemid.num);
+         
+         switch (p_vcd->pxd.descriptor_type) {
+           
+         case PSD_TYPE_SELECTION_LIST:
+         case PSD_TYPE_EXT_SELECTION_LIST: {
+           vcdinfo_itemid_t trans_itemid;
+           uint16_t trans_itemid_num;
+           
+           if (p_vcd->pxd.psd == NULL) return VLC_EGENERIC;
+           trans_itemid_num  = vcdinf_psd_get_itemid(p_vcd->pxd.psd);
+           vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
+           p_vcd->loop_count = 1;
+           p_vcd->loop_item  = trans_itemid;
+           return VCDPlay( p_access, trans_itemid );
+           break;
+         }
+           
+         case PSD_TYPE_PLAY_LIST: {
+           if (p_vcd->pxd.pld == NULL) return VLC_EGENERIC;
+           p_vcd->pdi = -1;
+           return vcdplayer_inc_play_item(p_access)
+             ? VLC_SUCCESS : VLC_EGENERIC;
+           break;
+         }
+           
+         case PSD_TYPE_END_LIST:
+         case PSD_TYPE_COMMAND_LIST:
+           
+         default:
+           ;
+         }
+       }
+       return VLC_EGENERIC;
+      case VCDINFO_ITEM_TYPE_ENTRY:
+       {
+         int i_entry = itemid.num;
+         
+         /* Entries go from 0..i_entries-1. */
+         if (itemid.num >= p_vcd->i_entries) {
+           LOG_ERR ("Invalid entry number: %d", i_entry );
+           return VLC_EGENERIC;
+         } else {
+           track_t i_track = vcdinfo_get_track(p_vcd->vcd,  i_entry);
+           p_vcd->in_still = VLC_FALSE;
+           VCDSetOrigin( p_access, p_vcd->p_sectors[i_track],
+                         vcdinfo_get_entry_lsn(p_vcd->vcd, i_entry),
+                         p_vcd->p_sectors[i_track+1],
+                         i_track, &itemid );
+         }
+         break;
+       }
+       
+      default:
+       LOG_ERR ("unknown entry type" );
+       return VLC_EGENERIC;
       }
-      break;
-    default:
-      LOG_ERR ("unknown entry type" );
-      return VLC_EGENERIC;
-    }
-
-    VCDSetArea( p_input, p_area );
-
-#undef area
 
-#if 1
-    if ( p_vcd->in_still != b_was_still ) {
-      if (p_input->stream.pp_selected_es) {
-        var_SetInteger( p_input, "state", PLAYING_S );
-      }
+      p_vcd->play_item = itemid;
+      
     }
-#endif
-
-    p_vcd->play_item = itemid;
-
-    dbg_print( (INPUT_DBG_CALL),
-               "i_start %lld, i_size: %lld, i_tell: %lld, lsn %lu",
-               p_area->i_start, p_area->i_size,
-               p_area->i_tell, 
-              (long unsigned int) p_vcd->cur_lsn );
-
+    
+      
     return VLC_SUCCESS;
 }
 
@@ -586,78 +494,81 @@ VCDPlay( input_thread_t *p_input, vcdinfo_itemid_t itemid )
   Before calling this track information should have been read in.
  *****************************************************************************/
 static int
-VCDEntryPoints( input_thread_t * p_input )
+VCDEntryPoints( access_t * p_access )
 {
-    thread_vcd_data_t *               p_vcd;
-    unsigned int                      i_nb;
-    unsigned int                      i, i_entry_index = 0;
-    unsigned int                      i_previous_track = CDIO_INVALID_TRACK;
-
-    p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-
-    i_nb = vcdinfo_get_num_entries(p_vcd->vcd);
-    if (0 == i_nb)
-      return -1;
-
-    p_vcd->p_entries  = malloc( sizeof( lba_t ) * i_nb );
-
-    if( p_vcd->p_entries == NULL )
-    {
-        LOG_ERR ("not enough memory for entry points treatment" );
-        return -1;
+  if (!p_access || !p_access->p_sys) return VLC_EGENERIC;
+  
+  {
+    access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
+    const unsigned int i_entries  =  vcdinfo_get_num_entries(p_vcd->vcd);
+    const track_t      i_last_track 
+      = cdio_get_num_tracks(vcdinfo_get_cd_image(p_vcd->vcd))
+      + cdio_get_first_track_num(vcdinfo_get_cd_image(p_vcd->vcd));
+    unsigned int i;
+   
+    if (0 == i_entries) {
+      LOG_ERR ("no entires found -- something is wrong" );
+      return VLC_EGENERIC;
     }
-
-    p_vcd->num_entries = 0;
-
-    for( i = 0 ; i < i_nb ; i++ )
+    
+    p_vcd->p_entries  = malloc( sizeof( lsn_t ) * i_entries );
+    
+    if( p_vcd->p_entries == NULL )
+      {
+       LOG_ERR ("not enough memory for entry points treatment" );
+       return VLC_EGENERIC;
+      }
+    
+    p_vcd->i_entries = i_entries;
+    
+    for( i = 0 ; i < i_entries ; i++ )
     {
-        track_t i_track = vcdinfo_get_track(p_vcd->vcd, i);
-        if( i_track <= p_input->stream.i_area_nb )
-        {
-            p_vcd->p_entries[i] =
-              vcdinfo_get_entry_lsn(p_vcd->vcd, i);
-            p_input->stream.pp_areas[i_track]->i_part_nb ++;
+       const track_t i_track = vcdinfo_get_track(p_vcd->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 );
 
-            /* if this entry belongs to a new track */
-            if( i_track != i_previous_track )
-            {
-                /* i_plugin_data is used to store the first entry of the area*/
-                p_input->stream.pp_areas[i_track]->i_plugin_data =
-                                                            i_entry_index;
-                i_previous_track = i_track;
-                p_input->stream.pp_areas[i_track]->i_part_nb = 1;
-            }
-            i_entry_index ++;
-            p_vcd->num_entries ++;
-        }
-        else
-            msg_Warn( p_input, "wrong track number found in entry points" );
+         p_vcd->p_entries[i] = vcdinfo_get_entry_lsn(p_vcd->vcd, i);
+         
+         s->psz_name      = strdup(psz_entry);
+         s->i_byte_offset = (p_vcd->p_entries[i] - p_vcd->p_sectors[i_track]) 
+           * M2F2_SECTOR_SIZE;
+         
+         TAB_APPEND( p_vcd->p_title[i_track-1]->i_seekpoint,
+                     p_vcd->p_title[i_track-1]->seekpoint, s );
+       } else 
+         msg_Warn( p_access, "wrong track number found in entry points" );
     }
     p_vcd->b_valid_ep = VLC_TRUE;
     return 0;
+  }
 }
 
+/*????? FIXME!!! */
+#ifdef FIXED 
 /*****************************************************************************
  * VCDSegments: Reads the information about the segments the disc.
  *****************************************************************************/
 static int
-VCDSegments( input_thread_t * p_input )
+VCDSegments( access_t * p_access )
 {
-    thread_vcd_data_t * p_vcd;
+    access_vcd_data_t * p_vcd;
     unsigned int        i;
-    unsigned int        num_segments;
+    unsigned int        i_segments;
 
 
-    p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-    num_segments = p_vcd->num_segments = vcdinfo_get_num_segments(p_vcd->vcd);
+    p_vcd = (access_vcd_data_t *) p_access->p_sys;
+    i_segments = p_vcd->num_segments = vcdinfo_get_num_segments(p_vcd->vcd);
 
-#define area p_input->stream.pp_areas
+#define area p_access->stream.pp_areas
 
     /* area 0 is reserved for segments. Set Absolute start offset
          and size */
     area[0]->i_plugin_data = 0;
-    input_DelArea( p_input, area[0] );
-    input_AddArea( p_input, 0, 0 );
+    input_DelArea( p_access, area[0] );
+    input_AddArea( p_access, 0, 0 );
 
     area[0]->i_start = (off_t)p_vcd->p_sectors[0]
       * (off_t)M2F2_SECTOR_SIZE;
@@ -677,12 +588,12 @@ VCDSegments( input_thread_t * p_input )
                "area[0] id: %d, i_start: %lld, i_size: %lld",
                area[0]->i_id, area[0]->i_start, area[0]->i_size );
 
-    if (num_segments == 0) return 0;
+    if (i_segments == 0) return 0;
 
     /* We have one additional segment allocated so we can get the size
        by subtracting seg[i+1] - seg[i].
      */
-    p_vcd->p_segments = malloc( sizeof( lba_t ) * (num_segments+1) );
+    p_vcd->p_segments = malloc( sizeof( lsn_t ) * (i_segments+1) );
     if( p_vcd->p_segments == NULL )
     {
         LOG_ERR ("not enough memory for segment treatment" );
@@ -690,82 +601,85 @@ VCDSegments( input_thread_t * p_input )
     }
 
     /* Update the navigation variables without triggering a callback */
-    VCDUpdateVar( p_input, 0, VLC_VAR_SETVALUE, "title", _("Track"),
+    VCDUpdateVar( p_access, 0, VLC_VAR_SETVALUE, "title", _("Track"),
                  "Setting track" );
 
-    var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL );
+    var_Change( p_access, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL );
 
-    for( i = 0 ; i < num_segments ; i++ )
+    for( i = 0 ; i < i_segments ; i++ )
     {
       p_vcd->p_segments[i] = vcdinfo_get_seg_lsn(p_vcd->vcd, i);
       area[0]->i_part_nb ++;
-      VCDUpdateVar( p_input, i , VLC_VAR_ADDCHOICE,
+      VCDUpdateVar( p_access, i , VLC_VAR_ADDCHOICE,
                     "chapter", _("Segment"), "Adding segment choice");
     }
 
 #undef area
 
-    p_vcd->p_segments[num_segments] = p_vcd->p_segments[num_segments-1]+
-      vcdinfo_get_seg_sector_count(p_vcd->vcd, num_segments-1);
+    p_vcd->p_segments[i_segments] = p_vcd->p_segments[i_segments-1]+
+      vcdinfo_get_seg_sector_count(p_vcd->vcd, i_segments-1);
 
     return 0;
 }
+#endif
 
 /*****************************************************************************
- VCDTracks: initializes area information.
- Before calling this track information should have been read in.
+ 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. 
  *****************************************************************************/
-static void
-VCDTracks( input_thread_t * p_input )
+static int
+VCDTitles( access_t * p_access )
 {
-    thread_vcd_data_t * p_vcd;
-    unsigned int        i;
-
-    p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-
-#define area p_input->stream.pp_areas
-
-    /* We start area addressing for tracks at 1 since the default area 0
-       is reserved for segments */
+    /* We'll assume a VCD has its first MPEG track
+       cdio_get_first_track_num()+1 could be used if one wanted to be
+       very careful about this. Note: cdio_get_first_track() will give the
+       ISO-9660 track before the MPEG tracks.
+     */
+    const unsigned int i_first_mpeg_track=2; 
+  
+    if (!p_access || !p_access->p_sys) return VLC_EGENERIC;
 
-    for( i = 1 ; i < p_vcd->num_tracks ; i++ )
     {
-        /* Tracks are Program Chains */
-        input_AddArea( p_input, i, i );
-
-        /* Absolute start byte offset and byte size */
-        area[i]->i_start = (off_t) p_vcd->p_sectors[i]
-                           * (off_t)M2F2_SECTOR_SIZE;
-        area[i]->i_size = (off_t)(p_vcd->p_sectors[i+1] - p_vcd->p_sectors[i])
-                           * (off_t)M2F2_SECTOR_SIZE;
+        access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
+       track_t            i;
 
-        /* Current entry being played in track */
-        area[i]->i_part = 0;
-
-        /* i_plugin_data is used to store which entry point is the first
-         * of the track (area) */
-        area[i]->i_plugin_data = 0;
-
-        dbg_print( INPUT_DBG_MRL,
-                   "area[%d] id: %d, i_start: %lld, i_size: %lld",
-                   i, area[i]->i_id, area[i]->i_start, area[i]->i_size );
+       p_vcd->i_titles = 0;
+       for( i = 2 ; i <= p_vcd->i_tracks ; i++ )
+        {
+           input_title_t *t = p_vcd->p_title[i - i_first_mpeg_track] 
+             = vlc_input_title_New();
+           char psz_track[100];
+           uint32_t i_secsize = 
+             cdio_get_track_sec_count( vcdinfo_get_cd_image(p_vcd->vcd), i );
+           
+           snprintf(psz_track, sizeof(psz_track), "%s%02d", _("Track "), 
+                    i-1 );
+           
+           t->i_size    = (i_secsize) * (int64_t) M2F2_SECTOR_SIZE;
+           t->psz_name  = strdup(psz_track);
+           
+           dbg_print( INPUT_DBG_MRL, "track[%d] i_size: %lld",
+                      i, t->i_size );
+
+           p_vcd->i_titles++;
+       }
+      
+      return VLC_SUCCESS;
     }
-
-#undef area
-
-    return ;
 }
 
 /*****************************************************************************
   VCDLIDs: Reads the LIST IDs from the LOT.
  *****************************************************************************/
 static int
-VCDLIDs( input_thread_t * p_input )
+VCDLIDs( access_t * p_access )
 {
-    thread_vcd_data_t *p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
+    access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
 
-    p_vcd->num_lids = vcdinfo_get_num_LIDs(p_vcd->vcd);
-    p_vcd->cur_lid  = VCDINFO_INVALID_ENTRY;
+    p_vcd->i_lids = vcdinfo_get_num_LIDs(p_vcd->vcd);
+    p_vcd->i_lid  = VCDINFO_INVALID_ENTRY;
 
     if (vcdinfo_read_psd (p_vcd->vcd)) {
 
@@ -784,7 +698,7 @@ VCDLIDs( input_thread_t * p_input )
     }
 
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),
-               "num LIDs=%d", p_vcd->num_lids);
+               "num LIDs=%d", p_vcd->i_lids);
 
     return 0;
 }
@@ -793,15 +707,15 @@ VCDLIDs( input_thread_t * p_input )
  * VCDParse: parse command line
  *****************************************************************************/
 static char *
-VCDParse( input_thread_t * p_input, /*out*/ vcdinfo_itemid_t * p_itemid,
+VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid,
           /*out*/ vlc_bool_t *play_single_item )
 {
-    thread_vcd_data_t *p_vcd = (thread_vcd_data_t *)p_input->p_access_data;
+    access_vcd_data_t *p_vcd = (access_vcd_data_t *)p_access->p_sys;
     char *             psz_parser;
     char *             psz_source;
     char *             psz_next;
 
-    if( config_GetInt( p_input, MODULE_STRING "-PBC" ) ) {
+    if( config_GetInt( p_access, MODULE_STRING "-PBC" ) ) {
       p_itemid->type = VCDINFO_ITEM_TYPE_LID;
       p_itemid->num = 1;
       *play_single_item = VLC_FALSE;
@@ -815,15 +729,15 @@ VCDParse( input_thread_t * p_input, /*out*/ vcdinfo_itemid_t * p_itemid,
 #ifdef WIN32
     /* On Win32 we want the VCD access plugin to be explicitly requested,
      * we end up with lots of problems otherwise */
-    if( !p_input->psz_access || !*p_input->psz_access ) return NULL;
+    if( !p_access->psz_access || !*p_access->psz_access ) return NULL;
 #endif
 
-    if( !p_input->psz_name )
+    if( !p_access->psz_path )
     {
         return NULL;
     }
 
-    psz_parser = psz_source = strdup( p_input->psz_name );
+    psz_parser = psz_source = strdup( p_access->psz_path );
 
     /* Parse input string :
      * [device][@[type][title]] */
@@ -881,9 +795,9 @@ VCDParse( input_thread_t * p_input, /*out*/ vcdinfo_itemid_t * p_itemid,
     if( !*psz_source ) {
 
       /* No source specified, so figure it out. */
-      if( !p_input->psz_access ) return NULL;
+      if( !p_access->psz_access ) return NULL;
 
-      psz_source = config_GetPsz( p_input, "vcd" );
+      psz_source = config_GetPsz( p_access, "vcd" );
 
       if( !psz_source || 0==strlen(psz_source) ) {
         /* Scan for a CD-ROM drive with a VCD in it. */
@@ -913,30 +827,33 @@ VCDParse( input_thread_t * p_input, /*out*/ vcdinfo_itemid_t * p_itemid,
    Set's start origin subsequent seeks/reads
 */
 static void
-VCDSetOrigin( input_thread_t *p_input, lsn_t origin_lsn,
-              lsn_t cur_lsn, lsn_t end_lsn, int cur_entry, track_t cur_track )
+VCDSetOrigin( access_t *p_access, lsn_t origin_lsn,
+              lsn_t i_lsn, lsn_t end_lsn, track_t i_track, 
+             const vcdinfo_itemid_t *p_itemid )
 {
-  thread_vcd_data_t * p_vcd  = (thread_vcd_data_t *) p_input->p_access_data;
+  access_vcd_data_t *p_vcd= (access_vcd_data_t *)p_access->p_sys;
 
   p_vcd->origin_lsn = origin_lsn;
-  p_vcd->cur_lsn    = cur_lsn;
+  p_vcd->i_lsn      = i_lsn;
   p_vcd->end_lsn    = end_lsn;
-  p_vcd->cur_track  = cur_track;
-  p_vcd->play_item.num  = cur_entry;
-  p_vcd->play_item.type = VCDINFO_ITEM_TYPE_ENTRY;
+  p_vcd->i_track    = i_track;
+  p_vcd->play_item.num  = p_itemid->num;
+  p_vcd->play_item.type = p_itemid->type;
+
+  p_access->info.i_title = i_track-1;
+  p_access->info.i_seekpoint = p_itemid->num;
+  p_access->info.i_size = p_vcd->p_title[i_track]->i_size;
+  p_access->info.i_pos = ( i_lsn - origin_lsn ) * M2F2_SECTOR_SIZE;
 
   dbg_print( (INPUT_DBG_CALL|INPUT_DBG_LSN),
-             "origin: %lu, cur_lsn: %lu, end_lsn: %lu, entry: %d, track: %d",
+             "origin: %lu, cur_lsn: %lu, end_lsn: %lu, track: %d",
              (long unsigned int) origin_lsn, 
-            (long unsigned int) cur_lsn, 
-            (long unsigned int) end_lsn, cur_entry, cur_track );
+            (long unsigned int) i_lsn, 
+            (long unsigned int) end_lsn, i_track );
 
-  p_input->stream.p_selected_area->i_tell =
-    (off_t) (p_vcd->cur_lsn - p_vcd->origin_lsn) * (off_t)M2F2_SECTOR_SIZE;
-
-  VCDUpdateVar( p_input, cur_entry, VLC_VAR_SETVALUE,
+  VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE,
                 "chapter", 
-               p_vcd->play_item.type == VCDINFO_ITEM_TYPE_ENTRY ?
+               p_itemid->type == VCDINFO_ITEM_TYPE_ENTRY ?
                _("Entry") : _("Segment"), 
                "Setting entry/segment");
 }
@@ -968,21 +885,21 @@ vcd_Open( vlc_object_t *p_this, const char *psz_dev )
  ****************************************************************************/
 static int
 VCDReadSector( vlc_object_t *p_this, const vcdinfo_obj_t *p_vcd,
-               lsn_t cur_lsn, byte_t * p_buffer )
+               lsn_t i_lsn, byte_t * p_buffer )
 {
   typedef struct {
-    uint8_t subheader   [8];
+    uint8_t subheader   [CDIO_CD_SUBHEADER_SIZE];
     uint8_t data        [M2F2_SECTOR_SIZE];
     uint8_t spare       [4];
   } vcdsector_t;
   vcdsector_t vcd_sector;
 
   if( cdio_read_mode2_sector( vcdinfo_get_cd_image( p_vcd ),
-                              &vcd_sector, cur_lsn, VLC_TRUE )
+                              &vcd_sector, i_lsn, VLC_TRUE )
       != 0)
   {
       msg_Warn( p_this, "Could not read LSN %lu", 
-               (long unsigned int) cur_lsn );
+               (long unsigned int) i_lsn );
       return -1;
   }
 
@@ -995,399 +912,24 @@ VCDReadSector( vlc_object_t *p_this, const vcdinfo_obj_t *p_vcd,
  Update the "varname" variable to i_num without triggering a callback.
 ****************************************************************************/
 static void
-VCDUpdateVar( input_thread_t *p_input, int i_num, int i_action,
+VCDUpdateVar( access_t *p_access, int i_num, int i_action,
               const char *p_varname, char *p_label, 
              const char *p_debug_label)
 {
   vlc_value_t val;
   val.i_int = i_num;
-  if (NULL != p_vcd_input) {
-    thread_vcd_data_t *p_vcd = (thread_vcd_data_t *)p_vcd_input->p_access_data;
+  if (p_access) {
+    const access_vcd_data_t *p_vcd = (access_vcd_data_t *)p_vcd_access->p_sys;
     dbg_print( INPUT_DBG_PBC, "%s %d", p_debug_label, i_num );
   }
   if (p_label) {
     vlc_value_t text;
     text.psz_string = p_label;
-    var_Change( p_input, p_varname, VLC_VAR_SETTEXT, &text, NULL );
-  }
-  var_Change( p_input, p_varname, i_action, &val, NULL );
-}
-
-
-static inline void
-MetaInfoAddStr(input_thread_t *p_input, char *p_cat,
-               char *title, const char *str)
-{
-  thread_vcd_data_t *p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-  if ( str ) {
-    dbg_print( INPUT_DBG_META, "field: %s: %s\n", title, str);
-    input_Control( p_input, INPUT_ADD_INFO, p_cat, title, "%s", str);
-  }
-}
-
-
-static inline void
-MetaInfoAddNum(input_thread_t *p_input, char *p_cat, char *title, int num)
-{
-  thread_vcd_data_t *p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-  dbg_print( INPUT_DBG_META, "field %s: %d\n", title, num);
-  input_Control( p_input, INPUT_ADD_INFO, p_cat, title, "%d", num );
-}
-
-#define addstr(title, str) \
-  MetaInfoAddStr( p_input, p_cat, title, str );
-
-#define addnum(title, num) \
-  MetaInfoAddNum( p_input, p_cat, title, num );
-
-static void InformationCreate( input_thread_t *p_input  )
-{
-  thread_vcd_data_t *p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-  unsigned int i_nb = vcdinfo_get_num_entries(p_vcd->vcd);
-  unsigned int last_entry = 0;
-  char *p_cat;
-  track_t i_track;
-
-  p_cat = _("General");
-
-  addstr( _("VCD Format"),  vcdinfo_get_format_version_str(p_vcd->vcd) );
-  addstr( _("Album"),       vcdinfo_get_album_id(p_vcd->vcd));
-  addstr( _("Application"), vcdinfo_get_application_id(p_vcd->vcd) );
-  addstr( _("Preparer"),    vcdinfo_get_preparer_id(p_vcd->vcd) );
-  addnum( _("Vol #"),       vcdinfo_get_volume_num(p_vcd->vcd) );
-  addnum( _("Vol max #"),   vcdinfo_get_volume_count(p_vcd->vcd) );
-  addstr( _("Volume Set"),  vcdinfo_get_volumeset_id(p_vcd->vcd) );
-  addstr( _("Volume"),      vcdinfo_get_volume_id(p_vcd->vcd) );
-  addstr( _("Publisher"),   vcdinfo_get_publisher_id(p_vcd->vcd) );
-  addstr( _("System Id"),   vcdinfo_get_system_id(p_vcd->vcd) );
-  addnum( "LIDs",           vcdinfo_get_num_LIDs(p_vcd->vcd) );
-  addnum( _("Entries"),     vcdinfo_get_num_entries(p_vcd->vcd) );
-  addnum( _("Segments"),    vcdinfo_get_num_segments(p_vcd->vcd) );
-  addnum( _("Tracks"),      vcdinfo_get_num_tracks(p_vcd->vcd) );
-
-  /* Spit out track information. Could also include MSF info.
-   */
-
-#define TITLE_MAX 30
-  for( i_track = 1 ; i_track < p_vcd->num_tracks ; i_track++ ) {
-    char psz_track[TITLE_MAX];
-    unsigned int audio_type = vcdinfo_get_track_audio_type(p_vcd->vcd, 
-                                                          i_track);
-    snprintf(psz_track, TITLE_MAX, "%s%02d", _("Track "), i_track);
-    p_cat = psz_track;
-
-    if (p_vcd->b_svd) {
-      addnum(_("Audio Channels"),  
-            vcdinfo_audio_type_num_channels(p_vcd->vcd, audio_type) );
-    }
-
-    addnum(_("First Entry Point"), last_entry );
-    for ( ; last_entry < i_nb 
-           && vcdinfo_get_track(p_vcd->vcd, last_entry) == i_track;
-         last_entry++ ) ;
-    addnum(_("Last Entry Point"), last_entry-1 );
-  }
-}
-
-#define add_format_str_info(val)                              \
-  {                                                           \
-    const char *str = val;                                    \
-    unsigned int len;                                         \
-    if (val != NULL) {                                        \
-      len=strlen(str);                                        \
-      if (len != 0) {                                         \
-        strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));         \
-        tp += len;                                            \
-      }                                                        \
-      saw_control_prefix = VLC_FALSE;                         \
-    }                                                         \
-  }
-
-#define add_format_num_info( val, fmt )                               \
-  {                                                           \
-    char num_str[10];                                         \
-    unsigned int len;                                         \
-    sprintf(num_str, fmt, val);                                \
-    len = strlen(num_str);                                    \
-    if( len != 0 )                                             \
-    {                                                         \
-      strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));        \
-      tp += len;                                              \
-    }                                                         \
-    saw_control_prefix = VLC_FALSE;                                \
-  }
-
-/*!
-   Take a format string and expand escape sequences, that is sequences that
-   begin with %, with information from the current VCD.
-   The expanded string is returned. Here is a list of escape sequences:
-
-   %A : The album information
-   %C : The VCD volume count - the number of CD's in the collection.
-   %c : The VCD volume num - the number of the CD in the collection.
-   %F : The VCD Format, e.g. VCD 1.0, VCD 1.1, VCD 2.0, or SVCD
-   %I : The current entry/segment/playback type, e.g. ENTRY, TRACK, SEGMENT...
-   %L : The playlist ID prefixed with " LID" if it exists
-   %M : MRL
-   %N : The current number of the %I - a decimal number
-   %P : The publisher ID
-   %p : The preparer ID
-   %S : If we are in a segment (menu), the kind of segment
-   %T : The track number
-   %V : The volume set ID
-   %v : The volume ID
-       A number between 1 and the volume count.
-   %% : a %
-*/
-static char *
-VCDFormatStr(const input_thread_t *p_input, thread_vcd_data_t *p_vcd,
-             const char format_str[], const char *mrl,
-             const vcdinfo_itemid_t *itemid)
-{
-#define TEMP_STR_SIZE 256
-#define TEMP_STR_LEN (TEMP_STR_SIZE-1)
-  static char    temp_str[TEMP_STR_SIZE];
-  size_t         i;
-  char *         tp = temp_str;
-  vlc_bool_t     saw_control_prefix = VLC_FALSE;
-  size_t         format_len = strlen(format_str);
-
-  memset(temp_str, 0, TEMP_STR_SIZE);
-
-  for (i=0; i<format_len; i++) {
-
-    if (!saw_control_prefix && format_str[i] != '%') {
-      *tp++ = format_str[i];
-      saw_control_prefix = VLC_FALSE;
-      continue;
-    }
-
-    switch(format_str[i]) {
-    case '%':
-      if (saw_control_prefix) {
-        *tp++ = '%';
-      }
-      saw_control_prefix = !saw_control_prefix;
-      break;
-    case 'A':
-      add_format_str_info(vcdinfo_strip_trail(vcdinfo_get_album_id(p_vcd->vcd),
-                                              MAX_ALBUM_LEN));
-      break;
-
-    case 'c':
-      add_format_num_info(vcdinfo_get_volume_num(p_vcd->vcd), "%d");
-      break;
-
-    case 'C':
-      add_format_num_info(vcdinfo_get_volume_count(p_vcd->vcd), "%d");
-      break;
-
-    case 'F':
-      add_format_str_info(vcdinfo_get_format_version_str(p_vcd->vcd));
-      break;
-
-    case 'I':
-      {
-        switch (itemid->type) {
-        case VCDINFO_ITEM_TYPE_TRACK:
-          strncat(tp, _("Track"), TEMP_STR_LEN-(tp-temp_str));
-          tp += strlen(_("Track"));
-        break;
-        case VCDINFO_ITEM_TYPE_ENTRY:
-          strncat(tp, _("Entry"), TEMP_STR_LEN-(tp-temp_str));
-          tp += strlen(_("Entry"));
-          break;
-        case VCDINFO_ITEM_TYPE_SEGMENT:
-          strncat(tp, _("Segment"), TEMP_STR_LEN-(tp-temp_str));
-          tp += strlen(_("Segment"));
-          break;
-        case VCDINFO_ITEM_TYPE_LID:
-          strncat(tp, _("List ID"), TEMP_STR_LEN-(tp-temp_str));
-          tp += strlen(_("List ID"));
-          break;
-        case VCDINFO_ITEM_TYPE_SPAREID2:
-          strncat(tp, _("Navigation"), TEMP_STR_LEN-(tp-temp_str));
-          tp += strlen(_("Navigation"));
-          break;
-        default:
-          /* What to do? */
-          ;
-        }
-        saw_control_prefix = VLC_FALSE;
-      }
-      break;
-
-    case 'L':
-      if (vcdplayer_pbc_is_on(p_vcd)) {
-        char num_str[40];
-        sprintf(num_str, "%s %d", _("List ID"), p_vcd->cur_lid);
-        strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));
-        tp += strlen(num_str);
-      }
-      saw_control_prefix = VLC_FALSE;
-      break;
-
-    case 'M':
-      add_format_str_info(mrl);
-      break;
-
-    case 'N':
-      add_format_num_info(itemid->num, "%d");
-      break;
-
-    case 'p':
-      add_format_str_info(vcdinfo_get_preparer_id(p_vcd->vcd));
-      break;
-
-    case 'P':
-      add_format_str_info(vcdinfo_get_publisher_id(p_vcd->vcd));
-      break;
-
-    case 'S':
-      if ( VCDINFO_ITEM_TYPE_SEGMENT==itemid->type ) {
-        char seg_type_str[10];
-
-        sprintf(seg_type_str, " %s",
-                vcdinfo_video_type2str(p_vcd->vcd, itemid->num));
-        strncat(tp, seg_type_str, TEMP_STR_LEN-(tp-temp_str));
-        tp += strlen(seg_type_str);
-      }
-      saw_control_prefix = VLC_FALSE;
-      break;
-
-    case 'T':
-      add_format_num_info(p_vcd->cur_track, "%d");
-      break;
-
-    case 'V':
-      add_format_str_info(vcdinfo_get_volumeset_id(p_vcd->vcd));
-      break;
-
-    case 'v':
-      add_format_str_info(vcdinfo_get_volume_id(p_vcd->vcd));
-      break;
-
-    default:
-      *tp++ = '%';
-      *tp++ = format_str[i];
-      saw_control_prefix = VLC_FALSE;
-    }
-  }
-  return strdup(temp_str);
-}
-
-static void
-VCDCreatePlayListItem(const input_thread_t *p_input,
-                      thread_vcd_data_t *p_vcd,
-                      playlist_t *p_playlist,
-                      const vcdinfo_itemid_t *itemid,
-                      char *psz_mrl, int psz_mrl_max,
-                      const char *psz_source, int playlist_operation,
-                      int i_pos)
-{
-  char *p_author;
-  char *p_title;
-  char c_type;
-
-  switch(itemid->type) {
-  case VCDINFO_ITEM_TYPE_TRACK:
-    c_type='T';
-    break;
-  case VCDINFO_ITEM_TYPE_SEGMENT:
-    c_type='S';
-    break;
-  case VCDINFO_ITEM_TYPE_LID:
-    c_type='P';
-    break;
-  case VCDINFO_ITEM_TYPE_ENTRY:
-    c_type='E';
-    break;
-  default:
-    c_type='?';
-    break;
+    var_Change( p_access, p_varname, VLC_VAR_SETTEXT, &text, NULL );
   }
-
-  snprintf(psz_mrl, psz_mrl_max, "%s%s@%c%u", VCD_MRL_PREFIX, psz_source,
-           c_type, itemid->num);
-
-  p_title =
-    VCDFormatStr( p_input, p_vcd,
-                 config_GetPsz( p_input, MODULE_STRING "-title-format" ),
-                 psz_mrl, itemid );
-  
-  playlist_Add( p_playlist, psz_mrl, p_title, playlist_operation, i_pos );
-
-  p_author =
-    VCDFormatStr( p_input, p_vcd,
-                 config_GetPsz( p_input, MODULE_STRING "-author-format" ),
-                 psz_mrl, itemid );
-
-  if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
-  playlist_AddInfo(p_playlist, i_pos, _("General"), _("Author"), "%s",
-                  p_author);
+  var_Change( p_access, p_varname, i_action, &val, NULL );
 }
 
-static int
-VCDFixupPlayList( input_thread_t *p_input, thread_vcd_data_t *p_vcd,
-                  const char *psz_source, vcdinfo_itemid_t *itemid,
-                  vlc_bool_t play_single_item )
-{
-  unsigned int i;
-  playlist_t * p_playlist;
-  char       * psz_mrl;
-  unsigned int psz_mrl_max = strlen(VCD_MRL_PREFIX) + strlen(psz_source) +
-    strlen("@T") + strlen("100") + 1;
-
-  psz_mrl = malloc( psz_mrl_max );
-
-  if( psz_mrl == NULL )
-    {
-      msg_Warn( p_input, "out of memory" );
-      return -1;
-    }
-
-  p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
-                                               FIND_ANYWHERE );
-  if( !p_playlist )
-    {
-      msg_Warn( p_input, "can't find playlist" );
-      free(psz_mrl);
-      return -1;
-    }
-
-  if ( play_single_item ) 
-    {
-    /* May fill out more information when the playlist user interface becomes
-       more mature.
-     */
-    VCDCreatePlayListItem(p_input, p_vcd, p_playlist, itemid,
-                          psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
-                          p_playlist->i_index);
-
-    }
-  else
-    {
-    vcdinfo_itemid_t list_itemid;
-    list_itemid.type=VCDINFO_ITEM_TYPE_ENTRY;
-
-    playlist_LockDelete( p_playlist, p_playlist->i_index);
-
-    for( i = 0 ; i < p_vcd->num_entries ; i++ )
-      {
-        list_itemid.num=i;
-        VCDCreatePlayListItem(p_input, p_vcd, p_playlist, &list_itemid,
-                              psz_mrl, psz_mrl_max, psz_source,
-                              PLAYLIST_APPEND, PLAYLIST_END);
-      }
-
-    playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
-
-  }
-
-  vlc_object_release( p_playlist );
-  free(psz_mrl);
-  return 0;
-}
 
 /*****************************************************************************
  * Public routines.
@@ -1396,14 +938,14 @@ int
 E_(DebugCallback)   ( vlc_object_t *p_this, const char *psz_name,
                       vlc_value_t oldval, vlc_value_t val, void *p_data )
 {
-  thread_vcd_data_t *p_vcd;
+  access_vcd_data_t *p_vcd;
 
-  if (NULL == p_vcd_input) return VLC_EGENERIC;
+  if (NULL == p_vcd_access) return VLC_EGENERIC;
 
-  p_vcd = (thread_vcd_data_t *)p_vcd_input->p_access_data;
+  p_vcd = (access_vcd_data_t *)p_vcd_access->p_sys;
 
   if (p_vcd->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
-    msg_Dbg( p_vcd_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
+    msg_Dbg( p_vcd_access, "Old debug (x%0x) %d, new debug (x%0x) %d",
              p_vcd->i_debug, p_vcd->i_debug, val.i_int, val.i_int);
   }
   p_vcd->i_debug = val.i_int;
@@ -1411,35 +953,8 @@ E_(DebugCallback)   ( vlc_object_t *p_this, const char *psz_name,
 }
 
 
-/*
-  The front-ends change spu-es - which sort of represents a symbolic
-  name. Internally we use spu-channel which runs from 0..3.
-
-  So we add a callback to intercept changes to spu-es and change them
-  to updates to spu-channel. Ugly.
-
-*/
-
-static int 
-VCDSPUCallback( vlc_object_t *p_this, const char *psz_variable,
-                vlc_value_t old_val, vlc_value_t new_val, void *param)
-{
-
-  input_thread_t    *p_input = (input_thread_t *)p_this;
-  thread_vcd_data_t *p_vcd = (thread_vcd_data_t *)p_input->p_access_data;
-  vlc_value_t val;
-  
-  dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EVENT), "old_val: %x, new_val %x", 
-            old_val.i_int, new_val.i_int);
-
-  val.i_int =  new_val.i_int;
-  var_Set( p_this, "spu-channel", val );
-  
-  return VLC_SUCCESS;
-}
-
 /*****************************************************************************
-  Open: open VCD.
+  VCDOpen: open VCD.
   read in meta-information about VCD: the number of tracks, segments,
   entries, size and starting information. Then set up state variables so
   that we read/seek starting at the location specified.
@@ -1448,21 +963,28 @@ VCDSPUCallback( vlc_object_t *p_this, const char *psz_variable,
   and VLC_EGENERIC for some other error.
  *****************************************************************************/
 int
-E_(Open) ( vlc_object_t *p_this )
+E_(VCDOpen) ( vlc_object_t *p_this )
 {
-    input_thread_t *        p_input = (input_thread_t *)p_this;
-    thread_vcd_data_t *     p_vcd;
+    access_t *              p_access = (access_t *)p_this;
+    access_vcd_data_t *     p_vcd;
     char *                  psz_source;
     vcdinfo_itemid_t        itemid;
     vlc_bool_t              b_play_ok;
     vlc_bool_t              play_single_item = VLC_FALSE;
 
-    p_input->pf_read        = VCDRead;
-    p_input->pf_seek        = VCDSeek;
-    p_input->pf_set_area    = VCDSetArea;
-    p_input->pf_set_program = VCDSetProgram;
+    p_access->pf_read          = NULL;
+    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.i_title     = 0;
+    p_access->info.i_seekpoint = 0;
 
-    p_vcd = malloc( sizeof(thread_vcd_data_t) );
+    p_vcd = malloc( sizeof(access_vcd_data_t) );
 
     if( p_vcd == NULL )
     {
@@ -1470,17 +992,21 @@ E_(Open) ( vlc_object_t *p_this )
         return VLC_ENOMEM;
     }
 
-    p_input->p_access_data = (void *)p_vcd;
+    p_access->p_sys     = (access_sys_t *) p_vcd;
+
     p_vcd->i_debug         = config_GetInt( p_this, MODULE_STRING "-debug" );
     p_vcd->in_still        = VLC_FALSE;
     p_vcd->play_item.type  = VCDINFO_ITEM_TYPE_NOTFOUND;
+    p_vcd->p_input         = vlc_object_find( p_access, VLC_OBJECT_INPUT, 
+                                             FIND_PARENT );
+    p_vcd->p_meta          = vlc_meta_New();
 
     /* Set where to log errors messages from libcdio. */
-    p_vcd_input = (input_thread_t *)p_this;
+    p_vcd_access = p_access;
     cdio_log_set_handler ( cdio_log_handler );
     vcd_log_set_handler ( vcd_log_handler );
 
-    psz_source = VCDParse( p_input, &itemid, &play_single_item );
+    psz_source = VCDParse( p_access, &itemid, &play_single_item );
 
     if ( NULL == psz_source )
     {
@@ -1489,109 +1015,86 @@ E_(Open) ( vlc_object_t *p_this )
     }
 
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "source: %s: mrl: %s",
-               psz_source, p_input->psz_name );
+               psz_source, p_access->psz_path );
 
     p_vcd->p_segments = NULL;
     p_vcd->p_entries  = NULL;
 
     /* set up input  */
-    p_input->i_mtu = VCD_DATA_ONCE;
-
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-
-    /* If we are here we can control the pace... */
-    p_input->stream.b_pace_control = 1;
-
-    p_input->stream.b_seekable = 1;
-    p_input->stream.p_selected_area->i_size = 0;
-    p_input->stream.p_selected_area->i_tell = 0;
-
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
 
     if( !(p_vcd->vcd = vcd_Open( p_this, psz_source )) )
     {
-        msg_Warn( p_input, "could not open %s", psz_source );
+        msg_Warn( p_access, "could not open %s", psz_source );
         goto err_exit;
     }
 
     p_vcd->b_svd= (vlc_bool_t) vcdinfo_get_tracksSVD(p_vcd->vcd);;
     
     /* Get track information. */
-    p_vcd->num_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
-                                            vcdinfo_get_cd_image(p_vcd->vcd),
-                                            &p_vcd->p_sectors );
-    if( p_vcd->num_tracks < 0 )
-        LOG_ERR ("unable to count tracks" );
-    else if( p_vcd->num_tracks <= 1 )
-        LOG_ERR ("no movie tracks found" );
-    if( p_vcd->num_tracks <= 1)
-    {
+    p_vcd->i_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_access),
+                                         vcdinfo_get_cd_image(p_vcd->vcd),
+                                         &p_vcd->p_sectors );
+    if( p_vcd->i_tracks <= 1 ) {
         vcdinfo_close( p_vcd->vcd );
+        LOG_ERR ("no movie tracks found" );
         goto err_exit;
     }
-
-    /* Set stream and area data */
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-
-    /* Initialize ES structures */
-    input_InitStream( p_input, sizeof( stream_ps_data_t ) );
-
-    /* disc input method */
-    p_input->stream.i_method = INPUT_METHOD_VCD;
-
-    p_input->stream.i_area_nb = 1;
-
-
+    
+#ifdef FIXED
     /* Initialize segment information. */
-    VCDSegments( p_input );
+    VCDSegments( p_access );
+#endif
 
-    /* Initialize track area information. */
-    VCDTracks( p_input );
+    /* Build Navigation Title table. */
+    VCDTitles( p_access );
 
-    if( VCDEntryPoints( p_input ) < 0 )
+    /* Map entry points into Chapters */
+    if( VCDEntryPoints( p_access ) < 0 )
     {
-        msg_Warn( p_input, "could not read entry points, will not use them" );
+        msg_Warn( p_access, "could not read entry points, will not use them" );
         p_vcd->b_valid_ep = VLC_FALSE;
     }
 
-    if( VCDLIDs( p_input ) < 0 )
+    if( VCDLIDs( p_access ) < 0 )
     {
-        msg_Warn( p_input, "could not read entry LIDs" );
+        msg_Warn( p_access, "could not read entry LIDs" );
     }
 
-    b_play_ok = (VLC_SUCCESS == VCDPlay( p_input, itemid ));
-
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
+#if FIXED
+    b_play_ok = (VLC_SUCCESS == VCDPlay( p_access, itemid ));
 
     if ( ! b_play_ok ) {
       vcdinfo_close( p_vcd->vcd );
       goto err_exit;
     }
-
-    if( !p_input->psz_demux || !*p_input->psz_demux )
-    {
-#if FIXED
-      p_input->psz_demux = "vcdx";
-#else
-      p_input->psz_demux = "ps";
+#else 
+    /* We assume playing CD track 2 (1st MPEG data) for now  */
+      
+    p_vcd->origin_lsn = p_vcd->i_lsn = p_vcd->p_sectors[1];
+    p_access->info.i_title = 0;
+    p_access->info.i_seekpoint = 0;
+    p_access->info.i_size = p_vcd->p_title[0]->i_size;
+    p_access->info.i_pos = 0;
+    
 #endif
-    }
 
-    p_vcd->p_intf = intf_Create( p_input, "vcdx" );
+    p_access->psz_demux = strdup( "ps" );
+
+#if FIXED
+    p_vcd->p_intf = intf_Create( p_access, "vcdx" );
     p_vcd->p_intf->b_block = VLC_FALSE;
     intf_RunThread( p_vcd->p_intf );
+#endif
 
-    InformationCreate( p_input );
-
+#if FIXED
     if (play_single_item)
-      VCDFixupPlayList( p_input, p_vcd, psz_source, &itemid, 
+      VCDFixupPlayList( p_access, p_vcd, psz_source, &itemid, 
                        play_single_item );
+#endif
+    
 
     free( psz_source );
 
-    var_AddCallback( p_this, "spu-es", VCDSPUCallback, NULL );
-
-
     return VLC_SUCCESS;
  err_exit:
     free( psz_source );
@@ -1600,17 +1103,16 @@ E_(Open) ( vlc_object_t *p_this )
 }
 
 /*****************************************************************************
- * Close: closes VCD releasing allocated memory.
+ * VCDClose: closes VCD releasing allocated memory.
  *****************************************************************************/
 void
-E_(Close) ( vlc_object_t *p_this )
+E_(VCDClose) ( vlc_object_t *p_this )
 {
-    input_thread_t *   p_input = (input_thread_t *)p_this;
-    thread_vcd_data_t *p_vcd = (thread_vcd_data_t *)p_input->p_access_data;
+    access_t          *p_access = (access_t *)p_this;
+    access_vcd_data_t *p_vcd    = (access_vcd_data_t *)p_access->p_sys;
 
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "VCDClose" );
 
-    var_DelCallback( p_this, "spu-es", VCDSPUCallback, NULL );
     vcdinfo_close( p_vcd->vcd );
 
     free( p_vcd->p_entries );
@@ -1627,6 +1129,164 @@ E_(Close) ( vlc_object_t *p_this )
     }
 
     free( p_vcd );
-    p_input->p_access_data = NULL;
-    p_vcd_input = NULL;
+    p_access->p_sys = NULL;
+    p_vcd_access    = NULL;
+}
+
+/*****************************************************************************
+ * Control: The front-end or vlc engine calls here to ether get
+ * information such as meta information or plugin capabilities or to
+ * issue miscellaneous "set" requests.
+ *****************************************************************************/
+static int VCDControl( access_t *p_access, int i_query, va_list args )
+{
+    access_vcd_data_t *     p_vcd= (access_vcd_data_t *)p_access->p_sys;
+    int          *pi_int;
+    int i;
+
+    dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
+               "query %d", i_query );
+
+    switch( i_query )
+    {
+        /* Pass back a copy of meta information that was gathered when we
+          during the Open/Initialize call.
+        */
+        case ACCESS_GET_META:
+         { 
+           vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
+
+           dbg_print( INPUT_DBG_EVENT, "get meta info" );
+
+           if ( p_vcd->p_meta ) {
+             *pp_meta = vlc_meta_Duplicate( p_vcd->p_meta );
+             dbg_print( INPUT_DBG_META, "%s", "Meta copied" );
+           } else 
+             msg_Warn( p_access, "tried to copy NULL meta info" );
+           
+           return VLC_SUCCESS;
+         }
+         return VLC_EGENERIC;
+
+        case ACCESS_CAN_SEEK:
+        case ACCESS_CAN_FASTSEEK:
+        case ACCESS_CAN_PAUSE:
+        case ACCESS_CAN_CONTROL_PACE: 
+         {
+            vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
+
+           dbg_print( INPUT_DBG_EVENT, 
+                      "seek/fastseek/pause/can_control_pace" );
+            *pb_bool = VLC_TRUE;
+           return VLC_SUCCESS;
+            break;
+         }
+
+        /* */
+        case ACCESS_GET_MTU:
+            pi_int = (int*)va_arg( args, int * );
+            *pi_int = (VCD_BLOCKS_ONCE * M2F2_SECTOR_SIZE);
+           dbg_print( INPUT_DBG_EVENT, "GET MTU: %d", *pi_int );
+            break;
+
+        case ACCESS_GET_PTS_DELAY:
+         { 
+           int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
+            *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
+             * MILLISECONDS_PER_SEC;
+           dbg_print( INPUT_DBG_EVENT, "GET PTS DELAY" );
+           return VLC_SUCCESS;
+            break;
+         }
+
+        /* */
+        case ACCESS_SET_PAUSE_STATE:
+           dbg_print( INPUT_DBG_EVENT, "SET PAUSE STATE" );
+           return VLC_SUCCESS;
+            break;
+
+        case ACCESS_GET_TITLE_INFO:
+         { 
+           input_title_t ***ppp_title;
+           unsigned int i;
+
+            ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
+            pi_int    = (int*)va_arg( args, int* );
+
+           dbg_print( INPUT_DBG_EVENT, "GET TITLE: i_titles %d", 
+                      p_vcd->i_titles );
+
+           VCDMetaInfo( p_access );
+
+            /* Duplicate title info */
+            if( p_vcd->i_titles == 0 )
+            {
+                *pi_int = 0; ppp_title = NULL;
+                return VLC_SUCCESS;
+            }
+            *pi_int = p_vcd->i_titles;
+            *ppp_title = malloc(sizeof( input_title_t **) * p_vcd->i_titles );
+
+           if (!*ppp_title) return VLC_ENOMEM;
+
+           for( i = 0; i < p_vcd->i_titles; i++ )
+           {
+               if ( p_vcd->p_title[i] )
+                 (*ppp_title)[i] = 
+                   vlc_input_title_Duplicate( p_vcd->p_title[i] );
+           }
+
+
+           return VLC_SUCCESS;
+         }
+         break;
+
+        case ACCESS_SET_TITLE:
+            i = (int)va_arg( args, int );
+
+           dbg_print( INPUT_DBG_EVENT, "set title %d" , i);
+            if( i != p_access->info.i_title )
+            {
+                /* Update info */
+                p_access->info.i_update |=
+                    INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
+                p_access->info.i_title = i;
+                p_access->info.i_size = p_vcd->p_title[i]->i_size;
+                p_access->info.i_pos = 0;
+
+                /* Next sector to read */
+                p_vcd->i_lsn = p_vcd->p_sectors[i];
+            }
+            break;
+
+        case ACCESS_SET_SEEKPOINT:
+        {
+            input_title_t *t = p_vcd->p_title[p_access->info.i_title];
+            i = (int)va_arg( args, int );
+            if( t->i_seekpoint > 0 )
+            {
+                p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;
+                p_access->info.i_seekpoint = i;
+
+                p_vcd->i_lsn = p_vcd->p_sectors[1+p_access->info.i_title] +
+                    t->seekpoint[i]->i_byte_offset / M2F2_SECTOR_SIZE;
+
+                p_access->info.i_pos = 
+                 (int64_t)(p_vcd->i_lsn - 
+                           p_vcd->p_sectors[1+p_access->info.i_title])
+                 * M2F2_SECTOR_SIZE;
+            }
+            return VLC_SUCCESS;
+        }
+
+        case ACCESS_SET_PRIVATE_ID_STATE:
+           dbg_print( INPUT_DBG_EVENT, "set seekpoint/set private id" );
+            return VLC_EGENERIC;
+
+        default:
+         msg_Warn( p_access, "unimplemented query in control" );
+            return VLC_EGENERIC;
+
+    }
+    return VLC_SUCCESS;
 }
index dba99e60a35acabdfb0c040c38e0a1a9be44b5fc..bf17b7b6eca34435f6ac96e33ef21e2f166b9fc0 100644 (file)
@@ -95,13 +95,15 @@ void ioctl_Close( cddev_t *p_cddev )
  *                     This makes finding the end of the last track uniform
  *                     how it is done for other tracks.
  *****************************************************************************/
-track_t ioctl_GetTracksMap( vlc_object_t *p_this, const CdIo *cdio,
+track_t ioctl_GetTracksMap( vlc_object_t *p_this, const CdIo *p_cdio,
                             lsn_t **pp_sectors )
 {
-    track_t i_tracks     = cdio_get_num_tracks(cdio);
-    track_t first_track  = cdio_get_first_track_num(cdio);
+    track_t i_tracks     = cdio_get_num_tracks(p_cdio);
+    track_t first_track  = cdio_get_first_track_num(p_cdio);
     track_t i;
 
+    if (CDIO_INVALID_TRACK == i_tracks) 
+      return 0;
 
     *pp_sectors = malloc( (i_tracks + 1) * sizeof(lsn_t) );
     if( *pp_sectors == NULL )
@@ -116,7 +118,7 @@ track_t ioctl_GetTracksMap( vlc_object_t *p_this, const CdIo *cdio,
      */
     for( i = 0 ; i <= i_tracks ; i++ )
       {
-        (*pp_sectors)[ i ] = cdio_get_track_lsn(cdio, first_track+i);
+        (*pp_sectors)[ i ] = cdio_get_track_lsn(p_cdio, first_track+i);
       }
     
     return i_tracks;
index 1d28982207ef516da7dceec9ae871b9a492abf6d..fe9cafa324d5817503676d6fdc6900dbd0747c3d 100644 (file)
@@ -2,7 +2,7 @@
  * cdrom.h: cdrom tools header
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: cdrom.h,v 1.2 2003/11/26 03:34:22 rocky Exp $
+ * $Id$
  *
  * Authors: Johan Bilien <jobi@via.ecp.fr>
  *          Gildas Bazin <gbazin@netcourrier.com>
index cf6dc5bf795f6ae07b0cd192d001b345993cb256..aa0ca319b797cb19ccfc3f2f061ff8e2dbcf79d9 100644 (file)
@@ -32,8 +32,6 @@
 #include <vlc/input.h>
 #include <vlc/intf.h>
 
-#include "../../demux/mpeg/system.h"
-
 #ifdef HAVE_UNISTD_H
 #   include <unistd.h>
 #endif
@@ -72,15 +70,15 @@ struct demux_sys_t
 };
 
 /*****************************************************************************
- * InitVCD: initializes structures
+ * VCDInit: initializes structures
  *****************************************************************************/
-int E_(InitVCD) ( vlc_object_t *p_this )
+int E_(VCDInit) ( vlc_object_t *p_this )
 {
     input_thread_t *p_input = (input_thread_t *)p_this;
-    vcd_data_t *    p_vcd = (vcd_data_t *)p_input->p_access_data;
+    vcd_data_t *    p_vcd = (vcd_data_t *)p_input->p_sys;
     demux_sys_t *   p_demux;
 
-    printf("++++ InitVCD CALLED\n");
+    printf("++++ VCDInit CALLED\n");
     
 
     if( p_input->stream.i_method != INPUT_METHOD_VCD )
@@ -115,9 +113,9 @@ int E_(InitVCD) ( vlc_object_t *p_this )
 }
 
 /*****************************************************************************
- * EndVCD: frees unused data
+ * VCDEnd: frees unused data
  *****************************************************************************/
-void E_(EndVCD) ( vlc_object_t *p_this )
+void E_(VCDEnd) ( vlc_object_t *p_this )
 {
     input_thread_t *p_input = (input_thread_t *)p_this;
     vcd_data_t *    p_vcd = p_input->p_demux_data->p_vcd;
diff --git a/modules/access/vcdx/info.c b/modules/access/vcdx/info.c
new file mode 100644 (file)
index 0000000..c6dbfbe
--- /dev/null
@@ -0,0 +1,405 @@
+/*****************************************************************************
+ * info.c : CD digital audio input information routines
+ *****************************************************************************
+ * Copyright (C) 2004 VideoLAN
+ * $Id: info.c 8845 2004-09-29 09:00:41Z rocky $
+ *
+ * Authors: Rocky Bernstein <rocky@panix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * 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.
+ *****************************************************************************/
+
+#include <vlc/vlc.h>
+#include <vlc/input.h>
+
+#include "vcd.h"
+#include <vlc_playlist.h> 
+#include "vcdplayer.h"
+#include "vlc_keys.h"
+
+#include <cdio/cdio.h>
+#include <cdio/cd_types.h>
+#include <cdio/logging.h>
+#include <cdio/util.h>
+#include <libvcd/info.h>
+#include <libvcd/logging.h>
+
+static inline void
+MetaInfoAddStr(access_t *p_access, char *p_cat,
+               char *title, const char *str)
+{
+  access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
+  if ( str ) {
+    dbg_print( INPUT_DBG_META, "field: %s: %s", title, str);
+    input_Control( p_vcd->p_input, INPUT_ADD_INFO, p_cat, title, "%s", str);
+  }
+}
+
+
+static inline void
+MetaInfoAddNum(access_t *p_access, char *psz_cat, char *title, int num)
+{
+  access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
+  dbg_print( INPUT_DBG_META, "field %s: %d", title, num);
+  input_Control( p_vcd->p_input, INPUT_ADD_INFO, psz_cat, title, "%d", num );
+}
+
+#define addstr(title, str) \
+  MetaInfoAddStr( p_access, psz_cat, title, str );
+
+#define addnum(title, num) \
+  MetaInfoAddNum( p_access, psz_cat, title, num );
+
+void 
+VCDMetaInfo( access_t *p_access  )
+{
+  access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
+  unsigned int i_entries = vcdinfo_get_num_entries(p_vcd->vcd);
+  unsigned int last_entry = 0;
+  char *psz_cat;
+  track_t i_track;
+
+  psz_cat = _("General");
+
+  addstr( _("VCD Format"),  vcdinfo_get_format_version_str(p_vcd->vcd) );
+  addstr( _("Album"),       vcdinfo_get_album_id(p_vcd->vcd));
+  addstr( _("Application"), vcdinfo_get_application_id(p_vcd->vcd) );
+  addstr( _("Preparer"),    vcdinfo_get_preparer_id(p_vcd->vcd) );
+  addnum( _("Vol #"),       vcdinfo_get_volume_num(p_vcd->vcd) );
+  addnum( _("Vol max #"),   vcdinfo_get_volume_count(p_vcd->vcd) );
+  addstr( _("Volume Set"),  vcdinfo_get_volumeset_id(p_vcd->vcd) );
+  addstr( _("Volume"),      vcdinfo_get_volume_id(p_vcd->vcd) );
+  addstr( _("Publisher"),   vcdinfo_get_publisher_id(p_vcd->vcd) );
+  addstr( _("System Id"),   vcdinfo_get_system_id(p_vcd->vcd) );
+  addnum( "LIDs",           vcdinfo_get_num_LIDs(p_vcd->vcd) );
+  addnum( _("Entries"),     vcdinfo_get_num_entries(p_vcd->vcd) );
+  addnum( _("Segments"),    vcdinfo_get_num_segments(p_vcd->vcd) );
+  addnum( _("Tracks"),      vcdinfo_get_num_tracks(p_vcd->vcd) );
+
+  /* Spit out track information. Could also include MSF info.
+     Also build title table.
+   */
+
+#define TITLE_MAX 30
+  for( i_track = 1 ; i_track < p_vcd->i_tracks ; i_track++ ) {
+    unsigned int audio_type = vcdinfo_get_track_audio_type(p_vcd->vcd, 
+                                                          i_track);
+    uint32_t i_secsize = 
+      p_vcd->p_sectors[i_track+1] - p_vcd->p_sectors[i_track];
+    if (p_vcd->b_svd) {
+      addnum(_("Audio Channels"),  
+            vcdinfo_audio_type_num_channels(p_vcd->vcd, audio_type) );
+    }
+
+    addnum(_("First Entry Point"), last_entry );
+    for ( ; last_entry < i_entries 
+           && vcdinfo_get_track(p_vcd->vcd, last_entry) == i_track;
+         last_entry++ ) ;
+    addnum(_("Last Entry Point"), last_entry-1 );
+    addnum(_("Track size (in sectors)"), i_secsize );
+  }
+}
+
+#define add_format_str_info(val)                              \
+  {                                                           \
+    const char *str = val;                                    \
+    unsigned int len;                                         \
+    if (val != NULL) {                                        \
+      len=strlen(str);                                        \
+      if (len != 0) {                                         \
+        strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));         \
+        tp += len;                                            \
+      }                                                        \
+      saw_control_prefix = VLC_FALSE;                         \
+    }                                                         \
+  }
+
+#define add_format_num_info( val, fmt )                               \
+  {                                                           \
+    char num_str[10];                                         \
+    unsigned int len;                                         \
+    sprintf(num_str, fmt, val);                                \
+    len = strlen(num_str);                                    \
+    if( len != 0 )                                             \
+    {                                                         \
+      strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));        \
+      tp += len;                                              \
+    }                                                         \
+    saw_control_prefix = VLC_FALSE;                                \
+  }
+
+/*!
+   Take a format string and expand escape sequences, that is sequences that
+   begin with %, with information from the current VCD.
+   The expanded string is returned. Here is a list of escape sequences:
+
+   %A : The album information
+   %C : The VCD volume count - the number of CD's in the collection.
+   %c : The VCD volume num - the number of the CD in the collection.
+   %F : The VCD Format, e.g. VCD 1.0, VCD 1.1, VCD 2.0, or SVCD
+   %I : The current entry/segment/playback type, e.g. ENTRY, TRACK, SEGMENT...
+   %L : The playlist ID prefixed with " LID" if it exists
+   %M : MRL
+   %N : The current number of the %I - a decimal number
+   %P : The publisher ID
+   %p : The preparer ID
+   %S : If we are in a segment (menu), the kind of segment
+   %T : The track number
+   %V : The volume set ID
+   %v : The volume ID
+       A number between 1 and the volume count.
+   %% : a %
+*/
+char *
+VCDFormatStr(const access_t *p_access, access_vcd_data_t *p_vcd,
+             const char format_str[], const char *mrl,
+             const vcdinfo_itemid_t *itemid)
+{
+#define TEMP_STR_SIZE 256
+#define TEMP_STR_LEN (TEMP_STR_SIZE-1)
+  static char    temp_str[TEMP_STR_SIZE];
+  size_t         i;
+  char *         tp = temp_str;
+  vlc_bool_t     saw_control_prefix = VLC_FALSE;
+  size_t         format_len = strlen(format_str);
+
+  memset(temp_str, 0, TEMP_STR_SIZE);
+
+  for (i=0; i<format_len; i++) {
+
+    if (!saw_control_prefix && format_str[i] != '%') {
+      *tp++ = format_str[i];
+      saw_control_prefix = VLC_FALSE;
+      continue;
+    }
+
+    switch(format_str[i]) {
+    case '%':
+      if (saw_control_prefix) {
+        *tp++ = '%';
+      }
+      saw_control_prefix = !saw_control_prefix;
+      break;
+    case 'A':
+      add_format_str_info(vcdinfo_strip_trail(vcdinfo_get_album_id(p_vcd->vcd),
+                                              MAX_ALBUM_LEN));
+      break;
+
+    case 'c':
+      add_format_num_info(vcdinfo_get_volume_num(p_vcd->vcd), "%d");
+      break;
+
+    case 'C':
+      add_format_num_info(vcdinfo_get_volume_count(p_vcd->vcd), "%d");
+      break;
+
+    case 'F':
+      add_format_str_info(vcdinfo_get_format_version_str(p_vcd->vcd));
+      break;
+
+    case 'I':
+      {
+        switch (itemid->type) {
+        case VCDINFO_ITEM_TYPE_TRACK:
+          strncat(tp, _("Track"), TEMP_STR_LEN-(tp-temp_str));
+          tp += strlen(_("Track"));
+        break;
+        case VCDINFO_ITEM_TYPE_ENTRY:
+          strncat(tp, _("Entry"), TEMP_STR_LEN-(tp-temp_str));
+          tp += strlen(_("Entry"));
+          break;
+        case VCDINFO_ITEM_TYPE_SEGMENT:
+          strncat(tp, _("Segment"), TEMP_STR_LEN-(tp-temp_str));
+          tp += strlen(_("Segment"));
+          break;
+        case VCDINFO_ITEM_TYPE_LID:
+          strncat(tp, _("List ID"), TEMP_STR_LEN-(tp-temp_str));
+          tp += strlen(_("List ID"));
+          break;
+        case VCDINFO_ITEM_TYPE_SPAREID2:
+          strncat(tp, _("Navigation"), TEMP_STR_LEN-(tp-temp_str));
+          tp += strlen(_("Navigation"));
+          break;
+        default:
+          /* What to do? */
+          ;
+        }
+        saw_control_prefix = VLC_FALSE;
+      }
+      break;
+
+    case 'L':
+      if (vcdplayer_pbc_is_on(p_vcd)) {
+        char num_str[40];
+        sprintf(num_str, "%s %d", _("List ID"), p_vcd->i_lid);
+        strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));
+        tp += strlen(num_str);
+      }
+      saw_control_prefix = VLC_FALSE;
+      break;
+
+    case 'M':
+      add_format_str_info(mrl);
+      break;
+
+    case 'N':
+      add_format_num_info(itemid->num, "%d");
+      break;
+
+    case 'p':
+      add_format_str_info(vcdinfo_get_preparer_id(p_vcd->vcd));
+      break;
+
+    case 'P':
+      add_format_str_info(vcdinfo_get_publisher_id(p_vcd->vcd));
+      break;
+
+    case 'S':
+      if ( VCDINFO_ITEM_TYPE_SEGMENT==itemid->type ) {
+        char seg_type_str[10];
+
+        sprintf(seg_type_str, " %s",
+                vcdinfo_video_type2str(p_vcd->vcd, itemid->num));
+        strncat(tp, seg_type_str, TEMP_STR_LEN-(tp-temp_str));
+        tp += strlen(seg_type_str);
+      }
+      saw_control_prefix = VLC_FALSE;
+      break;
+
+    case 'T':
+      add_format_num_info(p_vcd->i_track, "%d");
+      break;
+
+    case 'V':
+      add_format_str_info(vcdinfo_get_volumeset_id(p_vcd->vcd));
+      break;
+
+    case 'v':
+      add_format_str_info(vcdinfo_get_volume_id(p_vcd->vcd));
+      break;
+
+    default:
+      *tp++ = '%';
+      *tp++ = format_str[i];
+      saw_control_prefix = VLC_FALSE;
+    }
+  }
+  return strdup(temp_str);
+}
+
+static void
+VCDCreatePlayListItem(const access_t *p_access,
+                      access_vcd_data_t *p_vcd,
+                      playlist_t *p_playlist,
+                      const vcdinfo_itemid_t *itemid,
+                      char *psz_mrl, int psz_mrl_max,
+                      const char *psz_source, int playlist_operation,
+                      int i_pos)
+{
+  char *p_author;
+  char *p_title;
+  char c_type;
+
+  switch(itemid->type) {
+  case VCDINFO_ITEM_TYPE_TRACK:
+    c_type='T';
+    break;
+  case VCDINFO_ITEM_TYPE_SEGMENT:
+    c_type='S';
+    break;
+  case VCDINFO_ITEM_TYPE_LID:
+    c_type='P';
+    break;
+  case VCDINFO_ITEM_TYPE_ENTRY:
+    c_type='E';
+    break;
+  default:
+    c_type='?';
+    break;
+  }
+
+  snprintf(psz_mrl, psz_mrl_max, "%s%s@%c%u", VCD_MRL_PREFIX, psz_source,
+           c_type, itemid->num);
+
+  p_title =
+    VCDFormatStr( p_access, p_vcd,
+                 config_GetPsz( p_access, MODULE_STRING "-title-format" ),
+                 psz_mrl, itemid );
+  
+  playlist_Add( p_playlist, psz_mrl, p_title, playlist_operation, i_pos );
+
+  p_author =
+    VCDFormatStr( p_access, p_vcd,
+                 config_GetPsz( p_access, MODULE_STRING "-author-format" ),
+                 psz_mrl, itemid );
+
+  if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
+  playlist_AddInfo(p_playlist, i_pos, _("General"), _("Author"), "%s",
+                  p_author);
+}
+
+int
+VCDFixupPlayList( access_t *p_access, access_vcd_data_t *p_vcd,
+                  const char *psz_source, vcdinfo_itemid_t *itemid,
+                  vlc_bool_t b_single_item )
+{
+  unsigned int i;
+  playlist_t * p_playlist;
+  char       * psz_mrl;
+  unsigned int psz_mrl_max = strlen(VCD_MRL_PREFIX) + strlen(psz_source) +
+    strlen("@T") + strlen("100") + 1;
+
+  psz_mrl = malloc( psz_mrl_max );
+
+  if( psz_mrl == NULL )
+    {
+      msg_Warn( p_access, "out of memory" );
+      return -1;
+    }
+
+  p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
+                                               FIND_ANYWHERE );
+  if( !p_playlist )
+    {
+      msg_Warn( p_access, "can't find playlist" );
+      free(psz_mrl);
+      return -1;
+    }
+
+  {
+    vcdinfo_itemid_t list_itemid;
+    list_itemid.type=VCDINFO_ITEM_TYPE_ENTRY;
+
+    playlist_LockDelete( p_playlist, p_playlist->i_index);
+
+    for( i = 0 ; i < p_vcd->i_entries ; i++ )
+      {
+        list_itemid.num=i;
+        VCDCreatePlayListItem(p_access, p_vcd, p_playlist, &list_itemid,
+                              psz_mrl, psz_mrl_max, psz_source,
+                              PLAYLIST_APPEND, PLAYLIST_END);
+      }
+
+#if LOOKED_OVER
+    playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
+#endif
+
+  }
+
+  vlc_object_release( p_playlist );
+  free(psz_mrl);
+  return 0;
+}
+
diff --git a/modules/access/vcdx/info.h b/modules/access/vcdx/info.h
new file mode 100644 (file)
index 0000000..17ebc03
--- /dev/null
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ * info.h : VCD information routine headers
+ *****************************************************************************
+ * Copyright (C) 2004 VideoLAN
+ * $Id: info.h 8606 2004-08-31 18:32:54Z rocky $
+ *
+ * Authors: Rocky Bernstein <rocky@panix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 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 General Public License for more details.
+ *
+ * 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.
+ *****************************************************************************/
+
+/*
+ Fills out playlist information.
+ */
+int VCDFixupPlayList( access_t *p_access, access_vcd_data_t *p_vcd,
+                     const char *psz_source, vcdinfo_itemid_t *itemid,
+                     vlc_bool_t b_single_track );
+
+/*
+ Sets VCD meta information and navigation/playlist entries. 
+ */
+void VCDMetaInfo( access_t *p_access  );
+
+char *
+VCDFormatStr(const access_t *p_access, access_vcd_data_t *p_vcd,
+             const char format_str[], const char *mrl,
+             const vcdinfo_itemid_t *itemid);
index 90c04b04799082f31c20cc7edfab77264bdb7ff7..52475802eb078c750fad9e71bb29a67f7b3cd009 100644 (file)
@@ -2,7 +2,7 @@
  * intf.h: send info to intf.
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: intf.h,v 1.4 2003/12/22 14:32:55 sam Exp $
+ * $Id$
  *
  * Author: Stéphane Borel <stef@via.ecp.fr>
  *
@@ -27,7 +27,7 @@
 struct intf_sys_t
 {
   input_thread_t    * p_input;
-  thread_vcd_data_t * p_vcd;
+  access_vcd_data_t * p_vcd;
 
   vlc_bool_t          b_still;        /* True if we are in a still frame */
   vlc_bool_t          b_inf_still;    /* True if still wait time is infinite */
index 52db0a87fe1fb36750343a0f3da8569b0694772b..6cd87fa4d0e457c0d4ba546342c769bfaee76afc 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * vcd.c : VCD input module for vlc
  *****************************************************************************
- * Copyright (C) 2000,2003 VideoLAN
+ * Copyright (C) 2000, 2003, 2004 VideoLAN
  * $Id$
  *
  * Authors: Rocky Bernstein <rocky@panix.com>
 /*****************************************************************************
  * Exported prototypes
  *****************************************************************************/
-int  E_(Open)         ( vlc_object_t * );
-void E_(Close)        ( vlc_object_t * );
+int  E_(VCDOpen)      ( vlc_object_t * );
+void E_(VCDClose)     ( vlc_object_t * );
 int  E_(OpenIntf)     ( vlc_object_t * );
 void E_(CloseIntf)    ( vlc_object_t * );
-int  E_(InitVCD)      ( vlc_object_t * );
-void E_(EndVCD)       ( vlc_object_t * );
+int  E_(VCDInit)      ( vlc_object_t * );
+void E_(VCDEnd)       ( vlc_object_t * );
 
 int  E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name,
                          vlc_value_t oldval, vlc_value_t val,
@@ -90,12 +90,9 @@ int  E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name,
 vlc_module_begin();
     add_usage_hint( N_("vcdx://[device-or-file][@{P,S,T}num]") );
     set_description( _("Video CD (VCD 1.0, 1.1, 2.0, SVCD, HQVCD) input") );
-    set_capability( "access", 85 /* slightly higher than vcd */ );
-    set_callbacks( E_(Open), E_(Close) );
-    add_shortcut( "vcd" );
+    set_capability( "access2", 55 /* slightly lower than vcd */ );
+    set_callbacks( E_(VCDOpen), E_(VCDClose) );
     add_shortcut( "vcdx" );
-    set_category( CAT_INPUT );
-    set_subcategory( SUBCAT_INPUT_ACCESS );
 
     /* Configuration options */
     add_integer ( MODULE_STRING "-debug", 0, E_(DebugCallback),
@@ -123,11 +120,11 @@ vlc_module_begin();
 #ifdef FIXED
     add_submodule();
         set_capability( "demux", 0 );
-        set_callbacks( E_(InitVCD), E_(EndVCD) );
-#endif
-
+        set_callbacks( E_(VCDInit), E_(VCDEnd) );
     add_submodule();
         set_capability( "interface", 0 );
         set_callbacks( E_(OpenIntf), E_(CloseIntf) );
+#endif
+
 vlc_module_end();
 
index 416a1b7066008872a5a328c13630844a21b697e1..b6dcb48a41cb58bf24221adbfb945fbb3c333dec 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * vcd.h : VCD input module header for vlc
- *          using libcdio, libvcd and libvcdinfo
+ *         using libcdio, libvcd and libvcdinfo
  *****************************************************************************
- * Copyright (C) 2003 VideoLAN
+ * Copyright (C) 2003, 2004 VideoLAN
  * $Id$
  *
  * Authors: Rocky Bernstein <rocky@panix.com> 
@@ -24,6 +24,8 @@
 
 #include <libvcd/info.h>
 
+#define VCD_MRL_PREFIX "vcdx://"
+
 /*****************************************************************************
  * vcd_data_t: structure for communication between access and intf.
  *****************************************************************************/
@@ -40,7 +42,7 @@ typedef struct
 #endif
 
     int                     i_still_time;
-    vlc_bool_t                    b_end_of_cell;
+    vlc_bool_t              b_end_of_cell;
 
 #if FINISHED
     vcdplay_event_t         event;
@@ -50,6 +52,6 @@ typedef struct
 
 } vcd_data_t;
 
-int  VCDSetArea      ( input_thread_t *, input_area_t * );
-void VCDSeek         ( input_thread_t *, off_t );
-int  VCDPlay         ( input_thread_t *, vcdinfo_itemid_t );
+int  VCDSetArea      ( access_t * );
+int  VCDSeek         ( access_t *, off_t );
+int  VCDPlay         ( access_t *, vcdinfo_itemid_t );
index 247501e4aece5756c6aff91978ffda16395de29c..02fb87cea404acd3a3ac4e5940246e89fb053668 100644 (file)
@@ -2,7 +2,7 @@
  * vcdplayer.c : VCD input module for vlc
  *               using libcdio, libvcd and libvcdinfo
  *****************************************************************************
- * Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
+ * Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
  * $Id$
  *
  * This program is free software; you can redistribute it and/or modify
 /*!
   Return VLC_TRUE if playback control (PBC) is on
 */
-vlc_bool_t vcdplayer_pbc_is_on( const thread_vcd_data_t *p_vcd ) 
+vlc_bool_t 
+vcdplayer_pbc_is_on( const access_vcd_data_t *p_vcd ) 
 {
-  return VCDINFO_INVALID_ENTRY != p_vcd->cur_lid; 
+  return VCDINFO_INVALID_ENTRY != p_vcd->i_lid; 
 }
 
-static void vcdplayer_update_entry( input_thread_t * p_input, uint16_t ofs, 
+static void 
+vcdplayer_update_entry( access_t * p_access, uint16_t ofs, 
                         uint16_t *entry, const char *label)
 {
-  thread_vcd_data_t *     p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
+  access_vcd_data_t *     p_vcd= (access_vcd_data_t *)p_access->p_sys;
 
   if ( ofs == VCDINFO_INVALID_OFFSET ) {
     *entry = VCDINFO_INVALID_ENTRY;
@@ -79,17 +81,18 @@ static void vcdplayer_update_entry( input_thread_t * p_input, uint16_t ofs,
 
    return VLC_TRUE if the caller should return.
 */
-vcdplayer_read_status_t vcdplayer_non_pbc_nav ( input_thread_t * p_input )
+vcdplayer_read_status_t 
+vcdplayer_non_pbc_nav ( access_t * p_access )
 {
-  thread_vcd_data_t *     p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
+  access_vcd_data_t *     p_vcd= (access_vcd_data_t *)p_access->p_sys;
 
   /* Not in playback control. Do we advance automatically or stop? */
   switch (p_vcd->play_item.type) {
   case VCDINFO_ITEM_TYPE_TRACK:
   case VCDINFO_ITEM_TYPE_ENTRY: {
 
-    dbg_print( INPUT_DBG_LSN, "new track %d, lsn %d", p_vcd->cur_track, 
-               p_vcd->p_sectors[p_vcd->cur_track+1] );
+    dbg_print( INPUT_DBG_LSN, "new track %d, lsn %d", p_vcd->i_track, 
+               p_vcd->p_sectors[p_vcd->i_track+1] );
     return READ_END;
     break;
   }
@@ -97,7 +100,6 @@ vcdplayer_read_status_t vcdplayer_non_pbc_nav ( input_thread_t * p_input )
     dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN), 
                "SPAREID2" );
     /* FIXME */
-    p_input->stream.b_seekable = 0;
     if (p_vcd->in_still)
     {
       return READ_STILL_FRAME ;
@@ -112,7 +114,6 @@ vcdplayer_read_status_t vcdplayer_non_pbc_nav ( input_thread_t * p_input )
   case VCDINFO_ITEM_TYPE_SEGMENT:
       /* Hack: Just go back and do still again */
     /* FIXME */
-    p_input->stream.b_seekable = 0;
     if (p_vcd->in_still) 
     {
       dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN), 
@@ -126,9 +127,9 @@ vcdplayer_read_status_t vcdplayer_non_pbc_nav ( input_thread_t * p_input )
 
 /* Handles PBC navigation when reaching the end of a play item. */
 vcdplayer_read_status_t
-vcdplayer_pbc_nav ( input_thread_t * p_input )
+vcdplayer_pbc_nav ( access_t * p_access )
 {
-  thread_vcd_data_t *     p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
+  access_vcd_data_t *     p_vcd= (access_vcd_data_t *)p_access->p_sys;
 
   /* We are in playback control. */
   vcdinfo_itemid_t itemid;
@@ -137,12 +138,12 @@ vcdplayer_pbc_nav ( input_thread_t * p_input )
      sequence (or track). */
   
   if ( (VCDINFO_ITEM_TYPE_ENTRY == p_vcd->play_item.type) && 
-       (p_vcd->cur_lsn < p_vcd->end_lsn) ) {
+       (p_vcd->i_lsn < p_vcd->end_lsn) ) {
     /* Set up to just continue to the next entry */
     p_vcd->play_item.num++;
     dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), 
                "continuing into next entry: %u", p_vcd->play_item.num);
-    VCDPlay( p_input, p_vcd->play_item );
+    VCDPlay( p_access, p_vcd->play_item );
     /* p_vcd->update_title(); */
     return READ_BLOCK;
   }
@@ -156,20 +157,22 @@ vcdplayer_pbc_nav ( input_thread_t * p_input )
     
     dbg_print(INPUT_DBG_PBC, "playlist wait_time: %d", wait_time);
     
-    if (vcdplayer_inc_play_item(p_input))
+    if (vcdplayer_inc_play_item(p_access))
       return READ_BLOCK;
 
     /* Handle any wait time given. */
+#if FIXED
     if (p_vcd->in_still) {
       vcdIntfStillTime( p_vcd->p_intf, wait_time );
       return READ_STILL_FRAME;
     }
+#endif
 
-    vcdplayer_update_entry( p_input
+    vcdplayer_update_entry( p_access
                             vcdinf_pld_get_next_offset(p_vcd->pxd.pld),
                             &itemid.num, "next" );
     itemid.type = VCDINFO_ITEM_TYPE_LID;
-    VCDPlay( p_input, itemid );
+    VCDPlay( p_access, itemid );
     break;
   }
   case PSD_TYPE_SELECTION_LIST:     /* Selection List (+Ext. for SVCD) */
@@ -185,16 +188,18 @@ vcdplayer_pbc_nav ( input_thread_t * p_input )
                 wait_time, p_vcd->loop_count, max_loop);
       
       /* Handle any wait time given */
+#if FIXED
       if (p_vcd->in_still) {
        vcdIntfStillTime( p_vcd->p_intf, wait_time );
        return READ_STILL_FRAME;
       } 
+#endif
       
       /* Handle any looping given. */
       if ( max_loop == 0 || p_vcd->loop_count < max_loop ) {
         p_vcd->loop_count++;
         if (p_vcd->loop_count == 0x7f) p_vcd->loop_count = 0;
-        VCDSeek( p_input, 0 );
+        VCDSeek( p_access, 0 );
         /* if (p_vcd->in_still) p_vcd->force_redisplay();*/
         return READ_BLOCK;
       }
@@ -207,7 +212,7 @@ vcdplayer_pbc_nav ( input_thread_t * p_input )
         itemid.num  = offset_timeout_LID->lid;
         itemid.type = VCDINFO_ITEM_TYPE_LID;
         dbg_print(INPUT_DBG_PBC, "timeout to: %d", itemid.num);
-        VCDPlay( p_input, itemid );
+        VCDPlay( p_access, itemid );
         return READ_BLOCK;
       } else {
         int num_selections = vcdinf_get_num_selections(p_vcd->pxd.psd);
@@ -217,13 +222,13 @@ vcdplayer_pbc_nav ( input_thread_t * p_input )
           int rand_selection=bsn +
             (int) ((num_selections+0.0)*rand()/(RAND_MAX+1.0));
           lid_t rand_lid=vcdinfo_selection_get_lid (p_vcd->vcd, 
-                                                   p_vcd->cur_lid, 
+                                                   p_vcd->i_lid, 
                                                    rand_selection);
           itemid.num = rand_lid;
           itemid.type = VCDINFO_ITEM_TYPE_LID;
           dbg_print(INPUT_DBG_PBC, "random selection %d, lid: %d", 
                     rand_selection - bsn, rand_lid);
-          VCDPlay( p_input, itemid );
+          VCDPlay( p_access, itemid );
           return READ_BLOCK;
         } else if (p_vcd->in_still) {
           /* Hack: Just go back and do still again */
@@ -257,9 +262,10 @@ vcdplayer_pbc_nav ( input_thread_t * p_input )
   confused with a user's list of favorite things to play or the 
   "next" field of a LID which moves us to a different LID.
  */
-vlc_bool_t vcdplayer_inc_play_item( input_thread_t *p_input )
+vlc_bool_t 
+vcdplayer_inc_play_item( access_t *p_access )
 {
-  thread_vcd_data_t *     p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
+  access_vcd_data_t *     p_vcd= (access_vcd_data_t *)p_access->p_sys;
 
   int noi;
 
@@ -287,7 +293,7 @@ vlc_bool_t vcdplayer_inc_play_item( input_thread_t *p_input )
     vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
     dbg_print(INPUT_DBG_PBC, "  play-item[%d]: %s",
               p_vcd->pdi, vcdinfo_pin2str (trans_itemid_num));
-    return VLC_SUCCESS == VCDPlay( p_input, trans_itemid );
+    return VLC_SUCCESS == VCDPlay( p_access, trans_itemid );
   }
 }
 
@@ -296,9 +302,10 @@ vlc_bool_t vcdplayer_inc_play_item( input_thread_t *p_input )
 
   Return VLC_FALSE if there was some problem.
 */
-vlc_bool_t vcdplayer_play_default( input_thread_t * p_input )
+vlc_bool_t 
+vcdplayer_play_default( access_t * p_access )
 {
-  thread_vcd_data_t *p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
+  access_vcd_data_t *p_vcd= (access_vcd_data_t *)p_access->p_sys;
 
   vcdinfo_itemid_t   itemid;
 
@@ -317,27 +324,27 @@ vlc_bool_t vcdplayer_play_default( input_thread_t * p_input )
   if  (vcdplayer_pbc_is_on(p_vcd)) {
 
 #if defined(LIBVCD_VERSION)
-    lid_t lid=vcdinfo_get_multi_default_lid(p_vcd->vcd, p_vcd->cur_lid,
-                                           p_vcd->cur_lsn);
+    lid_t lid=vcdinfo_get_multi_default_lid(p_vcd->vcd, p_vcd->i_lid,
+                                           p_vcd->i_lsn);
 
     if (VCDINFO_INVALID_LID != lid) {
       itemid.num  = lid;
       itemid.type = VCDINFO_ITEM_TYPE_LID;
       dbg_print(INPUT_DBG_PBC, "DEFAULT to %d\n", itemid.num);
     } else {
-      dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d\n", p_vcd->cur_lid);
+      dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d\n", p_vcd->i_lid);
     }
 
 #else 
-    vcdinfo_lid_get_pxd(p_vcd->vcd, &(p_vcd->pxd), p_vcd->cur_lid);
+    vcdinfo_lid_get_pxd(p_vcd->vcd, &(p_vcd->pxd), p_vcd->i_lid);
     
     switch (p_vcd->pxd.descriptor_type) {
     case PSD_TYPE_SELECTION_LIST:
     case PSD_TYPE_EXT_SELECTION_LIST:
       if (p_vcd->pxd.psd == NULL) return VLC_FALSE;
-      vcdplayer_update_entry( p_input
+      vcdplayer_update_entry( p_access
                              vcdinfo_get_default_offset(p_vcd->vcd, 
-                                                        p_vcd->cur_lid), 
+                                                        p_vcd->i_lid), 
                              &itemid.num, "default");
       break;
 
@@ -360,7 +367,7 @@ vlc_bool_t vcdplayer_play_default( input_thread_t * p_input )
   }
 
   /** ??? p_vcd->update_title(); ***/
-  return VLC_SUCCESS == VCDPlay( p_input, itemid );
+  return VLC_SUCCESS == VCDPlay( p_access, itemid );
 
 }
 
@@ -369,9 +376,10 @@ vlc_bool_t vcdplayer_play_default( input_thread_t * p_input )
 
   Return VLC_FALSE if there was some problem.
 */
-vlc_bool_t vcdplayer_play_next( input_thread_t * p_input )
+vlc_bool_t 
+vcdplayer_play_next( access_t * p_access )
 {
-  thread_vcd_data_t *p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
+  access_vcd_data_t *p_vcd= (access_vcd_data_t *)p_access->p_sys;
 
   vcdinfo_obj_t     *obj;
   vcdinfo_itemid_t   itemid;
@@ -387,13 +395,13 @@ vlc_bool_t vcdplayer_play_next( input_thread_t * p_input )
 
   if  (vcdplayer_pbc_is_on(p_vcd)) {
 
-    vcdinfo_lid_get_pxd(obj, &(p_vcd->pxd), p_vcd->cur_lid);
+    vcdinfo_lid_get_pxd(obj, &(p_vcd->pxd), p_vcd->i_lid);
     
     switch (p_vcd->pxd.descriptor_type) {
     case PSD_TYPE_SELECTION_LIST:
     case PSD_TYPE_EXT_SELECTION_LIST:
       if (p_vcd->pxd.psd == NULL) return VLC_FALSE;
-      vcdplayer_update_entry( p_input
+      vcdplayer_update_entry( p_access
                              vcdinf_psd_get_next_offset(p_vcd->pxd.psd), 
                              &itemid.num, "next");
       itemid.type = VCDINFO_ITEM_TYPE_LID;
@@ -401,7 +409,7 @@ vlc_bool_t vcdplayer_play_next( input_thread_t * p_input )
 
     case PSD_TYPE_PLAY_LIST: 
       if (p_vcd->pxd.pld == NULL) return VLC_FALSE;
-      vcdplayer_update_entry( p_input
+      vcdplayer_update_entry( p_access
                              vcdinf_pld_get_next_offset(p_vcd->pxd.pld), 
                              &itemid.num, "next");
       itemid.type = VCDINFO_ITEM_TYPE_LID;
@@ -425,13 +433,13 @@ vlc_bool_t vcdplayer_play_next( input_thread_t * p_input )
       
       switch (p_vcd->play_item.type) {
       case VCDINFO_ITEM_TYPE_ENTRY: 
-       max_entry = p_vcd->num_entries;
+       max_entry = p_vcd->i_entries;
        break;
       case VCDINFO_ITEM_TYPE_SEGMENT: 
-       max_entry = p_vcd->num_segments;
+       max_entry = p_vcd->i_segments;
        break;
       case VCDINFO_ITEM_TYPE_TRACK: 
-       max_entry = p_vcd->num_tracks;
+       max_entry = p_vcd->i_tracks;
        break;
       default: ; /* Handle exceptional cases below */
       }
@@ -457,7 +465,7 @@ vlc_bool_t vcdplayer_play_next( input_thread_t * p_input )
   }
 
   /** ??? p_vcd->update_title(); ***/
-  return VLC_SUCCESS == VCDPlay( p_input, itemid );
+  return VLC_SUCCESS == VCDPlay( p_access, itemid );
 
 }
 
@@ -466,9 +474,10 @@ vlc_bool_t vcdplayer_play_next( input_thread_t * p_input )
 
   Return VLC_FALSE if there was some problem.
 */
-vlc_bool_t vcdplayer_play_prev( input_thread_t * p_input )
+vlc_bool_t 
+vcdplayer_play_prev( access_t * p_access )
 {
-  thread_vcd_data_t *p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
+  access_vcd_data_t *p_vcd= (access_vcd_data_t *)p_access->p_sys;
 
   vcdinfo_obj_t     *obj  = p_vcd->vcd;
   vcdinfo_itemid_t   itemid;
@@ -480,13 +489,13 @@ vlc_bool_t vcdplayer_play_prev( input_thread_t * p_input )
 
   if  (vcdplayer_pbc_is_on(p_vcd)) {
 
-    vcdinfo_lid_get_pxd(obj, &(p_vcd->pxd), p_vcd->cur_lid);
+    vcdinfo_lid_get_pxd(obj, &(p_vcd->pxd), p_vcd->i_lid);
     
     switch (p_vcd->pxd.descriptor_type) {
     case PSD_TYPE_SELECTION_LIST:
     case PSD_TYPE_EXT_SELECTION_LIST:
       if (p_vcd->pxd.psd == NULL) return VLC_FALSE;
-      vcdplayer_update_entry( p_input
+      vcdplayer_update_entry( p_access
                              vcdinf_psd_get_prev_offset(p_vcd->pxd.psd), 
                              &itemid.num, "prev");
       itemid.type = VCDINFO_ITEM_TYPE_LID;
@@ -494,7 +503,7 @@ vlc_bool_t vcdplayer_play_prev( input_thread_t * p_input )
 
     case PSD_TYPE_PLAY_LIST: 
       if (p_vcd->pxd.pld == NULL) return VLC_FALSE;
-      vcdplayer_update_entry( p_input
+      vcdplayer_update_entry( p_access
                              vcdinf_pld_get_prev_offset(p_vcd->pxd.pld), 
                              &itemid.num, "prev");
       itemid.type = VCDINFO_ITEM_TYPE_LID;
@@ -522,7 +531,7 @@ vlc_bool_t vcdplayer_play_prev( input_thread_t * p_input )
   }
 
   /** ??? p_vcd->update_title(); ***/
-  return VLC_SUCCESS == VCDPlay( p_input, itemid );
+  return VLC_SUCCESS == VCDPlay( p_access, itemid );
 
 }
 
@@ -531,9 +540,10 @@ vlc_bool_t vcdplayer_play_prev( input_thread_t * p_input )
 
   Return VLC_FALSE if there was some problem.
 */
-vlc_bool_t vcdplayer_play_return( input_thread_t * p_input )
+vlc_bool_t 
+vcdplayer_play_return( access_t * p_access )
 {
-  thread_vcd_data_t *p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
+  access_vcd_data_t *p_vcd= (access_vcd_data_t *)p_access->p_sys;
 
   vcdinfo_obj_t     *obj  = p_vcd->vcd;
   vcdinfo_itemid_t   itemid;
@@ -545,13 +555,13 @@ vlc_bool_t vcdplayer_play_return( input_thread_t * p_input )
 
   if  (vcdplayer_pbc_is_on(p_vcd)) {
 
-    vcdinfo_lid_get_pxd(obj, &(p_vcd->pxd), p_vcd->cur_lid);
+    vcdinfo_lid_get_pxd(obj, &(p_vcd->pxd), p_vcd->i_lid);
     
     switch (p_vcd->pxd.descriptor_type) {
     case PSD_TYPE_SELECTION_LIST:
     case PSD_TYPE_EXT_SELECTION_LIST:
       if (p_vcd->pxd.psd == NULL) return VLC_FALSE;
-      vcdplayer_update_entry( p_input
+      vcdplayer_update_entry( p_access
                              vcdinf_psd_get_return_offset(p_vcd->pxd.psd), 
                              &itemid.num, "return");
       itemid.type = VCDINFO_ITEM_TYPE_LID;
@@ -559,7 +569,7 @@ vlc_bool_t vcdplayer_play_return( input_thread_t * p_input )
 
     case PSD_TYPE_PLAY_LIST: 
       if (p_vcd->pxd.pld == NULL) return VLC_FALSE;
-      vcdplayer_update_entry( p_input
+      vcdplayer_update_entry( p_access
                              vcdinf_pld_get_return_offset(p_vcd->pxd.pld), 
                              &itemid.num, "return");
       itemid.type = VCDINFO_ITEM_TYPE_LID;
@@ -580,6 +590,6 @@ vlc_bool_t vcdplayer_play_return( input_thread_t * p_input )
   }
 
   /** ??? p_vcd->update_title(); ***/
-  return VLC_SUCCESS == VCDPlay( p_input, itemid );
+  return VLC_SUCCESS == VCDPlay( p_access, itemid );
 
 }
index 1addfacc038d242dab19462099157d8bf2aaa36c..ed1b5a8fb4a212ee6a83084230fbb7323c34c4b5 100644 (file)
@@ -25,6 +25,7 @@
 #define _VCDPLAYER_H_
 
 #include <libvcd/info.h>
+#include "vlc_meta.h"
 
 #define INPUT_DBG_META        1 /* Meta information */
 #define INPUT_DBG_EVENT       2 /* input (keyboard/mouse) events */
 #if INPUT_DEBUG
 #define dbg_print(mask, s, args...) \
    if (p_vcd && p_vcd->i_debug & mask) \
-     msg_Dbg(p_input, "%s: "s, __func__ , ##args)
+     msg_Dbg(p_access, "%s: "s, __func__ , ##args)
 #else
 #define dbg_print(mask, s, args...) 
 #endif
 
-#define LOG_ERR(args...)  msg_Err( p_input, args )
-#define LOG_WARN(args...) msg_Warn( p_input, args )
+#define LOG_ERR(args...)  msg_Err( p_access, args )
+#define LOG_WARN(args...) msg_Warn( p_access, args )
 
 /* vcdplayer_read return status */
 typedef enum {
@@ -60,29 +61,25 @@ typedef enum {
 } vcdplayer_read_status_t;
 
 /*****************************************************************************
- * thread_vcd_data_t: VCD information
+ * access_vcd_data_t: VCD information
  *****************************************************************************/
 typedef struct thread_vcd_data_s
 {
   vcdinfo_obj_t *vcd;                   /* CD device descriptor */
-  vlc_bool_t   in_still;              /*  true if in still */
-  vlc_bool_t   b_svd;                 /*  true if we have SVD info */
-  unsigned int num_tracks;              /* Nb of tracks (titles) */
-  unsigned int num_segments;            /* Nb of segments */
-  unsigned int num_entries;             /* Nb of entries */
-  unsigned int num_lids;                /* Nb of List IDs */
+  vlc_bool_t   in_still;                /*  true if in still */
+  vlc_bool_t   b_svd;                   /*  true if we have SVD info */
+  track_t      i_tracks;                /* # of tracks */
+  unsigned int i_segments;              /* # of segments */
+  unsigned int i_entries;               /* # of entries */
+  unsigned int i_lids;                  /* # of List IDs */
+  unsigned int i_titles;                /* # of navigatable titles. */
   vcdinfo_itemid_t play_item;           /* play-item, VCDPLAYER_BAD_ENTRY 
                                            if none */
-  int          cur_lid;                 /* LID that play item is in. Implies 
+  int          i_lid;                   /* LID that play item is in. Implies 
                                            PBC is on. VCDPLAYER_BAD_ENTRY if 
                                            not none or not in PBC */
-#if (defined LIBVCD_VERSION_NUM) && (LIBVCD_VERSION_NUM >= 21)
   PsdListDescriptor_t pxd;              /* If PBC is on, the relevant 
                                             PSD/PLD */
-#else
-  PsdListDescriptor pxd;                /* If PBC is on, the relevant
-                                           PSD/PLD */
-#endif
   int          pdi;                     /* current pld index of pxd. -1 if 
                                            no index*/
   vcdinfo_itemid_t loop_item;           /* Where do we loop back to? 
@@ -91,25 +88,37 @@ typedef struct thread_vcd_data_s
   int          loop_count;              /* # of times play-item has been 
                                            played. Meaningful only in a 
                                            selection list.              */
-  track_t      cur_track;               /* Current track number */
-  lsn_t        cur_lsn;                 /* Current logical sector number */
+  track_t      i_track;                 /* Current track number */
+  lsn_t        i_lsn;                   /* Current logical sector number */
   lsn_t        end_lsn;                 /* LSN of end of current 
                                            entry/segment/track. */
   lsn_t        origin_lsn;              /* LSN of start of seek/slider */
-  lsn_t *      p_sectors;               /* Track sectors */
+  lsn_t *      p_sectors;               /* Track sectors. This is 0 origin
+                                           so the first VCD track will be
+                                           at 0 and this is the ISO9660 
+                                           filesystem. The first Mode2 form2
+                                           MPEG track is probably track 2 or
+                                           p_sectors[1].
+                                         */
   lsn_t *      p_entries;               /* Entry points */
   lsn_t *      p_segments;              /* Segments */
   vlc_bool_t   b_valid_ep;              /* Valid entry points flag */
   vlc_bool_t   b_end_of_track;          /* If the end of track was reached */
   int          i_debug;                 /* Debugging mask */
 
+  /* Information about CD */
+  vlc_meta_t    *p_meta;
+
+  input_title_t *p_title[CDIO_CD_MAX_TRACKS];
+
   /* Probably gets moved into another structure...*/
-  intf_thread_t *         p_intf;
-  int                     i_audio_nb;
-  int                     i_still_time;
-  vlc_bool_t              b_end_of_cell;
+  intf_thread_t *p_intf;
+  int            i_audio_nb;
+  int            i_still_time;
+  vlc_bool_t     b_end_of_cell;
+  input_thread_t *p_input;
   
-} thread_vcd_data_t;
+} access_vcd_data_t;
 
 /*!
   Get the next play-item in the list given in the LIDs. Note play-item
@@ -117,33 +126,33 @@ typedef struct thread_vcd_data_s
   confused with a user's list of favorite things to play or the 
   "next" field of a LID which moves us to a different LID.
  */
-vlc_bool_t vcdplayer_inc_play_item( input_thread_t *p_input );
+vlc_bool_t vcdplayer_inc_play_item( access_t *p_access );
 
 /*!
   Return true if playback control (PBC) is on
 */
-vlc_bool_t vcdplayer_pbc_is_on(const thread_vcd_data_t *p_this);
+vlc_bool_t vcdplayer_pbc_is_on(const access_vcd_data_t *p_this);
 
 /*!
   Play item assocated with the "default" selection.
 
   Return false if there was some problem.
 */
-vlc_bool_t vcdplayer_play_default( input_thread_t * p_input );
+vlc_bool_t vcdplayer_play_default( access_t * p_access );
 
 /*!
   Play item assocated with the "next" selection.
 
   Return false if there was some problem.
 */
-vlc_bool_t vcdplayer_play_next( input_thread_t * p_input );
+vlc_bool_t vcdplayer_play_next( access_t * p_access );
 
 /*!
   Play item assocated with the "prev" selection.
 
   Return false if there was some problem.
 */
-vlc_bool_t vcdplayer_play_prev( input_thread_t * p_input );
+vlc_bool_t vcdplayer_play_prev( access_t * p_access );
 
 /*!
   Play item assocated with the "return" selection.
@@ -151,10 +160,10 @@ vlc_bool_t vcdplayer_play_prev( input_thread_t * p_input );
   Return false if there was some problem.
 */
 vlc_bool_t
-vcdplayer_play_return( input_thread_t * p_input );
+vcdplayer_play_return( access_t * p_access );
 
-vcdplayer_read_status_t vcdplayer_pbc_nav ( input_thread_t * p_input );
-vcdplayer_read_status_t vcdplayer_non_pbc_nav ( input_thread_t * p_input );
+vcdplayer_read_status_t vcdplayer_pbc_nav     ( access_t * p_access );
+vcdplayer_read_status_t vcdplayer_non_pbc_nav ( access_t * p_access );
 
 #endif /* _VCDPLAYER_H_ */
 /*