]> git.sesse.net Git - vlc/blobdiff - modules/access/cdda/info.c
Backport 13132
[vlc] / modules / access / cdda / info.c
index 2a396fc927c412aa4a21a730e5b28898adcd5227..9d6138a660d9dd3e5d9b4ce0202a55528d101ad5 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * info.c : CD digital audio input information routines
  *****************************************************************************
- * Copyright (C) 2004 VideoLAN
+ * Copyright (C) 2004, 2005 the VideoLAN team
  * $Id: info.c 8845 2004-09-29 09:00:41Z rocky $
  *
  * Authors: Rocky Bernstein <rocky@panix.com>
@@ -42,6 +42,8 @@ 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
 
 #define free_and_dup(var, val) \
@@ -55,7 +57,7 @@ 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), "" );
 
@@ -114,13 +116,14 @@ 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))
     {
@@ -228,6 +231,9 @@ CDDAMetaInfoInit( access_t *p_access )
     
     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);
     p_cdda->p_meta = vlc_meta_New();
 
@@ -259,26 +265,21 @@ CDDAMetaInfoInit( access_t *p_access )
  CD.
  */
 void 
-CDDAMetaInfo( access_t *p_access, track_t i_track, /*const*/ char *psz_mrl )
+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 = psz_mrl;
+    char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
     char *psz_meta_artist = NULL;
-    char *psz_name = NULL;
-    char *config_varname = MODULE_STRING "-title-format";
     
     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 (p_cdda->b_cddb_enabled)
-       {
-           config_varname = MODULE_STRING "-cddb-title-format";
-       }
-
         if( CDIO_INVALID_TRACK == i_track )
        {
 
@@ -294,7 +295,7 @@ CDDAMetaInfo( access_t *p_access, track_t i_track, /*const*/ char *psz_mrl )
          cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
          if (t != NULL )
          {
-             if( t->title != NULL )
+             if( t->title != NULL && ! p_cdda->b_nav_mode )
              {
                  add_meta_val( VLC_META_TITLE, t->title );
              }
@@ -384,7 +385,7 @@ CDDAMetaInfo( access_t *p_access, track_t i_track, /*const*/ char *psz_mrl )
            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;
+         char *psz_mrl = CDDAFormatMRL( p_access, i_track );
          
          snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
 
@@ -392,9 +393,6 @@ CDDAMetaInfo( access_t *p_access, track_t i_track, /*const*/ char *psz_mrl )
                         _("Duration"), "%s",
                         secstotimestr( psz_buffer, i_duration ) );
          
-         asprintf(&psz_mrl, "%s%s@T%u",
-                  CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
-
          input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
                         _("MRL"), "%s", psz_mrl );
          free(psz_mrl);
@@ -436,26 +434,31 @@ CDDAMetaInfo( access_t *p_access, track_t i_track, /*const*/ char *psz_mrl )
 
        /* 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. 
+          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.
 
-          We also set above config_varname to the format used
-          
-          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.
         */
-       add_meta_val( VLC_META_TITLE, psz_meta_title );
-       if (psz_meta_artist) 
-         add_meta_val( VLC_META_ARTIST, psz_meta_artist );
-
-       if ( CDIO_INVALID_TRACK != i_track )
-       { 
-           psz_name = 
-             CDDAFormatStr( p_access, p_cdda,
-                            config_GetPsz( p_access, config_varname ),
-                            psz_mrl, i_track );
-           
-           input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_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 );
        }
+       
     }
 }
 
@@ -509,6 +512,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
@@ -522,7 +526,7 @@ cdda_data_t *p_cdda, char *psz_cdtext)
    %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 *psz_mrl, track_t i_track)
 {
@@ -558,16 +562,16 @@ 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 = p_cdda->cddb.disc->artist;
                 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;
                 goto format_str;
@@ -578,20 +582,20 @@ CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
                                   CDDB_CATEGORY[p_cdda->cddb.disc->category]);
                 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 = p_cdda->cddb.disc->genre;
+                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)) {
+                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);
+                } else if (psz)
+                     add_format_str_info(psz);
                 break;
             case 'Y':
                 if (!p_cdda->b_cddb_enabled) goto not_special;
@@ -599,18 +603,18 @@ CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
                     add_format_num_info(p_cdda->cddb.disc->year, "%5d");
                 break;
             case 't':
-               if ( CDIO_INVALID_TRACK == i_track ) break;
+                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 {
+                    } else {
                       add_format_str_info(psz_mrl);
-                   }
+                    }
                 } else {
-                 if (p_cdda->p_cdtext[i_track] 
+                  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]);
                  
@@ -694,8 +698,7 @@ CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
                 {
                     char psz_buffer[MSTRTIME_MAX_SIZE];
                    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);
+                     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, 
@@ -748,56 +751,93 @@ 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 )
+                        track_t i_track )
 {
   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;
-    char *config_varname = MODULE_STRING "-title-format";
+    char *psz_title = NULL;
+    char *psz_mrl   = NULL;
 
     playlist_item_t *p_child = 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*/
-
-
-    snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
-             CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
+    if( !p_item ) return NULL;
 
-    psz_title = CDDAFormatStr( p_access, p_cdda,
-                               config_GetPsz( p_access, config_varname ),
-                               psz_mrl, 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_mduration / 1000000 );
 
     p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
     p_child->input.i_duration   = i_mduration;
+    free(psz_mrl);
+    free(psz_title);
 
     if( !p_child ) return NULL;
 
@@ -810,14 +850,12 @@ CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
 }
 
 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
-                       playlist_item_t *p_item, 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",  p_cdda->psz_source);
-    playlist_ItemAddInfo( p_item, _("Track"), _("Track Number"),
-                          "%d", i_track );
+    vlc_input_item_AddInfo( &p_item->input, _("Track"), _("Track Number"),
+                           "%d", i_track );
 
     if (p_cdda->p_cdtext[i_track])
     {
@@ -849,34 +887,32 @@ int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
             if (t->artist)
                 add_playlist_track_info_str("Artist (CDDB)",
                                              t->artist);
-           if (t->title)
+            if (t->title)
                 add_playlist_track_info_str("Title (CDDB)",
                                             t->title);
-           if (t->ext_data)
+            if (t->ext_data)
                 add_playlist_track_info_str("Extended information (CDDB)",
                                             t->ext_data);
         }
     }
 #endif /*HAVE_LIBCDDB*/
 
-    vlc_mutex_unlock( &p_item->input.lock );
-
     return VLC_SUCCESS;
 }
 
+/* 
+   Fixes up playlist. 
+*/
 int
 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 = NULL;
-    unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) 
-      + strlen(p_cdda->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 =
@@ -888,115 +924,112 @@ 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;
-    }
-
-    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 (! 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;
+         }
     }
 
-    if( b_single_track )
-    {
-        snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u", CDDA_MRL_PREFIX, 
-                p_cdda->psz_source, p_cdda->i_track);
-        CDDAMetaInfoInit( p_access );
-        CDDAMetaInfo( p_access, p_cdda->i_track, psz_mrl );
+    if( b_single_track || p_cdda->b_nav_mode ) {
+        i_track = p_cdda->i_track;
     }
     else
     {
-        snprintf(psz_mrl, psz_mrl_max, "%s%s", CDDA_MRL_PREFIX, 
-                p_cdda->psz_source);
-        CDDAMetaInfoInit( p_access );
-        CDDAMetaInfo( p_access, CDIO_INVALID_TRACK, psz_mrl );
+        i_track = CDIO_INVALID_TRACK;
     }
+    CDDAMetaInfoInit( p_access );
+    CDDAMetaInfo( p_access, p_cdda->i_track );
 
-    p_item = playlist_ItemGetByInput( p_playlist,
+    if (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_lsn(p_cdda->p_cdio, i_track+1) - 
-         cdio_get_track_lsn(p_cdda->p_cdio, i_track);
+         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 = 
-         i_track_frames * (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, i_track, VLC_FALSE );
-
+       if (p_item) 
+       {
+           CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
+           p_item->input.i_duration = i_track_frames 
+             * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
+           p_item->input.psz_uri    = CDDAFormatMRL(p_access, i_track);
+       }
+       
         p_cdda->i_titles = 1;
-        p_access->info.i_size =
-         i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
-       p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
-       p_item->input.psz_uri    = strdup(psz_mrl);
-       p_item->input.i_duration = i_track_frames 
-         * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
+       p_access->info.i_update = INPUT_UPDATE_TITLE;
     }
     else
     {
-        input_title_t *t;
-        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;
            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);
+             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 = 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 ) ;
-            CDDAAddMetaToItem( p_access, p_cdda, p_child, 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;
-        p_access->info.i_size = 
-         cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK)
-         * (int64_t) CDIO_CD_FRAMESIZE_RAW;
        p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
-       p_item->input.i_duration = 
-         p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
-       p_item->input.psz_uri    = strdup(psz_mrl);
+       if (p_item) {
+           p_item->input.i_duration = 
+             p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
+           p_item->input.psz_uri    = CDDAFormatMRL(p_access, 
+                                                    p_cdda->i_track);
+       }
     }
+    
 
     if( b_play )
     {
@@ -1005,8 +1038,7 @@ CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
                           p_playlist->status.p_item, NULL );
     }
 
-    vlc_object_release( p_playlist );
-
+    if (p_playlist) vlc_object_release( p_playlist );
     return VLC_SUCCESS;
 }