]> git.sesse.net Git - vlc/commitdiff
First attempt to reinstate a libcdio cdda.
authorRocky Bernstein <rocky@videolan.org>
Sat, 4 Sep 2004 14:51:04 +0000 (14:51 +0000)
committerRocky Bernstein <rocky@videolan.org>
Sat, 4 Sep 2004 14:51:04 +0000 (14:51 +0000)
vlc_meta.h: added CD-Text, ISO 9660, and CDDB fields. Separate email
will be sent about this.

Note: sound may be off by 2 seconds (150 sectors or pregap
amount). The sound for both this and the other cdda plugin don't work
for me. Before the last SVN update though that's what it sounded like.

configure.ac
include/vlc_meta.h
modules/access/cdda/access.c
modules/access/cdda/cdda.c
modules/access/cdda/cdda.h

index c46a936ccbee61e57201e9a2d0f8b03f4bacdf1e..afe68d41c7ae687d613f0851817fff6fd5867d38 100644 (file)
@@ -1486,46 +1486,46 @@ then
   VLC_ADD_PLUGINS([pvr])
 fi
 
-dnl dnl
-dnl dnl  VCDX and CDDAX modules
-dnl dnl
-dnl AC_ARG_ENABLE(libcdio,
-dnl   [  --enable-libcdio        CDDA support via libcdio (default enabled)])
-dnl 
-dnl AC_ARG_ENABLE(libcddb,
-dnl   [  --enable-libcddb        CDDB support for CDDAX (default enabled)])
-dnl 
+dnl
+dnl  VCDX and CDDAX modules
+dnl
+AC_ARG_ENABLE(libcdio,
+  [  --enable-libcdio        CDDA support via libcdio (default enabled)])
+AC_ARG_ENABLE(libcddb,
+  [  --enable-libcddb        CDDB support for CDDAX (default enabled)])
 dnl AC_ARG_ENABLE(vcdx,
 dnl   [  --enable-vcdx           VCD support with Navigation (default enabled)])
-dnl 
-dnl AC_ARG_ENABLE(cdda,           
-dnl   [  --enable-cdda           CDDA plugin support (default enabled)])
-dnl 
-dnl AC_ARG_ENABLE(cddax,
-dnl   [  --enable-cddax          CDDAX plugin support (default enabled)])
-dnl 
-dnl if test "${enable_cddax}" != "no"
-dnl then
-dnl   PKG_CHECK_MODULES(LIBCDIO, libcdio >= 0.65,
-dnl    [enable_cddax="no"
-dnl     AC_DEFINE(HAVE_CDDAX, [], [Define for the CD-DA plugin using libcdio])
-dnl     VLC_ADD_LDFLAGS([cddax],[$LIBCDIO_LIBS])
-dnl     VLC_ADD_CFLAGS([cddax],[$LIBCDIO_CFLAGS])
-dnl     VLC_ADD_PLUGINS([cddax])], 
-dnl    [AC_MSG_WARN(libcdio library not found)
-dnl    HAVE_CDDAX=no])
-dnl 
-dnl   if test "$enable_libcddb" != "no"; then
-dnl     PKG_CHECK_MODULES(LIBCDDB, libcddb >= 0.9.4, [
-dnl       HAVE_LIBCDDB=yes 
-dnl       AC_DEFINE(HAVE_LIBCDDB, [], [Define this if you have libcddb installed])
-dnl       VLC_ADD_LDFLAGS([cddax],[$LIBCDDB_LIBS])
-dnl       VLC_ADD_CFLAGS([cddax],[$LIBCDDB_CFLAGS])
-dnl       ],
-dnl       [AC_MSG_WARN(new enough libcddb not found. CDDB access disabled) 
-dnl       HAVE_LIBCDDB=no])
-dnl   fi
-dnl 
+AC_ARG_ENABLE(cdda,           
+  [  --enable-cdda           CDDA plugin support (default enabled)])
+AC_ARG_ENABLE(cddax,
+  [  --enable-cddax          CDDAX plugin support (default enabled)])
+if test "${enable_cddax}" != "no"
+then
+  PKG_CHECK_MODULES(LIBCDIO, libcdio >= 0.70,
+   [enable_cddax="no"
+    AC_DEFINE(HAVE_CDDAX, [], [Define for the CD-DA plugin using libcdio])
+    VLC_ADD_LDFLAGS([cddax],[$LIBCDIO_LIBS])
+    VLC_ADD_CFLAGS([cddax],[$LIBCDIO_CFLAGS])
+    VLC_ADD_PLUGINS([cddax])], 
+    [AC_MSG_WARN(libcdio library not found)
+    HAVE_CDDAX=no])
+
+  if test "$enable_libcddb" != "no"; then
+    PKG_CHECK_MODULES(LIBCDDB, libcddb >= 0.9.4, [
+      HAVE_LIBCDDB=yes 
+      AC_DEFINE(HAVE_LIBCDDB, [], [Define this if you have libcddb installed])
+      VLC_ADD_LDFLAGS([cddax],[$LIBCDDB_LIBS])
+      VLC_ADD_CFLAGS([cddax],[$LIBCDDB_CFLAGS])
+      ],
+      [AC_MSG_WARN(new enough libcddb not found. CDDB access disabled) 
+      HAVE_LIBCDDB=no])
+  fi
 dnl   if test "${enable_vcdx}" != "no"
 dnl   then
 dnl     PKG_CHECK_MODULES(VCDINFO, libvcdinfo >= 0.7.20,
@@ -1538,7 +1538,7 @@ dnl       VLC_ADD_PLUGINS([vcdx])],
 dnl      [AC_MSG_WARN(vcdinfo library not found)
 dnl      HAVE_VCDX=no])
 dnl   fi
-dnl fi
+fi
 
 dnl
 dnl  VCD module
index 71aeff3159b0ccd850ee44b1fdd65718a42db594..419a19dc4016f392572ec56f05505b885d261eac 100644 (file)
 #define VLC_META_SETTING            N_("Setting")
 #define VLC_META_URL                N_("URL")
 #define VLC_META_LANGUAGE           N_("Language")
+
+#define VLC_META_CDDB_ARTIST        N_("CDDB Artist")
+#define VLC_META_CDDB_CATEGORY      N_("CDDB Category")  
+#define VLC_META_CDDB_DISCID        N_("CDDB Disc ID")
+#define VLC_META_CDDB_EXT_DATA      N_("CDDB Extended Data")
+#define VLC_META_CDDB_GENRE         N_("CDDB Genre")
+#define VLC_META_CDDB_YEAR          N_("CDDB Year")      
+#define VLC_META_CDDB_TITLE         N_("CDDB Title")
+
+#define VLC_META_CDTEXT_ARRANGER    N_("CD-Text Arranger")
+#define VLC_META_CDTEXT_COMPOSER    N_("CD-Text Composer")
+#define VLC_META_CDTEXT_DISCID      N_("CD-Text Disc ID")
+#define VLC_META_CDTEXT_GENRE       N_("CD-Text Genre")
+#define VLC_META_CDTEXT_MESSAGE     N_("CD-Text Message")
+#define VLC_META_CDTEXT_SONGWRITER  N_("CD-Text Songwriter")
+#define VLC_META_CDTEXT_PERFORMER   N_("CD-Text Performer")
+#define VLC_META_CDTEXT_TITLE       N_("CD-Text Title")
+
+#define VLC_META_ISO_APPLICATION_ID N_("ISO-9660 Application ID") 
+#define VLC_META_ISO_PREPARER       N_("ISO-9660 Preparer") 
+#define VLC_META_ISO_PUBLISHER      N_("ISO-9660 Publisher") 
+#define VLC_META_ISO_VOLUME         N_("ISO-9660 Volume") 
+#define VLC_META_ISO_VOLUMESET      N_("ISO-9660 Volume Set") 
+
 #define VLC_META_CODEC_NAME         N_("Codec Name")
 #define VLC_META_CODEC_DESCRIPTION  N_("Codec Description")
 
index 7b50669836126cd29d4f78e76d5255a970da3f04..46132033fe8b484a4f14b3bacff5238418bda32e 100644 (file)
@@ -30,7 +30,7 @@
 #include <stdlib.h>
 
 #include <vlc/vlc.h>
-#include <vlc/intf.h>
+#include <vlc/input.h>
 
 #include <sys/types.h>
 #include <cdio/cdio.h>
 #define CDDA_MRL_PREFIX "cddax://"
 
 /* FIXME: This variable is a hack. Would be nice to eliminate. */
-static input_thread_t *p_cdda_input = NULL;
+static access_t *p_cdda_input = NULL;
 
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
-static int  CDDARead         ( input_thread_t *, byte_t *, size_t );
-static void CDDASeek         ( input_thread_t *, off_t );
-static int  CDDASetArea      ( input_thread_t *, input_area_t * );
-static int  CDDASetProgram   ( input_thread_t *, pgrm_descriptor_t * );
-
-static int  CDDAFixupPlayList( input_thread_t *p_input,
-                              cdda_data_t *p_cdda, const char *psz_source,
-                              bool play_single_track);
-
-#if NEED_UPDATE_VAR
-static void CDDAUpdateVar( input_thread_t *p_input, int i_entry, int i_action,
-                          const char *p_varname, char *p_label,
-                          const char *p_debug_label );
-#endif
-
+static block_t *CDDABlock( access_t * p_access );
+static int      CDDASeek( access_t * p_access, int64_t i_pos );
+static int      CDDAControl( access_t *p_access, int i_query, 
+                            va_list args );
+static void     CDDAMetaInfo( access_t *p_access  );
 
 /****************************************************************************
  * Private functions
@@ -87,7 +77,7 @@ static void CDDAUpdateVar( input_thread_t *p_input, int i_entry, int i_action,
 static void
 cdio_log_handler (cdio_log_level_t level, const char message[])
 {
-  cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
+  cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
   switch (level) {
   case CDIO_LOG_DEBUG:
   case CDIO_LOG_INFO:
@@ -103,7 +93,7 @@ cdio_log_handler (cdio_log_level_t level, const char message[])
     break;
   default:
     msg_Warn( p_cdda_input, message,
-            _("The above message had unknown vcdimager log level"),
+            _("The above message had unknown cdio log level"),
             level);
   }
   return;
@@ -117,7 +107,7 @@ cdio_log_handler (cdio_log_level_t level, const char message[])
 static void
 cddb_log_handler (cddb_log_level_t level, const char message[])
 {
-  cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
+  cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
   switch (level) {
   case CDDB_LOG_DEBUG:
   case CDDB_LOG_INFO:
@@ -136,7 +126,7 @@ cddb_log_handler (cddb_log_level_t level, const char message[])
 static void
 uninit_log_handler (cdio_log_level_t level, const char message[])
 {
-  cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
+  cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
   switch (level) {
   case CDIO_LOG_DEBUG:
   case CDIO_LOG_INFO:
@@ -163,283 +153,107 @@ uninit_log_handler (cdio_log_level_t level, const char message[])
 }
 
 /*****************************************************************************
- * CDDAPlay: Arrange things so we play the specified track.
- * VLC_TRUE is returned if there was no error.
+ * CDDARead: reads CDDA_BLOCKS_ONCE from the CD-DA and returns an
+ * allocated pointer to the data. NULL is returned if no data read. It
+ * is also possible if we haven't read a RIFF header in which case one 
+ * that we creaded during Open/Initialization is returned.
  *****************************************************************************/
-vlc_bool_t
-CDDAPlay( input_thread_t *p_input, int i_track )
+static block_t *
+CDDABlock( access_t * p_access )
 {
-  cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
+    block_t     *p_block;
+    cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
+    int          i_blocks = CDDA_BLOCKS_ONCE;
 
-  if( i_track > p_cdda->i_nb_tracks || i_track < 1 )
-    return VLC_FALSE;
+    dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called %d", 
+             p_cdda->i_sector);
 
-  CDDASetArea( p_input, p_input->stream.pp_areas[i_track] );
-  return VLC_TRUE;
-}
+    /* Check end of file */
+    if( p_access->info.b_eof ) return NULL;
 
-/*****************************************************************************
- * CDDARead: reads from the CDDA into PES packets.
- *****************************************************************************
- * Returns -1 in case of error, 0 in case of EOF, otherwise the number of
- * bytes.
- *****************************************************************************/
-static int CDDARead( input_thread_t * p_input, byte_t * p_buffer,
-                     size_t i_len )
-{
-    cdda_data_t *           p_cdda;
-    int                     i_blocks;
-    int                     i_index;
-    int                     i_read;
-
-    p_cdda = (cdda_data_t *)p_input->p_access_data;
-
-    /* Compute the number of blocks we have to read */
-    i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
-    i_read = 0;
-
-    if( !p_cdda->i_header_pos )
-    {
-        p_cdda->i_header_pos = sizeof(WAVEHEADER);
-        i_blocks = (i_len - sizeof(WAVEHEADER)) / CDIO_CD_FRAMESIZE_RAW;
-        memcpy( p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
-        p_buffer += sizeof(WAVEHEADER);
-        i_read += sizeof(WAVEHEADER);
+    if( !p_cdda->b_header )
+      {
+        /* Return only the dummy RIFF header we created in Open/Init */
+        p_block = block_New( p_access, sizeof( WAVEHEADER ) );
+        memcpy( p_block->p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
+        p_cdda->b_header = VLC_TRUE;
+        return p_block;
     }
 
-    for( i_index = 0; i_index < i_blocks; i_index++ )
+    /* Check end of track */
+    while( p_cdda->i_sector >= p_cdda->p_sectors[p_access->info.i_title + 1] )
     {
-
-        if( cdio_read_audio_sector( p_cdda->p_cddev->cdio, p_buffer,
-                                    p_cdda->i_sector) != 0 )
+        if( p_access->info.i_title + 1 >= p_cdda->i_tracks )
         {
-            msg_Err( p_input, "could not read sector %lu", 
-                    (long unsigned int) p_cdda->i_sector );
-            return -1;
+            p_access->info.b_eof = VLC_TRUE;
+            return NULL;
         }
 
-        p_cdda->i_sector ++;
-        if( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] )
-        {
-            input_area_t *p_area;
-
-            dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL),
-                       "end of track, cur: %lu", 
-                      (long unsigned int) p_cdda->i_sector );
-
-            /*???? if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )*/
-                return 0; /* EOF */
-
-            vlc_mutex_lock( &p_input->stream.stream_lock );
-            p_area = p_input->stream.pp_areas[
-                    p_input->stream.p_selected_area->i_id + 1 ];
-
-            p_area->i_part = 1;
-            CDDASetArea( p_input, p_area );
-            vlc_mutex_unlock( &p_input->stream.stream_lock );
-        }
-        i_read += CDIO_CD_FRAMESIZE_RAW;
-        p_buffer += CDIO_CD_FRAMESIZE_RAW;
+        p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE;
+        p_access->info.i_title++;
+        p_access->info.i_size = 
+         p_cdda->p_title[p_access->info.i_title]->i_size;
+        p_access->info.i_pos = 0;
     }
 
-    if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
+    /* Don't read after the end of a title */
+    if( p_cdda->i_sector + i_blocks >=
+        p_cdda->p_sectors[p_access->info.i_title + 1] )
     {
-        msg_Err( p_input, "must read full sectors" );
+        i_blocks = p_cdda->p_sectors[p_access->info.i_title + 1 ] -
+                   p_cdda->i_sector;
     }
 
-    return i_read;
-}
-
-/*****************************************************************************
- * CDDASetProgram: Does nothing since a CDDA is mono_program
- *****************************************************************************/
-static int CDDASetProgram( input_thread_t * p_input,
-                           pgrm_descriptor_t * p_program)
-{
-    cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
-    dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
-    return 0;
-}
-
-/*****************************************************************************
- * CDDASetArea: initialize input data for title x.
- * It should be called for each user navigation request.
- ****************************************************************************/
-static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
-{
-    cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
-    vlc_value_t val;
-    vlc_value_t text;
-
-    dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
-
-    text.psz_string = _("Track");
-    var_Change( p_input, "title", VLC_VAR_SETTEXT, &text, NULL );
-
-    /* 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 )
+    /* Do the actual reading */
+    p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW );
+    if( !p_block)
     {
-        /* Change the default area */
-        p_input->stream.p_selected_area = p_area;
-
-        /* Change the current track */
-        p_cdda->i_track = p_area->i_id - 1;
-        p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
-
-        /* Update the navigation variables without triggering a callback */
-        val.i_int = p_area->i_id;
-        var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL );
+        msg_Err( p_access, "cannot get a new block of size: %i",
+                 i_blocks * CDIO_CD_FRAMESIZE_RAW );
+        return NULL;
     }
 
-    p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track];
-
-    p_input->stream.p_selected_area->i_tell =
-        (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
-         - p_input->stream.p_selected_area->i_start;
+    if( cdio_read_audio_sectors( p_cdda->p_cddev->cdio, p_block->p_buffer,
+                                p_cdda->i_sector, i_blocks) != 0 )
+        {
+            msg_Err( p_access, "could not read sector %lu", 
+                    (long unsigned int) p_cdda->i_sector );
+            block_Release( p_block );
+
+           /* If we had problems above, assume the problem is with
+              the first sector of the read and set to skip it.  In
+              the future libcdio may have cdparanoia support.
+            */
+           p_cdda->i_sector++;
+           p_access->info.i_pos += CDIO_CD_FRAMESIZE_RAW;
+           return NULL;
+        }
 
-    /* warn interface that something has changed */
-    p_input->stream.b_seekable = 1;
-    p_input->stream.b_changed = 1;
+    p_cdda->i_sector     += i_blocks;
+    p_access->info.i_pos += p_block->i_buffer;
 
-    return 0;
+    return p_block;
 }
 
 /****************************************************************************
- * CDDASeek
+ * CDDASeek - change position for subsequent reads. For example, this
+ * can happen if the user moves a position slider bar in a GUI.
  ****************************************************************************/
-static void CDDASeek( input_thread_t * p_input, off_t i_off )
+static int 
+CDDASeek( access_t * p_access, int64_t i_pos )
 {
-    cdda_data_t * p_cdda;
-
-    p_cdda = (cdda_data_t *) p_input->p_access_data;
-
-    p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]
-                       + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW;
+    cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
 
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-    p_input->stream.p_selected_area->i_tell =
-        (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW
-         - p_input->stream.p_selected_area->i_start;
-
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
+    p_cdda->i_sector = p_cdda->p_sectors[p_access->info.i_title]
+                       + i_pos / CDIO_CD_FRAMESIZE_RAW;
+    p_access->info.i_pos = i_pos;
 
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
-               "sector %lu, offset: %lld, i_tell: %lld",  
-              (long unsigned int) p_cdda->i_sector, i_off,
-               p_input->stream.p_selected_area->i_tell );
-
-}
-
-#if NEED_UPDATE_VAR
-/****************************************************************************
- Update the "varname" variable to i_num without triggering a callback.
-****************************************************************************/
-static void
-CDDAUpdateVar( input_thread_t *p_input, 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 (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 );
-}
-#endif
-
-static void InformationCreate( input_thread_t *p_input  )
-{
-  cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
-
-#ifdef HAVE_LIBCDDB
-  if (p_cdda->i_cddb_enabled) {
-
-    dbg_print( INPUT_DBG_META, "field %s: %s\n", "Title",
-               p_cdda->cddb.disc->title );
-    input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Title"),
-                   "%s", p_cdda->cddb.disc->title );
-
-    dbg_print( INPUT_DBG_META, "field %s: %s\n", "Artist",
-               p_cdda->cddb.disc->artist );
-    input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Artist"),
-                   "%s", p_cdda->cddb.disc->artist );
-
-    dbg_print( INPUT_DBG_META, "field %s: %s\n", "Genre",
-               p_cdda->cddb.disc->genre );
-    input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Genre"),
-                   "%s", p_cdda->cddb.disc->genre );
-
-    dbg_print( INPUT_DBG_META, "field %s: %s\n", "Extended Data",
-               p_cdda->cddb.disc->ext_data );
-    input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Extended Data"),
-                   "%s", p_cdda->cddb.disc->ext_data );
-
-    if (p_cdda->cddb.disc->year != 0)
-      input_Control( p_input, INPUT_ADD_INFO, _("General"),
-                     _("Year"), "%d", p_cdda->cddb.disc->year );
-    if ( p_cdda->cddb.disc->discid )
-      input_Control( p_input, INPUT_ADD_INFO, _("General"),
-                     _("CDDB Disc ID"), "%x", p_cdda->cddb.disc->discid );
-
-    if ( p_cdda->cddb.disc->category != CDDB_CAT_INVALID )
-      input_Control( p_input, INPUT_ADD_INFO, _("General"),
-                     _("CDDB Disc Category"), "%s",
-                     CDDB_CATEGORY[p_cdda->cddb.disc->category] );
-  }
-
-#endif /*HAVE_LIBCDDB*/
-#define TITLE_MAX 30
-
-  {
-    track_t i_track = p_cdda->i_nb_tracks;
-    char psz_buffer[MSTRTIME_MAX_SIZE];
-    mtime_t i_duration =
-      (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[0])
-      / CDIO_CD_FRAMES_PER_SEC;
-
-    dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
-    input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Duration"), "%s",
-                  secstotimestr( psz_buffer, i_duration ) );
-
-    for( i_track = 0 ; i_track < p_cdda->i_nb_tracks ; i_track++ ) {
-      char track_str[TITLE_MAX];
-      mtime_t i_duration =
-        (p_cdda->p_sectors[i_track+1] - p_cdda->p_sectors[i_track])
-        / CDIO_CD_FRAMES_PER_SEC;
-      snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
-      input_Control( p_input, INPUT_ADD_INFO, track_str, _("Duration"), "%s",
-                     secstotimestr( psz_buffer, i_duration ) );
-
-#ifdef HAVE_LIBCDDB
-      if (p_cdda->i_cddb_enabled) {
-        cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
-                                            i_track);
-        if (t != NULL) {
-          if ( t->artist != NULL && strlen(t->artist) ) {
-            input_Control( p_input, INPUT_ADD_INFO, track_str,
-                           _("Artist"), "%s", t->artist );
-          }
-          if ( t->title != NULL && strlen(t->title) ) {
-            input_Control( p_input, INPUT_ADD_INFO, track_str,
-                           _("Title"), "%s",  t->title );
-          }
-          if ( t->ext_data != NULL && strlen(t->ext_data) ) {
-            input_Control( p_input, INPUT_ADD_INFO, track_str,
-                           _("Extended Data"), "%s",  t->ext_data );
-          }
-        }
-      }
-#endif
-    }
-  }
+               "sector %lu, offset: %lld",  
+              (long unsigned int) p_cdda->i_sector, i_pos );
+    return VLC_SUCCESS;
 }
 
-
 #ifdef HAVE_LIBCDDB
 
 #define free_and_dup(var, val) \
@@ -448,80 +262,82 @@ static void InformationCreate( input_thread_t *p_input  )
 
 
 static void
-GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
+GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
 {
 
   dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
 
-  if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
+  if (config_GetInt( p_access, MODULE_STRING "-cddb-enabled" )) {
     int i, i_matches;
     cddb_conn_t  *conn = cddb_new();
-    const CdIo *cdio = p_cdda->p_cddev->cdio;
+    const CdIo *p_cdio = p_cdda->p_cddev->cdio;
 
 
     cddb_log_set_handler (uninit_log_handler);
 
     if (!conn) {
-      msg_Warn( p_input, "unable to initialize libcddb" );
+      msg_Warn( p_access, "unable to initialize libcddb" );
       goto cddb_destroy;
     }
 
     cddb_set_email_address( conn,
-                            config_GetPsz( p_input,
+                            config_GetPsz( p_access,
                                            MODULE_STRING "-cddb-email") );
 
     cddb_set_server_name( conn,
-                          config_GetPsz( p_input,
+                          config_GetPsz( p_access,
                                          MODULE_STRING "-cddb-server") );
 
     cddb_set_server_port(conn,
-                          config_GetInt( p_input,
+                          config_GetInt( p_access,
                                          MODULE_STRING "-cddb-port") );
 
     /* Set the location of the local CDDB cache directory.
        The default location of this directory is */
 
-    if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" ))
+    if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
       cddb_cache_disable(conn);
 
     cddb_cache_set_dir(conn,
-                       config_GetPsz( p_input,
+                       config_GetPsz( p_access,
                                       MODULE_STRING "-cddb-cachedir") );
 
     cddb_set_timeout(conn,
-                     config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
+                     config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
 
 
-    if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
+    if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" )) {
       cddb_http_enable(conn);
     } else
       cddb_http_disable(conn);
 
     p_cdda->cddb.disc = cddb_disc_new();
     if (!p_cdda->cddb.disc) {
-      msg_Err( p_input, "Unable to create CDDB disc structure." );
+      msg_Err( p_access, "Unable to create CDDB disc structure." );
       goto cddb_end;
     }
 
-    for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
+    p_cdda->psz_mcn = cdio_get_mcn(p_cdio);
+
+    for(i = 1; i <= p_cdda->i_tracks; i++) {
       cddb_track_t *t = cddb_track_new();
-      t->frame_offset = cdio_get_track_lba(cdio, i);
+      t->frame_offset = cdio_get_track_lba(p_cdio, i);
       cddb_disc_add_track(p_cdda->cddb.disc, t);
     }
 
     p_cdda->cddb.disc->length =
-      cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK)
+      cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
       / CDIO_CD_FRAMES_PER_SEC;
 
     if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
-      msg_Err( p_input, "CDDB disc calc failed" );
+      msg_Err( p_access, "CDDB disc calc failed" );
       goto cddb_destroy;
     }
 
     i_matches = cddb_query(conn, p_cdda->cddb.disc);
     if (i_matches > 0) {
       if (i_matches > 1)
-        msg_Warn( p_input, "Found %d matches in CDDB. Using first one.",
+        msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
                   i_matches);
       cddb_read(conn, p_cdda->cddb.disc);
 
@@ -529,7 +345,7 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
         cddb_disc_print(p_cdda->cddb.disc);
 
     } else {
-      msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
+      msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
     }
 
   cddb_destroy:
@@ -539,6 +355,101 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
 }
 #endif /*HAVE_LIBCDDB*/
 
+#define add_meta_val(FIELD, VLC_META, VAL)                             \
+  if ( p_cdda->p_meta ) {                                              \
+    vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL );                     \
+    dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL );      \
+  }                                                                    \
+    
+#define add_cddb_meta(FIELD, VLC_META)                                 \
+  add_meta_val(FIELD, VLC_META, p_cdda->cddb.disc->FIELD);
+    
+#define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META)                        \
+  {                                                                    \
+    char psz_buf[100];                                                 \
+    snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC,                 \
+             p_cdda->cddb.disc->FIELD );                               \
+    psz_buf[sizeof(psz_buf)-1] = '\0';                                 \
+    add_meta_val(FIELD, VLC_META, psz_buf);                            \
+  }    
+
+/*
+ Gets and saves CDDA Meta Information. In the Control routine, 
+ we handle Meta Information requests and basically copy what we've
+ saved here. 
+ */    
+static void CDDAMetaInfo( access_t *p_access  )
+{
+  cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
+
+#ifdef HAVE_LIBCDDB
+  if ( p_cdda && p_cdda->i_cddb_enabled ) {
+
+    GetCDDBInfo(p_access, p_cdda);
+
+    if ( p_cdda->cddb.disc ) {
+
+      p_cdda->p_meta = vlc_meta_New();
+
+      add_cddb_meta(title,    VLC_META_CDDB_TITLE);
+      add_cddb_meta(artist,   VLC_META_CDDB_ARTIST);
+      add_cddb_meta(genre,    VLC_META_CDDB_GENRE);
+      add_cddb_meta(ext_data, VLC_META_CDDB_EXT_DATA);
+
+      add_cddb_meta_fmt(year,   "%d", VLC_META_CDDB_YEAR);
+      add_cddb_meta_fmt(discid, "%x", VLC_META_CDDB_DISCID);
+    }
+  }
+
+#endif /*HAVE_LIBCDDB*/
+#define TITLE_MAX 30
+
+#if UPDATE_TRACK_INFORMATION_FINISHED
+  {
+    track_t i_track = p_cdda->i_tracks;
+    char psz_buffer[MSTRTIME_MAX_SIZE];
+    mtime_t i_duration =
+      (p_cdda->p_sectors[i_track] - p_cdda->p_sectors[0])
+      / CDIO_CD_FRAMES_PER_SEC;
+
+    dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
+    input_Control( p_access, INPUT_ADD_INFO, _("General"), _("Duration"), "%s",
+                  secstotimestr( psz_buffer, i_duration ) );
+
+    for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ ) {
+      char track_str[TITLE_MAX];
+      mtime_t i_duration =
+        (p_cdda->p_sectors[i_track+1] - p_cdda->p_sectors[i_track])
+        / CDIO_CD_FRAMES_PER_SEC;
+      snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
+      input_Control( p_access, INPUT_ADD_INFO, track_str, _("Duration"), "%s",
+                     secstotimestr( psz_buffer, i_duration ) );
+
+#ifdef HAVE_LIBCDDB
+      if (p_cdda->i_cddb_enabled) {
+        cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
+                                            i_track);
+        if (t != NULL) {
+          if ( t->artist != NULL && strlen(t->artist) ) {
+            input_Control( p_access, INPUT_ADD_INFO, track_str,
+                           _("Artist"), "%s", t->artist );
+          }
+          if ( t->title != NULL && strlen(t->title) ) {
+            input_Control( p_access, INPUT_ADD_INFO, track_str,
+                           _("Title"), "%s",  t->title );
+          }
+          if ( t->ext_data != NULL && strlen(t->ext_data) ) {
+            input_Control( p_access, INPUT_ADD_INFO, track_str,
+                           _("Extended Data"), "%s",  t->ext_data );
+          }
+        }
+      }
+#endif /*HAVE_LIBCDDB*/
+    }
+  }
+#endif /* UPDATE_TRACK_INFORMATION_FINISHED */
+}
+
 #define add_format_str_info(val)                         \
   {                                                      \
     const char *str = val;                               \
@@ -587,8 +498,8 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
    %% : a %
 */
 static char *
-CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
-              const char format_str[], const char *mrl, int i_track)
+CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
+              const char format_str[], const char *mrl, int i_track)
 {
 #define TEMP_STR_SIZE 256
 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
@@ -618,30 +529,36 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
 #ifdef HAVE_LIBCDDB
     case 'a':
       if (!p_cdda->i_cddb_enabled) goto not_special;
-      add_format_str_info(p_cdda->cddb.disc->artist);
+      if (p_cdda->cddb.disc)
+       add_format_str_info(p_cdda->cddb.disc->artist);
       break;
     case 'A':
       if (!p_cdda->i_cddb_enabled) goto not_special;
-      add_format_str_info(p_cdda->cddb.disc->title);
+      if (p_cdda->cddb.disc)
+       add_format_str_info(p_cdda->cddb.disc->title);
       break;
     case 'C':
       if (!p_cdda->i_cddb_enabled) goto not_special;
-      add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
+      if (p_cdda->cddb.disc)
+       add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
       break;
     case 'G':
       if (!p_cdda->i_cddb_enabled) goto not_special;
-      add_format_str_info(p_cdda->cddb.disc->genre);
+      if (p_cdda->cddb.disc)
+       add_format_str_info(p_cdda->cddb.disc->genre);
       break;
     case 'I':
       if (!p_cdda->i_cddb_enabled) goto not_special;
-      add_format_num_info(p_cdda->cddb.disc->discid, "%x");
+      if (p_cdda->cddb.disc)
+       add_format_num_info(p_cdda->cddb.disc->discid, "%x");
       break;
     case 'Y':
       if (!p_cdda->i_cddb_enabled) goto not_special;
-      add_format_num_info(p_cdda->cddb.disc->year, "%5d");
+      if (p_cdda->cddb.disc)
+       add_format_num_info(p_cdda->cddb.disc->year, "%5d");
       break;
     case 't':
-      if (p_cdda->i_cddb_enabled) {
+      if (p_cdda && p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
                                             i_track-1);
         if (t != NULL && t->title != NULL)
@@ -649,7 +566,7 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
       } else goto not_special;
       break;
     case 'p':
-      if (p_cdda->i_cddb_enabled) {
+      if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
                                             i_track-1);
         if (t != NULL && t->artist != NULL)
@@ -657,7 +574,7 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
       } else goto not_special;
       break;
     case 'e':
-      if (p_cdda->i_cddb_enabled) {
+      if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
                                             i_track-1);
         if (t != NULL && t->ext_data != NULL)
@@ -670,17 +587,14 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
       add_format_str_info(mrl);
       break;
 
-#if FINISHED
     case 'm':
-      add_format_str_info(p_cdda->mcn);
+      add_format_str_info(p_cdda->psz_mcn);
       break;
-#endif
 
     case 'n':
-      add_format_num_info(p_cdda->i_nb_tracks, "%d");
+      add_format_num_info(p_cdda->i_tracks, "%d");
       break;
 
-#ifdef HAVE_LIBCDDB
     case 's':
       if (p_cdda->i_cddb_enabled) {
         char psz_buffer[MSTRTIME_MAX_SIZE];
@@ -690,7 +604,6 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
         add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
       } else goto not_special;
       break;
-#endif
 
     case 'T':
       add_format_num_info(i_track, "%02d");
@@ -707,8 +620,9 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
   return strdup(temp_str);
 }
 
+#ifdef TRACK_META_INFORMATION_FINISHED
 static void
-CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
+CDDACreatePlayListItem(const input_thread_t *p_access, cdda_data_t *p_cdda,
                        playlist_t *p_playlist, unsigned int i_track,
                        char *psz_mrl, int psz_mrl_max,
                        const char *psz_source, int playlist_operation,
@@ -731,8 +645,8 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
   snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
            CDDA_MRL_PREFIX, psz_source, i_track);
 
-  p_title = CDDAFormatStr(p_input, p_cdda,
-                          config_GetPsz( p_input, config_varname ),
+  p_title = CDDAFormatStr(p_access, p_cdda,
+                          config_GetPsz( p_access, config_varname ),
                           psz_mrl, i_track);
 
   dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
@@ -751,8 +665,8 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
   vlc_mutex_lock( &p_item->input.lock );
 
   p_author =
-    CDDAFormatStr( p_input, p_cdda,
-                   config_GetPsz( p_input, MODULE_STRING "-author-format" ),
+    CDDAFormatStr( p_access, p_cdda,
+                   config_GetPsz( p_access, MODULE_STRING "-author-format" ),
                    psz_mrl, i_track );
 
   playlist_ItemAddInfo( p_item ,  _("General"),_("Author"), p_author);
@@ -797,89 +711,54 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
 }
 
 static int
-CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda,
-                   const char *psz_source, bool play_single_track)
+CDDAFixupPlayList( access_t *p_access, cdda_data_t *p_cdda,
+                   const char *psz_source, track_t i_track)
 {
   int i;
-  playlist_t * p_playlist;
   char       * psz_mrl;
   unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
     strlen("@T") + strlen("100") + 1;
 
-#ifdef HAVE_LIBCDDB
-  p_cdda->i_cddb_enabled =
-    config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
-  if( play_single_track && !p_cdda->i_cddb_enabled ) return 0;
-#else
-  if( play_single_track ) return 0;
-#endif
-
-
   psz_mrl = malloc( psz_mrl_max );
 
   if( psz_mrl == NULL )
     {
-      msg_Warn( p_input, "out of memory" );
+      msg_Warn( p_access, "out of memory" );
       return -1;
     }
 
-  p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
-                                               FIND_ANYWHERE );
-  if( !p_playlist )
+  CDDAMetaInfo(p_access);
+
+  for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
     {
-      msg_Warn( p_input, "can't find playlist" );
-      free(psz_mrl);
-      return -1;
+      input_title_t *t = p_cdda->p_sectors[i-1] = vlc_input_title_New();
+      
+      asprintf( &t->psz_name, _("Track %i"), i );
+      t->i_size = ( p_sys->p_sectors[i] - p_sys->p_sectors[i-1] ) *
+       (int64_t)CDIO_CD_FRAMESIZE_RAW;
+
+      t->i_length = I64C(1000000) * t->i_size / 44100 / 4;
+      CDDACreatePlayListItem(p_access, p_cdda, i, psz_mrl,
+                            psz_mrl_max, psz_source, PLAYLIST_APPEND,
+                            PLAYLIST_END);
     }
 
-#ifdef HAVE_LIBCDDB
-  if (p_cdda->i_cddb_enabled)
-    GetCDDBInfo(p_input, p_cdda);
-  else
-    p_cdda->cddb.disc = NULL;
-#endif
-
-  InformationCreate(p_input);
-
-  if (play_single_track) {
-    /* May fill out more information when the playlist user interface becomes
-       more mature.
-     */
-    CDDACreatePlayListItem(p_input, p_cdda, p_playlist, p_cdda->i_track+1,
-                           psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
-                           p_playlist->i_index);
-  } else {
-
-    playlist_Delete( p_playlist, p_playlist->i_index);
-
-    for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
-      {
-        CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, 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;
 }
+#endif /* TRACK_META_INFORMATION_FINISHED*/
 
 /****************************************************************************
  * Public functions
  ****************************************************************************/
 int
-E_(DebugCB)   ( vlc_object_t *p_this, const char *psz_name,
-                vlc_value_t oldval, vlc_value_t val, void *p_data )
+E_(CDDADebugCB)   ( vlc_object_t *p_this, const char *psz_name,
+                   vlc_value_t oldval, vlc_value_t val, void *p_data )
 {
   cdda_data_t *p_cdda;
 
   if (NULL == p_cdda_input) return VLC_EGENERIC;
 
-  p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
+  p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
 
   if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
     msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d",
@@ -897,7 +776,7 @@ E_(CDDBEnabledCB)   ( vlc_object_t *p_this, const char *psz_name,
 
   if (NULL == p_cdda_input) return VLC_EGENERIC;
 
-  p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
+  p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
 
 #ifdef HAVE_LIBCDDB
   if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
@@ -910,83 +789,30 @@ E_(CDDBEnabledCB)   ( vlc_object_t *p_this, const char *psz_name,
   return VLC_SUCCESS;
 }
 
-/*FIXME*/
-#if PLAYLIST_INTERFACE_IS_FIXED
-int
-E_(TitleFormatCB)   ( vlc_object_t *p_this, const char *psz_name,
-                      vlc_value_t oldval, vlc_value_t val, void *p_data )
-{
-  cdda_data_t *p_cdda;
-
-  if (NULL == p_cdda_input) return VLC_EGENERIC;
-
-  p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
-
-  if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
-    msg_Dbg( p_cdda_input, "Old CDDB Enabled (%s), new (%s)",
-             oldval.psz_string, val.psz_string);
-  }
-  ????
-  return VLC_SUCCESS;
-}
-#endif
-
 /*****************************************************************************
- * Open: open cdda
+ * Open: open cdda device or image file and initialize structures 
+ * for subsequent operations.
  *****************************************************************************/
 int
-E_(Open)( vlc_object_t *p_this )
+E_(CDDAOpen)( vlc_object_t *p_this )
 {
-    input_thread_t *        p_input = (input_thread_t *)p_this;
-    char *                  psz_orig;
-    char *                  psz_parser;
+    access_t               *p_access = (access_t*)p_this;
     char *                  psz_source;
     cdda_data_t *           p_cdda;
     int                     i;
-    int                     i_track = 1;
     cddev_t                 *p_cddev;
-    vlc_value_t             val;
-    bool                    play_single_track = false;
 
     /* Set where to log errors messages from libcdio. */
-    p_cdda_input = (input_thread_t *)p_this;
+    p_cdda_input = p_access;
 
-    /* parse the options passed in command line : */
-    psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
-
-    if( !psz_orig )
-    {
-        return( -1 );
-    }
-
-    while( *psz_parser && *psz_parser != '@' )
+    if( !p_access->psz_path || !*p_access->psz_path )
     {
-        psz_parser++;
-    }
-
-    if( *psz_parser == '@' )
-    {
-        /* Found options */
-        *psz_parser = '\0';
-        ++psz_parser;
-
-        if ('T' == *psz_parser || 't' == *psz_parser )
-            ++psz_parser;
+        /* Only when selected */
+        if( !p_this->b_force ) return VLC_EGENERIC;
 
-        i_track = (int)strtol( psz_parser, NULL, 10 );
-        i_track = i_track ? i_track : 1;
-        play_single_track = true;
-    }
-
-    if( !*psz_source ) {
-      /* No source specified, so figure it out. */
-      if( !p_input->psz_access ) {
-        free( psz_orig );
-        return -1;
-      }
-      psz_source = config_GetPsz( p_input, "cd-audio" );
+        psz_source = var_CreateGetString( p_this, "cd-audio" );
 
-      if( !psz_source || 0==strlen(psz_source) ) {
+       if( !psz_source || !*psz_source ) {
         /* Scan for a CD-ROM drive with a CD-DA in it. */
         char **cd_drives =
           cdio_get_devices_with_cap(NULL,  CDIO_FS_AUDIO, false);
@@ -999,101 +825,108 @@ E_(Open)( vlc_object_t *p_this )
         cdio_free_device_list(cd_drives);
       }
     }
+    else 
+      psz_source = strdup( p_access->psz_path );
 
-    /* Open CDDA */
     cdio_log_set_handler ( cdio_log_handler );
-#ifdef HAVE_LIBCDDB
-    cddb_log_set_handler ( cddb_log_handler );
-#endif
 
+    /* Open CDDA */
     if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
     {
-        msg_Warn( p_input, "could not open %s", psz_source );
-        free( psz_source );
-        return VLC_EGENERIC;
+        msg_Warn( p_access, "could not open %s", psz_source );
+       goto error2;
     }
 
     p_cdda = malloc( sizeof(cdda_data_t) );
     if( p_cdda == NULL )
     {
-        msg_Err( p_input, "out of memory" );
+        msg_Err( p_access, "out of memory" );
         free( psz_source );
         return VLC_ENOMEM;
     }
 
-    p_cdda->p_cddev        = p_cddev;
-    p_cdda->i_debug        = config_GetInt( p_this, MODULE_STRING "-debug" );
-    p_input->p_access_data = (void *)p_cdda;
+#ifdef HAVE_LIBCDDB
+    cddb_log_set_handler ( cddb_log_handler );
+    p_cdda->cddb.disc = NULL;
+    p_cdda->i_cddb_enabled =
+      config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
+#endif
+
+    p_cdda->b_header = VLC_FALSE;
+    p_cdda->p_cddev  = p_cddev;
+    p_cdda->i_debug  = config_GetInt( p_this, MODULE_STRING "-debug" );
 
-    dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
+    printf("+++debug: %d\n", p_cdda->i_debug);
 
-    p_input->i_mtu = CDDA_DATA_ONCE;
+    dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
 
     /* We read the Table Of Content information */
-    p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
+    p_cdda->i_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_access),
                               p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
-    if( p_cdda->i_nb_tracks < 0 )
-        msg_Err( p_input, "unable to count tracks" );
-    else if( p_cdda->i_nb_tracks <= 0 )
-        msg_Err( p_input, "no audio tracks found" );
-
-    if( p_cdda->i_nb_tracks <= 0 )
-    {
-        ioctl_Close( p_cdda->p_cddev );
-        free( p_cdda );
-        free( psz_source );
-        return VLC_EGENERIC;
+    if( p_cdda->i_tracks < 0 ) {
+        msg_Err( p_access, "unable to count tracks" );
+        goto error;
+    } else if( p_cdda->i_tracks <= 0 ) {
+        msg_Err( p_access, "no audio tracks found" );
+        goto error;
     }
 
-    if( i_track > p_cdda->i_nb_tracks || i_track < 1 )
-        i_track = 1;
-
-    /* Set stream and area data */
-    vlc_mutex_lock( &p_input->stream.stream_lock );
-
-    /* Initialize ES structures */
-    input_InitStream( p_input, 0 );
-
-    /* cdda input method */
-    p_input->stream.i_method = INPUT_METHOD_CDDA;
-
-    p_input->stream.b_pace_control = 1;
-    p_input->stream.b_seekable = 1;
-    p_input->stream.i_mux_rate = 44100 * 4 / 50;
+    /* Set up p_access */
+    p_access->pf_read    = NULL;
+    p_access->pf_block   = CDDABlock;
+    p_access->pf_control = CDDAControl;
+    p_access->pf_seek    = CDDASeek;
+
+    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_access->p_sys     = (access_sys_t *) p_cdda;
+
+    CDDAMetaInfo(p_access);
+    
+    { 
+      char *psz_config_title_fmt = MODULE_STRING "-title-format";
+      const char *psz_title_fmt  = 
+       config_GetPsz( p_access, psz_config_title_fmt );
+      
+#ifdef HAVE_LIBCDDB
+      if (p_cdda->i_cddb_enabled) {
+       psz_config_title_fmt = MODULE_STRING "-cddb-title-format";
+      }
+#endif /*HAVE_LIBCDDB*/
 
-#define area p_input->stream.pp_areas
-    for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
-    {
-        input_AddArea( p_input, i, 1 );
-
-        /* Absolute start offset and size */
-        area[i]->i_start =
-            (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
-        area[i]->i_size =
-            (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1])
-            * (off_t)CDIO_CD_FRAMESIZE_RAW;
+      for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
+       {
+         char * psz_title;
+         input_title_t *t = p_cdda->p_title[i-1] = vlc_input_title_New();
+         char *psz_mrl;
+
+         asprintf(&psz_mrl, "%s%s@T%u", CDDA_MRL_PREFIX, psz_source, i);
+         
+         psz_title = CDDAFormatStr(p_access, p_cdda, psz_title_fmt,
+                                   psz_mrl, i);
+
+         t->psz_name = strdup(psz_title);
+
+         t->i_size = ( p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1] ) *
+           (int64_t)CDIO_CD_FRAMESIZE_RAW;
+         
+         t->i_length = I64C(1000000) * t->i_size / 44100 / 4;
+
+         dbg_print((INPUT_DBG_MRL), "track %d, start=%d, mrl %s", 
+                   i, p_cdda->p_sectors[i-1], psz_mrl );
+         
+         free (psz_mrl);
+       }
     }
-#undef area
-
-    CDDAPlay( p_input, i_track);
-    vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-    CDDAFixupPlayList(p_input, p_cdda, psz_source, play_single_track);
-
-    p_input->pf_read = CDDARead;
-    p_input->pf_seek = CDDASeek;
-    p_input->pf_set_area = CDDASetArea;
-    p_input->pf_set_program = CDDASetProgram;
-
-    /* Update default_pts to a suitable value for cdda access */
-    var_Create( p_input, MODULE_STRING "-caching",
-                VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
-    var_Get( p_input, MODULE_STRING "-caching", &val );
-    p_input->i_pts_delay = val.i_int * 1000;
-
-    free( psz_source );
-
-    /* Build a WAV header for the output data */
+    
+    /* Build a WAV header to put in front of the output data. 
+       This gets sent back in the Block (read) routine.
+     */
     memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
     SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
     SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
@@ -1109,22 +942,40 @@ E_(Open)( vlc_object_t *p_this )
     SetDWLE( &p_cdda->waveheader.BytesPerSec,
             2*16/8 /*BytesPerSample*/ * 44100 /*SampleFreq*/ );
     p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
-    p_cdda->waveheader.DataLength = 0;                 /* we just don't know */
-    p_cdda->i_header_pos = 0;
+    p_cdda->waveheader.DataLength  = 0;    /* we just don't know */
 
+    /* PTS delay */
+    var_Create( p_access, MODULE_STRING "-caching", 
+               VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
     return VLC_SUCCESS;
+
+ error:
+    ioctl_Close( p_cdda->p_cddev );
+    free( p_cdda );
+ error2:
+    free( psz_source );
+    return VLC_EGENERIC;
+
 }
 
 /*****************************************************************************
- * CDDAClose: closes cdda
+ * CDDAClose: closes cdda and frees any resources associded with it.
  *****************************************************************************/
 void
-E_(Close)( vlc_object_t *p_this )
+E_(CDDAClose)( vlc_object_t *p_this )
 {
-    input_thread_t *   p_input = (input_thread_t *)p_this;
-    cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data;
+    access_t    *p_access = (access_t *) p_this;
+    cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
+    track_t      i;
 
     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
+
+    /* Remove playlist titles */
+    for( i = 0; i < p_cdda->i_tracks; i++ )
+    {
+        vlc_input_title_Delete( p_cdda->p_title[i] );
+    }
+
     ioctl_Close( p_cdda->p_cddev );
 
     cdio_log_set_handler (uninit_log_handler);
@@ -1136,6 +987,108 @@ E_(Close)( vlc_object_t *p_this )
 #endif
 
     free( p_cdda->p_sectors );
+    if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
     free( p_cdda );
     p_cdda_input = 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 CDDAControl( access_t *p_access, int i_query, va_list args )
+{
+    cdda_data_t  *p_cdda = (cdda_data_t *) p_access->p_sys;
+    vlc_bool_t   *pb_bool;
+    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;
+           pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
+           dbg_print( INPUT_DBG_META, "Meta copied");
+           *pp_meta = vlc_meta_Duplicate( p_cdda->p_meta );
+           return VLC_SUCCESS;
+         }
+         return VLC_EGENERIC;
+
+        case ACCESS_CAN_SEEK:
+        case ACCESS_CAN_FASTSEEK:
+        case ACCESS_CAN_PAUSE:
+        case ACCESS_CAN_CONTROL_PACE:
+            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
+            *pb_bool = VLC_TRUE;
+            break;
+
+        /* */
+        case ACCESS_GET_MTU:
+            pi_int = (int*)va_arg( args, int * );
+            *pi_int = CDDA_DATA_ONCE;
+            break;
+
+        case ACCESS_GET_PTS_DELAY:
+         { 
+           int64_t      *pi_64;
+            pi_64 = (int64_t*)va_arg( args, int64_t * );
+            *pi_64 = 1000 * var_GetInteger( p_access, 
+                                           MODULE_STRING "-caching" );
+            break;
+         }
+
+        /* */
+        case ACCESS_SET_PAUSE_STATE:
+            break;
+
+        case ACCESS_GET_TITLE_INFO:
+         { input_title_t ***ppp_title;
+            ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
+            pi_int    = (int*)va_arg( args, int* );
+           *((int*)va_arg( args, int* )) = 1; /* Title offset */
+
+            /* Duplicate track info */
+            *pi_int = p_cdda->i_tracks;
+            *ppp_title = malloc(sizeof( input_title_t **) * p_cdda->i_tracks );
+            for( i = 0; i < p_cdda->i_tracks; i++ )
+            {
+                (*ppp_title)[i] = 
+                 vlc_input_title_Duplicate( p_cdda->p_title[i] );
+            }
+         }
+         break;
+
+        case ACCESS_SET_TITLE:
+            i = (int)va_arg( args, int );
+            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_cdda->p_title[i]->i_size;
+                p_access->info.i_pos = 0;
+
+                /* Next sector to read */
+                p_cdda->i_sector = p_cdda->p_sectors[i];
+            }
+            break;
+
+        case ACCESS_SET_SEEKPOINT:
+        case ACCESS_SET_PRIVATE_ID_STATE:
+            return VLC_EGENERIC;
+        default:
+            msg_Warn( p_access, "unimplemented query in control" );
+            return VLC_EGENERIC;
+
+    }
+    return VLC_SUCCESS;
+}
index f747ee528f3b11f43aed503be8fa6a5b2fe93613..583a9672826d8d020a7513700cdc38df8a4dbe2f 100644 (file)
 /*****************************************************************************
  * prototypes
  *****************************************************************************/
-int  E_(Open)         ( vlc_object_t * );
-void E_(Close)        ( vlc_object_t * );
+int  E_(CDDAOpen)     ( vlc_object_t * );
+void E_(CDDAClose)    ( vlc_object_t * );
 
-int  E_(OpenIntf)     ( vlc_object_t * );
-void E_(CloseIntf)    ( vlc_object_t * );
-
-int  E_(DebugCB)      ( vlc_object_t *p_this, const char *psz_name,
+int  E_(CDDADebugCB)  ( vlc_object_t *p_this, const char *psz_name,
                         vlc_value_t oldval, vlc_value_t val,
                         void *p_data );
 
@@ -104,15 +101,15 @@ int  E_(CDDBEnabledCB)( vlc_object_t *p_this, const char *psz_name,
  *****************************************************************************/
 
 vlc_module_begin();
-    add_usage_hint( N_("cddax://[device-or-file][@[T]num]") );
+    add_usage_hint( N_("cddax://[device-or-file][@[T]track]") );
     set_description( _("Compact Disc Digital Audio (CD-DA) input") );
-    set_capability( "access", 75 /* slightly higher than cdda */ );
-    set_callbacks( E_(Open), E_(Close) );
-    add_shortcut( "cdda" );
+    set_capability( "access2", 10 /* slightly higher than cdda */ );
+    set_callbacks( E_(CDDAOpen), E_(CDDAClose) );
     add_shortcut( "cddax" );
+    add_shortcut( "cd" );
 
     /* Configuration options */
-    add_integer ( MODULE_STRING "-debug", 0, E_(DebugCB),
+    add_integer ( MODULE_STRING "-debug", 0, E_(CDDADebugCB),
                   N_("If nonzero, this gives additional debug information."),
                   DEBUG_LONGTEXT, VLC_TRUE );
 
index e0eeffd5151c341da09943f1ef51cb63e4352dbf..3b6d0c5a94304fec4e874a124c953d191a443749 100644 (file)
@@ -3,7 +3,7 @@
  *          using libcdio, libvcd and libvcdinfo
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: cdda.h,v 1.6 2004/02/14 17:25:39 gbazin Exp $
+ * $Id$
  *
  * Author: Rocky Bernstein <rocky@panix.com>
  *
@@ -23,6 +23,7 @@
  *****************************************************************************/
 
 #include "../vcdx/cdrom.h"
+#include "vlc_meta.h"
 
 #ifdef HAVE_LIBCDDB
 #include <cddb/cddb.h>
@@ -45,7 +46,7 @@
 #if INPUT_DEBUG
 #define dbg_print(mask, s, args...) \
    if (p_cdda->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
  *****************************************************************************/
 typedef struct cdda_data_s
 {
-    cddev_t     *p_cddev;                           /* CD device descriptor */
-    int         i_nb_tracks;                        /* Nb of tracks (titles) */
-    int         i_track;                                    /* Current track */
-    lsn_t       i_sector;                                  /* Current Sector */
-    lsn_t *     p_sectors;                                  /* Track sectors */
-    vlc_bool_t  b_end_of_track;           /* If the end of track was reached */
+    cddev_t     *p_cddev;                 /* CD device descriptor */
+    int         i_tracks;                 /* # of tracks (titles) */
+
+    /* Current position */
+    int         i_track;                  /* Current track */
+    lsn_t       i_sector;                 /* Current Sector */
+    lsn_t *     p_sectors;                /* Track sectors */
+
     int         i_debug;                  /* Debugging mask */
-    char *      mcn;                      /* Media Catalog Number            */
-    intf_thread_t *p_intf;
+    char *      psz_mcn;                  /* Media Catalog Number            */
+    vlc_meta_t  *p_meta;
+
+    input_title_t *p_title[CDIO_CD_MAX_TRACKS]; 
+
 
 #ifdef HAVE_LIBCDDB
     int         i_cddb_enabled;
@@ -76,7 +82,7 @@ typedef struct cdda_data_s
 #endif
 
     WAVEHEADER  waveheader;               /* Wave header for the output data */
-    int         i_header_pos;
+    vlc_bool_t  b_header;
 
 } cdda_data_t;