1 /*****************************************************************************
2 * info.c : CD digital audio input information routines
3 *****************************************************************************
4 * Copyright (C) 2004 VideoLAN
5 * $Id: info.c 8845 2004-09-29 09:00:41Z rocky $
7 * Authors: Rocky Bernstein <rocky@panix.com>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include "callback.h" /* FIXME - reorganize callback.h, cdda.h better */
28 #include "cdda.h" /* private structures. Also #includes vlc things */
29 #include <vlc_playlist.h> /* Has to come *after* cdda.h */
31 #include <cdio/cdio.h>
32 #include <cdio/cdtext.h>
33 #include <cdio/logging.h>
34 #include <cdio/cd_types.h>
41 #define CDDA_MRL_PREFIX "cddax://"
45 #define free_and_dup(var, val) \
47 if (val) var=strdup(val);
51 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
55 cddb_conn_t *conn = cddb_new();
56 const CdIo *p_cdio = p_cdda->p_cdio;
58 dbg_print( (INPUT_DBG_CALL), "" );
61 cddb_log_set_handler (uninit_log_handler);
65 msg_Warn( p_access, "Unable to initialize libcddb" );
69 cddb_set_email_address( conn,
70 config_GetPsz( p_access,
71 MODULE_STRING "-cddb-email") );
73 cddb_set_server_name( conn,
74 config_GetPsz( p_access,
75 MODULE_STRING "-cddb-server") );
77 cddb_set_server_port(conn,
78 config_GetInt( p_access,
79 MODULE_STRING "-cddb-port") );
81 /* Set the location of the local CDDB cache directory.
82 The default location of this directory is */
84 if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
85 cddb_cache_disable(conn);
87 cddb_cache_set_dir(conn,
88 config_GetPsz( p_access,
89 MODULE_STRING "-cddb-cachedir") );
91 cddb_set_timeout(conn,
92 config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
95 if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" )) {
96 cddb_http_enable(conn);
98 cddb_http_disable(conn);
100 p_cdda->cddb.disc = cddb_disc_new();
101 if (!p_cdda->cddb.disc) {
102 msg_Err( p_access, "Unable to create CDDB disc structure." );
106 for(i = 0; i < p_cdda->i_tracks; i++) {
107 track_t i_track = p_cdda->i_first_track + i;
108 cddb_track_t *t = cddb_track_new();
109 t->frame_offset = cdio_get_track_lba(p_cdio, i_track);
110 cddb_disc_add_track(p_cdda->cddb.disc, t);
113 p_cdda->cddb.disc->length =
114 cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
115 / CDIO_CD_FRAMES_PER_SEC;
117 if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
118 msg_Err( p_access, "CDDB disc ID calculation failed" );
122 i_matches = cddb_query(conn, p_cdda->cddb.disc);
125 msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
127 cddb_read(conn, p_cdda->cddb.disc);
129 if (p_cdda->i_debug & INPUT_DBG_CDDB)
130 cddb_disc_print(p_cdda->cddb.disc);
133 msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
141 #endif /*HAVE_LIBCDDB*/
143 #define add_meta_val(FIELD, VLC_META, VAL) \
144 if ( p_cdda->p_meta && VAL) { \
145 vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL ); \
146 dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL ); \
149 #define add_cddb_meta(FIELD, VLC_META) \
150 add_meta_val(FIELD, VLC_META, p_cdda->cddb.disc->FIELD);
152 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
155 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
156 p_cdda->cddb.disc->FIELD ); \
157 psz_buf[sizeof(psz_buf)-1] = '\0'; \
158 add_meta_val(FIELD, VLC_META, psz_buf); \
161 /* Adds a string-valued entry to the stream and media information if
162 the string is not null or the null string.
164 #define add_info_str(CATEGORY, TITLE, FIELD) \
165 if (FIELD && strlen(FIELD)) { \
166 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
167 _(TITLE), "%s", FIELD ); \
170 /* Adds a numeric-valued entry to the stream and media information
171 if the number is not zero. */
172 #define add_info_val(CATEGORY, TITLE, FMT, FIELD) \
174 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
175 _(TITLE), FMT, FIELD ); \
178 /* Adds a CDDB string-valued entry to the stream and media information
179 under category "Disc" if the string is not null or the null string.
181 #define add_cddb_disc_info_str(TITLE, FIELD) \
182 add_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
184 /* Adds a CDDB numeric-valued entry to the stream and media information
185 under category "Disc" if the string is not null or the null string.
187 #define add_cddb_disc_info_val(TITLE, FMT, FIELD) \
188 add_info_val("Disc", TITLE, FMT, p_cdda->cddb.disc->FIELD)
190 /* Adds a CD-Text string-valued entry to the stream and media information
191 under category "Disc" if the string is not null or the null string.
193 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD) \
194 add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
196 /* Adds a CD-Text string-valued entry to the stream and media information
197 under category "Disc" if the string is not null or the null string.
199 #define add_cdtext_disc_info_str(TITLE, FIELD) \
200 add_cdtext_info_str("Disc", TITLE, 0, FIELD)
204 Gets and saves CDDA Meta Information about the CD.
206 In the Control routine, we handle Meta Information requests and
207 basically copy what we've saved here.
209 Meta information is also used elsewhere such as in "stream and
210 media info" or in playlist info. The intialization of CD-Text or CDDB
214 CDDAMetaInfo( access_t *p_access )
216 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
218 if ( ! p_cdda ) return;
220 p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
223 if ( p_cdda->b_cddb_enabled ) {
225 GetCDDBInfo(p_access, p_cdda);
227 if ( p_cdda->cddb.disc ) {
229 p_cdda->p_meta = vlc_meta_New();
231 add_cddb_meta(title, VLC_META_CDDB_TITLE);
232 add_cddb_meta(artist, VLC_META_CDDB_ARTIST);
233 add_cddb_meta(genre, VLC_META_CDDB_GENRE);
234 add_cddb_meta(ext_data, VLC_META_CDDB_EXT_DATA);
236 add_cddb_meta_fmt(year, "%d", VLC_META_CDDB_YEAR);
237 add_cddb_meta_fmt(discid, "%x", VLC_META_CDDB_DISCID);
241 #endif /*HAVE_LIBCDDB*/
245 track_t i = p_cdda->i_tracks;
246 const int i_first_track = p_cdda->i_first_track;
247 char psz_buffer[MSTRTIME_MAX_SIZE];
249 (p_cdda->lsn[i_first_track+i] - p_cdda->lsn[i_first_track])
250 / CDIO_CD_FRAMES_PER_SEC;
252 dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
253 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
254 _("Disc"), _("Duration"), "%s",
255 secstotimestr( psz_buffer, i_duration ) );
258 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc) {
259 add_cddb_disc_info_str("Artist (CDDB)", artist);
260 add_cddb_disc_info_str("Genre (CDDB)", genre);
261 add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
262 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
263 add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
264 add_cddb_disc_info_str("Title (CDDB)", title);
265 add_info_str("Disc", "Category (CDDB)",
266 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
268 #endif /*HAVE_LIBCDDB*/
270 p_cdda->p_cdtext[0] = cdio_get_cdtext(p_cdda->p_cdio, 0);
271 if (p_cdda->p_cdtext[0]) {
272 add_cdtext_disc_info_str("Arranger (CD-Text)", CDTEXT_ARRANGER);
273 add_cdtext_disc_info_str("Composer (CD-Text)", CDTEXT_COMPOSER);
274 add_cdtext_disc_info_str("Disc ID (CD-Text)", CDTEXT_DISCID);
275 add_cdtext_disc_info_str("Genre (CD-Text)", CDTEXT_GENRE);
276 add_cdtext_disc_info_str("Message (CD-Text)", CDTEXT_MESSAGE);
277 add_cdtext_disc_info_str("Performer (CD-Text)", CDTEXT_PERFORMER);
278 add_cdtext_disc_info_str("Songwriter (CD-Text)", CDTEXT_SONGWRITER);
279 add_cdtext_disc_info_str("Title (CD-Text)", CDTEXT_TITLE);
282 for( i = 0 ; i < p_cdda->i_tracks ; i++ ) {
284 char psz_track[TITLE_MAX];
285 const track_t i_track = i_first_track + i;
286 mtime_t i_duration = (p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track])
287 / CDIO_CD_FRAMES_PER_SEC;
288 snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
289 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
291 secstotimestr( psz_buffer, i_duration ) );
293 p_cdda->p_cdtext[i_track] = cdio_get_cdtext(p_cdda->p_cdio, i_track);
295 if (p_cdda->p_cdtext[i_track]) {
296 add_cdtext_info_str(psz_track, "Arranger (CD-Text)", i_track,
298 add_cdtext_info_str(psz_track, "Composer (CD-Text)", i_track,
300 add_cdtext_info_str(psz_track, "Disc ID (CD-Text)", i_track,
302 add_cdtext_info_str(psz_track, "Genre (CD-Text)", i_track,
304 add_cdtext_info_str(psz_track, "Message (CD-Text)", i_track,
306 add_cdtext_info_str(psz_track, "Performer (CD-Text)", i_track,
308 add_cdtext_info_str(psz_track, "Songwriter (CD-Text)", i_track,
310 add_cdtext_info_str(psz_track, "Title (CD-Text)", i_track,
315 if (p_cdda->b_cddb_enabled) {
316 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
318 add_info_str(psz_track, "Artist (CDDB)", t->artist);
319 add_info_str(psz_track, "Title (CDDB)", t->title);
320 add_info_str(psz_track, "Extended Data (CDDB)", t->ext_data);
323 #endif /*HAVE_LIBCDDB*/
328 #define add_format_str_info(val) \
330 const char *str = val; \
335 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
338 saw_control_prefix = false; \
342 #define add_format_num_info(val, fmt) \
346 sprintf(num_str, fmt, val); \
347 len=strlen(num_str); \
349 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
352 saw_control_prefix = false; \
356 Take a format string and expand escape sequences, that is sequences that
357 begin with %, with information from the current CD.
358 The expanded string is returned. Here is a list of escape sequences:
360 %a : The album artist **
361 %A : The album information **
366 %m : The CD-DA Media Catalog Number (MCN)
367 %n : The number of tracks on the CD
368 %p : The artist/performer/composer in the track **
369 %T : The track number **
370 %s : Number of seconds in this track
372 %Y : The year 19xx or 20xx **
376 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
377 const char format_str[], const char *mrl, track_t i_track)
379 #define TEMP_STR_SIZE 256
380 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
381 static char temp_str[TEMP_STR_SIZE];
383 char * tp = temp_str;
384 vlc_bool_t saw_control_prefix = false;
385 size_t format_len = strlen(format_str);
387 memset(temp_str, 0, TEMP_STR_SIZE);
389 for (i=0; i<format_len; i++) {
391 if (!saw_control_prefix && format_str[i] != '%') {
392 *tp++ = format_str[i];
393 saw_control_prefix = false;
397 switch(format_str[i]) {
399 if (saw_control_prefix) {
402 saw_control_prefix = !saw_control_prefix;
406 if (!p_cdda->b_cddb_enabled) goto not_special;
407 if (p_cdda->cddb.disc)
408 add_format_str_info(p_cdda->cddb.disc->artist);
411 if (!p_cdda->b_cddb_enabled) goto not_special;
412 if (p_cdda->cddb.disc)
413 add_format_str_info(p_cdda->cddb.disc->title);
416 if (!p_cdda->b_cddb_enabled) goto not_special;
417 if (p_cdda->cddb.disc)
418 add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
421 if (!p_cdda->b_cddb_enabled) goto not_special;
422 if (p_cdda->cddb.disc)
423 add_format_str_info(p_cdda->cddb.disc->genre);
426 if (!p_cdda->b_cddb_enabled) goto not_special;
427 if (p_cdda->cddb.disc)
428 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
431 if (!p_cdda->b_cddb_enabled) goto not_special;
432 if (p_cdda->cddb.disc)
433 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
436 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc) {
437 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
439 if (t != NULL && t->title != NULL)
440 add_format_str_info(t->title);
441 } else goto not_special;
444 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc) {
445 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
447 if (t != NULL && t->artist != NULL)
448 add_format_str_info(t->artist);
449 } else goto not_special;
452 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc) {
453 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
455 if (t != NULL && t->ext_data != NULL)
456 add_format_str_info(t->ext_data);
457 } else goto not_special;
460 if (p_cdda->b_cddb_enabled) {
461 char psz_buffer[MSTRTIME_MAX_SIZE];
462 mtime_t i_duration = (p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track])
463 / CDIO_CD_FRAMES_PER_SEC;
464 add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
468 #endif /*HAVE_LIBCDDB*/
471 add_format_str_info(mrl);
475 add_format_str_info(p_cdda->psz_mcn);
479 add_format_num_info(p_cdda->i_tracks, "%d");
483 add_format_num_info(i_track, "%02d");
490 *tp++ = format_str[i];
491 saw_control_prefix = false;
494 return strdup(temp_str);
497 /* Adds a string-valued entry to the playlist information under "Track"
498 if the string is not null or the null string.
500 #define add_playlist_track_info_str(TITLE, FIELD) \
501 if (FIELD && strlen(FIELD)) { \
502 playlist_ItemAddInfo( p_item, _("Track"), _(TITLE), \
507 CDDACreatePlaylistItem(const access_t *p_access, cdda_data_t *p_cdda,
508 playlist_t *p_playlist, track_t i_track,
509 char *psz_mrl, int psz_mrl_max,
510 const char *psz_source, int playlist_operation,
513 mtime_t i_duration = (p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track])
514 * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
516 char *config_varname = MODULE_STRING "-title-format";
517 playlist_item_t *p_item;
520 if (p_cdda->b_cddb_enabled) {
521 config_varname = MODULE_STRING "-cddb-title-format";
523 #endif /*HAVE_LIBCDDB*/
525 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
526 CDDA_MRL_PREFIX, psz_source, i_track);
528 psz_title = CDDAFormatStr(p_access, p_cdda,
529 config_GetPsz( p_access, config_varname ),
532 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
533 psz_mrl, psz_title, (long int) i_duration / 1000000 , i_pos );
534 playlist_AddExt( p_playlist, psz_mrl, psz_title, playlist_operation,
535 i_pos, i_duration , NULL, 0);
537 if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
539 vlc_mutex_lock( &p_playlist->object_lock );
540 p_item = playlist_ItemGetByPos( p_playlist, i_pos );
541 vlc_mutex_unlock( &p_playlist->object_lock );
545 vlc_mutex_lock( &p_item->input.lock );
547 add_playlist_track_info_str("Source", psz_source);
548 playlist_ItemAddInfo( p_item, _("Track"), _("Track Number"), "%d", i_track );
550 if (p_cdda->p_cdtext[0]) {
551 const cdtext_t *p = p_cdda->p_cdtext[0];
552 add_playlist_track_info_str("Disc Arranger (CD-Text)",
553 p->field[CDTEXT_ARRANGER]);
554 add_playlist_track_info_str("Disc Composer (CD-Text)",
555 p->field[CDTEXT_COMPOSER]);
556 add_playlist_track_info_str("Disc ID (CD-Text)",
557 p->field[CDTEXT_DISCID]);
558 add_playlist_track_info_str("Disc Genre (CD-Text)",
559 p->field[CDTEXT_GENRE]);
560 add_playlist_track_info_str("Disc Message (CD-Text)",
561 p->field[CDTEXT_MESSAGE]);
562 add_playlist_track_info_str("Disc Performer (CD-Text)",
563 p->field[CDTEXT_PERFORMER]);
564 add_playlist_track_info_str("Disc Songwriter (CD-Text)",
565 p->field[CDTEXT_SONGWRITER]);
566 add_playlist_track_info_str("Disc Title (CD-Text)",
567 p->field[CDTEXT_TITLE]);
570 if (p_cdda->p_cdtext[i_track]) {
571 const cdtext_t *p = p_cdda->p_cdtext[i_track];
572 add_playlist_track_info_str("Arranger (CD-Text)",
573 p->field[CDTEXT_ARRANGER]);
574 add_playlist_track_info_str("Composer (CD-Text)",
575 p->field[CDTEXT_COMPOSER]);
576 add_playlist_track_info_str("Genre (CD-Text)",
577 p->field[CDTEXT_GENRE]);
578 add_playlist_track_info_str("Message (CD-Text)",
579 p->field[CDTEXT_MESSAGE]);
580 add_playlist_track_info_str("Performer (CD-Text)",
581 p->field[CDTEXT_PERFORMER]);
582 add_playlist_track_info_str("Songwriter (CD-Text)",
583 p->field[CDTEXT_SONGWRITER]);
584 add_playlist_track_info_str("Title (CD-Text)",
585 p->field[CDTEXT_TITLE]);
590 if (p_cdda->b_cddb_enabled) {
591 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
592 i_track-p_cdda->i_first_track);
594 add_playlist_track_info_str("Disc Album (CDDB)",
595 p_cdda->cddb.disc->title);
596 add_playlist_track_info_str("Disc Artist(s) (CDDB)",
597 p_cdda->cddb.disc->artist);
598 add_playlist_track_info_str("Disc Category (CDDB)",
599 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
600 add_playlist_track_info_str("Disc Genre (CDDB)",
601 p_cdda->cddb.disc->genre);
602 if ( p_cdda->cddb.disc->discid ) {
603 playlist_ItemAddInfo( p_item, _("Track"), _("Disc ID (CDDB)"),
604 "%x", p_cdda->cddb.disc->discid );
606 if (p_cdda->cddb.disc->year != 0) {
607 playlist_ItemAddInfo( p_item, _("Track"), _("Year (CDDB)"),
608 "%5d", p_cdda->cddb.disc->year );
613 add_playlist_track_info_str("Track Artist (CDDB)",
616 add_playlist_track_info_str("Track Title (CDDB)",
620 #endif /*HAVE_LIBCDDB*/
622 vlc_mutex_unlock( &p_item->input.lock );
626 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
627 const char *psz_source, vlc_bool_t b_single_track )
630 playlist_t * p_playlist;
632 unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
633 strlen("@T") + strlen("100") + 1;
634 const track_t i_first_track = p_cdda->i_first_track;
637 p_cdda->b_cddb_enabled =
638 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
639 if( b_single_track && !p_cdda->b_cddb_enabled ) return VLC_SUCCESS;
641 if( b_single_track ) return VLC_SUCCESS;
644 psz_mrl = malloc( psz_mrl_max );
646 if( psz_mrl == NULL )
648 msg_Warn( p_access, "out of memory" );
652 p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
656 msg_Warn( p_access, "can't find playlist" );
661 CDDAMetaInfo(p_access);
663 if (b_single_track) {
664 /* May fill out more information when the playlist user interface becomes
667 track_t i_track = p_cdda->i_track;
669 input_title_t *t = p_cdda->p_title[i_track-i_first_track] =
670 vlc_input_title_New();
672 asprintf( &t->psz_name, _("Track %i"), i_track );
673 t->i_size = p_access->info.i_size =
674 ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) *
675 (int64_t) CDIO_CD_FRAMESIZE_RAW;
677 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
678 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i_track,
679 psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
680 p_playlist->i_index);
681 p_cdda->i_titles = 1;
684 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
686 const track_t i_track = i_first_track + i;
687 input_title_t *t = p_cdda->p_title[i] = vlc_input_title_New();
689 asprintf( &t->psz_name, _("Track %i"), i_track );
690 t->i_size = ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) *
691 (int64_t) CDIO_CD_FRAMESIZE_RAW;
693 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
694 CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i_track,
695 psz_mrl, psz_mrl_max, psz_source,
696 PLAYLIST_APPEND, PLAYLIST_END);
698 p_cdda->i_titles = p_cdda->i_tracks; /* should be +1 */
699 p_access->info.i_size =
700 (p_cdda->lsn[i_first_track + p_cdda->i_tracks]
701 - p_cdda->lsn[i_first_track]) * (int64_t) CDIO_CD_FRAMESIZE_RAW;