Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

info.c

00001 /*****************************************************************************
00002  * info.c : CD digital audio input information routines
00003  *****************************************************************************
00004  * Copyright (C) 2004, 2005 the VideoLAN team
00005  * $Id: info.c 8845 2004-09-29 09:00:41Z rocky $
00006  *
00007  * Authors: Rocky Bernstein <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include "callback.h"      /* FIXME - reorganize callback.h, cdda.h better */
00028 #include "cdda.h"          /* private structures. Also #includes vlc things */
00029 #include <vlc_playlist.h>  /* Has to come *after* cdda.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 /* Saves CDDB information about CD-DA via libcddb. */
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   /* Set the location of the local CDDB cache directory.
00085      The default location of this directory is */
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 /*HAVE_LIBCDDB*/
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 /* Adds a string-valued entry to the stream and media information if
00178    the string is not null or the null string.
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 /* Adds a numeric-valued entry to the stream and media information
00187    if the number is not zero. */
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 /* Adds a CDDB string-valued entry to the stream and media information
00195    under category "Disc" if the string is not null or the null string.
00196  */
00197 #define add_cddb_disc_info_str(TITLE, FIELD)                    \
00198   add_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
00199 
00200 /* Adds a CDDB numeric-valued entry to the stream and media information
00201    under category "Disc" if the string is not null or the null string.
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 /* Adds a CD-Text string-valued entry to the stream and media information
00207    under category "Disc" if the string is not null or the null string.
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 /* Adds a CD-Text string-valued entry to the stream and media information
00213    under category "Disc" if the string is not null or the null string.
00214  */
00215 #define add_cdtext_disc_info_str(TITLE, FIELD) \
00216   add_cdtext_info_str("Disc", TITLE, 0, FIELD)
00217 
00218 
00219 /*
00220   Saves Meta Information about the CD-DA.
00221 
00222   Meta information used in "stream and media info" or in playlist
00223   info. The intialization of CD-Text or CDDB is done here though.
00224   Therefore, this should be called before CDDAMetaInfo is called.
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 /*HAVE_LIBCDDB*/
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  In the Control routine, we handle Meta Information requests and
00262  basically copy what was saved in CDDAMetaInfoInit.
00263 
00264  If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
00265  CD.
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     /* Set up for Meta and name for CDDB access. */
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 /*HAVE_LIBCDDB*/
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 /*HAVE_LIBCDDB*/
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 /*HAVE_LIBCDDB*/
00433         }
00434 
00435         /* Above we should have set psz_meta_title and psz_meta_artist
00436            to CDDB or CD-Text values or the default value depending on
00437            availablity and user preferences.
00438 
00439            So now add the title and artist to VLC's meta, and the name
00440            as shown in the status bar and playlist entry.
00441 
00442            For playlist mode, the meta title is what's seen at the
00443            bottom and in the playlist. For nav-mode playing, it is
00444            done by input_control. I don't understand why they do
00445            different things. In either case, we may have customized to
00446            put in the track name.
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   /* We either don't have CD-Text info, or we do but we prefer to get CDDB
00497      which means CDDB has been enabled and we were able to retrieve the info.*/
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 /*HAVE_LIBCDDB*/
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                 /* Fall through to disc duration if CDIO_INVALID_TRACK  */
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 /* Return a MRL for the given track. The caller must free the 
00755    allocated string. */
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 /* Return a title string as specified by the titel format string for the 
00776    given track. The caller must free the allocated string. */
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 /*HAVE_LIBCDDB*/
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 /* Adds a string-valued entry to the playlist information under "Track"
00805    if the string is not null or the null string.
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 /*HAVE_LIBCDDB*/
00899 
00900     return VLC_SUCCESS;
00901 }
00902 
00903 /* 
00904    Fixes up playlist. 
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         /*May fill out more information when the playlist user interface becomes
00966            more mature.
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] = //i_track-i_first_track] =
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  * Local variables:
01048  *  mode: C
01049  *  style: gnu
01050  * End:
01051  */

Generated on Tue Dec 20 10:14:23 2005 for vlc-0.8.4a by  doxygen 1.4.2