]> git.sesse.net Git - vlc/commitdiff
Fill out more VCD player-independent parts. Modal (track, segment,
authorRocky Bernstein <rocky@videolan.org>
Thu, 23 Dec 2004 04:01:45 +0000 (04:01 +0000)
committerRocky Bernstein <rocky@videolan.org>
Thu, 23 Dec 2004 04:01:45 +0000 (04:01 +0000)
entry) playing is better.

Still frame and menu selection is still quite a mess.

modules/access/vcdx/access.c
modules/access/vcdx/vcdplayer.c
modules/access/vcdx/vcdplayer.h

index c2770a057791f0283b1b46a3c6d4adc09f671a5a..b7b3d72404a2fbccaf889e9ae3b4d2ae2637ade4 100644 (file)
@@ -47,6 +47,9 @@
 
 #define FREE_AND_NULL(ptr) if (NULL != ptr) free(ptr); ptr = NULL;
 
+extern void VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track, 
+                         const vcdinfo_itemid_t *p_itemid );
+
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
@@ -58,16 +61,10 @@ static int      VCDControl      ( access_t *p_access, int i_query,
                                  va_list args );
 
 /* Now those which are strictly internal */
-static void VCDSetOrigin    ( access_t *p_access, lsn_t i_lsn, 
-                              track_t track,  
-                             const vcdinfo_itemid_t * p_itemid );
 static vlc_bool_t  VCDEntryPoints  ( access_t * );
 static vlc_bool_t  VCDLIDs         ( access_t * );
 static vlc_bool_t  VCDSegments     ( access_t * );
 static int  VCDTitles       ( access_t * );
-static int  VCDReadSector   ( vlc_object_t *p_this,
-                              const vcdinfo_obj_t *p_vcd, lsn_t i_lsn,
-                              byte_t * p_buffer );
 static char *VCDParse       ( access_t *,
                               /*out*/ vcdinfo_itemid_t * p_itemid ,
                               /*out*/ vlc_bool_t *play_single_item );
@@ -150,14 +147,11 @@ VCDReadBlock( access_t * p_access )
     block_t     *p_block;
     const int   i_blocks = p_vcd->i_blocks_per_read;
     int         i_read;
-    byte_t      p_last_sector[ M2F2_SECTOR_SIZE ];
 
     i_read = 0;
 
-#if 0
-    dbg_print( (INPUT_DBG_CALL), "lsn: %lu", 
+    dbg_print( (INPUT_DBG_LSN), "lsn: %lu", 
               (long unsigned int) p_vcd->i_lsn );
-#endif
 
     /* Allocate a block for the reading */
     if( !( p_block = block_New( p_access, i_blocks * M2F2_SECTOR_SIZE ) ) )
@@ -170,95 +164,60 @@ VCDReadBlock( access_t * p_access )
 
     for ( i_read = 0 ; i_read < i_blocks ; i_read++ )
     {
+      const lsn_t old_lsn = p_vcd->i_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, end: %u", 
-                  (long unsigned int) p_vcd->i_lsn,
-                  p_vcd->end_lsn);
-
-        read_status = vcdplayer_pbc_is_on( p_vcd )
-          ? 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 NULL;
-
-        case READ_STILL_FRAME:
-          {
-            /* Reached the end of a still frame. */
-            byte_t * p_buf = (byte_t *) p_block->p_buffer;
-
-            p_buf += (i_read*M2F2_SECTOR_SIZE);
-            memset(p_buf, 0, M2F2_SECTOR_SIZE);
-            p_buf += 2;
-            *p_buf = 0x01;
-            dbg_print(INPUT_DBG_STILL, "Handled still event");
-
-            p_vcd->in_still = VLC_TRUE;
-            var_SetInteger( p_access, "state", PAUSE_S );
-
-            return p_block;
-          }
-        default:
-        case READ_BLOCK:
-          break;
-        }
-      }
-
-      if ( VCDReadSector( VLC_OBJECT(p_access), p_vcd->vcd,
-                          p_vcd->i_lsn,
-                          (byte_t *) p_block->p_buffer 
-                         + (i_read*M2F2_SECTOR_SIZE) ) < 0 )
-      {
-          LOG_ERR ("could not read sector %lu", 
-                  (long unsigned int) p_vcd->i_lsn );
-        /* Try to skip one sector (in case of bad sectors) */
-         p_vcd->i_lsn ++;
-         p_access->info.i_pos += M2F2_SECTOR_SIZE;
-          return NULL;
+      switch ( vcdplayer_read(p_access, (byte_t *) p_block->p_buffer 
+                             + (i_read*M2F2_SECTOR_SIZE)) ) {
+      case READ_END:
+       /* End reached. Return NULL to indicated this. */
+       block_Release( p_block );
+       return NULL;
+      case READ_ERROR:
+       /* Some sort of error. Should we increment lsn? to skip block?
+        */
+       block_Release( p_block );
+       return NULL;
+      case READ_STILL_FRAME: 
+       {
+         dbg_print(INPUT_DBG_STILL, "Handled still event\n");
+         /* Reached the end of a still frame. */
+         byte_t * p_buf = (byte_t *) p_block->p_buffer;
+         
+         p_buf += (i_read*M2F2_SECTOR_SIZE);
+         memset(p_buf, 0, M2F2_SECTOR_SIZE);
+         p_buf += 2;
+         *p_buf = 0x01;
+         dbg_print(INPUT_DBG_STILL, "Handled still event");
+         
+         p_vcd->in_still = VLC_TRUE;
+         var_SetInteger( p_access, "state", PAUSE_S );
+         
+         return p_block;
+       }
+       
+      default:
+      case READ_BLOCK:
+       /* Read buffer */
+       ;
       }
 
-      p_vcd->i_lsn ++;
-      p_access->info.i_pos += M2F2_SECTOR_SIZE;
+      p_access->info.i_pos += (p_vcd->i_lsn - old_lsn) *  M2F2_SECTOR_SIZE;
 
       /* Update seekpoint */
       if ( VCDINFO_ITEM_TYPE_ENTRY == p_vcd->play_item.type )
       {
        unsigned int i_entry = p_vcd->play_item.num+1;
-
-       if (p_vcd->i_lsn >= vcdinfo_get_entry_lba(p_vcd->vcd, i_entry))
+       lsn_t        i_lsn   = vcdinfo_get_entry_lba(p_vcd->vcd, i_entry);
+       if (p_vcd->i_lsn >= i_lsn )
         {
            const track_t i_track = p_vcd->i_track;
            p_vcd->play_item.num = i_entry;
            dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "entry change" );
-           VCDSetOrigin( p_access, 
-                         vcdinfo_get_entry_lba(p_vcd->vcd, i_entry),
-                         i_track, &(p_vcd->play_item) );
+           VCDSetOrigin( p_access,  i_lsn, i_track, &(p_vcd->play_item) );
         }
       }
     }
-
-    if ( i_read != i_blocks ) /* this should not happen */
-    {
-        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->i_lsn );
-        }
-       
-       p_vcd->i_lsn ++;
-       return NULL;
-    }
-
+    
     return p_block;
 }
 
@@ -294,10 +253,14 @@ VCDSeek( access_t * p_access, int64_t i_pos )
                  break;
                }
            }
-         p_vcd->play_item.num  = i_entry;
-         p_vcd->play_item.type = VCDINFO_ITEM_TYPE_ENTRY;
-         vcdplayer_set_origin(p_access);
-         VCDUpdateTitle(p_access);
+
+         { 
+             vcdinfo_itemid_t itemid;
+             itemid.num  = i_entry;
+             itemid.type = VCDINFO_ITEM_TYPE_ENTRY;
+             VCDSetOrigin(p_access, p_vcd->i_lsn, p_vcd->i_track, 
+                          &itemid);
+         }
        }
       
       dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
@@ -327,155 +290,6 @@ VCDSeek( access_t * p_access, int64_t i_pos )
     
 }
 
-/*****************************************************************************
-  VCDPlay: set up internal structures so seeking/reading places an item.
-  itemid: the thing to play.
-  user_entry: true if itemid is a user selection (rather than internally-
-  generated selection such as via PBC) in which case we may have to adjust
-  for differences in numbering.
- *****************************************************************************/
-int
-VCDPlay( access_t *p_access, vcdinfo_itemid_t itemid )
-{
-    if (!p_access || !p_access->p_sys) return VLC_EGENERIC;
-    
-    {
-      
-      vcdplayer_t *p_vcd= (vcdplayer_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);
-
-      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 MPEG tracks go from 1...i_tracks. */
-       
-         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, 
-                       vcdinfo_get_entry_lba(p_vcd->vcd, i_entry),
-                       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], 
-                         0, &itemid );
-         }
-
-       }
-       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, 
-                         vcdinfo_get_entry_lba(p_vcd->vcd, i_entry),
-                         i_track, &itemid );
-         }
-         break;
-       }
-       
-      default:
-       LOG_ERR ("unknown entry type" );
-       return VLC_EGENERIC;
-      }
-
-      p_vcd->play_item = itemid;
-      
-    }
-    
-      
-    return VLC_SUCCESS;
-}
-
 /*****************************************************************************
   VCDEntryPoints: Reads the information about the entry points on the disc
   and initializes area information with that.
@@ -526,7 +340,7 @@ VCDEntryPoints( access_t * p_access )
            * M2F2_SECTOR_SIZE;
          
          dbg_print( INPUT_DBG_MRL, 
-                    "%s, lsn %d,  byte_offset %ld\n",
+                    "%s, lsn %d,  byte_offset %ld",
                     s->psz_name, p_vcd->p_entries[i], 
                     (unsigned long int) s->i_byte_offset);
          TAB_APPEND( p_vcd->p_title[i_track-1]->i_seekpoint,
@@ -553,7 +367,7 @@ VCDSegments( access_t * p_access )
     p_vcd->i_segments = vcdinfo_get_num_segments(p_vcd->vcd);
 
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),
-               "num LIDs=%d", p_vcd->i_segments);
+               "Segments: %d", p_vcd->i_segments);
 
     if ( 0 == p_vcd->i_segments ) return VLC_FALSE;
 
@@ -652,7 +466,7 @@ VCDLIDs( access_t * p_access )
     p_vcd->i_lid  = VCDINFO_INVALID_ENTRY;
 
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),
-               "num LIDs=%d", p_vcd->i_lids);
+               "LIDs: %d", p_vcd->i_lids);
 
     if ( 0 == p_vcd->i_lids ) return VLC_FALSE;
     
@@ -826,51 +640,57 @@ VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid,
 /*
    Set's start origin subsequent seeks/reads
 */
-static void
+void
 VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track, 
              const vcdinfo_itemid_t *p_itemid )
 {
   vcdplayer_t *p_vcd= (vcdplayer_t *)p_access->p_sys;
-  
-  unsigned int i_title = i_track - 1; /* For now */
 
   dbg_print( (INPUT_DBG_CALL|INPUT_DBG_LSN),
              "i_lsn: %lu, track: %d", (long unsigned int) i_lsn, 
             i_track );
 
-  p_vcd->i_lsn      = i_lsn;
-  p_vcd->i_track    = i_track;
-  p_vcd->track_lsn  = vcdinfo_get_track_lsn(p_vcd->vcd, i_track);
-
-  p_vcd->play_item.num  = p_itemid->num;
-  p_vcd->play_item.type = p_itemid->type;
-
-  vcdplayer_set_origin(p_access);
+  vcdplayer_set_origin(p_access, i_lsn, i_track, p_itemid);
 
   p_access->info.i_pos       = ( i_lsn - p_vcd->track_lsn ) 
                              * M2F2_SECTOR_SIZE;
   p_access->info.i_update   |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE
                             |  INPUT_UPDATE_SEEKPOINT;
 
-  if (p_itemid->type == VCDINFO_ITEM_TYPE_ENTRY) {
-    VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE,
-                 "chapter", _("Entry"), "Setting entry/segment");
-    p_access->info.i_title     = i_track-1;
-    p_access->info.i_size      = p_vcd->p_title[i_title]->i_size;
-    p_access->info.i_seekpoint = p_itemid->num;
-  } else if (p_itemid->type == VCDINFO_ITEM_TYPE_SEGMENT) {
-    VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE,
+  
+  switch (p_vcd->play_item.type) {
+  case VCDINFO_ITEM_TYPE_ENTRY: 
+      VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE,
+                   "chapter", _("Entry"), "Setting entry/segment");
+      p_access->info.i_title     = i_track-1;
+      p_access->info.i_size      = p_vcd->p_title[i_track-1]->i_size;
+      p_access->info.i_seekpoint = p_itemid->num;
+      break;
+
+  case VCDINFO_ITEM_TYPE_SEGMENT:
+      VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE,
                  "chapter", _("Segment"),  "Setting entry/segment");
-    /* The last title entry is the for segments (when segments exist
-       and they must here. The segment seekpoints are stored after
-       the entry seekpoints and (zeroed) lid seekpoints. 
-    */
-    p_access->info.i_title     = p_vcd->i_titles - 1;
-    p_access->info.i_size      = 150 * M2F2_SECTOR_SIZE;
-    p_access->info.i_seekpoint = p_vcd->i_entries 
-                               + p_vcd->i_lids + p_itemid->num;
-
+      /* The last title entry is the for segments (when segments exist
+        and they must here. The segment seekpoints are stored after
+        the entry seekpoints and (zeroed) lid seekpoints. 
+      */
+      p_access->info.i_title     = p_vcd->i_titles - 1;
+      p_access->info.i_size      = 150 * M2F2_SECTOR_SIZE;
+      p_access->info.i_seekpoint = p_vcd->i_entries 
+       + p_vcd->i_lids + p_itemid->num;
+      break;
+      
+  case VCDINFO_ITEM_TYPE_TRACK: 
+      p_access->info.i_title     = i_track-1;
+      p_access->info.i_size      = p_vcd->p_title[i_track-1]->i_size;
+      p_access->info.i_seekpoint = vcdinfo_track_get_entry(p_vcd->vcd, 
+                                                          i_track);
+      break;
+  default:
+      msg_Warn( p_access, "can't set origin for play type %d", 
+               p_vcd->play_item.type );
   }
+  
 
   VCDUpdateTitle( p_access );
   
@@ -889,7 +709,7 @@ vcd_Open( vlc_object_t *p_this, const char *psz_dev )
     char  *actual_dev;
     unsigned int i;
 
-    dbg_print(INPUT_DBG_CALL, "called with %s\n", psz_dev);
+    dbg_print(INPUT_DBG_CALL, "called with %s", psz_dev);
 
     if( !psz_dev ) return NULL;
 
@@ -945,34 +765,6 @@ vcd_Open( vlc_object_t *p_this, const char *psz_dev )
     return p_vcdobj;
 }
 
-/****************************************************************************
- * VCDReadSector: Read a sector (2324 bytes)
- ****************************************************************************/
-static int
-VCDReadSector( vlc_object_t *p_this, const vcdinfo_obj_t *p_vcd,
-               lsn_t i_lsn, byte_t * p_buffer )
-{
-  typedef struct {
-    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, i_lsn, VLC_TRUE )
-      != 0)
-  {
-      msg_Warn( p_this, "Could not read LSN %lu", 
-               (long unsigned int) i_lsn );
-      return -1;
-  }
-
-  memcpy (p_buffer, vcd_sector.data, M2F2_SECTOR_SIZE);
-
-  return( 0 );
-}
-
 /****************************************************************************
  Update the "varname" variable to i_num without triggering a callback.
 ****************************************************************************/
@@ -1016,7 +808,6 @@ E_(VCDOpen) ( vlc_object_t *p_this )
     vcdplayer_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_access->pf_read          = NULL;
@@ -1105,15 +896,16 @@ E_(VCDOpen) ( vlc_object_t *p_this )
         msg_Warn( p_access, "could not read entry LIDs" );
     }
 
+    /* Do we set PBC (via LID) on? */
+    p_vcd->i_lid = 
+      ( VCDINFO_ITEM_TYPE_LID == itemid.type && p_vcd->i_lids > itemid.num )
+      ? itemid.num
+      :  VCDINFO_INVALID_ENTRY;
+
     /* Initialize segment information and add that a "Track". */
     VCDSegments( p_access );
 
-    b_play_ok = (VLC_SUCCESS == VCDPlay( p_access, itemid ));
-
-    if ( ! b_play_ok ) {
-      vcdinfo_close( p_vcd->vcd );
-      goto err_exit;
-    }
+    vcdplayer_play( p_access, itemid );
 
     p_access->psz_demux = strdup( "ps" );
 
index 8e25b6961819d457e2becd13c46e00f037b1f47b..fdb53fcb88d416a9b5a4ca5c2faeaeb3abd86148 100644 (file)
@@ -47,6 +47,9 @@
 #define sleep(A) Sleep((A)*1000)
 #endif
 
+extern void VCDSetOrigin ( access_t *p_access, lsn_t i_lsn, track_t i_track,
+                          const vcdinfo_itemid_t * p_itemid );
+
 /*!
   Return VLC_TRUE if playback control (PBC) is on
 */
@@ -80,7 +83,7 @@ vcdplayer_get_item_size(access_t * p_access, vcdinfo_itemid_t itemid)
   case VCDINFO_ITEM_TYPE_NOTFOUND:
   case VCDINFO_ITEM_TYPE_SPAREID2:
   default:
-    LOG_ERR("%s %d\n", _("bad item type"), itemid.type);
+    LOG_ERR("%s %d", _("bad item type"), itemid.type);
     return 0;
   }
 }
@@ -97,7 +100,7 @@ vcdplayer_update_entry( access_t * p_access, uint16_t ofs,
     vcdinfo_offset_t *off = vcdinfo_get_offset_t(p_vcd->vcd, ofs);
     if (off != NULL) {
       *entry = off->lid;
-      dbg_print(INPUT_DBG_PBC, "%s: LID %d\n", label, off->lid);
+      dbg_print(INPUT_DBG_PBC, "%s: LID %d", label, off->lid);
     } else
       *entry = VCDINFO_INVALID_ENTRY;
   }
@@ -119,10 +122,10 @@ vcdplayer_non_pbc_nav ( access_t *p_access )
   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->i_track+1, 
-               vcdinfo_get_track_lsn(p_vcd->vcd, p_vcd->i_track+1) );
-    return READ_END;
+    if ( ! vcdplayer_play_next( p_access ) )
+    {
+       return READ_END;
+    }
     break;
   }
   case VCDINFO_ITEM_TYPE_SPAREID2:  
@@ -154,7 +157,6 @@ vcdplayer_non_pbc_nav ( access_t *p_access )
   return READ_BLOCK;
 }
 
-#if 1
 /*!
   Set reading to play an entire track.
 */
@@ -171,14 +173,11 @@ _vcdplayer_set_track(access_t * p_access, track_t i_track)
     itemid.num       = i_track;
     itemid.type      = VCDINFO_ITEM_TYPE_TRACK;
     p_vcd->in_still  = 0;
-    p_vcd->i_lsn     = vcdinfo_get_track_lsn(p_obj, i_track);
-    p_vcd->play_item = itemid;
-    p_vcd->i_track   = i_track;
-    p_vcd->track_lsn = p_vcd->i_lsn;
 
-    vcdplayer_set_origin(p_access);
+    VCDSetOrigin(p_access, vcdinfo_get_track_lsn(p_obj, i_track), 
+                i_track, &itemid);
 
-    dbg_print(INPUT_DBG_LSN, "LSN: %u\n", p_vcd->i_lsn);
+    dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcd->i_lsn);
   }
 }
 
@@ -193,7 +192,7 @@ _vcdplayer_set_entry(access_t * p_access, unsigned int num)
   unsigned int   num_entries = vcdinfo_get_num_entries(p_obj);
 
   if (num >= num_entries) {
-    LOG_ERR("%s %d\n", _("bad entry number"), num);
+    LOG_ERR("%s %d", _("bad entry number"), num);
     return;
   } else {
     vcdinfo_itemid_t itemid;
@@ -201,16 +200,11 @@ _vcdplayer_set_entry(access_t * p_access, unsigned int num)
     itemid.num           = num;
     itemid.type          = VCDINFO_ITEM_TYPE_ENTRY;
     p_vcd->in_still      = 0;
-    p_vcd->i_lsn         = vcdinfo_get_entry_lsn(p_obj, num);
-    p_vcd->play_item     = itemid;
-    p_vcd->i_track       = vcdinfo_get_track(p_obj, num);
-    p_vcd->track_lsn     = vcdinfo_get_track_lsn(p_obj, p_vcd->i_track);
-    p_vcd->track_end_lsn = p_vcd->track_lsn + 
-      p_vcd->track[p_vcd->i_track-1].size;
 
-    vcdplayer_set_origin(p_access);
+    VCDSetOrigin(p_access, vcdinfo_get_entry_lba(p_obj, num),
+               vcdinfo_get_track(p_obj, num), &itemid);
 
-    dbg_print(INPUT_DBG_LSN, "LSN: %u, track_end LSN: %u\n", 
+    dbg_print(INPUT_DBG_LSN, "LSN: %u, track_end LSN: %u", 
               p_vcd->i_lsn, p_vcd->track_end_lsn);
   }
 }
@@ -226,27 +220,23 @@ _vcdplayer_set_segment(access_t * p_access, unsigned int num)
   segnum_t num_segs  = vcdinfo_get_num_segments(p_obj);
 
   if (num >= num_segs) {
-    LOG_ERR("%s %d\n", _("bad segment number"), num);
+    LOG_ERR("%s %d", _("bad segment number"), num);
     return;
   } else {
     vcdinfo_itemid_t itemid;
 
-    p_vcd->i_lsn   = vcdinfo_get_seg_lsn(p_obj, num);
-    p_vcd->i_track = 0;
-
     if (VCDINFO_NULL_LSN==p_vcd->i_lsn) {
-      LOG_ERR("%s %d\n", 
+      LOG_ERR("%s %d", 
               _("Error in getting current segment number"), num);
       return;
     }
     
     itemid.num = num;
     itemid.type = VCDINFO_ITEM_TYPE_SEGMENT;
-    p_vcd->play_item = itemid;
 
-    vcdplayer_set_origin(p_access);
+    VCDSetOrigin(p_access, vcdinfo_get_seg_lsn(p_obj, num), 0, &itemid);
     
-    dbg_print(INPUT_DBG_LSN, "LSN: %u\n", p_vcd->i_lsn);
+    dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcd->i_lsn);
   }
 }
 
@@ -258,7 +248,7 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid)
   vcdplayer_t   *p_vcd = (vcdplayer_t *)p_access->p_sys;
   vcdinfo_obj_t *p_obj = p_vcd->vcd;
 
-  dbg_print(INPUT_DBG_CALL, "called itemid.num: %d, itemid.type: %d\n", 
+  dbg_print(INPUT_DBG_CALL, "called itemid.num: %d, itemid.type: %d",
             itemid.num, itemid.type);
 
   p_vcd->in_still = 0;
@@ -270,7 +260,7 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid)
         = vcdinfo_get_video_type(p_obj, itemid.num);
       segnum_t num_segs = vcdinfo_get_num_segments(p_obj);
 
-      dbg_print(INPUT_DBG_PBC, "%s (%d), itemid.num: %d\n", 
+      dbg_print(INPUT_DBG_PBC, "%s (%d), itemid.num: %d", 
                 vcdinfo_video_type2str(p_obj, itemid.num), 
                 (int) segtype, itemid.num);
 
@@ -293,7 +283,7 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid)
     }
     
   case VCDINFO_ITEM_TYPE_TRACK:
-    dbg_print(INPUT_DBG_PBC, "track %d\n", itemid.num);
+    dbg_print(INPUT_DBG_PBC, "track %d", itemid.num);
     if (itemid.num < 1 || itemid.num > p_vcd->i_tracks) return;
     _vcdplayer_set_track(p_access, itemid.num);
     break;
@@ -301,23 +291,23 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid)
   case VCDINFO_ITEM_TYPE_ENTRY: 
     {
       unsigned int num_entries = vcdinfo_get_num_entries(p_obj);
-      dbg_print(INPUT_DBG_PBC, "entry %d\n", itemid.num);
+      dbg_print(INPUT_DBG_PBC, "entry %d", itemid.num);
       if (itemid.num >= num_entries) return;
       _vcdplayer_set_entry(p_access, itemid.num);
       break;
     }
     
   case VCDINFO_ITEM_TYPE_LID:
-    LOG_ERR("%s\n", _("Should have converted p_vcd above"));
+    LOG_ERR("%s", _("Should have converted p_vcd above"));
     break;
 
   case VCDINFO_ITEM_TYPE_NOTFOUND:
-    dbg_print(INPUT_DBG_PBC, "play nothing\n");
+    dbg_print(INPUT_DBG_PBC, "play nothing");
     p_vcd->i_lsn = p_vcd->end_lsn;
     return;
 
   default:
-    LOG_ERR("item type %d not implemented.\n", itemid.type);
+    LOG_ERR("item type %d not implemented.", itemid.type);
     return;
   }
   
@@ -327,11 +317,8 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid)
      that need to be flushed when playing a new selection. */
   /*  if (p_vcd->flush_buffers)
       p_vcd->flush_buffers(); */
-
 }
 
-#endif /* FINISHED */
-
 /* 
    Set's start origin and size for subsequent seeks.  
    input: p_vcd->i_lsn, p_vcd->play_item
@@ -340,15 +327,24 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid)
 
 /* FIXME: add parameters lsn, i_track, p_itemid and set accordingly. */
 void 
-vcdplayer_set_origin(access_t *p_access)
+vcdplayer_set_origin(access_t *p_access, lsn_t i_lsn, track_t i_track,
+                    const vcdinfo_itemid_t *p_itemid)
 {
   vcdplayer_t *p_vcd = (vcdplayer_t *)p_access->p_sys;
-  size_t       i_size= vcdplayer_get_item_size(p_access, p_vcd->play_item);
-
-  p_vcd->end_lsn    = p_vcd->i_lsn + i_size;
-  p_vcd->origin_lsn = p_vcd->i_lsn;
-
-  dbg_print((INPUT_DBG_CALL|INPUT_DBG_LSN), "end LSN: %u\n", p_vcd->end_lsn);
+  const size_t i_size= vcdplayer_get_item_size(p_access, *p_itemid);
+
+  p_vcd->play_item.num   = p_itemid->num;
+  p_vcd->play_item.type  = p_itemid->type;
+  p_vcd->i_lsn           = i_lsn;
+  p_vcd->end_lsn         = p_vcd->i_lsn + i_size;
+  p_vcd->origin_lsn      = p_vcd->i_lsn;
+  p_vcd->i_track         = i_track;
+  p_vcd->track_lsn       = vcdinfo_get_track_lba(p_vcd->vcd, i_track);
+
+  dbg_print((INPUT_DBG_CALL|INPUT_DBG_LSN), 
+           "lsn %u, end LSN: %u item.num %d, item.type %d", 
+           p_vcd->i_lsn, p_vcd->end_lsn,
+           p_vcd->play_item.num, p_vcd->play_item.type);
 }
 
 /*
@@ -363,7 +359,7 @@ _vcdplayer_inc_play_item(access_t *p_access)
   vcdplayer_t *p_vcd = (vcdplayer_t *)p_access->p_sys;
   int noi;
 
-  dbg_print(INPUT_DBG_CALL, "called pli: %d\n", p_vcd->pdi);
+  dbg_print(INPUT_DBG_CALL, "called pli: %d", p_vcd->pdi);
 
   if ( NULL == p_vcd || NULL == p_vcd->pxd.pld  ) return false;
 
@@ -385,13 +381,65 @@ _vcdplayer_inc_play_item(access_t *p_access)
     if (VCDINFO_INVALID_ITEMID == trans_itemid_num) return false;
     
     vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
-    dbg_print(INPUT_DBG_PBC, "  play-item[%d]: %s\n",
+    dbg_print(INPUT_DBG_PBC, "  play-item[%d]: %s",
               p_vcd->pdi, vcdinfo_pin2str (trans_itemid_num));
     vcdplayer_play_single_item(p_access, trans_itemid);
     return true;
   }
 }
 
+void
+vcdplayer_play(access_t *p_access, vcdinfo_itemid_t itemid)
+{
+  vcdplayer_t *p_vcd = (vcdplayer_t *)p_access->p_sys;
+
+  dbg_print(INPUT_DBG_CALL, "called itemid.num: %d itemid.type: %d", 
+            itemid.num, itemid.type);
+
+  if  (!vcdplayer_pbc_is_on(p_vcd)) {
+    vcdplayer_play_single_item(p_access, itemid);
+  } else {
+    /* PBC on - Itemid.num is LID. */
+
+    vcdinfo_obj_t *obj = p_vcd->vcd;
+
+    if (obj == NULL) return;
+
+    p_vcd->i_lid = itemid.num;
+    vcdinfo_lid_get_pxd(obj, &(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;
+      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;
+      vcdplayer_play_single_item(p_access, trans_itemid);
+      break;
+    }
+      
+    case PSD_TYPE_PLAY_LIST: {
+      if (p_vcd->pxd.pld == NULL) return;
+      p_vcd->pdi = -1;
+      _vcdplayer_inc_play_item(p_access);
+      break;
+    }
+      
+    case PSD_TYPE_END_LIST:
+    case PSD_TYPE_COMMAND_LIST:
+      
+    default:
+      ;
+    }
+  }
+}
+
 /* Handles PBC navigation when reaching the end of a play item. */
 vcdplayer_read_status_t
 vcdplayer_pbc_nav ( access_t * p_access )
@@ -410,7 +458,7 @@ vcdplayer_pbc_nav ( access_t * p_access )
     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_access, p_vcd->play_item );
+    vcdplayer_play( p_access, p_vcd->play_item );
     /* p_vcd->update_title(); */
     return READ_BLOCK;
   }
@@ -439,7 +487,7 @@ vcdplayer_pbc_nav ( access_t * p_access )
                             vcdinf_pld_get_next_offset(p_vcd->pxd.pld),
                             &itemid.num, "next" );
     itemid.type = VCDINFO_ITEM_TYPE_LID;
-    VCDPlay( p_access, itemid );
+    vcdplayer_play( p_access, itemid );
     break;
   }
   case PSD_TYPE_SELECTION_LIST:     /* Selection List (+Ext. for SVCD) */
@@ -479,7 +527,7 @@ vcdplayer_pbc_nav ( access_t * p_access )
         itemid.num  = offset_timeout_LID->lid;
         itemid.type = VCDINFO_ITEM_TYPE_LID;
         dbg_print(INPUT_DBG_PBC, "timeout to: %d", itemid.num);
-        VCDPlay( p_access, itemid );
+        vcdplayer_play( p_access, itemid );
         return READ_BLOCK;
       } else {
         int num_selections = vcdinf_get_num_selections(p_vcd->pxd.psd);
@@ -495,7 +543,7 @@ vcdplayer_pbc_nav ( access_t * p_access )
           itemid.type = VCDINFO_ITEM_TYPE_LID;
           dbg_print(INPUT_DBG_PBC, "random selection %d, lid: %d", 
                     rand_selection - bsn, rand_lid);
-          VCDPlay( p_access, itemid );
+          vcdplayer_play( p_access, itemid );
           return READ_BLOCK;
         } else if (p_vcd->in_still) {
           /* Hack: Just go back and do still again */
@@ -523,6 +571,83 @@ vcdplayer_pbc_nav ( access_t * p_access )
   return READ_ERROR;
 }
 
+/*!
+  Read block into p_buf and return the status back.
+
+  This routine is a bit complicated because on reaching the end of 
+  a track or entry we may automatically advance to the item, or 
+  interpret the next item in the playback-control list.
+*/
+vcdplayer_read_status_t
+vcdplayer_read (access_t * p_access, uint8_t *p_buf)
+{
+
+  /* p_access->handle_events (); */
+
+  vcdplayer_t *p_vcd= (vcdplayer_t *)p_access->p_sys;
+  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: %u, end: %u\n", p_vcd->i_lsn, p_vcd->end_lsn);
+
+  handle_item_continuation:
+    read_status = vcdplayer_pbc_is_on( p_vcd ) 
+      ? vcdplayer_pbc_nav( p_access ) 
+      : vcdplayer_non_pbc_nav( p_access );
+
+    if (READ_BLOCK != read_status) return read_status;
+  }
+
+  /* Read the next block. 
+     
+    Important note: we probably speed things up by removing "data"
+    and the memcpy to it by extending vcd_image_source_read_mode2
+    to allow a mode to do what's below in addition to its 
+    "raw" and "block" mode. It also would probably improve the modularity
+    a little bit as well.
+  */
+
+  {
+    CdIo *p_img = vcdinfo_get_cd_image(p_vcd->vcd);
+    typedef struct {
+      uint8_t subheader [CDIO_CD_SUBHEADER_SIZE];
+      uint8_t data     [M2F2_SECTOR_SIZE];
+      uint8_t spare     [4];
+    } vcdsector_t;
+    vcdsector_t vcd_sector;
+
+    do {
+      if (cdio_read_mode2_sector(p_img, &vcd_sector, p_vcd->i_lsn, true)!=0) {
+        dbg_print(INPUT_DBG_LSN, "read error\n");
+        return READ_ERROR;
+      }
+      p_vcd->i_lsn++;
+
+      if ( p_vcd->i_lsn >= p_vcd->end_lsn ) {
+        /* We've run off of the end of p_vcd entry. Do we continue or stop? */
+        dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), 
+                   "end reached in reading, cur: %u, end: %u\n", 
+                   p_vcd->i_lsn, p_vcd->end_lsn);
+        break;
+      }
+      
+      /* Check header ID for a padding sector and simply discard
+         these.  It is alleged that VCD's put these in to keep the
+         bitrate constant.
+      */
+    } while((vcd_sector.subheader[2]&~0x01)==0x60);
+
+    if ( p_vcd->i_lsn >= p_vcd->end_lsn ) 
+      /* We've run off of the end of this entry. Do we continue or stop? */
+      goto handle_item_continuation;
+      
+    memcpy (p_buf, vcd_sector.data, M2F2_SECTOR_SIZE);
+    return READ_BLOCK;
+  }
+}
+
 /*!
   Get the next play-item in the list given in the LIDs. Note play-item
   here refers to list of play-items for a single LID It shouldn't be
@@ -560,7 +685,8 @@ vcdplayer_inc_play_item( access_t *p_access )
     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_access, trans_itemid );
+    vcdplayer_play( p_access, trans_itemid );
+    return VLC_SUCCESS;
   }
 }
 
@@ -597,9 +723,9 @@ vcdplayer_play_default( access_t * p_access )
     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);
+      dbg_print(INPUT_DBG_PBC, "DEFAULT to %d", itemid.num);
     } else {
-      dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d\n", p_vcd->i_lid);
+      dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d", p_vcd->i_lid);
     }
 
 #else 
@@ -634,7 +760,8 @@ vcdplayer_play_default( access_t * p_access )
   }
 
   /** ??? p_vcd->update_title(); ***/
-  return VLC_SUCCESS == VCDPlay( p_access, itemid );
+  vcdplayer_play( p_access, itemid );
+  return VLC_SUCCESS;
 
 }
 
@@ -732,7 +859,8 @@ vcdplayer_play_next( access_t * p_access )
   }
 
   /** ??? p_vcd->update_title(); ***/
-  return VLC_SUCCESS == VCDPlay( p_access, itemid );
+  vcdplayer_play( p_access, itemid );
+  return VLC_SUCCESS;
 
 }
 
@@ -797,7 +925,8 @@ vcdplayer_play_prev( access_t * p_access )
   }
 
   /** ??? p_vcd->update_title(); ***/
-  return VLC_SUCCESS == VCDPlay( p_access, itemid );
+  vcdplayer_play( p_access, itemid );
+  return VLC_SUCCESS;
 
 }
 
@@ -855,6 +984,7 @@ vcdplayer_play_return( access_t * p_access )
   }
 
   /** ??? p_vcd->update_title(); ***/
-  return VLC_SUCCESS == VCDPlay( p_access, itemid );
+  vcdplayer_play( p_access, itemid );
+  return VLC_SUCCESS;
 
 }
index fa423fe438bbfefe36f1f554fe2c42c9ef7f71c8..d592dcfd31e6901ffa556841ceb4bc6c8ba30e6a 100644 (file)
@@ -196,11 +196,17 @@ vcdplayer_play_return( access_t * p_access );
    input: p_vcd->i_lsn, p_vcd->play_item
    changed: p_vcd->origin_lsn, p_vcd->end_lsn
 */
-void vcdplayer_set_origin(access_t * p_access);
+void vcdplayer_set_origin(access_t *p_access, lsn_t i_lsn, track_t i_track,
+                          const vcdinfo_itemid_t *p_itemid);
+
+void vcdplayer_play(access_t *p_access, vcdinfo_itemid_t itemid);
 
 vcdplayer_read_status_t vcdplayer_pbc_nav     ( access_t * p_access );
 vcdplayer_read_status_t vcdplayer_non_pbc_nav ( access_t * p_access );
 
+vcdplayer_read_status_t vcdplayer_read (access_t * p_access_t, 
+                                        uint8_t *p_buf);
+
 #endif /* _VCDPLAYER_H_ */
 /* 
  * Local variables: