]> git.sesse.net Git - vlc/blob - modules/access/cdda/info.c
Copyright fixes
[vlc] / modules / access / cdda / info.c
1 /*****************************************************************************
2  * info.c : CD digital audio input information routines
3  *****************************************************************************
4  * Copyright (C) 2004, 2005 VideoLAN (Centrale Réseaux) and its contributors
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 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "callback.h"      /* FIXME - reorganize callback.h, cdda.h better */
28 #include "cdda.h"          /* private structures. Also #includes vlc things */
29 #include <vlc_playlist.h>  /* Has to come *after* cdda.h */
30
31 #include <cdio/cdio.h>
32 #include <cdio/cdtext.h>
33 #include <cdio/logging.h>
34 #include <cdio/cd_types.h>
35 #include "info.h"
36
37 #ifdef HAVE_ERRNO_H
38 #   include <errno.h>
39 #endif
40
41 static char *CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
42                             const char format_str[], const char *psz_mrl, 
43                             track_t i_track);
44
45 static char *CDDAFormatMRL( const access_t *p_access, track_t i_track );
46
47 #ifdef HAVE_LIBCDDB
48
49 #define free_and_dup(var, val) \
50   if (var) free(var);          \
51   if (val) var=strdup(val);
52
53
54 /* Saves CDDB information about CD-DA via libcddb. */
55 static void 
56 GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
57 {
58     int i, i_matches;
59     cddb_conn_t  *conn = cddb_new();
60     const CdIo_t *p_cdio = p_cdda->p_cdio;
61
62     dbg_print( (INPUT_DBG_CALL), "" );
63
64 #ifdef FIXME_NOW
65     cddb_log_set_handler (uninit_log_handler);
66 #endif
67
68     if (!conn)
69     {
70         msg_Warn( p_access, "Unable to initialize libcddb" );
71         goto cddb_destroy;
72     }
73
74     cddb_set_email_address( conn,
75                             config_GetPsz( p_access,
76                                            MODULE_STRING "-cddb-email") );
77     cddb_set_server_name( conn,
78                           config_GetPsz( p_access,
79                                          MODULE_STRING "-cddb-server") );
80     cddb_set_server_port(conn,
81                          config_GetInt( p_access,
82                                         MODULE_STRING "-cddb-port") );
83
84   /* Set the location of the local CDDB cache directory.
85      The default location of this directory is */
86
87     if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
88         cddb_cache_disable(conn);
89
90     cddb_cache_set_dir(conn,
91                      config_GetPsz( p_access,
92                                     MODULE_STRING "-cddb-cachedir") );
93
94     cddb_set_timeout(conn,
95                    config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
96
97
98     if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" ) )
99     {
100         cddb_http_enable(conn);
101     }
102     else
103     {
104         cddb_http_disable(conn);
105     }
106
107     p_cdda->cddb.disc = cddb_disc_new();
108
109     if (!p_cdda->cddb.disc)
110     {
111         msg_Err( p_access, "Unable to create CDDB disc structure." );
112         goto cddb_end;
113     }
114
115     for(i = 0; i < p_cdda->i_tracks; i++)
116     {
117         track_t i_track =  p_cdda->i_first_track + i;
118         cddb_track_t *t = cddb_track_new();
119         t->frame_offset = cdio_get_track_lba(p_cdio, i_track);
120         cddb_disc_add_track(p_cdda->cddb.disc, t);
121     }
122
123     p_cdda->cddb.disc->length =
124         cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
125         / CDIO_CD_FRAMES_PER_SEC;
126
127     if (!cddb_disc_calc_discid(p_cdda->cddb.disc))
128     {
129         msg_Err( p_access, "CDDB disc ID calculation failed" );
130         goto cddb_destroy;
131     }
132
133     i_matches = cddb_query(conn, p_cdda->cddb.disc);
134
135     if (i_matches > 0)
136     {
137         if (i_matches > 1)
138              msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
139                                  i_matches);
140         cddb_read(conn, p_cdda->cddb.disc);
141
142         if (p_cdda->i_debug & INPUT_DBG_CDDB)
143             cddb_disc_print(p_cdda->cddb.disc);
144
145     }
146     else
147     {
148         msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
149     }
150
151 cddb_destroy:
152     cddb_destroy(conn);
153
154 cddb_end: ;
155 }
156 #endif /*HAVE_LIBCDDB*/
157
158 #define add_meta_val(VLC_META, VAL)                                     \
159   if ( p_cdda->p_meta && VAL) {                                         \
160     vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL );                      \
161     dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL );       \
162   }                                                                     \
163
164 #define add_cddb_meta(FIELD, VLC_META)                                  \
165   add_meta_val(VLC_META, p_cdda->cddb.disc->FIELD);
166
167 #define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META)                 \
168   {                                                                     \
169     char psz_buf[100];                                                  \
170     snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC,                  \
171               p_cdda->cddb.disc->FIELD );                               \
172     psz_buf[sizeof(psz_buf)-1] = '\0';                                  \
173     add_meta_val(VLC_META, psz_buf);                                    \
174   }
175
176 /* Adds a string-valued entry to the stream and media information if
177    the string is not null or the null string.
178  */
179 #define add_info_str(CATEGORY, TITLE, FIELD)                      \
180   if (FIELD && strlen(FIELD)) {                                   \
181     input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY,     \
182                    _(TITLE), "%s", FIELD );                       \
183   }
184
185 /* Adds a numeric-valued entry to the stream and media information
186    if the number is not zero. */
187 #define add_info_val(CATEGORY, TITLE, FMT, FIELD)                 \
188   if (FIELD) {                                                    \
189     input_Control( p_cdda->p_input, INPUT_ADD_INFO, CATEGORY,     \
190                    _(TITLE), FMT, FIELD );                        \
191   }
192
193 /* Adds a CDDB string-valued entry to the stream and media information
194    under category "Disc" if the string is not null or the null string.
195  */
196 #define add_cddb_disc_info_str(TITLE, FIELD)                    \
197   add_info_str("Disc", TITLE, p_cdda->cddb.disc->FIELD)
198
199 /* Adds a CDDB numeric-valued entry to the stream and media information
200    under category "Disc" if the string is not null or the null string.
201  */
202 #define add_cddb_disc_info_val(TITLE, FMT, FIELD)               \
203   add_info_val("Disc", TITLE, FMT, p_cdda->cddb.disc->FIELD)
204
205 /* Adds a CD-Text string-valued entry to the stream and media information
206    under category "Disc" if the string is not null or the null string.
207  */
208 #define add_cdtext_info_str(CATEGORY, TITLE, INDEX, FIELD)              \
209     add_info_str(CATEGORY, TITLE, p_cdda->p_cdtext[INDEX]->field[FIELD])
210
211 /* Adds a CD-Text string-valued entry to the stream and media information
212    under category "Disc" if the string is not null or the null string.
213  */
214 #define add_cdtext_disc_info_str(TITLE, FIELD) \
215   add_cdtext_info_str("Disc", TITLE, 0, FIELD)
216
217
218 /*
219   Saves Meta Information about the CD-DA.
220
221   Meta information used in "stream and media info" or in playlist
222   info. The intialization of CD-Text or CDDB is done here though.
223   Therefore, this should be called before CDDAMetaInfo is called.
224
225  */
226 void 
227 CDDAMetaInfoInit( access_t *p_access )
228 {
229     cdda_data_t *p_cdda   = (cdda_data_t *) p_access->p_sys;
230     
231     if ( ! p_cdda ) return;
232
233     dbg_print( (INPUT_DBG_CALL), "p_cdda->i_tracks %d", 
234                p_cdda->i_tracks );
235
236     p_cdda->psz_mcn = cdio_get_mcn(p_cdda->p_cdio);
237     p_cdda->p_meta = vlc_meta_New();
238
239 #ifdef HAVE_LIBCDDB
240     if ( p_cdda->b_cddb_enabled )
241     {
242         GetCDDBInfo(p_access, p_cdda);
243     }
244
245 #endif /*HAVE_LIBCDDB*/
246     
247 #define TITLE_MAX 30
248     {
249         track_t i_track;
250
251         for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ )
252         {
253             p_cdda->p_cdtext[i_track] =
254               cdio_get_cdtext(p_cdda->p_cdio, i_track);
255         }
256     }
257 }
258
259 /*
260  In the Control routine, we handle Meta Information requests and
261  basically copy what was saved in CDDAMetaInfoInit.
262
263  If i_track is CDIO_INVALID_TRACK we are probably asking about the entire
264  CD.
265  */
266 void 
267 CDDAMetaInfo( access_t *p_access, track_t i_track )
268 {
269     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
270     char *psz_meta_title = CDDAFormatMRL( p_access, i_track );
271     char *psz_meta_artist = NULL;
272     
273     if ( ! p_cdda ) return;
274
275     dbg_print( (INPUT_DBG_CALL), "i_track %d", i_track );
276
277 #ifdef HAVE_LIBCDDB
278
279     /* Set up for Meta and name for CDDB access. */
280     if ( p_cdda->b_cddb_enabled &&  p_cdda->cddb.disc )
281     {
282         if( CDIO_INVALID_TRACK == i_track )
283         {
284
285             psz_meta_title  = p_cdda->cddb.disc->title;
286             psz_meta_artist = p_cdda->cddb.disc->artist;
287             if ( p_cdda->cddb.disc->genre && strlen(p_cdda->cddb.disc->genre) )
288                 add_cddb_meta(genre, VLC_META_GENRE);
289             if ( 0 != p_cdda->cddb.disc->year )
290                 add_cddb_meta_fmt(year, "%d", VLC_META_DATE );
291         }
292         else
293         {
294           cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i_track-1);
295           if (t != NULL )
296           {
297               if( t->title != NULL && ! p_cdda->b_nav_mode )
298               {
299                   add_meta_val( VLC_META_TITLE, t->title );
300               }
301               if( t->artist != NULL )
302               {
303                 add_meta_val( VLC_META_ARTIST, t->artist );
304               }
305           }
306         }
307     }
308
309 #endif /*HAVE_LIBCDDB*/
310     
311 #define TITLE_MAX 30
312     {
313         track_t i = p_cdda->i_tracks;
314         const int i_first_track = p_cdda->i_first_track;
315         char psz_buffer[MSTRTIME_MAX_SIZE];
316         unsigned int i_track_frames = 
317           cdio_get_track_lba(p_cdda->p_cdio, CDIO_CDROM_LEADOUT_TRACK);
318           
319         mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
320
321         dbg_print( INPUT_DBG_META, "Duration %ld, tracks %d", 
322                    (long int) i_duration, p_cdda->i_tracks );
323         input_Control( p_cdda->p_input, INPUT_ADD_INFO,
324                        _("Disc"), _("Duration"), "%s",
325                        secstotimestr( psz_buffer, i_duration ) );
326
327         if (p_cdda->psz_mcn) {
328             input_Control( p_cdda->p_input, INPUT_ADD_INFO,
329                            _("Disc"), _("Media Catalog Number (MCN)"), "%s", 
330                            p_cdda->psz_mcn );
331             
332             input_Control( p_cdda->p_input, INPUT_ADD_INFO,
333                            _("Disc"), _("Tracks"), "%d", p_cdda->i_tracks );
334         }
335         
336
337 #ifdef HAVE_LIBCDDB
338         if (p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
339         {
340           add_cddb_disc_info_str("Artist (CDDB)", artist);
341           if ( CDDB_CAT_INVALID != p_cdda->cddb.disc->category )
342             add_info_str("Disc", "Category (CDDB)",
343                          CDDB_CATEGORY[p_cdda->cddb.disc->category]);
344           add_cddb_disc_info_val("Disc ID (CDDB)", "%x", discid);
345           add_cddb_disc_info_str("Extended Data (CDDB)", ext_data);
346           add_cddb_disc_info_str("Genre (CDDB)",  genre);
347           add_cddb_disc_info_str("Title (CDDB)",  title);
348           if ( 0 != p_cdda->cddb.disc->year ) 
349             add_cddb_disc_info_val("Year (CDDB)", "%d", year);
350
351         }
352 #endif /*HAVE_LIBCDDB*/
353
354         if (p_cdda->p_cdtext[0])
355         {
356             char *psz_field;
357           
358             add_cdtext_disc_info_str("Arranger (CD-Text)",    CDTEXT_ARRANGER);
359             add_cdtext_disc_info_str("Composer (CD-Text)",    CDTEXT_COMPOSER);
360             add_cdtext_disc_info_str("Disc ID (CD-Text)",     CDTEXT_DISCID);
361             add_cdtext_disc_info_str("Genre (CD-Text)",       CDTEXT_GENRE);
362             add_cdtext_disc_info_str("Message (CD-Text)",     CDTEXT_MESSAGE);
363             add_cdtext_disc_info_str("Performer (CD-Text)",   CDTEXT_PERFORMER);
364             add_cdtext_disc_info_str("Songwriter (CD-Text)",  CDTEXT_SONGWRITER);
365             add_cdtext_disc_info_str("Title (CD-Text)",       CDTEXT_TITLE);
366
367             psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
368             if (psz_field && strlen(psz_field)) {   
369               psz_meta_title = psz_field;
370             }
371             psz_field = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
372             if (psz_field && strlen(psz_field)) {   
373               psz_meta_artist = psz_field;
374             }
375             
376         }
377
378         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
379         {
380           char psz_track[TITLE_MAX];
381           const track_t i_track = i_first_track + i;
382           unsigned int i_track_frames = 
383             cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) - 
384             cdio_get_track_lsn(p_cdda->p_cdio, i_track);
385
386           mtime_t i_duration = i_track_frames / CDIO_CD_FRAMES_PER_SEC;
387           char *psz_mrl = CDDAFormatMRL( p_access, i_track );
388           
389           snprintf(psz_track, TITLE_MAX, "%s %02d", _("Track"), i_track);
390
391           input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
392                          _("Duration"), "%s",
393                          secstotimestr( psz_buffer, i_duration ) );
394           
395           input_Control( p_cdda->p_input, INPUT_ADD_INFO, psz_track,
396                          _("MRL"), "%s", psz_mrl );
397           free(psz_mrl);
398           
399           if (p_cdda->p_cdtext[i_track])
400             {
401               add_cdtext_info_str( psz_track, "Arranger (CD-Text)",
402                                    i_track, CDTEXT_ARRANGER);
403               add_cdtext_info_str( psz_track, "Composer (CD-Text)",
404                                    i_track, CDTEXT_COMPOSER);
405               add_cdtext_info_str( psz_track, "Disc ID (CD-Text)",
406                                    i_track, CDTEXT_DISCID);
407               add_cdtext_info_str( psz_track, "Genre (CD-Text)",
408                                    i_track, CDTEXT_GENRE);
409               add_cdtext_info_str( psz_track, "Message (CD-Text)",
410                                    i_track, CDTEXT_MESSAGE);
411               add_cdtext_info_str( psz_track, "Performer (CD-Text)",
412                                    i_track, CDTEXT_PERFORMER);
413               add_cdtext_info_str( psz_track, "Songwriter (CD-Text)",
414                                    i_track, CDTEXT_SONGWRITER);
415               add_cdtext_info_str( psz_track, "Title (CD-Text)",
416                                    i_track, CDTEXT_TITLE);
417             }
418           
419 #ifdef HAVE_LIBCDDB
420           if (p_cdda->b_cddb_enabled)
421             {
422               cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc, i);
423               if (t != NULL)
424                 {
425                   add_info_str(psz_track, "Artist (CDDB)", t->artist);
426                   add_info_str(psz_track, "Title (CDDB)",  t->title);
427                   add_info_str(psz_track, "Extended Data (CDDB)",
428                                t->ext_data);
429                 }
430             }
431 #endif /*HAVE_LIBCDDB*/
432         }
433
434         /* Above we should have set psz_meta_title and psz_meta_artist
435            to CDDB or CD-Text values or the default value depending on
436            availablity and user preferences.
437
438            So now add the title and artist to VLC's meta, and the name
439            as shown in the status bar and playlist entry.
440
441            For playlist mode, the meta title is what's seen at the
442            bottom and in the playlist. For nav-mode playing, it is
443            done by input_control. I don't understand why they do
444            different things. In either case, we may have customized to
445            put in the track name.
446          */
447         if ( CDIO_INVALID_TRACK != i_track ) 
448         {
449             char *psz_name = CDDAFormatTitle( p_access, i_track ) ;
450             if ( !p_cdda->b_nav_mode ) {
451                 add_meta_val( VLC_META_TITLE, psz_name );
452             } else 
453             { 
454                 input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_name );
455                 free(psz_name);
456             }
457             if (psz_meta_artist) 
458               add_meta_val( VLC_META_ARTIST, psz_meta_artist );
459         }
460         
461     }
462 }
463
464 #define add_format_str_info(val)                         \
465   {                                                      \
466     const char *str = val;                               \
467     unsigned int len;                                    \
468     if (val != NULL) {                                   \
469       len=strlen(str);                                   \
470       if (len != 0) {                                    \
471         strncat(tp, str, TEMP_STR_LEN-(tp-temp_str));    \
472         tp += len;                                       \
473       }                                                  \
474       saw_control_prefix = false;                        \
475     }                                                    \
476   }
477
478 #define add_format_num_info(val, fmt)                    \
479   {                                                      \
480     char num_str[10];                                    \
481     unsigned int len;                                    \
482     sprintf(num_str, fmt, val);                          \
483     len=strlen(num_str);                                 \
484     if (len != 0) {                                      \
485       strncat(tp, num_str, TEMP_STR_LEN-(tp-temp_str));  \
486       tp += len;                                         \
487     }                                                    \
488     saw_control_prefix = false;                          \
489   }
490
491 static inline bool
492 want_cddb_info(
493 cdda_data_t *p_cdda, char *psz_cdtext) 
494 {
495   /* We either don't have CD-Text info, or we do but we prefer to get CDDB
496      which means CDDB has been enabled and we were able to retrieve the info.*/
497 #ifdef HAVE_LIBCDDB
498   return !psz_cdtext || 
499     (!p_cdda->b_cdtext_prefer && p_cdda->b_cddb_enabled && p_cdda->cddb.disc);
500 #else
501   return false;
502 #endif
503 }
504
505
506 /*!
507    Take a format string and expand escape sequences, that is sequences that
508    begin with %, with information from the current CD.
509    The expanded string is returned. Here is a list of escape sequences:
510
511    %a : The album artist **
512    %A : The album information **
513    %C : Category **
514    %e : The extended track data
515    %I : CDDB disk ID **
516    %G : Genre **
517    %M : The current MRL
518    %m : The CD-DA Media Catalog Number (MCN)
519    %n : The number of tracks on the CD
520    %p : The artist/performer/composer in the track **
521    %T : The track number **
522    %s : Number of seconds in this track, or seconds in CD if invalid track
523    %S : Number of seconds on the CD
524    %t : The track name or MRL if no name 
525    %Y : The year 19xx or 20xx **
526    %% : a %
527 */
528 char *
529 CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
530                const char format_str[], const char *psz_mrl, track_t i_track)
531 {
532 #define TEMP_STR_SIZE 256
533 #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
534     static char temp_str[TEMP_STR_SIZE];
535     size_t i;
536     char * tp = temp_str;
537     vlc_bool_t saw_control_prefix = false;
538     size_t format_len = strlen(format_str);
539
540     memset(temp_str, 0, TEMP_STR_SIZE);
541
542     for (i=0; i<format_len; i++)
543     {
544         char *psz = NULL;
545
546         if (!saw_control_prefix && format_str[i] != '%')
547         {
548             *tp++ = format_str[i];
549             saw_control_prefix = false;
550             continue;
551         }
552
553         switch(format_str[i])
554         {
555             case '%':
556               if (saw_control_prefix)
557               {
558                   *tp++ = '%';
559               }
560               saw_control_prefix = !saw_control_prefix;
561               break;
562 #ifdef HAVE_LIBCDDB
563             case 'a':
564                 if (p_cdda->p_cdtext[0]
565                     && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
566                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
567                 if (want_cddb_info(p_cdda, psz))
568                   psz = p_cdda->cddb.disc->artist;
569                 goto format_str;
570             case 'A':
571                 if (p_cdda->p_cdtext[0]
572                     && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
573                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
574                 if (want_cddb_info(p_cdda, psz))
575                   psz =  p_cdda->cddb.disc->title;
576                 goto format_str;
577             case 'C':
578                 if (!p_cdda->b_cddb_enabled) goto not_special;
579                 if (p_cdda->cddb.disc)
580                     add_format_str_info(
581                                   CDDB_CATEGORY[p_cdda->cddb.disc->category]);
582                 break;
583             case 'G':
584                 if (p_cdda->p_cdtext[0]
585                     && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
586                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
587                 if (want_cddb_info(p_cdda, psz))
588                   psz = p_cdda->cddb.disc->genre;
589                 goto format_str;
590             case 'I':
591                 if (p_cdda->p_cdtext[0]
592                     && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
593                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_DISCID];
594                 if (want_cddb_info(p_cdda, psz)) {
595                      add_format_num_info(p_cdda->cddb.disc->discid, "%x");
596                 } else if (psz)
597                      add_format_str_info(psz);
598                 break;
599             case 'Y':
600                 if (!p_cdda->b_cddb_enabled) goto not_special;
601                 if (p_cdda->cddb.disc)
602                     add_format_num_info(p_cdda->cddb.disc->year, "%5d");
603                 break;
604             case 't':
605                 if ( CDIO_INVALID_TRACK == i_track ) break;
606                 if (p_cdda && p_cdda->b_cddb_enabled && p_cdda->cddb.disc)
607                 {
608                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
609                                                         i_track-1);
610                     if (t != NULL && t->title != NULL) {
611                       add_format_str_info(t->title);
612                     } else {
613                       add_format_str_info(psz_mrl);
614                     }
615                 } else {
616                   if (p_cdda->p_cdtext[i_track]
617                       && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]) {
618                     add_format_str_info(p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE]);
619                   
620                   } else 
621                     add_format_str_info(psz_mrl);
622                 }
623                 break;
624             case 'p':
625                 if ( CDIO_INVALID_TRACK == i_track ) break;
626                 if (p_cdda->p_cdtext[i_track] 
627                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
628                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
629                 if (want_cddb_info(p_cdda, psz))
630                   {
631                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
632                                                         i_track-1);
633                     if (t != NULL && t->artist != NULL)
634                       psz = t->artist;
635                   }
636                 goto format_str;
637             case 'e':
638                 if ( CDIO_INVALID_TRACK == i_track ) break;
639                 if (p_cdda->p_cdtext[i_track] 
640                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
641                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
642                 if (want_cddb_info(p_cdda, psz))
643                 {
644                     cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
645                                                         i_track-1);
646                     if (t != NULL && t->ext_data != NULL)
647                         psz = t->ext_data;
648                 } 
649                 goto format_str;
650                 break;
651 #else
652             case 'a':
653                 if (p_cdda->p_cdtext[0] 
654                     && p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER])
655                     psz = p_cdda->p_cdtext[0]->field[CDTEXT_PERFORMER];
656                 goto format_str;
657             case 'A':
658                 if (p_cdda->p_cdtext[0] 
659                     && p_cdda->p_cdtext[0]->field[CDTEXT_TITLE])
660                     psz = p_cdda->p_cdtext[0]->field[CDTEXT_TITLE];
661                 goto format_str;
662             case 'G':
663                 if (p_cdda->p_cdtext[0] 
664                     && p_cdda->p_cdtext[0]->field[CDTEXT_GENRE])
665                   psz = p_cdda->p_cdtext[0]->field[CDTEXT_GENRE];
666                 goto format_str;
667             case 'I':
668                 if (p_cdda->p_cdtext[0] 
669                     && p_cdda->p_cdtext[0]->field[CDTEXT_DISCID])
670                   add_format_str_info(p_cdda->p_cdtext[0]->field[CDTEXT_DISCID]);
671                 break;
672             case 'p':
673                 if ( CDIO_INVALID_TRACK == i_track ) break;
674                 if (p_cdda->p_cdtext[i_track] 
675                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER])
676                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_PERFORMER];
677                 goto format_str;
678             case 't':
679                 if ( CDIO_INVALID_TRACK == i_track ) break;
680                 if (p_cdda->p_cdtext[i_track] 
681                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE])
682                     psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_TITLE];
683                 else 
684                     psz = psz_mrl;
685                 goto format_str;
686             case 'e':
687                 if ( CDIO_INVALID_TRACK == i_track ) break;
688                 if (p_cdda->p_cdtext[i_track] 
689                     && p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE])
690                   psz = p_cdda->p_cdtext[i_track]->field[CDTEXT_MESSAGE];
691                 goto format_str;
692                 break;
693 #endif /*HAVE_LIBCDDB*/
694
695             case 's':
696                 if ( CDIO_INVALID_TRACK != i_track )
697                 {
698                     char psz_buffer[MSTRTIME_MAX_SIZE];
699                     unsigned int i_track_frames = 
700                       cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
701                     mtime_t i_duration = 
702                       i_track_frames / CDIO_CD_FRAMES_PER_SEC;
703                     add_format_str_info( secstotimestr( psz_buffer, 
704                                                         i_duration ) );
705                     break;
706                 }
707
708                 /* Fall through to disc duration if CDIO_INVALID_TRACK  */
709             case 'S':
710                 {
711                     char psz_buffer[MSTRTIME_MAX_SIZE];
712                     unsigned int i_track_frames = 
713                       cdio_get_track_lba(p_cdda->p_cdio, 
714                                          CDIO_CDROM_LEADOUT_TRACK);
715                     mtime_t i_duration = 
716                       i_track_frames / CDIO_CD_FRAMES_PER_SEC;
717                     add_format_str_info( secstotimestr( psz_buffer, 
718                                                         i_duration ) );
719                     break;
720                 }
721
722             case 'M':
723               add_format_str_info(psz_mrl);
724               break;
725
726             case 'm':
727               add_format_str_info(p_cdda->psz_mcn);
728               break;
729
730             case 'n':
731               add_format_num_info(p_cdda->i_tracks, "%d");
732               break;
733
734             case 'T':
735               add_format_num_info(i_track, "%02d");
736               break;
737             format_str:
738               if (psz)
739                 add_format_str_info(psz);
740               break;
741 #ifdef HAVE_LIBCDDB
742             not_special:
743 #endif
744             default:
745                 *tp++ = '%';
746                 *tp++ = format_str[i];
747                 saw_control_prefix = false;
748         }
749     }
750     return strdup(temp_str);
751 }
752
753 /* Return a MRL for the given track. The caller must free the 
754    allocated string. */
755 static char *
756 CDDAFormatMRL( const access_t *p_access, track_t i_track )
757 {
758     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
759     const unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) 
760       + strlen(p_cdda->psz_source) +
761       + strlen("@T") + strlen("100") + 1;
762     char *psz_mrl = calloc( 1, psz_mrl_max );
763     
764     if (CDIO_INVALID_TRACK == i_track)
765       snprintf(psz_mrl, psz_mrl_max, "%s%s",
766                CDDA_MRL_PREFIX, p_cdda->psz_source);
767     else 
768       snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
769                CDDA_MRL_PREFIX, p_cdda->psz_source, i_track);
770     return psz_mrl;
771 }
772
773
774 /* Return a title string as specified by the titel format string for the 
775    given track. The caller must free the allocated string. */
776 char *
777 CDDAFormatTitle( const access_t *p_access, track_t i_track )
778
779
780     char *config_varname = MODULE_STRING "-title-format";
781     cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
782     char *psz_mrl = CDDAFormatMRL( p_access, i_track );
783
784     if( psz_mrl ) 
785     {
786         char *psz_name;
787 #ifdef HAVE_LIBCDDB
788         if (p_cdda->b_cddb_enabled)
789         {
790             config_varname = MODULE_STRING "-cddb-title-format";
791         }
792 #endif /*HAVE_LIBCDDB*/
793         psz_name = 
794           CDDAFormatStr( p_access, p_cdda,
795                          config_GetPsz( p_access, config_varname ),
796                          psz_mrl, i_track );
797         free(psz_mrl);
798         return psz_name;
799     }
800     return(NULL);
801 }
802
803 /* Adds a string-valued entry to the playlist information under "Track"
804    if the string is not null or the null string.
805  */
806 #define add_playlist_track_info_str(TITLE, FIELD)                        \
807     if (FIELD && strlen(FIELD))                                          \
808     {                                                                    \
809         vlc_input_item_AddInfo( &p_item->input, _("Track"), _(TITLE),    \
810                               "%s", FIELD);                              \
811     }
812
813 static playlist_item_t *
814 CDDACreatePlaylistItem( const access_t *p_access, cdda_data_t *p_cdda,
815                         playlist_t *p_playlist, playlist_item_t *p_item, 
816                         track_t i_track )
817 {
818   unsigned int i_track_frames = 
819     cdio_get_track_lsn(p_cdda->p_cdio, i_track+1) - 
820     cdio_get_track_lsn(p_cdda->p_cdio, i_track);
821     mtime_t i_mduration = 
822       i_track_frames * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
823     char *psz_title = NULL;
824     char *psz_mrl   = NULL;
825
826     playlist_item_t *p_child = NULL;
827
828     if( !p_item ) return NULL;
829
830     psz_title = CDDAFormatTitle( p_access, i_track ) ;
831     psz_mrl = CDDAFormatMRL( p_access, i_track  ) ;
832
833     dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld",
834                psz_mrl, psz_title, (long int) i_mduration / 1000000 );
835
836     p_child = playlist_ItemNew( p_playlist, psz_mrl, psz_title );
837     p_child->input.i_duration   = i_mduration;
838     free(psz_mrl);
839     free(psz_title);
840
841     if( !p_child ) return NULL;
842
843     playlist_NodeAddItem( p_playlist, p_child,
844                           p_item->pp_parents[0]->i_view,
845                           p_item, PLAYLIST_APPEND, PLAYLIST_END );
846     playlist_CopyParents( p_item, p_child );
847
848     return p_child;
849 }
850
851 int CDDAAddMetaToItem( access_t *p_access, cdda_data_t *p_cdda,
852                        playlist_item_t *p_item, int i_track,
853                        vlc_bool_t b_single )
854 {
855     add_playlist_track_info_str("Source",  p_cdda->psz_source);
856     vlc_input_item_AddInfo( &p_item->input, _("Track"), _("Track Number"),
857                            "%d", i_track );
858
859     if (p_cdda->p_cdtext[i_track])
860     {
861         const cdtext_t *p = p_cdda->p_cdtext[i_track];
862         add_playlist_track_info_str("Arranger (CD-Text)",
863                                     p->field[CDTEXT_ARRANGER]);
864         add_playlist_track_info_str("Composer (CD-Text)",
865                                     p->field[CDTEXT_COMPOSER]);
866         add_playlist_track_info_str("Genre (CD-Text)",
867                                     p->field[CDTEXT_GENRE]);
868         add_playlist_track_info_str("Message (CD-Text)",
869                                     p->field[CDTEXT_MESSAGE]);
870         add_playlist_track_info_str("Performer (CD-Text)",
871                                     p->field[CDTEXT_PERFORMER]);
872         add_playlist_track_info_str("Songwriter (CD-Text)",
873                                     p->field[CDTEXT_SONGWRITER]);
874         add_playlist_track_info_str("Title (CD-Text)",
875                                     p->field[CDTEXT_TITLE]);
876     }
877
878 #ifdef HAVE_LIBCDDB
879     if (p_cdda->b_cddb_enabled)
880     {
881         cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
882                                             i_track-p_cdda->i_first_track);
883
884         if (t)
885         {
886             if (t->artist)
887                 add_playlist_track_info_str("Artist (CDDB)",
888                                              t->artist);
889             if (t->title)
890                 add_playlist_track_info_str("Title (CDDB)",
891                                             t->title);
892             if (t->ext_data)
893                 add_playlist_track_info_str("Extended information (CDDB)",
894                                             t->ext_data);
895         }
896     }
897 #endif /*HAVE_LIBCDDB*/
898
899     return VLC_SUCCESS;
900 }
901
902 /* 
903    Fixes up playlist. 
904 */
905 int
906 CDDAFixupPlaylist( access_t *p_access, cdda_data_t *p_cdda, 
907                    vlc_bool_t b_single_track )
908 {
909     int i;
910     playlist_t * p_playlist = NULL;
911     const track_t i_first_track = p_cdda->i_first_track;
912     playlist_item_t *p_item = NULL;
913     vlc_bool_t b_play = VLC_FALSE;
914     track_t    i_track;
915
916 #ifdef HAVE_LIBCDDB
917     p_cdda->b_cddb_enabled =
918         config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
919     if( b_single_track && !p_cdda->b_cddb_enabled )
920         return VLC_SUCCESS;
921 #else
922     if( b_single_track )
923         return VLC_SUCCESS;
924 #endif
925
926     if (! p_cdda->b_nav_mode ) {
927         p_playlist = (playlist_t *) vlc_object_find( p_access, 
928                                                      VLC_OBJECT_PLAYLIST,
929                                                      FIND_ANYWHERE );
930         if( !p_playlist )
931           {
932               msg_Warn( p_access, "can't find playlist" );
933               return VLC_EGENERIC;
934           }
935     }
936
937     if( b_single_track || p_cdda->b_nav_mode ) {
938         i_track = p_cdda->i_track;
939     }
940     else
941     {
942         i_track = CDIO_INVALID_TRACK;
943     }
944     CDDAMetaInfoInit( p_access );
945     CDDAMetaInfo( p_access, p_cdda->i_track );
946
947     if (p_playlist) {
948
949       p_item = playlist_LockItemGetByInput( p_playlist,
950                         ((input_thread_t *)p_access->p_parent)->input.p_item );
951
952       if( p_item == p_playlist->status.p_item && !b_single_track )
953         {
954           b_play = VLC_TRUE;
955         }
956       else
957         {
958           b_play = VLC_FALSE;
959         }
960     }
961
962     if( b_single_track && !p_cdda->b_nav_mode )
963     {
964         /*May fill out more information when the playlist user interface becomes
965            more mature.
966          */
967         track_t i_track = p_cdda->i_track;
968         unsigned int i_track_frames = 
969           cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
970         
971         input_title_t *t = p_cdda->p_title[0] = //i_track-i_first_track] =
972         vlc_input_title_New();
973
974         asprintf( &t->psz_name, _("Track %i"), i_track );
975         t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
976
977         t->i_length = I64C(1000000) * t->i_size / CDDA_FREQUENCY_SAMPLE / 4;
978
979
980         if (p_item) 
981         {
982             CDDAAddMetaToItem( p_access, p_cdda, p_item, i_track, VLC_FALSE );
983             p_item->input.i_duration = i_track_frames 
984               * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC);
985             p_item->input.psz_uri    = CDDAFormatMRL(p_access, i_track);
986         }
987         
988         p_cdda->i_titles = 1;
989         p_access->info.i_update = INPUT_UPDATE_TITLE;
990     }
991     else
992     {
993         input_title_t *t;
994
995         if ( !p_cdda->b_nav_mode )
996           playlist_ItemToNode( p_playlist, p_item );
997
998         for( i = 0 ; i < p_cdda->i_tracks ; i++ )
999         {
1000             playlist_item_t *p_child;
1001             const track_t i_track = i_first_track + i;
1002             unsigned int i_track_frames = 
1003               cdio_get_track_sec_count(p_cdda->p_cdio, i_track);
1004
1005             t = p_cdda->p_title[i] = vlc_input_title_New();
1006
1007             asprintf( &t->psz_name, _("Track %i"), i_track );
1008             t->i_size = i_track_frames * (int64_t) CDIO_CD_FRAMESIZE_RAW;
1009
1010             t->i_length = I64C(1000000) * t->i_size 
1011               / CDDA_FREQUENCY_SAMPLE / 4;
1012
1013             if ( ! p_cdda->b_nav_mode ) {
1014               p_child = CDDACreatePlaylistItem( p_access, p_cdda, p_playlist,
1015                                                 p_item,
1016                                                 i_track );
1017               CDDAAddMetaToItem( p_access, p_cdda, p_child, i_track, 
1018                                  VLC_TRUE );
1019             }
1020         }
1021
1022         p_cdda->i_titles = p_cdda->i_tracks;
1023         p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
1024         if (p_item) {
1025             p_item->input.i_duration = 
1026               p_access->info.i_size * (CLOCK_FREQ / CDIO_CD_FRAMES_PER_SEC) ;
1027             p_item->input.psz_uri    = CDDAFormatMRL(p_access, 
1028                                                      p_cdda->i_track);
1029         }
1030     }
1031     
1032
1033     if( b_play )
1034     {
1035         playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
1036                           p_playlist->status.i_view,
1037                           p_playlist->status.p_item, NULL );
1038     }
1039
1040     if (p_playlist) vlc_object_release( p_playlist );
1041     return VLC_SUCCESS;
1042 }
1043
1044
1045 /* 
1046  * Local variables:
1047  *  mode: C
1048  *  style: gnu
1049  * End:
1050  */