]> git.sesse.net Git - vlc/blobdiff - modules/access/cdda/info.c
* This makes the cddax and vcdx modules compile again. meta is disabled. functionalit...
[vlc] / modules / access / cdda / info.c
index aa2cc75731e5da2fa2f1e0fb8b764852991cfb80..5d06afe899193b0fd6868903aae559b3f83ec076 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * info.c : CD digital audio input information routines
  *****************************************************************************
- * Copyright (C) 2004 VideoLAN
- * $Id: info.c 8845 2004-09-29 09:00:41Z rocky $
+ * Copyright (C) 2004, 2005 the VideoLAN team
+ * $Id$
  *
  * Authors: Rocky Bernstein <rocky@panix.com>
  *
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /*****************************************************************************
 #   include <errno.h>
 #endif
 
-#define CDDA_MRL_PREFIX "cddax://"
+static char *CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
+                           const char format_str[], const char *psz_mrl, 
+                           track_t i_track);
+
+static char *CDDAFormatMRL( const access_t *p_access, track_t i_track );
 
 #ifdef HAVE_LIBCDDB
 
   if (val) var=strdup(val);
 
 
-static void GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
+/* Saves CDDB information about CD-DA via libcddb. */
+static void 
+GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
 {
     int i, i_matches;
     cddb_conn_t  *conn = cddb_new();
-    const CdIo *p_cdio = p_cdda->p_cdio;
+    const CdIo_t *p_cdio = p_cdda->p_cdio;
 
     dbg_print( (INPUT_DBG_CALL), "" );
 
@@ -110,13 +116,14 @@ static void GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
     {
         track_t i_track =  p_cdda->i_first_track + i;
         cddb_track_t *t = cddb_track_new();
-        t->frame_offset = cdio_get_track_lba(p_cdio, i_track);
+       cddb_track_set_frame_offset(t, 
+                                   cdio_get_track_lba(p_cdio, i_track));
         cddb_disc_add_track(p_cdda->cddb.disc, t);
     }
 
-    p_cdda->cddb.disc->length =
-        cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
-        / CDIO_CD_FRAMES_PER_SEC;
+    cddb_disc_set_length(p_cdda->cddb.disc,
+                        cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
+                        / CDIO_CD_FRAMES_PER_SEC);
 
     if (!cddb_disc_calc_discid(p_cdda->cddb.disc))
     {
@@ -149,22 +156,22 @@ cddb_end: ;
 }
 #endif /*HAVE_LIBCDDB*/
 
-#define add_meta_val(FIELD, VLC_META, VAL)                              \
+#define add_meta_val(VLC_META, VAL)                                    \
   if ( p_cdda->p_meta && VAL) {                                         \
-    vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL );                      \
+    /*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(FIELD, VLC_META)                                 \
+  add_meta_val(VLC_META, cddb_disc_get_##FIELD(p_cdda->cddb.disc));
 
 #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 );                               \
+              cddb_disc_get_##FIELD(p_cdda->cddb.disc));                               \
     psz_buf[sizeof(psz_buf)-1] = '\0';                                  \
-    add_meta_val(FIELD, VLC_META, psz_buf);                             \
+    add_meta_val(VLC_META, psz_buf);                                   \
   }
 
 /* Adds a string-valued entry to the stream and media information if
@@ -188,13 +195,13 @@ cddb_end: ;
    under category "Disc" if the string is not null or the null string.
  */
 #define add_cddb_disc_info_str(TITLE, FIELD)                    \
-  add_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
+  add_info_str("Disc", TITLE, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
 
 /* Adds a CDDB numeric-valued entry to the stream and media information
    under category "Disc" if the string is not null or the null string.
  */
 #define add_cddb_disc_info_val(TITLE, FMT, FIELD)               \
-  add_info_val("Disc", TITLE, FMT, p_cdda->cddb.disc->FIELD)
+  add_info_val("Disc", TITLE, FMT, cddb_disc_get_##FIELD(p_cdda->cddb.disc))
 
 /* Adds a CD-Text string-valued entry to the stream and media information
    under category "Disc" if the string is not null or the null string.
@@ -210,67 +217,110 @@ cddb_end: ;
 
 
 /*
Gets and saves Meta Information about the CD-DA.
 Saves Meta Information about the CD-DA.
 
- In the Control routine, we handle Meta Information requests and
- basically copy what we've saved here.
+  Meta information used in "stream and media info" or in playlist
+  info. The intialization of CD-Text or CDDB is done here though.
+  Therefore, this should be called before CDDAMetaInfo is called.
 
- Meta information is also used elsewhere such as in "stream and
- media info" or in playlist info. The intialization of CD-Text or CDDB
- is done here though.
  */
-void CDDAMetaInfo( access_t *p_access, int i_track )
+void 
+CDDAMetaInfoInit( access_t *p_access )
 {
-    cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
-
+    cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
+    
     if ( ! p_cdda ) return;
 
+    dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d", 
+              p_cdda->i_tracks );
+
     p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
+#if 0
+    p_cdda->p_meta = vlc_meta_New();
+#endif
 
 #ifdef HAVE_LIBCDDB
     if ( p_cdda->b_cddb_enabled )
     {
         GetCDDBInfo(p_access, p_cdda);
-        if ( p_cdda->cddb.disc )
-        {
-            p_cdda->p_meta = vlc_meta_New();
-            if( i_track == -1 )
-            {
-                add_cddb_meta(title,    VLC_META_TITLE);
-                add_cddb_meta(artist,   VLC_META_ARTIST);
-                input_Control( p_cdda->p_input, INPUT_SET_NAME,
-                               p_cdda->cddb.disc->artist );
-            }
-            else
-            {
-                cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
-                                                    i_track-1);
-                if (t != NULL )
-                {
-                    if( t->title != NULL )
-                    {
-                        add_meta_val( NULL, VLC_META_TITLE, t->title );
-                    }
-                    if( t->artist != NULL )
-                    {
-                        add_meta_val( NULL, VLC_META_ARTIST, t->artist );
-                    }
-                }
-            }
-            add_cddb_meta(genre,    VLC_META_GENRE);
-            add_cddb_meta_fmt(year,   "%d", VLC_META_DATE );
-        }
     }
 
 #endif /*HAVE_LIBCDDB*/
+    
+#define TITLE_MAX 30
+    {
+        track_t i_track;
+
+       for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
+       {
+           p_cdda->p_cdtext[i_track] =
+             cdio_get_cdtext(p_cdda->p_cdio, i_track);
+       }
+    }
+}
+
+/*
+ In the Control routine, we handle Meta Information requests and
+ basically copy what was saved in CDDAMetaInfoInit.
+
+ If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
+ CD.
+ */
+void 
+CDDAMetaInfo( access_t *p_access, track_t i_track )
+{
+    cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
+    char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
+    char *psz_meta_artist = NULL;
+    
+    if ( ! p_cdda ) return;
+
+    dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
+
+#ifdef HAVE_LIBCDDB
+
+    /* Set up for Meta and name for CDDB access. */
+    if ( p_cdda->b_cddb_enabled &&  p_cdda->cddb.disc )
+    {
+        if( CDIO_INVALID_TRACK == i_track )
+       {
+
+           psz_meta_title  = (char *)cddb_disc_get_title(p_cdda->cddb.disc);
+           psz_meta_artist = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
+           if ( cddb_disc_get_genre(p_cdda->cddb.disc) && 
+                    strlen(cddb_disc_get_genre(p_cdda->cddb.disc)) )
+               add_cddb_meta(genre, VLC_META_GENRE);
+           if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc))
+               add_cddb_meta_fmt(year, "%d", VLC_META_DATE );
+       }
+       else
+       {
+         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
+         if (t != NULL )
+         {
+             if( cddb_track_get_title(t) != NULL && ! p_cdda->b_nav_mode )
+             {
+                 add_meta_val( VLC_META_TITLE, cddb_track_get_title(t) );
+             }
+             if( cddb_track_get_artist(t) != NULL )
+             {
+               add_meta_val( VLC_META_ARTIST, cddb_track_get_artist(t) );
+             }
+         }
+       }
+    }
+
+#endif /*HAVE_LIBCDDB*/
+    
 #define TITLE_MAX 30
     {
         track_t i = p_cdda->i_tracks;
         const int i_first_track = p_cdda->i_first_track;
         char psz_buffer[MSTRTIME_MAX_SIZE];
-        mtime_t i_duration =
-              (p_cdda->lsn[i_first_track+i] - p_cdda->lsn[i_first_track])
-              / CDIO_CD_FRAMES_PER_SEC;
+       unsigned int i_track_frames = 
+         cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
+         
+        mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
 
         dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d", 
                   (long int) i_duration, p_cdda->i_tracks );
@@ -278,27 +328,37 @@ void CDDAMetaInfo( access_t *p_access, int i_track )
                        _("Disc"), _("Duration"), "%s",
                        secstotimestr( psz_buffer, i_duration ) );
 
-        input_Control( p_cdda->p_input, INPUT_ADD_INFO,
-                       _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
+       if (p_cdda->psz_mcn) {
+           input_Control( p_cdda->p_input, INPUT_ADD_INFO,
+                          _("Disc"), _("Media Catalog Number (MCN)"), "%s", 
+                          p_cdda->psz_mcn );
+           
+           input_Control( p_cdda->p_input, INPUT_ADD_INFO,
+                          _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
+       }
+       
 
 #ifdef HAVE_LIBCDDB
         if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
         {
           add_cddb_disc_info_str("Artist (CDDB)", artist);
-          add_cddb_disc_info_str("Genre (CDDB)",  genre);
-          add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
-          add_cddb_disc_info_val("Year (CDDB)", "%d", year);
+         if ( CDDB_CAT_INVALID != cddb_disc_get_category(p_cdda->cddb.disc) )
+           add_info_str("Disc", "Category (CDDB)",
+                        CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
           add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
+          add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
+         add_cddb_disc_info_str("Genre (CDDB)",  genre);
           add_cddb_disc_info_str("Title (CDDB)",  title);
-          add_info_str("Disc", "Category (CDDB)",
-                        CDDB_CATEGORY[p_cdda->cddb.disc->category]);
+         if ( 0 != cddb_disc_get_year(p_cdda->cddb.disc) ) 
+           add_cddb_disc_info_val("Year (CDDB)", "%d", year);
 
         }
 #endif /*HAVE_LIBCDDB*/
 
-        p_cdda->p_cdtext[0] = cdio_get_cdtext(p_cdda->p_cdio, 0);
         if (p_cdda->p_cdtext[0])
         {
+           char *psz_field;
+         
             add_cdtext_disc_info_str("Arranger (CD-Text)",    CDTEXT_ARRANGER);
             add_cdtext_disc_info_str("Composer (CD-Text)",    CDTEXT_COMPOSER);
             add_cdtext_disc_info_str("Disc ID (CD-Text)",     CDTEXT_DISCID);
@@ -307,23 +367,38 @@ void CDDAMetaInfo( access_t *p_access, int i_track )
             add_cdtext_disc_info_str("Performer (CD-Text)",   CDTEXT_PERFORMER);
             add_cdtext_disc_info_str("Songwriter (CD-Text)",  CDTEXT_SONGWRITER);
             add_cdtext_disc_info_str("Title (CD-Text)",       CDTEXT_TITLE);
+
+           psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
+           if (psz_field && strlen(psz_field)) {   
+             psz_meta_title = psz_field;
+           }
+           psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
+           if (psz_field && strlen(psz_field)) {   
+             psz_meta_artist = psz_field;
+           }
+           
         }
 
        for( i = 0 ; i < p_cdda->i_tracks ; i++ )
        {
          char psz_track[TITLE_MAX];
          const track_t i_track = i_first_track + i;
-         mtime_t i_duration = (p_cdda->lsn[i_track+1] -
-                               p_cdda->lsn[i_track])
-           / CDIO_CD_FRAMES_PER_SEC;
+         unsigned int i_track_frames = 
+           cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) - 
+           cdio_get_track_lsn(p_cdda->p_cdio, i_track);
+
+         mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
+         char *psz_mrl = CDDAFormatMRL( p_access, i_track );
+         
          snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
 
          input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
                         _("Duration"), "%s",
                         secstotimestr( psz_buffer, i_duration ) );
          
-         p_cdda->p_cdtext[i_track] =
-           cdio_get_cdtext(p_cdda->p_cdio, i_track);
+         input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
+                        _("MRL"), "%s", psz_mrl );
+         free(psz_mrl);
          
          if (p_cdda->p_cdtext[i_track])
            {
@@ -351,14 +426,44 @@ void CDDAMetaInfo( access_t *p_access, int i_track )
              cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
              if (t != NULL)
                {
-                 add_info_str(psz_track, "Artist (CDDB)", t->artist);
-                 add_info_str(psz_track, "Title (CDDB)",  t->title);
+                 add_info_str(psz_track, "Artist (CDDB)", 
+                              cddb_track_get_artist(t));
+                 add_info_str(psz_track, "Title (CDDB)",  
+                              cddb_track_get_title(t));
                  add_info_str(psz_track, "Extended Data (CDDB)",
-                              t->ext_data);
+                              cddb_track_get_ext_data(t));
                }
            }
 #endif /*HAVE_LIBCDDB*/
        }
+
+       /* Above we should have set psz_meta_title and psz_meta_artist
+          to CDDB or CD-Text values or the default value depending on
+          availablity and user preferences.
+
+          So now add the title and artist to VLC's meta, and the name
+          as shown in the status bar and playlist entry.
+
+          For playlist mode, the meta title is what's seen at the
+          bottom and in the playlist. For nav-mode playing, it is
+          done by input_control. I don't understand why they do
+          different things. In either case, we may have customized to
+          put in the track name.
+        */
+       if ( CDIO_INVALID_TRACK != i_track ) 
+       {
+           char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
+           if ( !p_cdda->b_nav_mode ) {
+               add_meta_val( VLC_META_TITLE, psz_name );
+           } else 
+           { 
+               input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
+               free(psz_name);
+           }
+           if (psz_meta_artist) 
+             add_meta_val( VLC_META_ARTIST, psz_meta_artist );
+       }
+       
     }
 }
 
@@ -412,6 +517,7 @@ cdda_data_t *p_cdda, char *psz_cdtext)
    %a : The album artist **
    %A : The album information **
    %C : Category **
+   %e : The extended track data
    %I : CDDB disk ID **
    %G : Genre **
    %M : The current MRL
@@ -419,18 +525,19 @@ cdda_data_t *p_cdda, char *psz_cdtext)
    %n : The number of tracks on the CD
    %p : The artist/performer/composer in the track **
    %T : The track number **
-   %s : Number of seconds in this track
-   %t : The name **
+   %s : Number of seconds in this track, or seconds in CD if invalid track
+   %S : Number of seconds on the CD
+   %t : The track name or MRL if no name 
    %Y : The year 19xx or 20xx **
    %% : a %
 */
-static char *
+char *
 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
-               const char format_str[], const char *mrl, track_t i_track)
+               const char format_str[], const char *psz_mrl, track_t i_track)
 {
 #define TEMP_STR_SIZE 256
 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
-    static char    temp_str[TEMP_STR_SIZE];
+    static char temp_str[TEMP_STR_SIZE];
     size_t i;
     char * tp = temp_str;
     vlc_bool_t saw_control_prefix = false;
@@ -460,57 +567,68 @@ CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
               break;
 #ifdef HAVE_LIBCDDB
             case 'a':
-               if (p_cdda->p_cdtext[0] 
-                   && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
-                 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
-               if (want_cddb_info(p_cdda, psz))
-                 psz = p_cdda->cddb.disc->artist;
+                if (p_cdda->p_cdtext[0]
+                    && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
+                  psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
+                if (want_cddb_info(p_cdda, psz))
+                  psz = (char *)cddb_disc_get_artist(p_cdda->cddb.disc);
                 goto format_str;
             case 'A':
-               if (p_cdda->p_cdtext[0] 
-                   && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
-                 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
+                if (p_cdda->p_cdtext[0]
+                    && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
+                  psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
                if (want_cddb_info(p_cdda, psz))
-                 psz =  p_cdda->cddb.disc->title;
+                 psz =  (char *)cddb_disc_get_title(p_cdda->cddb.disc);
                 goto format_str;
             case 'C':
                 if (!p_cdda->b_cddb_enabled) goto not_special;
                 if (p_cdda->cddb.disc)
-                    add_format_str_info(
-                                  CDDB_CATEGORY[p_cdda->cddb.disc->category]);
+                    add_format_str_info(CDDB_CATEGORY[cddb_disc_get_category(p_cdda->cddb.disc)]);
                 break;
             case 'G':
-               if (p_cdda->p_cdtext[0] 
-                   && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
-                 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
-               if (want_cddb_info(p_cdda, psz))
-                 psz = p_cdda->cddb.disc->genre;
-               goto format_str;
+                if (p_cdda->p_cdtext[0]
+                    && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
+                  psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
+                if (want_cddb_info(p_cdda, psz))
+                  psz = (char *)cddb_disc_get_genre(p_cdda->cddb.disc);
+                goto format_str;
             case 'I':
-               if (p_cdda->p_cdtext[0] 
-                   && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
-                 psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
-               if (want_cddb_info(p_cdda, psz)) {
-                     add_format_num_info(p_cdda->cddb.disc->discid, "%x");
-               } else if (psz)
-                    add_format_str_info(psz);
+                if (p_cdda->p_cdtext[0]
+                    && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
+                  psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
+                if (want_cddb_info(p_cdda, psz)) {
+                     add_format_num_info(cddb_disc_get_discid(p_cdda->cddb.disc), "%x");
+                } else if (psz)
+                     add_format_str_info(psz);
                 break;
             case 'Y':
                 if (!p_cdda->b_cddb_enabled) goto not_special;
                 if (p_cdda->cddb.disc)
-                    add_format_num_info(p_cdda->cddb.disc->year, "%5d");
+                    add_format_num_info(cddb_disc_get_year(p_cdda->cddb.disc), 
+                                       "%5d");
                 break;
             case 't':
+                if ( CDIO_INVALID_TRACK == i_track ) break;
                 if (p_cdda && p_cdda->b_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)
-                      add_format_str_info(t->title);
-                }
-                else goto not_special;
+                    if (t != NULL && cddb_track_get_title(t) != NULL) {
+                      add_format_str_info(cddb_track_get_title(t));
+                    } else {
+                      add_format_str_info(psz_mrl);
+                    }
+                } else {
+                  if (p_cdda->p_cdtext[i_track]
+                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]) {
+                   add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
+                 
+                 } else 
+                   add_format_str_info(psz_mrl);
+               }
                 break;
            case 'p':
+               if ( CDIO_INVALID_TRACK == i_track ) break;
                if (p_cdda->p_cdtext[i_track] 
                    && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
                  psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
@@ -518,11 +636,12 @@ CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
                  {
                    cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
                                                        i_track-1);
-                   if (t != NULL && t->artist != NULL)
-                     psz = t->artist;
+                   if (t != NULL && cddb_track_get_artist(t) != NULL)
+                     psz = (char *)cddb_track_get_artist(t);
                  }
                goto format_str;
             case 'e':
+               if ( CDIO_INVALID_TRACK == i_track ) break;
                if (p_cdda->p_cdtext[i_track] 
                    && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
                  psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
@@ -530,22 +649,11 @@ CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
                 {
                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
                                                         i_track-1);
-                    if (t != NULL && t->ext_data != NULL)
-                        psz = t->ext_data;
+                    if (t != NULL && cddb_track_get_ext_data(t) != NULL)
+                        psz = (char *)cddb_track_get_ext_data(t);
                 } 
                goto format_str;
                 break;
-            case 's':
-                if (p_cdda->b_cddb_enabled)
-                {
-                    char psz_buffer[MSTRTIME_MAX_SIZE];
-                    mtime_t i_duration = (p_cdda->lsn[i_track+1] -
-                                          p_cdda->lsn[i_track])
-                                          / CDIO_CD_FRAMES_PER_SEC;
-                    add_format_str_info(secstotimestr( psz_buffer,
-                                       i_duration ) );
-                } else goto not_special;
-                break;
 #else
             case 'a':
                if (p_cdda->p_cdtext[0] 
@@ -568,11 +676,21 @@ CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
                  add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
                 break;
            case 'p':
+               if ( CDIO_INVALID_TRACK == i_track ) break;
                if (p_cdda->p_cdtext[i_track] 
                    && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
                  psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
                goto format_str;
+            case 't':
+               if ( CDIO_INVALID_TRACK == i_track ) break;
+               if (p_cdda->p_cdtext[i_track] 
+                   && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
+                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
+               else 
+                   psz = psz_mrl;
+                goto format_str;
             case 'e':
+               if ( CDIO_INVALID_TRACK == i_track ) break;
                if (p_cdda->p_cdtext[i_track] 
                    && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
                  psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
@@ -580,8 +698,35 @@ CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
                 break;
 #endif /*HAVE_LIBCDDB*/
 
+            case 's':
+               if ( CDIO_INVALID_TRACK != i_track )
+                {
+                    char psz_buffer[MSTRTIME_MAX_SIZE];
+                   unsigned int i_track_frames = 
+                     cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
+                    mtime_t i_duration = 
+                     i_track_frames / CDIO_CD_FRAMES_PER_SEC;
+                    add_format_str_info( secstotimestr( psz_buffer, 
+                                                       i_duration ) );
+                   break;
+                }
+
+               /* Fall through to disc duration if CDIO_INVALID_TRACK  */
+            case 'S':
+                {
+                    char psz_buffer[MSTRTIME_MAX_SIZE];
+                   unsigned int i_track_frames = 
+                     cdio_get_track_lba(p_cdda->p_cdio, 
+                                        CDIO_CDROM_LEADOUT_TRACK);
+                    mtime_t i_duration = 
+                     i_track_frames / CDIO_CD_FRAMES_PER_SEC;
+                    add_format_str_info( secstotimestr( psz_buffer, 
+                                                       i_duration ) );
+                   break;
+                }
+
             case 'M':
-              add_format_str_info(mrl);
+              add_format_str_info(psz_mrl);
               break;
 
             case 'm':
@@ -611,95 +756,111 @@ CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
     return strdup(temp_str);
 }
 
+/* Return a MRL for the given track. The caller must free the 
+   allocated string. */
+static char *
+CDDAFormatMRL( const access_t *p_access, track_t i_track )
+{
+    cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
+    const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) 
+      + strlen(p_cdda->psz_source) +
+      + strlen("@T") + strlen("100") + 1;
+    char *psz_mrl = calloc( 1, psz_mrl_max );
+    
+    if (CDIO_INVALID_TRACK == i_track)
+      snprintf(psz_mrl, psz_mrl_max, "%s%s",
+              CDDA_MRL_PREFIX, p_cdda->psz_source);
+    else 
+      snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
+              CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
+    return psz_mrl;
+}
+
+
+/* Return a title string as specified by the titel format string for the 
+   given track. The caller must free the allocated string. */
+char *
+CDDAFormatTitle( const access_t *p_access, track_t i_track )
+{ 
+
+    char *config_varname = MODULE_STRING "-title-format";
+    cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
+    char *psz_mrl = CDDAFormatMRL( p_access, i_track );
+
+    if( psz_mrl ) 
+    {
+        char *psz_name;
+#ifdef HAVE_LIBCDDB
+       if (p_cdda->b_cddb_enabled)
+       {
+           config_varname = MODULE_STRING "-cddb-title-format";
+       }
+#endif /*HAVE_LIBCDDB*/
+       psz_name = 
+         CDDAFormatStr( p_access, p_cdda,
+                        config_GetPsz( p_access, config_varname ),
+                        psz_mrl, i_track );
+       free(psz_mrl);
+       return psz_name;
+    }
+    return(NULL);
+}
+
 /* Adds a string-valued entry to the playlist information under "Track"
    if the string is not null or the null string.
  */
 #define add_playlist_track_info_str(TITLE, FIELD)                        \
     if (FIELD && strlen(FIELD))                                          \
     {                                                                    \
-        playlist_ItemAddInfo( p_item, _("Track"), _(TITLE),              \
+        vlc_input_item_AddInfo( &p_item->input, _("Track"), _(TITLE),    \
                               "%s", FIELD);                              \
     }
 
-playlist_item_t *
+static playlist_item_t *
 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
                         playlist_t *p_playlist, playlist_item_t *p_item, 
-                        track_t i_track, char *psz_mrl, int psz_mrl_max,
-                        const char *psz_source )
+                        track_t i_track )
 {
-    mtime_t i_duration = (p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track])
-                         * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
-    char *psz_title;
-    char *config_varname = MODULE_STRING "-title-format";
+    unsigned int i_track_frames = 
+        cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) - 
+        cdio_get_track_lsn(p_cdda->p_cdio, i_track);
+    mtime_t i_mduration = i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
+    char *psz_title = NULL;
+    char *psz_mrl   = NULL;
 
     playlist_item_t *p_child = NULL;
 
-    if( !p_item )
-    {
-        return NULL;
-    }
+    if( !p_item ) return NULL;
 
-#ifdef HAVE_LIBCDDB
-    if (p_cdda->b_cddb_enabled)
-    {
-        config_varname = MODULE_STRING "-cddb-title-format";
-    }
-#endif /*HAVE_LIBCDDB*/
-
-
-    psz_title = CDDAFormatStr( p_access, p_cdda,
-                               config_GetPsz( p_access, config_varname ),
-                               psz_mrl, i_track);
-
-    snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
-             CDDA_MRL_PREFIX, psz_source, i_track);
+    psz_title = CDDAFormatTitle( p_access, i_track ) ;
+    psz_mrl = CDDAFormatMRL( p_access, i_track  ) ;
 
     dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
-               psz_mrl, psz_title, (long int) i_duration / 1000000 );
+               psz_mrl, psz_title, (long int) i_mduration / 1000000 );
 
     p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
-    p_child->input.b_fixed_name = VLC_TRUE;
+    p_child->p_input->i_duration = (mtime_t) i_mduration;
+    free(psz_mrl);
+    free(psz_title);
 
     if( !p_child ) return NULL;
-
+#if 0
     playlist_NodeAddItem( p_playlist, p_child,
-                          p_item->pp_parents[0]->i_view,
+                          p_item->p_parent->i_view,
                           p_item, PLAYLIST_APPEND, PLAYLIST_END );
     playlist_CopyParents( p_item, p_child );
-
+#endif
     return p_child;
 }
 
 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
-                       playlist_item_t *p_item, const char *psz_source,
-                       int i_track, vlc_bool_t b_single )
+                       playlist_item_t *p_item, int i_track,
+                       vlc_bool_t b_single )
 {
-    vlc_mutex_lock( &p_item->input.lock );
-
-    add_playlist_track_info_str("Source",  psz_source);
-    playlist_ItemAddInfo( p_item, _("Track"), _("Track Number"),
-                          "%d", i_track );
-
-    if (p_cdda->p_cdtext[0])
-    {
-        const cdtext_t *p = p_cdda->p_cdtext[0];
-        add_playlist_track_info_str("Disc Arranger (CD-Text)",
-                                     p->field[CDTEXT_ARRANGER]);
-        add_playlist_track_info_str("Disc Composer (CD-Text)",
-                                    p->field[CDTEXT_COMPOSER]);
-        add_playlist_track_info_str("Disc ID (CD-Text)",
-                                    p->field[CDTEXT_DISCID]);
-        add_playlist_track_info_str("Disc Genre (CD-Text)",
-                                    p->field[CDTEXT_GENRE]);
-        add_playlist_track_info_str("Disc Message (CD-Text)",
-                                    p->field[CDTEXT_MESSAGE]);
-        add_playlist_track_info_str("Disc Performer (CD-Text)",
-                                    p->field[CDTEXT_PERFORMER]);
-        add_playlist_track_info_str("Disc Songwriter (CD-Text)",
-                                    p->field[CDTEXT_SONGWRITER]);
-        add_playlist_track_info_str("Disc Title (CD-Text)",
-                                    p->field[CDTEXT_TITLE]);
-    }
+#if 0
+    add_playlist_track_info_str("Source",  p_cdda->psz_source);
+    vlc_input_item_AddInfo( &p_item->input, _("Track"), _("Track Number"),
+                           "%d", i_track );
 
     if (p_cdda->p_cdtext[i_track])
     {
@@ -726,55 +887,37 @@ int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
                                             i_track-p_cdda->i_first_track);
 
-        add_playlist_track_info_str("Disc Album (CDDB)",
-                                    p_cdda->cddb.disc->title);
-        add_playlist_track_info_str("Disc Artist(s) (CDDB)",
-                                    p_cdda->cddb.disc->artist);
-        add_playlist_track_info_str("Disc Category (CDDB)",
-                                    CDDB_CATEGORY[p_cdda->cddb.disc->category]);
-        add_playlist_track_info_str("Disc Genre (CDDB)",
-                                    p_cdda->cddb.disc->genre);
-
-        if ( p_cdda->cddb.disc->discid )
-        {
-            playlist_ItemAddInfo( p_item, _("Track"), _("Disc ID (CDDB)"),
-                                  "%x", p_cdda->cddb.disc->discid );
-        }
-        if (p_cdda->cddb.disc->year != 0)
-        {
-            playlist_ItemAddInfo( p_item, _("Track"), _("Year (CDDB)"),
-                                 "%5d", p_cdda->cddb.disc->year );
-        }
-
         if (t)
         {
-            if (t->artist)
-                add_playlist_track_info_str("Track Artist (CDDB)",
-                                             t->artist);
-           if (t->title)
-                add_playlist_track_info_str("Track Title (CDDB)",
-                                            t->title);
+            if (cddb_track_get_artist(t))
+                add_playlist_track_info_str("Artist (CDDB)",
+                                             cddb_track_get_artist(t));
+            if (cddb_track_get_title(t))
+                add_playlist_track_info_str("Title (CDDB)",
+                                            cddb_track_get_title(t));
+            if (cddb_track_get_ext_data(t))
+                add_playlist_track_info_str("Extended information (CDDB)",
+                                            cddb_track_get_ext_data(t));
         }
     }
 #endif /*HAVE_LIBCDDB*/
-
-    vlc_mutex_unlock( &p_item->input.lock );
-
+#endif
     return VLC_SUCCESS;
 }
 
+/* 
+   Fixes up playlist. 
+*/
 int
-CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
-                   const char *psz_source, vlc_bool_t b_single_track )
+CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda, 
+                   vlc_bool_t b_single_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;
+    playlist_t * p_playlist = NULL;
     const track_t i_first_track = p_cdda->i_first_track;
-    playlist_item_t *p_item;
+    playlist_item_t *p_item = NULL;
     vlc_bool_t b_play = VLC_FALSE;
+    track_t    i_track;
 
 #ifdef HAVE_LIBCDDB
     p_cdda->b_cddb_enabled =
@@ -786,104 +929,126 @@ CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
         return VLC_SUCCESS;
 #endif
 
-    psz_mrl = malloc( psz_mrl_max );
-
-    if( psz_mrl == NULL )
-    {
-        msg_Warn( p_access, "out of memory" );
-        return VLC_ENOMEM;
+    if (! p_cdda->b_nav_mode ) {
+        p_playlist = (playlist_t *) vlc_object_find( p_access, 
+                                                    VLC_OBJECT_PLAYLIST,
+                                                    FIND_ANYWHERE );
+       if( !p_playlist )
+         {
+             msg_Warn( p_access, "can't find playlist" );
+             return VLC_EGENERIC;
+         }
     }
 
-    p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
-                                               FIND_ANYWHERE );
-    if( !p_playlist )
-    {
-        msg_Warn( p_access, "can't find playlist" );
-        free(psz_mrl);
-        return VLC_EGENERIC;
-    }
-
-    if( b_single_track )
-    {
-        CDDAMetaInfo( p_access, p_cdda->i_track );
+    if( b_single_track || p_cdda->b_nav_mode ) {
+        i_track = p_cdda->i_track;
     }
     else
     {
-        CDDAMetaInfo( p_access, -1 );
+        i_track = CDIO_INVALID_TRACK;
     }
+    CDDAMetaInfoInit( p_access );
+    CDDAMetaInfo( p_access, p_cdda->i_track );
+
+    if (p_playlist) {
 
-    p_item = playlist_ItemGetByInput( p_playlist,
+      p_item = playlist_LockItemGetByInput( p_playlist,
                         ((input_thread_t *)p_access->p_parent)->input.p_item );
 
-    if( p_item == p_playlist->status.p_item && !b_single_track )
-    {
-        b_play = VLC_TRUE;
-    }
-    else
-    {
-        b_play = VLC_FALSE;
+      if( p_item == p_playlist->status.p_item && !b_single_track )
+       {
+         b_play = VLC_TRUE;
+       }
+      else
+       {
+         b_play = VLC_FALSE;
+       }
     }
 
-    if( b_single_track )
+    if( b_single_track && !p_cdda->b_nav_mode )
     {
         /*May fill out more information when the playlist user interface becomes
            more mature.
          */
         track_t i_track = p_cdda->i_track;
-
+       unsigned int i_track_frames = 
+         cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
+       
         input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
         vlc_input_title_New();
 
         asprintf( &t->psz_name, _("Track %i"), i_track );
-        t->i_size = p_access->info.i_size =
-                  ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) *
-                             (int64_t) CDIO_CD_FRAMESIZE_RAW;
+        t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
 
         t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
 
-
-        CDDAAddMetaToItem( p_access, p_cdda, p_item, psz_source, i_track,
-                           VLC_FALSE );
-
+       if( p_item ) 
+       {
+           CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
+           p_item->p_input->i_duration = (mtime_t) i_track_frames 
+             * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
+           p_item->p_input->psz_uri = CDDAFormatMRL( p_access, i_track );
+       }
+       
         p_cdda->i_titles = 1;
+       p_access->info.i_update = INPUT_UPDATE_TITLE;
     }
     else
     {
-        playlist_ItemToNode( p_playlist, p_item );
+       input_title_t *t;
+
+       if ( !p_cdda->b_nav_mode )
+         playlist_ItemToNode( p_playlist, p_item );
+
         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
         {
             playlist_item_t *p_child;
             const track_t i_track = i_first_track + i;
-            input_title_t *t = p_cdda->p_title[i] = vlc_input_title_New();
+           unsigned int i_track_frames = 
+             cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
+
+            t = p_cdda->p_title[i] = vlc_input_title_New();
 
             asprintf( &t->psz_name, _("Track %i"), i_track );
-            t->i_size = ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) *
-                          (int64_t) CDIO_CD_FRAMESIZE_RAW;
+            t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
 
-            t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
+            t->i_length = I64C(1000000) * t->i_size 
+             / CDDA_FREQUENCY_SAMPLE / 4;
 
-            p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
-                                              p_item,
-                                              i_track, psz_mrl,
-                                              psz_mrl_max, psz_source );
-            CDDAAddMetaToItem( p_access, p_cdda, p_child, psz_source,
-                               i_track, VLC_TRUE );
+           if ( ! p_cdda->b_nav_mode ) {
+             p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
+                                               p_item,
+                                               i_track );
+             CDDAAddMetaToItem( p_access, p_cdda, p_child, i_track, 
+                                VLC_TRUE );
+           }
         }
-        p_cdda->i_titles = p_cdda->i_tracks; /* should be +1 */
-        p_access->info.i_size =
-               (p_cdda->lsn[i_first_track + p_cdda->i_tracks]
-               - p_cdda->lsn[i_first_track]) * (int64_t) CDIO_CD_FRAMESIZE_RAW;
+
+        p_cdda->i_titles = p_cdda->i_tracks;
+       p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
+       if( p_item )
+        {
+           p_item->p_input->i_duration = (mtime_t)
+             p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
+           p_item->p_input->psz_uri    = CDDAFormatMRL( p_access, p_cdda->i_track );
+       }
     }
+    
 
     if( b_play )
     {
-        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
-                          p_playlist->status.i_view,
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, 0,
                           p_playlist->status.p_item, NULL );
     }
 
-    vlc_object_release( p_playlist );
-
+    if (p_playlist) vlc_object_release( p_playlist );
     return VLC_SUCCESS;
 }
 
+
+/* 
+ * Local variables:
+ *  mode: C
+ *  style: gnu
+ * End:
+ */