]> git.sesse.net Git - vlc/blob - modules/access/cdda/access.c
Fill in playlist information and stream & media information
[vlc] / modules / access / cdda / access.c
1 /*****************************************************************************
2  * cddax.c : CD digital audio input module for vlc using libcdio
3  *****************************************************************************
4  * Copyright (C) 2000, 2003, 2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Rocky Bernstein <rocky@panix.com>
8  *          Laurent Aimar <fenrir@via.ecp.fr>
9  *          Gildas Bazin <gbazin@netcourrier.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include "callback.h"      /* FIXME - reorganize callback.h, cdda.h better */
30 #include "cdda.h"          /* private structures. Also #includes vlc things */
31 #include <vlc_playlist.h>  /* Has to come *after* cdda.h */
32 #include "vlc_keys.h"
33
34 #include <cdio/cdio.h>
35 #include <cdio/logging.h>
36 #include <cdio/cd_types.h>
37
38 #include <stdio.h>
39
40 /* #ifdef variables below are defined via config.h via #include vlc above. */
41 #ifdef HAVE_STDLIB_H
42 #include <stdlib.h>
43 #endif
44
45 #ifdef HAVE_SYS_TYPES_H
46 #include <sys/types.h>
47 #endif
48
49 #ifdef HAVE_STRING_H
50 #include <string.h>
51 #endif
52
53 #ifdef HAVE_UNISTD_H
54 #   include <unistd.h>
55 #endif
56
57 #ifdef HAVE_ERRNO_H
58 #   include <errno.h>
59 #endif
60
61 #define CDDA_MRL_PREFIX "cddax://"
62
63 /* Frequency of sample in bits per second. */
64 #define CDDA_FREQUENCY_SAMPLE 44100
65
66 /* FIXME: This variable is a hack. Would be nice to eliminate. */
67 access_t *p_cdda_input = NULL;
68
69 /*****************************************************************************
70  * Local prototypes
71  *****************************************************************************/
72 static block_t *CDDAReadBlocks( access_t * p_access );
73 static int      CDDASeek( access_t * p_access, int64_t i_pos );
74 static int      CDDAControl( access_t *p_access, int i_query, 
75                              va_list args );
76 static void     CDDAMetaInfo( access_t *p_access  );
77 static int      CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda, 
78                                    const char *psz_source, 
79                                    vlc_bool_t b_single_track );
80 static void     CDDACreatePlaylistItem(const access_t *p_access, 
81                                        cdda_data_t *p_cdda,
82                                        playlist_t *p_playlist, 
83                                        track_t i_track,
84                                        char *psz_mrl, int psz_mrl_max,
85                                        const char *psz_source, 
86                                        int playlist_operation,
87                                        int i_pos);
88
89 static int      GetCDInfo( access_t *p_access, cdda_data_t *p_cdda ) ;
90
91
92
93
94 /****************************************************************************
95  * Private functions
96  ****************************************************************************/
97
98 /* process messages that originate from libcdio. */
99 static void
100 cdio_log_handler (cdio_log_level_t level, const char message[])
101 {
102   cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
103
104   if( p_cdda == NULL )
105       return;
106
107   switch (level) {
108   case CDIO_LOG_DEBUG:
109   case CDIO_LOG_INFO:
110     if (p_cdda->i_debug & INPUT_DBG_CDIO)
111       msg_Dbg( p_cdda_input, message);
112     break;
113   case CDIO_LOG_WARN:
114     msg_Warn( p_cdda_input, message);
115     break;
116   case CDIO_LOG_ERROR:
117   case CDIO_LOG_ASSERT:
118     msg_Err( p_cdda_input, message);
119     break;
120   default:
121     msg_Warn( p_cdda_input, message,
122             "The above message had unknown cdio log level",
123             level);
124   }
125   return;
126 }
127
128
129 #ifdef HAVE_LIBCDDB
130 /*! This routine is called by libcddb routines on error.
131    Setup is done by init_input_plugin.
132 */
133 static void
134 cddb_log_handler (cddb_log_level_t level, const char message[])
135 {
136   cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
137   switch (level) {
138   case CDDB_LOG_DEBUG:
139   case CDDB_LOG_INFO:
140     if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return;
141     /* Fall through if to warn case */
142   default:
143     cdio_log_handler (level, message);
144   }
145 }
146 #endif /*HAVE_LIBCDDB*/
147
148
149 /*! This routine is when xine is not fully set up (before full initialization)
150    or is not around (before finalization).
151 */
152 static void
153 uninit_log_handler (cdio_log_level_t level, const char message[])
154 {
155   cdda_data_t *p_cdda = NULL;
156
157   if (p_cdda_input)
158     p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
159
160   switch (level) {
161   case CDIO_LOG_DEBUG:
162   case CDIO_LOG_INFO:
163     if (!p_cdda || !(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB)))
164       return;
165     /* Fall through if to warn case */
166   case CDIO_LOG_WARN:
167     fprintf(stderr, "WARN: %s\n", message);
168     break;
169   case CDIO_LOG_ERROR:
170     fprintf(stderr, "ERROR: %s\n", message);
171     break;
172   case CDIO_LOG_ASSERT:
173     fprintf(stderr, "ASSERT ERROR: %s\n", message);
174     break;
175   default:
176     fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n",
177             message,
178             "The above message had unknown cdio log level",
179             level);
180   }
181
182   /* gl_default_cdio_log_handler (level, message); */
183 }
184
185 /*****************************************************************************
186  * CDDAReadBlocks: reads a group of blocks from the CD-DA and returns
187  * an allocated pointer to the data. NULL is returned if no data
188  * read. It is also possible if we haven't read a RIFF header in which
189  * case one that we creaded during Open/Initialization is returned.
190  *****************************************************************************/
191 static block_t *
192 CDDAReadBlocks( access_t * p_access )
193 {
194     block_t     *p_block;
195     cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
196     int          i_blocks = p_cdda->i_blocks_per_read;
197
198     dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called %d", 
199               p_cdda->i_lsn);
200
201     /* Check end of file */
202     if( p_access->info.b_eof ) return NULL;
203
204     if( !p_cdda->b_header )
205       {
206         /* Return only the dummy RIFF header we created in Open/Init */
207         p_block = block_New( p_access, sizeof( WAVEHEADER ) );
208         memcpy( p_block->p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
209         p_cdda->b_header = VLC_TRUE;
210         return p_block;
211     }
212
213     /* Check end of track */
214     while( p_cdda->i_lsn >= p_cdda->p_lsns[p_access->info.i_title + 1] )
215     {
216         if( p_access->info.i_title + 1 >= p_cdda->i_tracks )
217         {
218             p_access->info.b_eof = VLC_TRUE;
219             return NULL;
220         }
221
222         p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE;
223         p_access->info.i_title++;
224         p_access->info.i_size = 
225           p_cdda->p_title[p_access->info.i_title]->i_size;
226         p_access->info.i_pos = 0;
227         p_cdda->i_track++;
228     }
229
230     /* Possibly adjust i_blocks so we don't read past the end of a track. */
231     if( p_cdda->i_lsn + i_blocks >=
232         p_cdda->p_lsns[p_access->info.i_title + 1] )
233     {
234         i_blocks = p_cdda->p_lsns[p_access->info.i_title + 1 ] -
235                    p_cdda->i_lsn;
236     }
237
238     /* Do the actual reading */
239     p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW );
240     if( !p_block)
241     {
242       msg_Err( p_access, "Cannot get a new block of size: %i",
243                i_blocks * CDIO_CD_FRAMESIZE_RAW );
244       return NULL;
245     }
246
247     if( cdio_read_audio_sectors( p_cdda->p_cdio, p_block->p_buffer,
248                                  p_cdda->i_lsn, i_blocks) != 0 )
249         {
250           msg_Err( p_access, "could not read sector %lu",
251                    (long unsigned int) p_cdda->i_lsn );
252           block_Release( p_block );
253
254           /* If we had problems above, assume the problem is with
255              the first sector of the read and set to skip it.  In
256              the future libcdio may have cdparanoia support.
257           */
258           p_cdda->i_lsn++;
259           p_access->info.i_pos += CDIO_CD_FRAMESIZE_RAW;
260           return NULL;
261         }
262     
263     p_cdda->i_lsn     += i_blocks;
264     p_access->info.i_pos += p_block->i_buffer;
265
266     return p_block;
267 }
268
269 /****************************************************************************
270  * CDDASeek - change position for subsequent reads. For example, this
271  * can happen if the user moves a position slider bar in a GUI.
272  ****************************************************************************/
273 static int 
274 CDDASeek( access_t * p_access, int64_t i_pos )
275 {
276     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
277
278     p_cdda->i_lsn = p_cdda->p_lsns[p_access->info.i_title]
279                   + (i_pos / CDIO_CD_FRAMESIZE_RAW);
280     p_access->info.i_pos = i_pos;
281
282     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
283                "lsn %lu, offset: %lld",  
284                (long unsigned int) p_cdda->i_lsn, i_pos );
285     return VLC_SUCCESS;
286 }
287
288 #ifdef HAVE_LIBCDDB
289
290 #define free_and_dup(var, val) \
291   if (var) free(var);          \
292   if (val) var=strdup(val);
293
294
295 static void
296 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
297 {
298
299   dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
300
301   if (config_GetInt( p_access, MODULE_STRING "-cddb-enabled" )) {
302     int i, i_matches;
303     cddb_conn_t  *conn = cddb_new();
304     const CdIo *p_cdio = p_cdda->p_cdio;
305
306
307     cddb_log_set_handler (uninit_log_handler);
308
309     if (!conn) {
310       msg_Warn( p_access, "Unable to initialize libcddb" );
311       goto cddb_destroy;
312     }
313
314     cddb_set_email_address( conn,
315                             config_GetPsz( p_access,
316                                            MODULE_STRING "-cddb-email") );
317
318     cddb_set_server_name( conn,
319                           config_GetPsz( p_access,
320                                          MODULE_STRING "-cddb-server") );
321
322     cddb_set_server_port(conn,
323                           config_GetInt( p_access,
324                                          MODULE_STRING "-cddb-port") );
325
326     /* Set the location of the local CDDB cache directory.
327        The default location of this directory is */
328
329     if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
330       cddb_cache_disable(conn);
331
332     cddb_cache_set_dir(conn,
333                        config_GetPsz( p_access,
334                                       MODULE_STRING "-cddb-cachedir") );
335
336     cddb_set_timeout(conn,
337                      config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
338
339
340     if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" )) {
341       cddb_http_enable(conn);
342     } else
343       cddb_http_disable(conn);
344
345     p_cdda->cddb.disc = cddb_disc_new();
346     if (!p_cdda->cddb.disc) {
347       msg_Err( p_access, "Unable to create CDDB disc structure." );
348       goto cddb_end;
349     }
350
351     p_cdda->psz_mcn = cdio_get_mcn(p_cdio);
352
353     for(i = 1; i <= p_cdda->i_tracks; i++) {
354       cddb_track_t *t = cddb_track_new();
355       t->frame_offset = cdio_get_track_lba(p_cdio, i);
356       cddb_disc_add_track(p_cdda->cddb.disc, t);
357     }
358
359     p_cdda->cddb.disc->length =
360       cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
361       / CDIO_CD_FRAMES_PER_SEC;
362
363     if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
364       msg_Err( p_access, "CDDB disc ID calculation failed" );
365       goto cddb_destroy;
366     }
367
368     i_matches = cddb_query(conn, p_cdda->cddb.disc);
369     if (i_matches > 0) {
370       if (i_matches > 1)
371         msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
372                   i_matches);
373       cddb_read(conn, p_cdda->cddb.disc);
374
375       if (p_cdda->i_debug & INPUT_DBG_CDDB)
376         cddb_disc_print(p_cdda->cddb.disc);
377
378     } else {
379       msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
380     }
381
382   cddb_destroy:
383     cddb_destroy(conn);
384   }
385   cddb_end: ;
386 }
387 #endif /*HAVE_LIBCDDB*/
388
389 #define add_meta_val(FIELD, VLC_META, VAL)                              \
390   if ( p_cdda->p_meta && VAL) {                                         \
391     vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL );                      \
392     dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL );       \
393   }                                                                     \
394     
395 #define add_cddb_meta(FIELD, VLC_META)                                  \
396   add_meta_val(FIELD, VLC_META, p_cdda->cddb.disc->FIELD);
397     
398 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META)                 \
399   {                                                                     \
400     char psz_buf[100];                                                  \
401     snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC,                  \
402               p_cdda->cddb.disc->FIELD );                               \
403     psz_buf[sizeof(psz_buf)-1] = '\0';                                  \
404     add_meta_val(FIELD, VLC_META, psz_buf);                             \
405   }    
406
407 /*
408  Gets and saves CDDA Meta Information. In the Control routine, 
409  we handle Meta Information requests and basically copy what we've
410  saved here. 
411  */    
412 static void CDDAMetaInfo( access_t *p_access  )
413 {
414   cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
415
416 #ifdef HAVE_LIBCDDB
417   if ( p_cdda && p_cdda->i_cddb_enabled ) {
418
419     GetCDDBInfo(p_access, p_cdda);
420
421     if ( p_cdda->cddb.disc ) {
422
423       p_cdda->p_meta = vlc_meta_New();
424
425       add_cddb_meta(title,    VLC_META_CDDB_TITLE);
426       add_cddb_meta(artist,   VLC_META_CDDB_ARTIST);
427       add_cddb_meta(genre,    VLC_META_CDDB_GENRE);
428       add_cddb_meta(ext_data, VLC_META_CDDB_EXT_DATA);
429
430       add_cddb_meta_fmt(year,   "%d", VLC_META_CDDB_YEAR);
431       add_cddb_meta_fmt(discid, "%x", VLC_META_CDDB_DISCID);
432     }
433   }
434
435 #endif /*HAVE_LIBCDDB*/
436 #define TITLE_MAX 30
437   
438 /* Adds a string-valued entry to the stream and media information if
439    the string is not null or the null string.
440  */
441 #define add_cddb_info_str(CATEGORY, TITLE, FIELD)                 \
442   if (FIELD && strlen(FIELD)) {                                   \
443     input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY,     \
444                    _(TITLE), "%s", FIELD );                       \
445   }  
446   
447 /* Adds a numeric-valued entry to the stream and media information */
448 #define add_cddb_info_val(CATEGORY, TITLE, FMT, FIELD)            \
449   if (FIELD) {                                                    \
450     input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY,     \
451                    _(TITLE), FMT, FIELD );                        \
452   }  
453
454 #define add_cddb_disc_info_str(TITLE, FIELD)                    \
455   add_cddb_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
456
457 #define add_cddb_disc_info_val(TITLE, FMT, FIELD)                   \
458   add_cddb_info_val("Disc", TITLE, FMT, p_cdda->cddb.disc->FIELD)
459
460 /*#if UPDATE_TRACK_INFORMATION_FINISHED*/
461 #if 1
462   {
463     track_t i_track = p_cdda->i_tracks;
464     char psz_buffer[MSTRTIME_MAX_SIZE];
465     mtime_t i_duration =
466       (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[0])
467       / CDIO_CD_FRAMES_PER_SEC;
468
469     dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
470     input_Control( p_cdda->p_input, INPUT_ADD_INFO, 
471                    _("Disc"), _("Duration"), "%s",
472                    secstotimestr( psz_buffer, i_duration ) );
473
474 #ifdef HAVE_LIBCDDB
475       if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
476         add_cddb_disc_info_str("Artist (CDDB)", artist);
477         add_cddb_disc_info_str("Genre (CDDB)",  genre);
478         add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
479         add_cddb_disc_info_val("Year (CDDB)", "%d", year);
480         add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
481         add_cddb_disc_info_str("Title (CDDB)",  title);
482         add_cddb_info_str("Disc", "Category (CDDB)",  
483                           CDDB_CATEGORY[p_cdda->cddb.disc->category]);
484       }
485 #endif /*HAVE_LIBCDDB*/
486
487     for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ ) {
488
489       char track_str[TITLE_MAX];
490       mtime_t i_duration =
491         (p_cdda->p_lsns[i_track+1] - p_cdda->p_lsns[i_track])
492         / CDIO_CD_FRAMES_PER_SEC;
493       snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
494       input_Control( p_cdda->p_input, INPUT_ADD_INFO, track_str, 
495                      _("Duration"), "%s", 
496                      secstotimestr( psz_buffer, i_duration ) );
497
498 #ifdef HAVE_LIBCDDB
499       if (p_cdda->i_cddb_enabled) {
500         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track);
501         if (t != NULL) {
502           add_cddb_info_str(track_str, "Artist (CDDB)", t->artist);
503           add_cddb_info_str(track_str, "Title (CDDB)",  t->title);
504           add_cddb_info_str(track_str, "Extended Data (CDDB)", t->ext_data);
505         }
506       }
507 #endif /*HAVE_LIBCDDB*/
508     }
509   }
510 #endif /* UPDATE_TRACK_INFORMATION_FINISHED */
511 }
512
513 #define add_format_str_info(val)                         \
514   {                                                      \
515     const char *str = val;                               \
516     unsigned int len;                                    \
517     if (val != NULL) {                                   \
518       len=strlen(str);                                   \
519       if (len != 0) {                                    \
520         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    \
521         tp += len;                                       \
522       }                                                  \
523       saw_control_prefix = false;                        \
524     }                                                    \
525   }
526
527 #define add_format_num_info(val, fmt)                    \
528   {                                                      \
529     char num_str[10];                                    \
530     unsigned int len;                                    \
531     sprintf(num_str, fmt, val);                          \
532     len=strlen(num_str);                                 \
533     if (len != 0) {                                      \
534       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  \
535       tp += len;                                         \
536     }                                                    \
537     saw_control_prefix = false;                          \
538   }
539
540 /*!
541    Take a format string and expand escape sequences, that is sequences that
542    begin with %, with information from the current CD.
543    The expanded string is returned. Here is a list of escape sequences:
544
545    %a : The album artist **
546    %A : The album information **
547    %C : Category **
548    %I : CDDB disk ID **
549    %G : Genre **
550    %M : The current MRL
551    %m : The CD-DA Media Catalog Number (MCN)
552    %n : The number of tracks on the CD
553    %p : The artist/performer/composer in the track **
554    %T : The track number **
555    %s : Number of seconds in this track
556    %t : The name **
557    %Y : The year 19xx or 20xx **
558    %% : a %
559 */
560 static char *
561 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
562                const char format_str[], const char *mrl, int i_track)
563 {
564 #define TEMP_STR_SIZE 256
565 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
566   static char    temp_str[TEMP_STR_SIZE];
567   size_t i;
568   char * tp = temp_str;
569   vlc_bool_t saw_control_prefix = false;
570   size_t format_len = strlen(format_str);
571
572   memset(temp_str, 0, TEMP_STR_SIZE);
573
574   for (i=0; i<format_len; i++) {
575
576     if (!saw_control_prefix && format_str[i] != '%') {
577       *tp++ = format_str[i];
578       saw_control_prefix = false;
579       continue;
580     }
581
582     switch(format_str[i]) {
583     case '%':
584       if (saw_control_prefix) {
585         *tp++ = '%';
586       }
587       saw_control_prefix = !saw_control_prefix;
588       break;
589 #ifdef HAVE_LIBCDDB
590     case 'a':
591       if (!p_cdda->i_cddb_enabled) goto not_special;
592       if (p_cdda->cddb.disc)
593         add_format_str_info(p_cdda->cddb.disc->artist);
594       break;
595     case 'A':
596       if (!p_cdda->i_cddb_enabled) goto not_special;
597       if (p_cdda->cddb.disc)
598         add_format_str_info(p_cdda->cddb.disc->title);
599       break;
600     case 'C':
601       if (!p_cdda->i_cddb_enabled) goto not_special;
602       if (p_cdda->cddb.disc)
603         add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
604       break;
605     case 'G':
606       if (!p_cdda->i_cddb_enabled) goto not_special;
607       if (p_cdda->cddb.disc)
608         add_format_str_info(p_cdda->cddb.disc->genre);
609       break;
610     case 'I':
611       if (!p_cdda->i_cddb_enabled) goto not_special;
612       if (p_cdda->cddb.disc)
613         add_format_num_info(p_cdda->cddb.disc->discid, "%x");
614       break;
615     case 'Y':
616       if (!p_cdda->i_cddb_enabled) goto not_special;
617       if (p_cdda->cddb.disc)
618         add_format_num_info(p_cdda->cddb.disc->year, "%5d");
619       break;
620     case 't':
621       if (p_cdda && p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
622         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
623                                             i_track-1);
624         if (t != NULL && t->title != NULL)
625           add_format_str_info(t->title);
626       } else goto not_special;
627       break;
628     case 'p':
629       if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
630         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
631                                             i_track-1);
632         if (t != NULL && t->artist != NULL)
633           add_format_str_info(t->artist);
634       } else goto not_special;
635       break;
636     case 'e':
637       if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
638         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
639                                             i_track-1);
640         if (t != NULL && t->ext_data != NULL)
641           add_format_str_info(t->ext_data);
642       } else goto not_special;
643       break;
644 #endif
645
646     case 'M':
647       add_format_str_info(mrl);
648       break;
649
650     case 'm':
651       add_format_str_info(p_cdda->psz_mcn);
652       break;
653
654     case 'n':
655       add_format_num_info(p_cdda->i_tracks, "%d");
656       break;
657
658     case 's':
659       if (p_cdda->i_cddb_enabled) {
660         char psz_buffer[MSTRTIME_MAX_SIZE];
661         mtime_t i_duration =
662           (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
663           / CDIO_CD_FRAMES_PER_SEC;
664         add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
665       } else goto not_special;
666       break;
667
668     case 'T':
669       add_format_num_info(i_track, "%02d");
670       break;
671 #ifdef HAVE_LIBCDDB
672     not_special:
673 #endif
674     default:
675       *tp++ = '%';
676       *tp++ = format_str[i];
677       saw_control_prefix = false;
678     }
679   }
680   return strdup(temp_str);
681 }
682
683 /* Adds a string-valued entry to the playlist information under "Disc"
684    if the string is not null or the null string.
685  */
686 #define add_playlist_disc_info_str(TITLE, FIELD)                  \
687   if (FIELD && strlen(FIELD)) {                                   \
688     playlist_ItemAddInfo( p_item, _("Disc"), _(TITLE),            \
689                           "%s", FIELD);                           \
690   }  
691
692 static void
693 CDDACreatePlaylistItem(const access_t *p_access, cdda_data_t *p_cdda,
694                        playlist_t *p_playlist, track_t i_track,
695                        char *psz_mrl, int psz_mrl_max,
696                        const char *psz_source, int playlist_operation,
697                        int i_pos)
698 {
699   mtime_t i_duration =
700     (p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1])
701     * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
702   char *psz_disc_info;
703   char *psz_title;
704   char *config_varname = MODULE_STRING "-title-format";
705   playlist_item_t *p_item;
706
707 #ifdef HAVE_LIBCDDB
708   if (p_cdda->i_cddb_enabled) {
709     config_varname = MODULE_STRING "-cddb-title-format";
710   }
711 #endif /*HAVE_LIBCDDB*/
712
713   snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
714            CDDA_MRL_PREFIX, psz_source, i_track);
715
716   psz_title = CDDAFormatStr(p_access, p_cdda,
717                             config_GetPsz( p_access, config_varname ),
718                             psz_mrl, i_track);
719
720   dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
721              psz_mrl, psz_title, (long int) i_duration / 1000000 , i_pos );
722   playlist_AddExt( p_playlist, psz_mrl, psz_title, playlist_operation,
723                          i_pos, i_duration , NULL, 0);
724
725   if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
726
727   vlc_mutex_lock( &p_playlist->object_lock );
728   p_item = playlist_ItemGetByPos( p_playlist, i_pos );
729   vlc_mutex_unlock( &p_playlist->object_lock );
730   if( !p_item )
731       return;
732
733   vlc_mutex_lock( &p_item->input.lock );
734
735   psz_disc_info =
736     CDDAFormatStr( p_access, p_cdda,
737                    config_GetPsz( p_access, MODULE_STRING "-title-format" ),
738                    psz_mrl, i_track );
739
740   playlist_ItemAddInfo( p_item ,  _("Disc"),_("Title"), psz_disc_info);
741
742 #ifdef HAVE_LIBCDDB
743   if (p_cdda->i_cddb_enabled) {
744     const char *psz_general_cat = _("Disc");
745     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
746
747     add_playlist_disc_info_str("Disc Album (CDDB)",
748                                p_cdda->cddb.disc->title);
749     add_playlist_disc_info_str("Disc Artist(s) (CDDB)", 
750                                p_cdda->cddb.disc->artist);
751     add_playlist_disc_info_str("Disc Category (CDDB)", 
752                                CDDB_CATEGORY[p_cdda->cddb.disc->category]);
753     add_playlist_disc_info_str("Disc Genre (CDDB)", 
754                                p_cdda->cddb.disc->genre);
755     if ( p_cdda->cddb.disc->discid ) {
756       playlist_ItemAddInfo( p_item, psz_general_cat, _("Disc ID (CDDB)"),
757                             "%x", p_cdda->cddb.disc->discid );
758     }
759     if (p_cdda->cddb.disc->year != 0) {
760       playlist_ItemAddInfo( p_item, psz_general_cat,
761                             _("Year"), "%5d", p_cdda->cddb.disc->year );
762     }
763     
764     if (t) {
765       if (t->artist)
766         add_playlist_disc_info_str("Track Artist (CDDB)", 
767                                    t->artist);
768       if (t->title)
769         add_playlist_disc_info_str("Track Title (CDDB)", 
770                                    t->title);
771     }
772   }
773 #endif /*HAVE_LIBCDDB*/
774
775   vlc_mutex_unlock( &p_item->input.lock );
776 }
777
778 static int
779 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda, 
780                    const char *psz_source, vlc_bool_t b_single_track )
781 {
782   int i;
783   playlist_t * p_playlist;
784   char       * psz_mrl;
785   unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
786     strlen("@T") + strlen("100") + 1;
787
788 #ifdef HAVE_LIBCDDB
789   p_cdda->i_cddb_enabled =
790     config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
791   if( b_single_track && !p_cdda->i_cddb_enabled ) return VLC_SUCCESS;
792 #else
793   if( b_single_track ) return VLC_SUCCESS;
794 #endif
795
796   psz_mrl = malloc( psz_mrl_max );
797
798   if( psz_mrl == NULL )
799     {
800       msg_Warn( p_access, "out of memory" );
801       return VLC_ENOMEM;
802     }
803
804   p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
805                                                FIND_ANYWHERE );
806   if( !p_playlist )
807     {
808       msg_Warn( p_access, "can't find playlist" );
809       free(psz_mrl);
810       return VLC_EGENERIC;
811     }
812
813   CDDAMetaInfo(p_access);
814
815   if (b_single_track) {
816     /* May fill out more information when the playlist user interface becomes
817        more mature.
818      */
819     track_t i_track = p_cdda->i_track;
820
821     input_title_t *t = p_cdda->p_title[i_track-1] = vlc_input_title_New();
822         
823     asprintf( &t->psz_name, _("Track %i"), i_track );
824     t->i_size = ( p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1] ) *
825       (int64_t)CDIO_CD_FRAMESIZE_RAW;
826         
827     t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
828     CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i_track,
829                            psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
830                            p_playlist->i_index);
831     p_access->info.i_size = 
832       ( p_cdda->p_lsns[i_track] - p_cdda->p_lsns[i_track-1] ) *
833       (int64_t)CDIO_CD_FRAMESIZE_RAW;
834
835   } else {
836
837     for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
838       {
839         input_title_t *t = p_cdda->p_title[i-1] = vlc_input_title_New();
840         
841         asprintf( &t->psz_name, _("Track %i"), i );
842         t->i_size = ( p_cdda->p_lsns[i] - p_cdda->p_lsns[i-1] ) *
843           (int64_t)CDIO_CD_FRAMESIZE_RAW;
844         
845         t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
846         CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i, psz_mrl,
847                                psz_mrl_max, psz_source, PLAYLIST_APPEND,
848                                PLAYLIST_END);
849       }
850     p_access->info.i_size = 
851       (p_cdda->p_lsns[p_cdda->i_tracks] - p_cdda->p_lsns[0]) * 
852       (int64_t)CDIO_CD_FRAMESIZE_RAW;
853   }
854
855   return VLC_SUCCESS;
856 }
857
858 /****************************************************************************
859  * Public functions
860  ****************************************************************************/
861
862 /*****************************************************************************
863  * Open: open cdda device or image file and initialize structures 
864  * for subsequent operations.
865  *****************************************************************************/
866 int
867 E_(CDDAOpen)( vlc_object_t *p_this )
868 {
869     access_t    *p_access = (access_t*)p_this;
870     char *      psz_source = NULL;
871     cdda_data_t *p_cdda;
872     CdIo        *p_cdio;
873     track_t     i_track = 1;
874     vlc_bool_t  b_single_track = false;
875     int         i_rc = VLC_EGENERIC;
876
877     p_access->p_sys = NULL;
878
879     /* Set where to log errors messages from libcdio. */
880     p_cdda_input = p_access;
881
882     /* parse the options passed in command line : */
883
884     if( p_access->psz_path && *p_access->psz_path )
885     {
886       char *psz_parser = psz_source = strdup( p_access->psz_path );
887
888       while( *psz_parser && *psz_parser != '@' )
889         {
890           psz_parser++;
891         }
892       
893       if( *psz_parser == '@' )
894         {
895           /* Found options */
896           *psz_parser = '\0';
897           ++psz_parser;
898           
899           if ('T' == *psz_parser || 't' == *psz_parser )
900             ++psz_parser;
901           
902           i_track = (int)strtol( psz_parser, NULL, 10 );
903           i_track = i_track ? i_track : 1;
904           b_single_track = true;
905         }
906     } 
907
908     if (!psz_source || !*psz_source)
909       {
910         /* No device/track given. Continue only when this plugin was 
911            selected */
912         if( !p_this->b_force ) return VLC_EGENERIC;
913
914         psz_source = var_CreateGetString( p_this, "cd-audio" );
915
916         if( !psz_source || !*psz_source ) {
917         /* Scan for a CD-ROM drive with a CD-DA in it. */
918         char **cd_drives =
919           cdio_get_devices_with_cap(NULL,  CDIO_FS_AUDIO, false);
920
921         if (NULL == cd_drives || NULL == cd_drives[0] ) {
922           msg_Err( p_access, 
923                    "libcdio couldn't find something with a CD-DA in it" );
924           if (cd_drives) cdio_free_device_list(cd_drives);
925           return VLC_EGENERIC;
926         }
927         
928         psz_source = strdup(cd_drives[0]);
929         cdio_free_device_list(cd_drives);
930       }
931     }
932
933     cdio_log_set_handler ( cdio_log_handler );
934
935     /* Open CDDA */
936     if( !(p_cdio = cdio_open( psz_source, DRIVER_UNKNOWN )) )
937     {
938         msg_Warn( p_access, "could not open %s", psz_source );
939         goto error2;
940     }
941
942     p_cdda = malloc( sizeof(cdda_data_t) );
943     if( p_cdda == NULL )
944     {
945         msg_Err( p_access, "out of memory" );
946         free( psz_source );
947         return VLC_ENOMEM;
948     }
949     memset( p_cdda, 0, sizeof(cdda_data_t) );
950
951 #ifdef HAVE_LIBCDDB
952     cddb_log_set_handler ( cddb_log_handler );
953     p_cdda->cddb.disc = NULL;
954     p_cdda->i_cddb_enabled =
955       config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
956 #endif
957
958     p_cdda->b_header = VLC_FALSE;
959     p_cdda->p_cdio   = p_cdio;
960     p_cdda->i_track  = i_track;
961     p_cdda->i_debug  = config_GetInt(p_this, MODULE_STRING "-debug");
962     p_cdda->i_blocks_per_read
963                      = config_GetInt(p_this, MODULE_STRING "-blocks-per-read");
964
965     p_cdda->p_input  = vlc_object_find( p_access, VLC_OBJECT_INPUT, 
966                                         FIND_PARENT );
967
968     if (0 == p_cdda->i_blocks_per_read)
969       p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
970     
971     if ( p_cdda->i_blocks_per_read < MIN_BLOCKS_PER_READ 
972          || p_cdda->i_blocks_per_read > MAX_BLOCKS_PER_READ ) {
973       msg_Warn( p_cdda_input, 
974                 "Number of blocks (%d) has to be between %d and %d. "
975                 "Using %d.", 
976                 p_cdda->i_blocks_per_read, 
977                 MIN_BLOCKS_PER_READ, MAX_BLOCKS_PER_READ,
978                 DEFAULT_BLOCKS_PER_READ );
979       p_cdda->i_blocks_per_read = DEFAULT_BLOCKS_PER_READ;
980     }
981
982
983     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
984
985     /* Set up p_access */
986     p_access->pf_read    = NULL;
987     p_access->pf_block   = CDDAReadBlocks;
988     p_access->pf_control = CDDAControl;
989     p_access->pf_seek    = CDDASeek;
990
991     p_access->info.i_size      = 0;
992
993     p_access->info.i_update    = 0;
994     p_access->info.b_eof       = VLC_FALSE;
995     p_access->info.i_title     = 0;
996     p_access->info.i_seekpoint = 0;
997
998     p_access->p_sys     = (access_sys_t *) p_cdda;
999
1000     /* We read the Table Of Content information */
1001     i_rc = GetCDInfo( p_access, p_cdda );
1002     if ( VLC_SUCCESS != i_rc ) goto error;
1003
1004     CDDAFixupPlaylist( p_access, p_cdda, psz_source, b_single_track );
1005     
1006     /* Build a WAV header to put in front of the output data. 
1007        This gets sent back in the Block (read) routine.
1008      */
1009     memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
1010     SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
1011     SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
1012     p_cdda->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
1013     p_cdda->waveheader.Length = 0;                     /* we just don't know */
1014     p_cdda->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
1015     p_cdda->waveheader.SubChunkID  = VLC_FOURCC('f', 'm', 't', ' ');
1016     SetDWLE( &p_cdda->waveheader.SubChunkLength, 16);
1017     SetWLE( &p_cdda->waveheader.Modus, 2);
1018     SetDWLE( &p_cdda->waveheader.SampleFreq, CDDA_FREQUENCY_SAMPLE);
1019     SetWLE( &p_cdda->waveheader.BytesPerSample,
1020             2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
1021     SetDWLE( &p_cdda->waveheader.BytesPerSec,
1022              2*16/8 /*BytesPerSample*/ * CDDA_FREQUENCY_SAMPLE );
1023     p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
1024     p_cdda->waveheader.DataLength  = 0;    /* we just don't know */
1025
1026     /* PTS delay */
1027     var_Create( p_access, MODULE_STRING "-caching", 
1028                 VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
1029     return VLC_SUCCESS;
1030
1031  error:
1032     cdio_destroy( p_cdda->p_cdio );
1033     free( p_cdda );
1034  error2:
1035     free( psz_source );
1036     return i_rc;
1037
1038 }
1039
1040 /*****************************************************************************
1041  * CDDAClose: closes cdda and frees any resources associded with it.
1042  *****************************************************************************/
1043 void
1044 E_(CDDAClose)( vlc_object_t *p_this )
1045 {
1046     access_t    *p_access = (access_t *) p_this;
1047     cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
1048     track_t      i;
1049
1050     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
1051
1052     /* Remove playlist titles */
1053     for( i = 0; i < p_cdda->i_tracks; i++ )
1054     {
1055         vlc_input_title_Delete( p_cdda->p_title[i] );
1056     }
1057
1058     cdio_destroy( p_cdda->p_cdio );
1059
1060     cdio_log_set_handler (uninit_log_handler);
1061
1062 #ifdef HAVE_LIBCDDB
1063     cddb_log_set_handler (uninit_log_handler);
1064     if (p_cdda->i_cddb_enabled)
1065       cddb_disc_destroy(p_cdda->cddb.disc);
1066 #endif
1067
1068     free( p_cdda->p_lsns );
1069     if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
1070     free( p_cdda );
1071     p_cdda_input = NULL;
1072 }
1073
1074 /*****************************************************************************
1075  * Control: The front-end or vlc engine calls here to ether get
1076  * information such as meta information or plugin capabilities or to
1077  * issue miscellaneous "set" requests.
1078  *****************************************************************************/
1079 static int CDDAControl( access_t *p_access, int i_query, va_list args )
1080 {
1081     cdda_data_t  *p_cdda = (cdda_data_t *) p_access->p_sys;
1082     int          *pi_int;
1083     int i;
1084
1085     dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
1086                "query %d", i_query );
1087
1088     switch( i_query )
1089     {
1090         /* Pass back a copy of meta information that was gathered when we
1091            during the Open/Initialize call.
1092          */
1093         case ACCESS_GET_META:
1094           { 
1095             vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
1096             if ( p_cdda->p_meta ) {
1097               *pp_meta = vlc_meta_Duplicate( p_cdda->p_meta );
1098               dbg_print( INPUT_DBG_META, "%s", "Meta copied" );
1099             } else 
1100               msg_Warn( p_access, "tried to copy NULL meta info" );
1101             
1102             return VLC_SUCCESS;
1103           }
1104           return VLC_EGENERIC;
1105
1106         case ACCESS_CAN_SEEK:
1107         case ACCESS_CAN_FASTSEEK:
1108         case ACCESS_CAN_PAUSE:
1109         case ACCESS_CAN_CONTROL_PACE: 
1110           {
1111             vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
1112             *pb_bool = VLC_TRUE;
1113             break;
1114           }
1115
1116         /* */
1117         case ACCESS_GET_MTU:
1118             pi_int = (int*)va_arg( args, int * );
1119             *pi_int = p_cdda-> i_blocks_per_read * CDIO_CD_FRAMESIZE_RAW;
1120             break;
1121
1122         case ACCESS_GET_PTS_DELAY:
1123           { 
1124             int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * );
1125             *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" )
1126               * MILLISECONDS_PER_SEC;
1127             break;
1128           }
1129
1130         /* */
1131         case ACCESS_SET_PAUSE_STATE:
1132             break;
1133
1134         case ACCESS_GET_TITLE_INFO:
1135           { input_title_t ***ppp_title;
1136             ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
1137             pi_int    = (int*)va_arg( args, int* );
1138             *((int*)va_arg( args, int* )) = 1; /* Title offset */
1139
1140             /* Duplicate track info */
1141             *pi_int = p_cdda->i_tracks;
1142             *ppp_title = malloc(sizeof( input_title_t **) * p_cdda->i_tracks );
1143
1144             if (!*ppp_title) return VLC_ENOMEM;
1145
1146             for( i = 0; i < p_cdda->i_tracks; i++ )
1147             {
1148               if ( p_cdda->p_title[i] )
1149                 (*ppp_title)[i] = 
1150                   vlc_input_title_Duplicate( p_cdda->p_title[i] );
1151             }
1152           }
1153           break;
1154
1155         case ACCESS_SET_TITLE:
1156             i = (int)va_arg( args, int );
1157             if( i != p_access->info.i_title )
1158             {
1159                 /* Update info */
1160                 p_access->info.i_update |=
1161                     INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1162                 p_access->info.i_title = i;
1163                 p_access->info.i_size = p_cdda->p_title[i]->i_size;
1164                 p_access->info.i_pos = 0;
1165
1166                 /* Next sector to read */
1167                 p_cdda->i_lsn = p_cdda->p_lsns[i];
1168             }
1169             break;
1170
1171         case ACCESS_SET_SEEKPOINT:
1172         case ACCESS_SET_PRIVATE_ID_STATE:
1173             return VLC_EGENERIC;
1174
1175         default:
1176           msg_Warn( p_access, "unimplemented query in control" );
1177             return VLC_EGENERIC;
1178
1179     }
1180     return VLC_SUCCESS;
1181 }
1182
1183 /*****************************************************************************
1184   GetCDInfo: 
1185
1186  Initialize information pertaining to the CD: the number of tracks,
1187  first track number, LSNs for each track and the leadout. The leadout
1188  information is stored after the last track. The LSN array is
1189  0-origin, same as p_access->info.  Add first_track to get what track
1190  number this is on the CD. Note: libcdio uses the real track number.
1191
1192  On input we assume p_cdda->p_cdio and p_cdda->i_track have been set.
1193
1194  We return the VLC-type status, e.g. VLC_SUCCESS, VLC_ENOMEM, etc.
1195  *****************************************************************************/
1196 static int
1197 GetCDInfo( access_t *p_access, cdda_data_t *p_cdda ) 
1198 {
1199     track_t i;
1200     discmode_t  discmode = CDIO_DISC_MODE_NO_INFO;
1201
1202     p_cdda->i_tracks       = cdio_get_num_tracks(p_cdda->p_cdio);
1203     p_cdda->i_first_track  = cdio_get_first_track_num(p_cdda->p_cdio);
1204
1205     discmode = cdio_get_discmode(p_cdda->p_cdio);
1206     switch(discmode) {
1207     case CDIO_DISC_MODE_CD_DA:
1208     case CDIO_DISC_MODE_CD_MIXED:
1209       /* These are possible for CD-DA */
1210       break;
1211     default:
1212       /* These are not possible for CD-DA */
1213       msg_Err( p_access, 
1214                "Disc seems not to be CD-DA. libcdio reports it is %s",
1215                discmode2str[discmode]
1216                );
1217       return VLC_EGENERIC;
1218     }
1219     
1220     p_cdda->p_lsns = malloc( (p_cdda->i_tracks + 1) * sizeof(lsn_t) );
1221
1222     if( p_cdda->p_lsns == NULL )
1223       {
1224         msg_Err( p_access, "out of memory" );
1225         return VLC_ENOMEM;
1226       }
1227
1228
1229     /* Fill the p_lsns structure with the track/sector matches.
1230        Note cdio_get_track_lsn when given num_tracks + 1 will return
1231        the leadout LSN.
1232      */
1233     for( i = 0 ; i <= p_cdda->i_tracks ; i++ )
1234       {
1235         (p_cdda->p_lsns)[ i ] = 
1236           cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_first_track+i);
1237       }
1238
1239     /* Set reading start LSN. */
1240     p_cdda->i_lsn = p_cdda->p_lsns[p_cdda->i_track - p_cdda->i_first_track];
1241
1242     return VLC_SUCCESS;
1243 }