00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "callback.h"
00028 #include "cdda.h"
00029 #include <vlc_playlist.h>
00030
00031 #include <cdio/cdio.h>
00032 #include <cdio/cdtext.h>
00033 #include <cdio/logging.h>
00034 #include <cdio/cd_types.h>
00035 #include "info.h"
00036
00037 #ifdef HAVE_ERRNO_H
00038 # include <errno.h>
00039 #endif
00040
00041 static char *CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
00042 const char format_str[], const char *psz_mrl,
00043 track_t i_track);
00044
00045 static char *CDDAFormatMRL( const access_t *p_access, track_t i_track );
00046
00047 #ifdef HAVE_LIBCDDB
00048
00049 #define free_and_dup(var, val) \
00050 if (var) free(var); \
00051 if (val) var=strdup(val);
00052
00053
00054
00055 static void
00056 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
00057 {
00058 int i, i_matches;
00059 cddb_conn_t *conn = cddb_new();
00060 const CdIo_t *p_cdio = p_cdda->p_cdio;
00061
00062 dbg_print( (INPUT_DBG_CALL), "" );
00063
00064 #ifdef FIXME_NOW
00065 cddb_log_set_handler (uninit_log_handler);
00066 #endif
00067
00068 if (!conn)
00069 {
00070 msg_Warn( p_access, "Unable to initialize libcddb" );
00071 goto cddb_destroy;
00072 }
00073
00074 cddb_set_email_address( conn,
00075 config_GetPsz( p_access,
00076 MODULE_STRING "-cddb-email") );
00077 cddb_set_server_name( conn,
00078 config_GetPsz( p_access,
00079 MODULE_STRING "-cddb-server") );
00080 cddb_set_server_port(conn,
00081 config_GetInt( p_access,
00082 MODULE_STRING "-cddb-port") );
00083
00084
00085
00086
00087 if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
00088 cddb_cache_disable(conn);
00089
00090 cddb_cache_set_dir(conn,
00091 config_GetPsz( p_access,
00092 MODULE_STRING "-cddb-cachedir") );
00093
00094 cddb_set_timeout(conn,
00095 config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
00096
00097
00098 if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" ) )
00099 {
00100 cddb_http_enable(conn);
00101 }
00102 else
00103 {
00104 cddb_http_disable(conn);
00105 }
00106
00107 p_cdda->cddb.disc = cddb_disc_new();
00108
00109 if (!p_cdda->cddb.disc)
00110 {
00111 msg_Err( p_access, "Unable to create CDDB disc structure." );
00112 goto cddb_end;
00113 }
00114
00115 for(i = 0; i < p_cdda->i_tracks; i++)
00116 {
00117 track_t i_track = p_cdda->i_first_track + i;
00118 cddb_track_t *t = cddb_track_new();
00119 cddb_track_set_frame_offset(t,
00120 cdio_get_track_lba(p_cdio, i_track));
00121 cddb_disc_add_track(p_cdda->cddb.disc, t);
00122 }
00123
00124 cddb_disc_set_length(p_cdda->cddb.disc,
00125 cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
00126 / CDIO_CD_FRAMES_PER_SEC);
00127
00128 if (!cddb_disc_calc_discid(p_cdda->cddb.disc))
00129 {
00130 msg_Err( p_access, "CDDB disc ID calculation failed" );
00131 goto cddb_destroy;
00132 }
00133
00134 i_matches = cddb_query(conn, p_cdda->cddb.disc);
00135
00136 if (i_matches > 0)
00137 {
00138 if (i_matches > 1)
00139 msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
00140 i_matches);
00141 cddb_read(conn, p_cdda->cddb.disc);
00142
00143 if (p_cdda->i_debug & INPUT_DBG_CDDB)
00144 cddb_disc_print(p_cdda->cddb.disc);
00145
00146 }
00147 else
00148 {
00149 msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
00150 }
00151
00152 cddb_destroy:
00153 cddb_destroy(conn);
00154
00155 cddb_end: ;
00156 }
00157 #endif
00158
00159 #define add_meta_val(VLC_META, VAL) \
00160 if ( p_cdda->p_meta && VAL) { \
00161 vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL ); \
00162 dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL ); \
00163 } \
00164
00165 #define add_cddb_meta(FIELD, VLC_META) \
00166 add_meta_val(VLC_META, p_cdda->cddb.disc->FIELD);
00167
00168 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
00169 { \
00170 char psz_buf[100]; \
00171 snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
00172 p_cdda->cddb.disc->FIELD ); \
00173 psz_buf[sizeof(psz_buf)-1] = '\0'; \
00174 add_meta_val(VLC_META, psz_buf); \
00175 }
00176
00177
00178
00179
00180 #define add_info_str(CATEGORY, TITLE, FIELD) \
00181 if (FIELD && strlen(FIELD)) { \
00182 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
00183 _(TITLE), "%s", FIELD ); \
00184 }
00185
00186
00187
00188 #define add_info_val(CATEGORY, TITLE, FMT, FIELD) \
00189 if (FIELD) { \
00190 input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY, \
00191 _(TITLE), FMT, FIELD ); \
00192 }
00193
00194
00195
00196
00197 #define add_cddb_disc_info_str(TITLE, FIELD) \
00198 add_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
00199
00200
00201
00202
00203 #define add_cddb_disc_info_val(TITLE, FMT, FIELD) \
00204 add_info_val("Disc", TITLE, FMT, p_cdda->cddb.disc->FIELD)
00205
00206
00207
00208
00209 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD) \
00210 add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
00211
00212
00213
00214
00215 #define add_cdtext_disc_info_str(TITLE, FIELD) \
00216 add_cdtext_info_str("Disc", TITLE, 0, FIELD)
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 void
00228 CDDAMetaInfoInit( access_t *p_access )
00229 {
00230 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00231
00232 if ( ! p_cdda ) return;
00233
00234 dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d",
00235 p_cdda->i_tracks );
00236
00237 p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
00238 p_cdda->p_meta = vlc_meta_New();
00239
00240 #ifdef HAVE_LIBCDDB
00241 if ( p_cdda->b_cddb_enabled )
00242 {
00243 GetCDDBInfo(p_access, p_cdda);
00244 }
00245
00246 #endif
00247
00248 #define TITLE_MAX 30
00249 {
00250 track_t i_track;
00251
00252 for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
00253 {
00254 p_cdda->p_cdtext[i_track] =
00255 cdio_get_cdtext(p_cdda->p_cdio, i_track);
00256 }
00257 }
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267 void
00268 CDDAMetaInfo( access_t *p_access, track_t i_track )
00269 {
00270 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00271 char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
00272 char *psz_meta_artist = NULL;
00273
00274 if ( ! p_cdda ) return;
00275
00276 dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
00277
00278 #ifdef HAVE_LIBCDDB
00279
00280
00281 if ( p_cdda->b_cddb_enabled && p_cdda->cddb.disc )
00282 {
00283 if( CDIO_INVALID_TRACK == i_track )
00284 {
00285
00286 psz_meta_title = p_cdda->cddb.disc->title;
00287 psz_meta_artist = p_cdda->cddb.disc->artist;
00288 if ( p_cdda->cddb.disc->genre && strlen(p_cdda->cddb.disc->genre) )
00289 add_cddb_meta(genre, VLC_META_GENRE);
00290 if ( 0 != p_cdda->cddb.disc->year )
00291 add_cddb_meta_fmt(year, "%d", VLC_META_DATE );
00292 }
00293 else
00294 {
00295 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
00296 if (t != NULL )
00297 {
00298 if( t->title != NULL && ! p_cdda->b_nav_mode )
00299 {
00300 add_meta_val( VLC_META_TITLE, t->title );
00301 }
00302 if( t->artist != NULL )
00303 {
00304 add_meta_val( VLC_META_ARTIST, t->artist );
00305 }
00306 }
00307 }
00308 }
00309
00310 #endif
00311
00312 #define TITLE_MAX 30
00313 {
00314 track_t i = p_cdda->i_tracks;
00315 const int i_first_track = p_cdda->i_first_track;
00316 char psz_buffer[MSTRTIME_MAX_SIZE];
00317 unsigned int i_track_frames =
00318 cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
00319
00320 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
00321
00322 dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d",
00323 (long int) i_duration, p_cdda->i_tracks );
00324 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
00325 _("Disc"), _("Duration"), "%s",
00326 secstotimestr( psz_buffer, i_duration ) );
00327
00328 if (p_cdda->psz_mcn) {
00329 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
00330 _("Disc"), _("Media Catalog Number (MCN)"), "%s",
00331 p_cdda->psz_mcn );
00332
00333 input_Control( p_cdda->p_input, INPUT_ADD_INFO,
00334 _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
00335 }
00336
00337
00338 #ifdef HAVE_LIBCDDB
00339 if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
00340 {
00341 add_cddb_disc_info_str("Artist (CDDB)", artist);
00342 if ( CDDB_CAT_INVALID != p_cdda->cddb.disc->category )
00343 add_info_str("Disc", "Category (CDDB)",
00344 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
00345 add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
00346 add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
00347 add_cddb_disc_info_str("Genre (CDDB)", genre);
00348 add_cddb_disc_info_str("Title (CDDB)", title);
00349 if ( 0 != p_cdda->cddb.disc->year )
00350 add_cddb_disc_info_val("Year (CDDB)", "%d", year);
00351
00352 }
00353 #endif
00354
00355 if (p_cdda->p_cdtext[0])
00356 {
00357 char *psz_field;
00358
00359 add_cdtext_disc_info_str("Arranger (CD-Text)", CDTEXT_ARRANGER);
00360 add_cdtext_disc_info_str("Composer (CD-Text)", CDTEXT_COMPOSER);
00361 add_cdtext_disc_info_str("Disc ID (CD-Text)", CDTEXT_DISCID);
00362 add_cdtext_disc_info_str("Genre (CD-Text)", CDTEXT_GENRE);
00363 add_cdtext_disc_info_str("Message (CD-Text)", CDTEXT_MESSAGE);
00364 add_cdtext_disc_info_str("Performer (CD-Text)", CDTEXT_PERFORMER);
00365 add_cdtext_disc_info_str("Songwriter (CD-Text)", CDTEXT_SONGWRITER);
00366 add_cdtext_disc_info_str("Title (CD-Text)", CDTEXT_TITLE);
00367
00368 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
00369 if (psz_field && strlen(psz_field)) {
00370 psz_meta_title = psz_field;
00371 }
00372 psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
00373 if (psz_field && strlen(psz_field)) {
00374 psz_meta_artist = psz_field;
00375 }
00376
00377 }
00378
00379 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
00380 {
00381 char psz_track[TITLE_MAX];
00382 const track_t i_track = i_first_track + i;
00383 unsigned int i_track_frames =
00384 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
00385 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
00386
00387 mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
00388 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
00389
00390 snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
00391
00392 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
00393 _("Duration"), "%s",
00394 secstotimestr( psz_buffer, i_duration ) );
00395
00396 input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
00397 _("MRL"), "%s", psz_mrl );
00398 free(psz_mrl);
00399
00400 if (p_cdda->p_cdtext[i_track])
00401 {
00402 add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
00403 i_track, CDTEXT_ARRANGER);
00404 add_cdtext_info_str( psz_track, "Composer (CD-Text)",
00405 i_track, CDTEXT_COMPOSER);
00406 add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
00407 i_track, CDTEXT_DISCID);
00408 add_cdtext_info_str( psz_track, "Genre (CD-Text)",
00409 i_track, CDTEXT_GENRE);
00410 add_cdtext_info_str( psz_track, "Message (CD-Text)",
00411 i_track, CDTEXT_MESSAGE);
00412 add_cdtext_info_str( psz_track, "Performer (CD-Text)",
00413 i_track, CDTEXT_PERFORMER);
00414 add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
00415 i_track, CDTEXT_SONGWRITER);
00416 add_cdtext_info_str( psz_track, "Title (CD-Text)",
00417 i_track, CDTEXT_TITLE);
00418 }
00419
00420 #ifdef HAVE_LIBCDDB
00421 if (p_cdda->b_cddb_enabled)
00422 {
00423 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
00424 if (t != NULL)
00425 {
00426 add_info_str(psz_track, "Artist (CDDB)", t->artist);
00427 add_info_str(psz_track, "Title (CDDB)", t->title);
00428 add_info_str(psz_track, "Extended Data (CDDB)",
00429 t->ext_data);
00430 }
00431 }
00432 #endif
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 if ( CDIO_INVALID_TRACK != i_track )
00449 {
00450 char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
00451 if ( !p_cdda->b_nav_mode ) {
00452 add_meta_val( VLC_META_TITLE, psz_name );
00453 } else
00454 {
00455 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
00456 free(psz_name);
00457 }
00458 if (psz_meta_artist)
00459 add_meta_val( VLC_META_ARTIST, psz_meta_artist );
00460 }
00461
00462 }
00463 }
00464
00465 #define add_format_str_info(val) \
00466 { \
00467 const char *str = val; \
00468 unsigned int len; \
00469 if (val != NULL) { \
00470 len=strlen(str); \
00471 if (len != 0) { \
00472 strncat(tp, str, TEMP_STR_LEN-(tp-temp_str)); \
00473 tp += len; \
00474 } \
00475 saw_control_prefix = false; \
00476 } \
00477 }
00478
00479 #define add_format_num_info(val, fmt) \
00480 { \
00481 char num_str[10]; \
00482 unsigned int len; \
00483 sprintf(num_str, fmt, val); \
00484 len=strlen(num_str); \
00485 if (len != 0) { \
00486 strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str)); \
00487 tp += len; \
00488 } \
00489 saw_control_prefix = false; \
00490 }
00491
00492 static inline bool
00493 want_cddb_info(
00494 cdda_data_t *p_cdda, char *psz_cdtext)
00495 {
00496
00497
00498 #ifdef HAVE_LIBCDDB
00499 return !psz_cdtext ||
00500 (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
00501 #else
00502 return false;
00503 #endif
00504 }
00505
00506
00529 char *
00530 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
00531 const char format_str[], const char *psz_mrl, track_t i_track)
00532 {
00533 #define TEMP_STR_SIZE 256
00534 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
00535 static char temp_str[TEMP_STR_SIZE];
00536 size_t i;
00537 char * tp = temp_str;
00538 vlc_bool_t saw_control_prefix = false;
00539 size_t format_len = strlen(format_str);
00540
00541 memset(temp_str, 0, TEMP_STR_SIZE);
00542
00543 for (i=0; i<format_len; i++)
00544 {
00545 char *psz = NULL;
00546
00547 if (!saw_control_prefix && format_str[i] != '%')
00548 {
00549 *tp++ = format_str[i];
00550 saw_control_prefix = false;
00551 continue;
00552 }
00553
00554 switch(format_str[i])
00555 {
00556 case '%':
00557 if (saw_control_prefix)
00558 {
00559 *tp++ = '%';
00560 }
00561 saw_control_prefix = !saw_control_prefix;
00562 break;
00563 #ifdef HAVE_LIBCDDB
00564 case 'a':
00565 if (p_cdda->p_cdtext[0]
00566 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
00567 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
00568 if (want_cddb_info(p_cdda, psz))
00569 psz = p_cdda->cddb.disc->artist;
00570 goto format_str;
00571 case 'A':
00572 if (p_cdda->p_cdtext[0]
00573 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
00574 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
00575 if (want_cddb_info(p_cdda, psz))
00576 psz = p_cdda->cddb.disc->title;
00577 goto format_str;
00578 case 'C':
00579 if (!p_cdda->b_cddb_enabled) goto not_special;
00580 if (p_cdda->cddb.disc)
00581 add_format_str_info(
00582 CDDB_CATEGORY[p_cdda->cddb.disc->category]);
00583 break;
00584 case 'G':
00585 if (p_cdda->p_cdtext[0]
00586 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
00587 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
00588 if (want_cddb_info(p_cdda, psz))
00589 psz = p_cdda->cddb.disc->genre;
00590 goto format_str;
00591 case 'I':
00592 if (p_cdda->p_cdtext[0]
00593 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
00594 psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
00595 if (want_cddb_info(p_cdda, psz)) {
00596 add_format_num_info(p_cdda->cddb.disc->discid, "%x");
00597 } else if (psz)
00598 add_format_str_info(psz);
00599 break;
00600 case 'Y':
00601 if (!p_cdda->b_cddb_enabled) goto not_special;
00602 if (p_cdda->cddb.disc)
00603 add_format_num_info(p_cdda->cddb.disc->year, "%5d");
00604 break;
00605 case 't':
00606 if ( CDIO_INVALID_TRACK == i_track ) break;
00607 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
00608 {
00609 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
00610 i_track-1);
00611 if (t != NULL && t->title != NULL) {
00612 add_format_str_info(t->title);
00613 } else {
00614 add_format_str_info(psz_mrl);
00615 }
00616 } else {
00617 if (p_cdda->p_cdtext[i_track]
00618 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]) {
00619 add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
00620
00621 } else
00622 add_format_str_info(psz_mrl);
00623 }
00624 break;
00625 case 'p':
00626 if ( CDIO_INVALID_TRACK == i_track ) break;
00627 if (p_cdda->p_cdtext[i_track]
00628 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
00629 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
00630 if (want_cddb_info(p_cdda, psz))
00631 {
00632 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
00633 i_track-1);
00634 if (t != NULL && t->artist != NULL)
00635 psz = t->artist;
00636 }
00637 goto format_str;
00638 case 'e':
00639 if ( CDIO_INVALID_TRACK == i_track ) break;
00640 if (p_cdda->p_cdtext[i_track]
00641 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
00642 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
00643 if (want_cddb_info(p_cdda, psz))
00644 {
00645 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
00646 i_track-1);
00647 if (t != NULL && t->ext_data != NULL)
00648 psz = t->ext_data;
00649 }
00650 goto format_str;
00651 break;
00652 #else
00653 case 'a':
00654 if (p_cdda->p_cdtext[0]
00655 && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
00656 psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
00657 goto format_str;
00658 case 'A':
00659 if (p_cdda->p_cdtext[0]
00660 && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
00661 psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
00662 goto format_str;
00663 case 'G':
00664 if (p_cdda->p_cdtext[0]
00665 && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
00666 psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
00667 goto format_str;
00668 case 'I':
00669 if (p_cdda->p_cdtext[0]
00670 && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
00671 add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
00672 break;
00673 case 'p':
00674 if ( CDIO_INVALID_TRACK == i_track ) break;
00675 if (p_cdda->p_cdtext[i_track]
00676 && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
00677 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
00678 goto format_str;
00679 case 't':
00680 if ( CDIO_INVALID_TRACK == i_track ) break;
00681 if (p_cdda->p_cdtext[i_track]
00682 && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
00683 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
00684 else
00685 psz = psz_mrl;
00686 goto format_str;
00687 case 'e':
00688 if ( CDIO_INVALID_TRACK == i_track ) break;
00689 if (p_cdda->p_cdtext[i_track]
00690 && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
00691 psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
00692 goto format_str;
00693 break;
00694 #endif
00695
00696 case 's':
00697 if ( CDIO_INVALID_TRACK != i_track )
00698 {
00699 char psz_buffer[MSTRTIME_MAX_SIZE];
00700 unsigned int i_track_frames =
00701 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
00702 mtime_t i_duration =
00703 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
00704 add_format_str_info( secstotimestr( psz_buffer,
00705 i_duration ) );
00706 break;
00707 }
00708
00709
00710 case 'S':
00711 {
00712 char psz_buffer[MSTRTIME_MAX_SIZE];
00713 unsigned int i_track_frames =
00714 cdio_get_track_lba(p_cdda->p_cdio,
00715 CDIO_CDROM_LEADOUT_TRACK);
00716 mtime_t i_duration =
00717 i_track_frames / CDIO_CD_FRAMES_PER_SEC;
00718 add_format_str_info( secstotimestr( psz_buffer,
00719 i_duration ) );
00720 break;
00721 }
00722
00723 case 'M':
00724 add_format_str_info(psz_mrl);
00725 break;
00726
00727 case 'm':
00728 add_format_str_info(p_cdda->psz_mcn);
00729 break;
00730
00731 case 'n':
00732 add_format_num_info(p_cdda->i_tracks, "%d");
00733 break;
00734
00735 case 'T':
00736 add_format_num_info(i_track, "%02d");
00737 break;
00738 format_str:
00739 if (psz)
00740 add_format_str_info(psz);
00741 break;
00742 #ifdef HAVE_LIBCDDB
00743 not_special:
00744 #endif
00745 default:
00746 *tp++ = '%';
00747 *tp++ = format_str[i];
00748 saw_control_prefix = false;
00749 }
00750 }
00751 return strdup(temp_str);
00752 }
00753
00754
00755
00756 static char *
00757 CDDAFormatMRL( const access_t *p_access, track_t i_track )
00758 {
00759 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00760 const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX)
00761 + strlen(p_cdda->psz_source) +
00762 + strlen("@T") + strlen("100") + 1;
00763 char *psz_mrl = calloc( 1, psz_mrl_max );
00764
00765 if (CDIO_INVALID_TRACK == i_track)
00766 snprintf(psz_mrl, psz_mrl_max, "%s%s",
00767 CDDA_MRL_PREFIX, p_cdda->psz_source);
00768 else
00769 snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
00770 CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
00771 return psz_mrl;
00772 }
00773
00774
00775
00776
00777 char *
00778 CDDAFormatTitle( const access_t *p_access, track_t i_track )
00779 {
00780
00781 char *config_varname = MODULE_STRING "-title-format";
00782 cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
00783 char *psz_mrl = CDDAFormatMRL( p_access, i_track );
00784
00785 if( psz_mrl )
00786 {
00787 char *psz_name;
00788 #ifdef HAVE_LIBCDDB
00789 if (p_cdda->b_cddb_enabled)
00790 {
00791 config_varname = MODULE_STRING "-cddb-title-format";
00792 }
00793 #endif
00794 psz_name =
00795 CDDAFormatStr( p_access, p_cdda,
00796 config_GetPsz( p_access, config_varname ),
00797 psz_mrl, i_track );
00798 free(psz_mrl);
00799 return psz_name;
00800 }
00801 return(NULL);
00802 }
00803
00804
00805
00806
00807 #define add_playlist_track_info_str(TITLE, FIELD) \
00808 if (FIELD && strlen(FIELD)) \
00809 { \
00810 vlc_input_item_AddInfo( &p_item->input, _("Track"), _(TITLE), \
00811 "%s", FIELD); \
00812 }
00813
00814 static playlist_item_t *
00815 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
00816 playlist_t *p_playlist, playlist_item_t *p_item,
00817 track_t i_track )
00818 {
00819 unsigned int i_track_frames =
00820 cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) -
00821 cdio_get_track_lsn(p_cdda->p_cdio, i_track);
00822 mtime_t i_mduration =
00823 i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
00824 char *psz_title = NULL;
00825 char *psz_mrl = NULL;
00826
00827 playlist_item_t *p_child = NULL;
00828
00829 if( !p_item ) return NULL;
00830
00831 psz_title = CDDAFormatTitle( p_access, i_track ) ;
00832 psz_mrl = CDDAFormatMRL( p_access, i_track ) ;
00833
00834 dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
00835 psz_mrl, psz_title, (long int) i_mduration / 1000000 );
00836
00837 p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
00838 p_child->input.i_duration = i_mduration;
00839 free(psz_mrl);
00840 free(psz_title);
00841
00842 if( !p_child ) return NULL;
00843
00844 playlist_NodeAddItem( p_playlist, p_child,
00845 p_item->pp_parents[0]->i_view,
00846 p_item, PLAYLIST_APPEND, PLAYLIST_END );
00847 playlist_CopyParents( p_item, p_child );
00848
00849 return p_child;
00850 }
00851
00852 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
00853 playlist_item_t *p_item, int i_track,
00854 vlc_bool_t b_single )
00855 {
00856 add_playlist_track_info_str("Source", p_cdda->psz_source);
00857 vlc_input_item_AddInfo( &p_item->input, _("Track"), _("Track Number"),
00858 "%d", i_track );
00859
00860 if (p_cdda->p_cdtext[i_track])
00861 {
00862 const cdtext_t *p = p_cdda->p_cdtext[i_track];
00863 add_playlist_track_info_str("Arranger (CD-Text)",
00864 p->field[CDTEXT_ARRANGER]);
00865 add_playlist_track_info_str("Composer (CD-Text)",
00866 p->field[CDTEXT_COMPOSER]);
00867 add_playlist_track_info_str("Genre (CD-Text)",
00868 p->field[CDTEXT_GENRE]);
00869 add_playlist_track_info_str("Message (CD-Text)",
00870 p->field[CDTEXT_MESSAGE]);
00871 add_playlist_track_info_str("Performer (CD-Text)",
00872 p->field[CDTEXT_PERFORMER]);
00873 add_playlist_track_info_str("Songwriter (CD-Text)",
00874 p->field[CDTEXT_SONGWRITER]);
00875 add_playlist_track_info_str("Title (CD-Text)",
00876 p->field[CDTEXT_TITLE]);
00877 }
00878
00879 #ifdef HAVE_LIBCDDB
00880 if (p_cdda->b_cddb_enabled)
00881 {
00882 cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
00883 i_track-p_cdda->i_first_track);
00884
00885 if (t)
00886 {
00887 if (t->artist)
00888 add_playlist_track_info_str("Artist (CDDB)",
00889 t->artist);
00890 if (t->title)
00891 add_playlist_track_info_str("Title (CDDB)",
00892 t->title);
00893 if (t->ext_data)
00894 add_playlist_track_info_str("Extended information (CDDB)",
00895 t->ext_data);
00896 }
00897 }
00898 #endif
00899
00900 return VLC_SUCCESS;
00901 }
00902
00903
00904
00905
00906 int
00907 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda,
00908 vlc_bool_t b_single_track )
00909 {
00910 int i;
00911 playlist_t * p_playlist = NULL;
00912 const track_t i_first_track = p_cdda->i_first_track;
00913 playlist_item_t *p_item = NULL;
00914 vlc_bool_t b_play = VLC_FALSE;
00915 track_t i_track;
00916
00917 #ifdef HAVE_LIBCDDB
00918 p_cdda->b_cddb_enabled =
00919 config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
00920 if( b_single_track && !p_cdda->b_cddb_enabled )
00921 return VLC_SUCCESS;
00922 #else
00923 if( b_single_track )
00924 return VLC_SUCCESS;
00925 #endif
00926
00927 if (! p_cdda->b_nav_mode ) {
00928 p_playlist = (playlist_t *) vlc_object_find( p_access,
00929 VLC_OBJECT_PLAYLIST,
00930 FIND_ANYWHERE );
00931 if( !p_playlist )
00932 {
00933 msg_Warn( p_access, "can't find playlist" );
00934 return VLC_EGENERIC;
00935 }
00936 }
00937
00938 if( b_single_track || p_cdda->b_nav_mode ) {
00939 i_track = p_cdda->i_track;
00940 }
00941 else
00942 {
00943 i_track = CDIO_INVALID_TRACK;
00944 }
00945 CDDAMetaInfoInit( p_access );
00946 CDDAMetaInfo( p_access, p_cdda->i_track );
00947
00948 if (p_playlist) {
00949
00950 p_item = playlist_LockItemGetByInput( p_playlist,
00951 ((input_thread_t *)p_access->p_parent)->input.p_item );
00952
00953 if( p_item == p_playlist->status.p_item && !b_single_track )
00954 {
00955 b_play = VLC_TRUE;
00956 }
00957 else
00958 {
00959 b_play = VLC_FALSE;
00960 }
00961 }
00962
00963 if( b_single_track && !p_cdda->b_nav_mode )
00964 {
00965
00966
00967
00968 track_t i_track = p_cdda->i_track;
00969 unsigned int i_track_frames =
00970 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
00971
00972 input_title_t *t = p_cdda->p_title[0] =
00973 vlc_input_title_New();
00974
00975 asprintf( &t->psz_name, _("Track %i"), i_track );
00976 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
00977
00978 t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
00979
00980
00981 if (p_item)
00982 {
00983 CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
00984 p_item->input.i_duration = i_track_frames
00985 * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
00986 p_item->input.psz_uri = CDDAFormatMRL(p_access, i_track);
00987 }
00988
00989 p_cdda->i_titles = 1;
00990 p_access->info.i_update = INPUT_UPDATE_TITLE;
00991 }
00992 else
00993 {
00994 input_title_t *t;
00995
00996 if ( !p_cdda->b_nav_mode )
00997 playlist_ItemToNode( p_playlist, p_item );
00998
00999 for( i = 0 ; i < p_cdda->i_tracks ; i++ )
01000 {
01001 playlist_item_t *p_child;
01002 const track_t i_track = i_first_track + i;
01003 unsigned int i_track_frames =
01004 cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
01005
01006 t = p_cdda->p_title[i] = vlc_input_title_New();
01007
01008 asprintf( &t->psz_name, _("Track %i"), i_track );
01009 t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
01010
01011 t->i_length = I64C(1000000) * t->i_size
01012 / CDDA_FREQUENCY_SAMPLE / 4;
01013
01014 if ( ! p_cdda->b_nav_mode ) {
01015 p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
01016 p_item,
01017 i_track );
01018 CDDAAddMetaToItem( p_access, p_cdda, p_child, i_track,
01019 VLC_TRUE );
01020 }
01021 }
01022
01023 p_cdda->i_titles = p_cdda->i_tracks;
01024 p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
01025 if (p_item) {
01026 p_item->input.i_duration =
01027 p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
01028 p_item->input.psz_uri = CDDAFormatMRL(p_access,
01029 p_cdda->i_track);
01030 }
01031 }
01032
01033
01034 if( b_play )
01035 {
01036 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
01037 p_playlist->status.i_view,
01038 p_playlist->status.p_item, NULL );
01039 }
01040
01041 if (p_playlist) vlc_object_release( p_playlist );
01042 return VLC_SUCCESS;
01043 }
01044
01045
01046
01047
01048
01049
01050
01051