info.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:23k
源码类别:

多媒体

开发平台:

MultiPlatform

  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 $
  6.  *
  7.  * Authors: Rocky Bernstein <rocky@panix.com>
  8.  *
  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.
  13.  *
  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.
  18.  *
  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.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include "callback.h"      /* FIXME - reorganize callback.h, cdda.h better */
  27. #include "cdda.h"          /* private structures. Also #includes vlc things */
  28. #include <vlc_playlist.h>  /* Has to come *after* cdda.h */
  29. #include <cdio/cdio.h>
  30. #include <cdio/cdtext.h>
  31. #include <cdio/logging.h>
  32. #include <cdio/cd_types.h>
  33. #include "info.h"
  34. #ifdef HAVE_ERRNO_H
  35. #   include <errno.h>
  36. #endif
  37. #define CDDA_MRL_PREFIX "cddax://"
  38. #ifdef HAVE_LIBCDDB
  39. #define free_and_dup(var, val) 
  40.   if (var) free(var);          
  41.   if (val) var=strdup(val);
  42. static void
  43. GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
  44. {
  45.   int i, i_matches;
  46.   cddb_conn_t  *conn = cddb_new();
  47.   const CdIo *p_cdio = p_cdda->p_cdio;
  48.   dbg_print( (INPUT_DBG_CALL), "" );
  49. #ifdef FIXME_NOW
  50.   cddb_log_set_handler (uninit_log_handler);
  51. #endif
  52.   
  53.   if (!conn) {
  54.     msg_Warn( p_access, "Unable to initialize libcddb" );
  55.     goto cddb_destroy;
  56.   }
  57.   
  58.   cddb_set_email_address( conn,
  59.   config_GetPsz( p_access,
  60.  MODULE_STRING "-cddb-email") );
  61.   
  62.   cddb_set_server_name( conn,
  63. config_GetPsz( p_access,
  64.        MODULE_STRING "-cddb-server") );
  65.   
  66.   cddb_set_server_port(conn,
  67.        config_GetInt( p_access,
  68.       MODULE_STRING "-cddb-port") );
  69.   
  70.   /* Set the location of the local CDDB cache directory.
  71.      The default location of this directory is */
  72.   
  73.   if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
  74.     cddb_cache_disable(conn);
  75.   
  76.   cddb_cache_set_dir(conn,
  77.      config_GetPsz( p_access,
  78.     MODULE_STRING "-cddb-cachedir") );
  79.   
  80.   cddb_set_timeout(conn,
  81.    config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
  82.   
  83.   
  84.   if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" )) {
  85.     cddb_http_enable(conn);
  86.   } else
  87.     cddb_http_disable(conn);
  88.   
  89.   p_cdda->cddb.disc = cddb_disc_new();
  90.   if (!p_cdda->cddb.disc) {
  91.     msg_Err( p_access, "Unable to create CDDB disc structure." );
  92.     goto cddb_end;
  93.   }
  94.   
  95.   for(i = 0; i < p_cdda->i_tracks; i++) {
  96.     track_t i_track =  p_cdda->i_first_track + i;
  97.     cddb_track_t *t = cddb_track_new();
  98.     t->frame_offset = cdio_get_track_lba(p_cdio, i_track);
  99.     cddb_disc_add_track(p_cdda->cddb.disc, t);
  100.   }
  101.   
  102.   p_cdda->cddb.disc->length =
  103.     cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
  104.     / CDIO_CD_FRAMES_PER_SEC;
  105.   
  106.   if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
  107.     msg_Err( p_access, "CDDB disc ID calculation failed" );
  108.     goto cddb_destroy;
  109.   }
  110.   
  111.   i_matches = cddb_query(conn, p_cdda->cddb.disc);
  112.   if (i_matches > 0) {
  113.     if (i_matches > 1)
  114.       msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
  115. i_matches);
  116.     cddb_read(conn, p_cdda->cddb.disc);
  117.     
  118.     if (p_cdda->i_debug & INPUT_DBG_CDDB)
  119.       cddb_disc_print(p_cdda->cddb.disc);
  120.     
  121.   } else {
  122.     msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
  123.   }
  124.  cddb_destroy:
  125.   cddb_destroy(conn);
  126.  cddb_end: ;
  127. }
  128. #endif /*HAVE_LIBCDDB*/
  129. #define add_meta_val(FIELD, VLC_META, VAL)
  130.   if ( p_cdda->p_meta && VAL) {
  131.     vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL );
  132.     dbg_print( INPUT_DBG_META, "field %s: %sn", VLC_META, VAL );
  133.   }
  134.     
  135. #define add_cddb_meta(FIELD, VLC_META)
  136.   add_meta_val(FIELD, VLC_META, p_cdda->cddb.disc->FIELD);
  137.     
  138. #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META)
  139.   {
  140.     char psz_buf[100];
  141.     snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC,
  142.       p_cdda->cddb.disc->FIELD );
  143.     psz_buf[sizeof(psz_buf)-1] = '';
  144.     add_meta_val(FIELD, VLC_META, psz_buf);
  145.   }    
  146. /* Adds a string-valued entry to the stream and media information if
  147.    the string is not null or the null string.
  148.  */
  149. #define add_info_str(CATEGORY, TITLE, FIELD)   
  150.   if (FIELD && strlen(FIELD)) {   
  151.     input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY,   
  152.    _(TITLE), "%s", FIELD );   
  153.   }  
  154.   
  155. /* Adds a numeric-valued entry to the stream and media information 
  156.    if the number is not zero. */
  157. #define add_info_val(CATEGORY, TITLE, FMT, FIELD)   
  158.   if (FIELD) {   
  159.     input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY,   
  160.    _(TITLE), FMT, FIELD );   
  161.   }  
  162. /* Adds a CDDB string-valued entry to the stream and media information
  163.    under category "Disc" if the string is not null or the null string.
  164.  */
  165. #define add_cddb_disc_info_str(TITLE, FIELD)
  166.   add_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
  167. /* Adds a CDDB numeric-valued entry to the stream and media information
  168.    under category "Disc" if the string is not null or the null string.
  169.  */
  170. #define add_cddb_disc_info_val(TITLE, FMT, FIELD)
  171.   add_info_val("Disc", TITLE, FMT, p_cdda->cddb.disc->FIELD)
  172. /* Adds a CD-Text string-valued entry to the stream and media information
  173.    under category "Disc" if the string is not null or the null string.
  174.  */
  175. #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD)
  176.     add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
  177. /* Adds a CD-Text string-valued entry to the stream and media information
  178.    under category "Disc" if the string is not null or the null string.
  179.  */
  180. #define add_cdtext_disc_info_str(TITLE, FIELD)
  181.   add_cdtext_info_str("Disc", TITLE, 0, FIELD)
  182. /*
  183.  Gets and saves CDDA Meta Information about the CD.
  184.  In the Control routine, we handle Meta Information requests and
  185.  basically copy what we've saved here.
  186.  Meta information is also used elsewhere such as in "stream and
  187.  media info" or in playlist info. The intialization of CD-Text or CDDB
  188.  is done here though.
  189.  */    
  190. void 
  191. CDDAMetaInfo( access_t *p_access  )
  192. {
  193.   cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
  194.   if ( ! p_cdda ) return;
  195.   p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
  196.   
  197. #ifdef HAVE_LIBCDDB
  198.   if ( p_cdda->b_cddb_enabled ) {
  199.     
  200.     GetCDDBInfo(p_access, p_cdda);
  201.     
  202.     if ( p_cdda->cddb.disc ) {
  203.       
  204.       p_cdda->p_meta = vlc_meta_New();
  205.       
  206.       add_cddb_meta(title,    VLC_META_CDDB_TITLE);
  207.       add_cddb_meta(artist,   VLC_META_CDDB_ARTIST);
  208.       add_cddb_meta(genre,    VLC_META_CDDB_GENRE);
  209.       add_cddb_meta(ext_data, VLC_META_CDDB_EXT_DATA);
  210.       
  211.       add_cddb_meta_fmt(year,   "%d", VLC_META_CDDB_YEAR);
  212.       add_cddb_meta_fmt(discid, "%x", VLC_META_CDDB_DISCID);
  213.     }
  214.   }
  215. #endif /*HAVE_LIBCDDB*/
  216. #define TITLE_MAX 30
  217.   
  218.   {
  219.     track_t i = p_cdda->i_tracks;
  220.     const int i_first_track = p_cdda->i_first_track;
  221.     char psz_buffer[MSTRTIME_MAX_SIZE];
  222.     mtime_t i_duration =
  223.       (p_cdda->lsn[i_first_track+i] - p_cdda->lsn[i_first_track])
  224.       / CDIO_CD_FRAMES_PER_SEC;
  225.     
  226.     dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
  227.     input_Control( p_cdda->p_input, INPUT_ADD_INFO, 
  228.    _("Disc"), _("Duration"), "%s",
  229.    secstotimestr( psz_buffer, i_duration ) );
  230.     
  231. #ifdef HAVE_LIBCDDB
  232.     if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc) {
  233.       add_cddb_disc_info_str("Artist (CDDB)", artist);
  234.       add_cddb_disc_info_str("Genre (CDDB)",  genre);
  235.       add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
  236.       add_cddb_disc_info_val("Year (CDDB)", "%d", year);
  237.       add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
  238.       add_cddb_disc_info_str("Title (CDDB)",  title);
  239.       add_info_str("Disc", "Category (CDDB)",  
  240.    CDDB_CATEGORY[p_cdda->cddb.disc->category]);
  241.     }
  242. #endif /*HAVE_LIBCDDB*/
  243.     p_cdda->p_cdtext[0] = cdio_get_cdtext(p_cdda->p_cdio, 0);
  244.     if (p_cdda->p_cdtext[0]) {
  245.       add_cdtext_disc_info_str("Arranger (CD-Text)",    CDTEXT_ARRANGER);
  246.       add_cdtext_disc_info_str("Composer (CD-Text)",    CDTEXT_COMPOSER);
  247.       add_cdtext_disc_info_str("Disc ID (CD-Text)",     CDTEXT_DISCID);
  248.       add_cdtext_disc_info_str("Genre (CD-Text)",       CDTEXT_GENRE);
  249.       add_cdtext_disc_info_str("Message (CD-Text)",     CDTEXT_MESSAGE);
  250.       add_cdtext_disc_info_str("Performer (CD-Text)",   CDTEXT_PERFORMER);
  251.       add_cdtext_disc_info_str("Songwriter (CD-Text)",  CDTEXT_SONGWRITER);
  252.       add_cdtext_disc_info_str("Title (CD-Text)",       CDTEXT_TITLE);
  253.     }
  254.     
  255.     for( i = 0 ; i < p_cdda->i_tracks ; i++ ) {
  256.       char psz_track[TITLE_MAX];
  257.       const track_t i_track = i_first_track + i;
  258.       mtime_t i_duration = (p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track]) 
  259.         / CDIO_CD_FRAMES_PER_SEC;
  260.       snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
  261.       input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track, 
  262.      _("Duration"), "%s", 
  263.      secstotimestr( psz_buffer, i_duration ) );
  264.       p_cdda->p_cdtext[i_track] = cdio_get_cdtext(p_cdda->p_cdio, i_track);
  265.       
  266.       if (p_cdda->p_cdtext[i_track]) {
  267. add_cdtext_info_str(psz_track, "Arranger (CD-Text)",    i_track, 
  268.     CDTEXT_ARRANGER);
  269. add_cdtext_info_str(psz_track, "Composer (CD-Text)",    i_track, 
  270.     CDTEXT_COMPOSER);
  271. add_cdtext_info_str(psz_track, "Disc ID (CD-Text)",     i_track, 
  272.     CDTEXT_DISCID);
  273. add_cdtext_info_str(psz_track, "Genre (CD-Text)",       i_track, 
  274.     CDTEXT_GENRE);
  275. add_cdtext_info_str(psz_track, "Message (CD-Text)",     i_track, 
  276.     CDTEXT_MESSAGE);
  277. add_cdtext_info_str(psz_track, "Performer (CD-Text)",   i_track, 
  278.     CDTEXT_PERFORMER);
  279. add_cdtext_info_str(psz_track, "Songwriter (CD-Text)",  i_track, 
  280.     CDTEXT_SONGWRITER);
  281. add_cdtext_info_str(psz_track, "Title (CD-Text)",       i_track, 
  282.     CDTEXT_TITLE);
  283.       }
  284. #ifdef HAVE_LIBCDDB
  285.       if (p_cdda->b_cddb_enabled) {
  286.         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
  287.         if (t != NULL) {
  288.   add_info_str(psz_track, "Artist (CDDB)", t->artist);
  289.   add_info_str(psz_track, "Title (CDDB)",  t->title);
  290.   add_info_str(psz_track, "Extended Data (CDDB)", t->ext_data);
  291.         }
  292.       }
  293. #endif /*HAVE_LIBCDDB*/
  294.     }
  295.   }
  296. }
  297. #define add_format_str_info(val)                         
  298.   {                                                      
  299.     const char *str = val;                               
  300.     unsigned int len;                                    
  301.     if (val != NULL) {                                   
  302.       len=strlen(str);                                   
  303.       if (len != 0) {                                    
  304.         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    
  305.         tp += len;                                       
  306.       }                                                  
  307.       saw_control_prefix = false;                        
  308.     }                                                    
  309.   }
  310. #define add_format_num_info(val, fmt)                    
  311.   {                                                      
  312.     char num_str[10];                                    
  313.     unsigned int len;                                    
  314.     sprintf(num_str, fmt, val);                          
  315.     len=strlen(num_str);                                 
  316.     if (len != 0) {                                      
  317.       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  
  318.       tp += len;                                         
  319.     }                                                    
  320.     saw_control_prefix = false;                          
  321.   }
  322. /*!
  323.    Take a format string and expand escape sequences, that is sequences that
  324.    begin with %, with information from the current CD.
  325.    The expanded string is returned. Here is a list of escape sequences:
  326.    %a : The album artist **
  327.    %A : The album information **
  328.    %C : Category **
  329.    %I : CDDB disk ID **
  330.    %G : Genre **
  331.    %M : The current MRL
  332.    %m : The CD-DA Media Catalog Number (MCN)
  333.    %n : The number of tracks on the CD
  334.    %p : The artist/performer/composer in the track **
  335.    %T : The track number **
  336.    %s : Number of seconds in this track
  337.    %t : The name **
  338.    %Y : The year 19xx or 20xx **
  339.    %% : a %
  340. */
  341. static char *
  342. CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
  343.        const char format_str[], const char *mrl, track_t i_track)
  344. {
  345. #define TEMP_STR_SIZE 256
  346. #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
  347.   static char    temp_str[TEMP_STR_SIZE];
  348.   size_t i;
  349.   char * tp = temp_str;
  350.   vlc_bool_t saw_control_prefix = false;
  351.   size_t format_len = strlen(format_str);
  352.   memset(temp_str, 0, TEMP_STR_SIZE);
  353.   for (i=0; i<format_len; i++) {
  354.     if (!saw_control_prefix && format_str[i] != '%') {
  355.       *tp++ = format_str[i];
  356.       saw_control_prefix = false;
  357.       continue;
  358.     }
  359.     switch(format_str[i]) {
  360.     case '%':
  361.       if (saw_control_prefix) {
  362.         *tp++ = '%';
  363.       }
  364.       saw_control_prefix = !saw_control_prefix;
  365.       break;
  366. #ifdef HAVE_LIBCDDB
  367.     case 'a':
  368.       if (!p_cdda->b_cddb_enabled) goto not_special;
  369.       if (p_cdda->cddb.disc)
  370. add_format_str_info(p_cdda->cddb.disc->artist);
  371.       break;
  372.     case 'A':
  373.       if (!p_cdda->b_cddb_enabled) goto not_special;
  374.       if (p_cdda->cddb.disc)
  375. add_format_str_info(p_cdda->cddb.disc->title);
  376.       break;
  377.     case 'C':
  378.       if (!p_cdda->b_cddb_enabled) goto not_special;
  379.       if (p_cdda->cddb.disc)
  380. add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
  381.       break;
  382.     case 'G':
  383.       if (!p_cdda->b_cddb_enabled) goto not_special;
  384.       if (p_cdda->cddb.disc)
  385. add_format_str_info(p_cdda->cddb.disc->genre);
  386.       break;
  387.     case 'I':
  388.       if (!p_cdda->b_cddb_enabled) goto not_special;
  389.       if (p_cdda->cddb.disc)
  390. add_format_num_info(p_cdda->cddb.disc->discid, "%x");
  391.       break;
  392.     case 'Y':
  393.       if (!p_cdda->b_cddb_enabled) goto not_special;
  394.       if (p_cdda->cddb.disc)
  395. add_format_num_info(p_cdda->cddb.disc->year, "%5d");
  396.       break;
  397.     case 't':
  398.       if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc) {
  399.         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
  400.                                             i_track-1);
  401.         if (t != NULL && t->title != NULL)
  402.           add_format_str_info(t->title);
  403.       } else goto not_special;
  404.       break;
  405.     case 'p':
  406.       if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc) {
  407.         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
  408.                                             i_track-1);
  409.         if (t != NULL && t->artist != NULL)
  410.           add_format_str_info(t->artist);
  411.       } else goto not_special;
  412.       break;
  413.     case 'e':
  414.       if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc) {
  415.         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
  416.                                             i_track-1);
  417.         if (t != NULL && t->ext_data != NULL)
  418.           add_format_str_info(t->ext_data);
  419.       } else goto not_special;
  420.       break;
  421.     case 's':
  422.       if (p_cdda->b_cddb_enabled) {
  423.         char psz_buffer[MSTRTIME_MAX_SIZE];
  424.         mtime_t i_duration = (p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track]) 
  425.           / CDIO_CD_FRAMES_PER_SEC;
  426.         add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
  427.       } else 
  428. goto not_special;
  429.       break;
  430. #endif /*HAVE_LIBCDDB*/
  431.     case 'M':
  432.       add_format_str_info(mrl);
  433.       break;
  434.     case 'm':
  435.       add_format_str_info(p_cdda->psz_mcn);
  436.       break;
  437.     case 'n':
  438.       add_format_num_info(p_cdda->i_tracks, "%d");
  439.       break;
  440.     case 'T':
  441.       add_format_num_info(i_track, "%02d");
  442.       break;
  443. #ifdef HAVE_LIBCDDB
  444.     not_special:
  445. #endif
  446.     default:
  447.       *tp++ = '%';
  448.       *tp++ = format_str[i];
  449.       saw_control_prefix = false;
  450.     }
  451.   }
  452.   return strdup(temp_str);
  453. }
  454. /* Adds a string-valued entry to the playlist information under "Track"
  455.    if the string is not null or the null string.
  456.  */
  457. #define add_playlist_track_info_str(TITLE, FIELD)   
  458.   if (FIELD && strlen(FIELD)) {   
  459.     playlist_ItemAddInfo( p_item, _("Track"), _(TITLE),   
  460.   "%s", FIELD);   
  461.   }  
  462. void
  463. CDDACreatePlaylistItem(const access_t *p_access, cdda_data_t *p_cdda,
  464.                        playlist_t *p_playlist, track_t i_track,
  465.                        char *psz_mrl, int psz_mrl_max,
  466.                        const char *psz_source, int playlist_operation,
  467.                        int i_pos)
  468. {
  469.   mtime_t i_duration = (p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track])
  470.     * (1000000 / CDIO_CD_FRAMES_PER_SEC) ;
  471.   char *psz_title;
  472.   char *config_varname = MODULE_STRING "-title-format";
  473.   playlist_item_t *p_item;
  474. #ifdef HAVE_LIBCDDB
  475.   if (p_cdda->b_cddb_enabled) {
  476.     config_varname = MODULE_STRING "-cddb-title-format";
  477.   }
  478. #endif /*HAVE_LIBCDDB*/
  479.   snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
  480.            CDDA_MRL_PREFIX, psz_source, i_track);
  481.   psz_title = CDDAFormatStr(p_access, p_cdda,
  482.     config_GetPsz( p_access, config_varname ),
  483.     psz_mrl, i_track);
  484.   dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
  485.              psz_mrl, psz_title, (long int) i_duration / 1000000 , i_pos );
  486.   playlist_AddExt( p_playlist, psz_mrl, psz_title, playlist_operation,
  487.                          i_pos, i_duration , NULL, 0);
  488.   if( i_pos == PLAYLIST_END ) i_pos = p_playlist->i_size - 1;
  489.   vlc_mutex_lock( &p_playlist->object_lock );
  490.   p_item = playlist_ItemGetByPos( p_playlist, i_pos );
  491.   vlc_mutex_unlock( &p_playlist->object_lock );
  492.   if( !p_item )
  493.       return;
  494.   vlc_mutex_lock( &p_item->input.lock );
  495.   add_playlist_track_info_str("Source",  psz_source);
  496.   playlist_ItemAddInfo( p_item, _("Track"), _("Track Number"), "%d", i_track );
  497.   if (p_cdda->p_cdtext[0]) {
  498.     const cdtext_t *p = p_cdda->p_cdtext[0];
  499.     add_playlist_track_info_str("Disc Arranger (CD-Text)",
  500. p->field[CDTEXT_ARRANGER]);
  501.     add_playlist_track_info_str("Disc Composer (CD-Text)",
  502. p->field[CDTEXT_COMPOSER]);
  503.     add_playlist_track_info_str("Disc ID (CD-Text)",
  504. p->field[CDTEXT_DISCID]);
  505.     add_playlist_track_info_str("Disc Genre (CD-Text)",
  506. p->field[CDTEXT_GENRE]);
  507.     add_playlist_track_info_str("Disc Message (CD-Text)",
  508. p->field[CDTEXT_MESSAGE]);
  509.     add_playlist_track_info_str("Disc Performer (CD-Text)",
  510. p->field[CDTEXT_PERFORMER]);
  511.     add_playlist_track_info_str("Disc Songwriter (CD-Text)",
  512. p->field[CDTEXT_SONGWRITER]);
  513.     add_playlist_track_info_str("Disc Title (CD-Text)",
  514. p->field[CDTEXT_TITLE]);
  515.   }
  516.   if (p_cdda->p_cdtext[i_track]) {
  517.     const cdtext_t *p = p_cdda->p_cdtext[i_track];
  518.     add_playlist_track_info_str("Arranger (CD-Text)",
  519. p->field[CDTEXT_ARRANGER]);
  520.     add_playlist_track_info_str("Composer (CD-Text)",
  521. p->field[CDTEXT_COMPOSER]);
  522.     add_playlist_track_info_str("Genre (CD-Text)",
  523. p->field[CDTEXT_GENRE]);
  524.     add_playlist_track_info_str("Message (CD-Text)",
  525. p->field[CDTEXT_MESSAGE]);
  526.     add_playlist_track_info_str("Performer (CD-Text)",
  527. p->field[CDTEXT_PERFORMER]);
  528.     add_playlist_track_info_str("Songwriter (CD-Text)",
  529. p->field[CDTEXT_SONGWRITER]);
  530.     add_playlist_track_info_str("Title (CD-Text)",
  531. p->field[CDTEXT_TITLE]);
  532.   }
  533.   
  534. #ifdef HAVE_LIBCDDB
  535.   if (p_cdda->b_cddb_enabled) {
  536.     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, 
  537. i_track-p_cdda->i_first_track);
  538.     add_playlist_track_info_str("Disc Album (CDDB)",
  539.        p_cdda->cddb.disc->title);
  540.     add_playlist_track_info_str("Disc Artist(s) (CDDB)", 
  541.        p_cdda->cddb.disc->artist);
  542.     add_playlist_track_info_str("Disc Category (CDDB)", 
  543.        CDDB_CATEGORY[p_cdda->cddb.disc->category]);
  544.     add_playlist_track_info_str("Disc Genre (CDDB)", 
  545.        p_cdda->cddb.disc->genre);
  546.     if ( p_cdda->cddb.disc->discid ) {
  547.       playlist_ItemAddInfo( p_item, _("Track"), _("Disc ID (CDDB)"),
  548.     "%x", p_cdda->cddb.disc->discid );
  549.     }
  550.     if (p_cdda->cddb.disc->year != 0) {
  551.       playlist_ItemAddInfo( p_item, _("Track"), _("Year (CDDB)"), 
  552.     "%5d", p_cdda->cddb.disc->year );
  553.     }
  554.     
  555.     if (t) {
  556.       if (t->artist)
  557. add_playlist_track_info_str("Track Artist (CDDB)", 
  558.    t->artist);
  559.       if (t->title)
  560. add_playlist_track_info_str("Track Title (CDDB)", 
  561.    t->title);
  562.     }
  563.   }
  564. #endif /*HAVE_LIBCDDB*/
  565.   vlc_mutex_unlock( &p_item->input.lock );
  566. }
  567. int
  568. CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda, 
  569.    const char *psz_source, vlc_bool_t b_single_track )
  570. {
  571.   int i;
  572.   playlist_t * p_playlist;
  573.   char       * psz_mrl;
  574.   unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
  575.     strlen("@T") + strlen("100") + 1;
  576.   const track_t i_first_track = p_cdda->i_first_track;
  577. #ifdef HAVE_LIBCDDB
  578.   p_cdda->b_cddb_enabled =
  579.     config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
  580.   if( b_single_track && !p_cdda->b_cddb_enabled ) return VLC_SUCCESS;
  581. #else
  582.   if( b_single_track ) return VLC_SUCCESS;
  583. #endif
  584.   psz_mrl = malloc( psz_mrl_max );
  585.   if( psz_mrl == NULL )
  586.     {
  587.       msg_Warn( p_access, "out of memory" );
  588.       return VLC_ENOMEM;
  589.     }
  590.   p_playlist = (playlist_t *) vlc_object_find( p_access, VLC_OBJECT_PLAYLIST,
  591.                                                FIND_ANYWHERE );
  592.   if( !p_playlist )
  593.     {
  594.       msg_Warn( p_access, "can't find playlist" );
  595.       free(psz_mrl);
  596.       return VLC_EGENERIC;
  597.     }
  598.   CDDAMetaInfo(p_access);
  599.   if (b_single_track) {
  600.     /* May fill out more information when the playlist user interface becomes
  601.        more mature.
  602.      */
  603.     track_t i_track = p_cdda->i_track;
  604.     input_title_t *t = p_cdda->p_title[i_track-i_first_track] = 
  605.       vlc_input_title_New();
  606.     asprintf( &t->psz_name, _("Track %i"), i_track );
  607.     t->i_size = p_access->info.i_size =
  608.       ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) * 
  609.       (int64_t) CDIO_CD_FRAMESIZE_RAW;
  610.     t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
  611.     CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i_track,
  612.                            psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
  613.                            p_playlist->i_index);
  614.     p_cdda->i_titles = 1;
  615.   } else {
  616.     for( i = 0 ; i < p_cdda->i_tracks ; i++ )
  617.       {
  618. const track_t i_track = i_first_track + i;
  619. input_title_t *t = p_cdda->p_title[i] = vlc_input_title_New();
  620. asprintf( &t->psz_name, _("Track %i"), i_track );
  621. t->i_size = ( p_cdda->lsn[i_track+1] - p_cdda->lsn[i_track] ) *
  622.   (int64_t) CDIO_CD_FRAMESIZE_RAW;
  623. t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
  624. CDDACreatePlaylistItem(p_access, p_cdda, p_playlist, i_track, 
  625.        psz_mrl, psz_mrl_max, psz_source, 
  626.        PLAYLIST_APPEND, PLAYLIST_END);
  627.       }
  628.     p_cdda->i_titles = p_cdda->i_tracks; /* should be +1 */
  629.     p_access->info.i_size = 
  630.       (p_cdda->lsn[i_first_track + p_cdda->i_tracks] 
  631.        - p_cdda->lsn[i_first_track]) * (int64_t) CDIO_CD_FRAMESIZE_RAW;
  632.   }
  633.   return VLC_SUCCESS;
  634. }