1 /*****************************************************************************
2 * cdda.c : CD digital audio input module for vlc
3 *****************************************************************************
4 * Copyright (C) 2000, 2003-2006, 2008-2009 the VideoLAN team
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin@netcourrier.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
27 * - Improve CDDB support (non-blocking, cache, ...)
28 * - Fix tracknumber in MRL
31 /*****************************************************************************
33 *****************************************************************************/
40 #include <vlc_common.h>
41 #include <vlc_plugin.h>
42 #include <vlc_input.h>
43 #include <vlc_access.h>
45 #include <vlc_charset.h> /* ToLocaleDup */
47 #include <vlc_codecs.h> /* For WAVEHEADER */
48 #include "vcd/cdrom.h" /* For CDDA_DATA_SIZE */
51 #include <cddb/cddb.h>
55 /*****************************************************************************
57 *****************************************************************************/
58 static int Open ( vlc_object_t
* );
59 static void Close( vlc_object_t
* );
61 #define CACHING_TEXT N_("Caching value in ms")
62 #define CACHING_LONGTEXT N_( \
63 "Default caching value for Audio CDs. This " \
64 "value should be set in milliseconds." )
67 set_shortname( N_("Audio CD") )
68 set_description( N_("Audio CD input") )
69 set_capability( "access", 10 )
70 set_category( CAT_INPUT
)
71 set_subcategory( SUBCAT_INPUT_ACCESS
)
72 set_callbacks( Open
, Close
)
74 add_usage_hint( N_("[cdda:][device][@[track]]") )
75 add_integer( "cdda-caching", DEFAULT_PTS_DELAY
/ 1000, NULL
, CACHING_TEXT
,
76 CACHING_LONGTEXT
, true )
79 add_integer( "cdda-track", 0 , NULL
, NULL
, NULL
, true )
81 add_integer( "cdda-first-sector", -1, NULL
, NULL
, NULL
, true )
83 add_integer( "cdda-last-sector", -1, NULL
, NULL
, NULL
, true )
87 add_string( "cddb-server", "freedb.freedb.org", N_( "CDDB Server" ),
88 N_( "Address of the CDDB server to use." ), true )
89 add_integer( "cddb-port", 8880, NULL
, N_( "CDDB port" ),
90 N_( "CDDB Server port to use." ), true )
93 add_shortcut( "cdda", "cddasimple" )
97 /* how many blocks VCDRead will read in each loop */
98 #define CDDA_BLOCKS_ONCE 20
99 #define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDDA_DATA_SIZE)
101 /*****************************************************************************
102 * Access: local prototypes
103 *****************************************************************************/
106 vcddev_t
*vcddev
; /* vcd device descriptor */
108 /* Current position */
109 int i_sector
; /* Current Sector */
110 int *p_sectors
; /* Track sectors */
112 /* Wave header for the output data */
113 WAVEHEADER waveheader
;
121 static block_t
*Block( access_t
* );
122 static int Seek( access_t
*, uint64_t );
123 static int Control( access_t
*, int, va_list );
125 static int GetTracks( access_t
*p_access
, input_item_t
*p_current
);
128 static cddb_disc_t
*GetCDDBInfo( access_t
*p_access
, int i_titles
, int *p_sectors
);
131 /*****************************************************************************
133 *****************************************************************************/
134 static int Open( vlc_object_t
*p_this
)
136 access_t
*p_access
= (access_t
*)p_this
;
141 if( !p_access
->psz_filepath
|| !*p_access
->psz_filepath
)
143 /* Only when selected */
144 if( !p_access
->psz_access
|| !*p_access
->psz_access
)
147 psz_name
= var_InheritString( p_this
, "cd-audio" );
151 else psz_name
= ToLocaleDup( p_access
->psz_filepath
);
154 if( psz_name
[0] && psz_name
[1] == ':' &&
155 psz_name
[2] == '\\' && psz_name
[3] == '\0' ) psz_name
[2] = '\0';
159 if( (vcddev
= ioctl_Open( VLC_OBJECT(p_access
), psz_name
) ) == NULL
)
161 msg_Warn( p_access
, "could not open %s", psz_name
);
167 /* Set up p_access */
168 STANDARD_BLOCK_ACCESS_INIT
169 p_sys
->vcddev
= vcddev
;
171 /* Do we play a single track ? */
172 p_sys
->i_track
= var_InheritInteger( p_access
, "cdda-track" ) - 1;
174 if( p_sys
->i_track
< 0 )
176 /* We only do separate items if the whole disc is requested */
177 input_thread_t
*p_input
= access_GetParentInput( p_access
);
182 input_item_t
*p_current
= input_GetItem( p_input
);
184 i_ret
= GetTracks( p_access
, p_current
);
186 vlc_object_release( p_input
);
193 /* Build a WAV header for the output data */
194 memset( &p_sys
->waveheader
, 0, sizeof(WAVEHEADER
) );
195 SetWLE( &p_sys
->waveheader
.Format
, 1 ); /*WAVE_FORMAT_PCM*/
196 SetWLE( &p_sys
->waveheader
.BitsPerSample
, 16);
197 p_sys
->waveheader
.MainChunkID
= VLC_FOURCC('R', 'I', 'F', 'F');
198 p_sys
->waveheader
.Length
= 0; /* we just don't know */
199 p_sys
->waveheader
.ChunkTypeID
= VLC_FOURCC('W', 'A', 'V', 'E');
200 p_sys
->waveheader
.SubChunkID
= VLC_FOURCC('f', 'm', 't', ' ');
201 SetDWLE( &p_sys
->waveheader
.SubChunkLength
, 16);
202 SetWLE( &p_sys
->waveheader
.Modus
, 2);
203 SetDWLE( &p_sys
->waveheader
.SampleFreq
, 44100);
204 SetWLE( &p_sys
->waveheader
.BytesPerSample
,
205 2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
206 SetDWLE( &p_sys
->waveheader
.BytesPerSec
,
207 2*16/8 /*BytesPerSample*/ * 44100 /*SampleFreq*/ );
208 p_sys
->waveheader
.DataChunkID
= VLC_FOURCC('d', 'a', 't', 'a');
209 p_sys
->waveheader
.DataLength
= 0; /* we just don't know */
211 p_sys
->i_first_sector
= var_InheritInteger( p_access
,
212 "cdda-first-sector" );
213 p_sys
->i_last_sector
= var_InheritInteger( p_access
,
214 "cdda-last-sector" );
215 /* Tracknumber in MRL */
216 if( p_sys
->i_first_sector
< 0 || p_sys
->i_last_sector
< 0 )
218 const int i_titles
= ioctl_GetTracksMap( VLC_OBJECT(p_access
),
219 p_sys
->vcddev
, &p_sys
->p_sectors
);
220 if( p_sys
->i_track
>= i_titles
)
222 msg_Err( p_access
, "invalid track number" );
225 p_sys
->i_first_sector
= p_sys
->p_sectors
[p_sys
->i_track
];
226 p_sys
->i_last_sector
= p_sys
->p_sectors
[p_sys
->i_track
+1];
229 p_sys
->i_sector
= p_sys
->i_first_sector
;
230 p_access
->info
.i_size
= (p_sys
->i_last_sector
- p_sys
->i_first_sector
)
231 * (int64_t)CDDA_DATA_SIZE
;
235 var_Create( p_access
, "cdda-caching", VLC_VAR_INTEGER
|VLC_VAR_DOINHERIT
);
240 free( p_sys
->p_sectors
);
241 ioctl_Close( VLC_OBJECT(p_access
), p_sys
->vcddev
);
246 /*****************************************************************************
248 *****************************************************************************/
249 static void Close( vlc_object_t
*p_this
)
251 access_t
*p_access
= (access_t
*)p_this
;
252 access_sys_t
*p_sys
= p_access
->p_sys
;
254 free( p_sys
->p_sectors
);
255 ioctl_Close( p_this
, p_sys
->vcddev
);
259 /*****************************************************************************
260 * Block: read data (CDDA_DATA_ONCE)
261 *****************************************************************************/
262 static block_t
*Block( access_t
*p_access
)
264 access_sys_t
*p_sys
= p_access
->p_sys
;
265 int i_blocks
= CDDA_BLOCKS_ONCE
;
268 if( p_sys
->i_track
< 0 ) p_access
->info
.b_eof
= true;
270 /* Check end of file */
271 if( p_access
->info
.b_eof
) return NULL
;
273 if( !p_sys
->b_header
)
275 /* Return only the header */
276 p_block
= block_New( p_access
, sizeof( WAVEHEADER
) );
277 memcpy( p_block
->p_buffer
, &p_sys
->waveheader
, sizeof(WAVEHEADER
) );
278 p_sys
->b_header
= true;
282 if( p_sys
->i_sector
>= p_sys
->i_last_sector
)
284 p_access
->info
.b_eof
= true;
288 /* Don't read too far */
289 if( p_sys
->i_sector
+ i_blocks
>= p_sys
->i_last_sector
)
290 i_blocks
= p_sys
->i_last_sector
- p_sys
->i_sector
;
292 /* Do the actual reading */
293 if( !( p_block
= block_New( p_access
, i_blocks
* CDDA_DATA_SIZE
) ) )
295 msg_Err( p_access
, "cannot get a new block of size: %i",
296 i_blocks
* CDDA_DATA_SIZE
);
300 if( ioctl_ReadSectors( VLC_OBJECT(p_access
), p_sys
->vcddev
,
301 p_sys
->i_sector
, p_block
->p_buffer
, i_blocks
, CDDA_TYPE
) < 0 )
303 msg_Err( p_access
, "cannot read sector %i", p_sys
->i_sector
);
304 block_Release( p_block
);
306 /* Try to skip one sector (in case of bad sectors) */
308 p_access
->info
.i_pos
+= CDDA_DATA_SIZE
;
312 /* Update a few values */
313 p_sys
->i_sector
+= i_blocks
;
314 p_access
->info
.i_pos
+= p_block
->i_buffer
;
319 /****************************************************************************
321 ****************************************************************************/
322 static int Seek( access_t
*p_access
, uint64_t i_pos
)
324 access_sys_t
*p_sys
= p_access
->p_sys
;
326 /* Next sector to read */
327 p_sys
->i_sector
= p_sys
->i_first_sector
+ i_pos
/ CDDA_DATA_SIZE
;
328 assert( p_sys
->i_sector
>= 0 );
329 p_access
->info
.i_pos
= i_pos
;
334 /*****************************************************************************
336 *****************************************************************************/
337 static int Control( access_t
*p_access
, int i_query
, va_list args
)
341 case ACCESS_CAN_SEEK
:
342 case ACCESS_CAN_FASTSEEK
:
343 case ACCESS_CAN_PAUSE
:
344 case ACCESS_CAN_CONTROL_PACE
:
345 *va_arg( args
, bool* ) = true;
348 case ACCESS_GET_PTS_DELAY
:
349 *va_arg( args
, int64_t * ) =
350 var_GetInteger( p_access
, "cdda-caching" ) * INT64_C(1000);
353 case ACCESS_SET_PAUSE_STATE
:
356 case ACCESS_GET_TITLE_INFO
:
357 case ACCESS_SET_TITLE
:
358 case ACCESS_GET_META
:
359 case ACCESS_SET_SEEKPOINT
:
360 case ACCESS_SET_PRIVATE_ID_STATE
:
361 case ACCESS_GET_CONTENT_TYPE
:
365 msg_Warn( p_access
, "unimplemented query in control" );
371 static int GetTracks( access_t
*p_access
, input_item_t
*p_current
)
373 access_sys_t
*p_sys
= p_access
->p_sys
;
375 const int i_titles
= ioctl_GetTracksMap( VLC_OBJECT(p_access
),
376 p_sys
->vcddev
, &p_sys
->p_sectors
);
380 msg_Err( p_access
, "unable to count tracks" );
381 else if( i_titles
<= 0 )
382 msg_Err( p_access
, "no audio tracks found" );
383 return VLC_EGENERIC
;;
387 input_item_SetName( p_current
, "Audio CD" );
389 const char *psz_album
= NULL
;
390 const char *psz_year
= NULL
;
391 const char *psz_genre
= NULL
;
392 const char *psz_artist
= NULL
;
393 const char *psz_description
= NULL
;
395 /* Return true if the given string is not NULL and not empty */
396 #define NONEMPTY( psz ) ( (psz) && *(psz) )
397 /* If the given string is NULL or empty, fill it by the return value of 'code' */
398 #define ON_EMPTY( psz, code ) do { if( !NONEMPTY( psz) ) { (psz) = code; } } while(0)
400 /* Retreive CDDB information */
402 char psz_year_buffer
[4+1];
403 msg_Dbg( p_access
, "fetching infos with CDDB" );
404 cddb_disc_t
*p_disc
= GetCDDBInfo( p_access
, i_titles
, p_sys
->p_sectors
);
407 psz_album
= cddb_disc_get_title( p_disc
);
408 psz_genre
= cddb_disc_get_genre( p_disc
);
411 const unsigned i_year
= cddb_disc_get_year( p_disc
);
414 psz_year
= psz_year_buffer
;
415 snprintf( psz_year_buffer
, sizeof(psz_year_buffer
), "%u", i_year
);
418 /* Set artist only if unique */
419 for( int i
= 0; i
< i_titles
; i
++ )
421 cddb_track_t
*t
= cddb_disc_get_track( p_disc
, i
);
424 const char *psz_track_artist
= cddb_track_get_artist( t
);
425 if( psz_artist
&& psz_track_artist
&&
426 strcmp( psz_artist
, psz_track_artist
) )
431 psz_artist
= psz_track_artist
;
437 vlc_meta_t
**pp_cd_text
;
440 if( ioctl_GetCdText( VLC_OBJECT(p_access
), p_sys
->vcddev
, &pp_cd_text
, &i_cd_text
) )
442 msg_Dbg( p_access
, "CD-TEXT information missing" );
447 /* Retrieve CD-TEXT information but prefer CDDB */
448 if( i_cd_text
> 0 && pp_cd_text
[0] )
450 const vlc_meta_t
*p_disc
= pp_cd_text
[0];
451 ON_EMPTY( psz_album
, vlc_meta_Get( p_disc
, vlc_meta_Album
) );
452 ON_EMPTY( psz_genre
, vlc_meta_Get( p_disc
, vlc_meta_Genre
) );
453 ON_EMPTY( psz_artist
, vlc_meta_Get( p_disc
, vlc_meta_Artist
) );
454 ON_EMPTY( psz_description
, vlc_meta_Get( p_disc
, vlc_meta_Description
) );
457 if( NONEMPTY( psz_album
) )
459 input_item_SetName( p_current
, psz_album
);
460 input_item_SetAlbum( p_current
, psz_album
);
463 if( NONEMPTY( psz_genre
) )
464 input_item_SetGenre( p_current
, psz_genre
);
466 if( NONEMPTY( psz_artist
) )
467 input_item_SetArtist( p_current
, psz_artist
);
469 if( NONEMPTY( psz_year
) )
470 input_item_SetDate( p_current
, psz_year
);
472 if( NONEMPTY( psz_description
) )
473 input_item_SetDescription( p_current
, psz_description
);
475 const mtime_t i_duration
= (int64_t)( p_sys
->p_sectors
[i_titles
] - p_sys
->p_sectors
[0] ) *
476 CDDA_DATA_SIZE
* 1000000 / 44100 / 2 / 2;
477 input_item_SetDuration( p_current
, i_duration
);
479 input_item_node_t
*p_root
= input_item_node_Create( p_current
);
481 /* Build title table */
482 for( int i
= 0; i
< i_titles
; i
++ )
484 input_item_t
*p_input_item
;
486 char *psz_uri
, *psz_opt
, *psz_first
, *psz_last
;
489 msg_Dbg( p_access
, "track[%d] start=%d", i
, p_sys
->p_sectors
[i
] );
492 if( asprintf( &psz_uri
, "cdda://%s", p_access
->psz_location
) == -1 )
494 if( asprintf( &psz_opt
, "cdda-track=%i", i
+1 ) == -1 )
496 if( asprintf( &psz_first
, "cdda-first-sector=%i",p_sys
->p_sectors
[i
] ) == -1 )
498 if( asprintf( &psz_last
, "cdda-last-sector=%i", p_sys
->p_sectors
[i
+1] ) == -1 )
501 /* Define a "default name" */
502 if( asprintf( &psz_name
, _("Audio CD - Track %02i"), (i
+1) ) == -1 )
505 /* Create playlist items */
506 const mtime_t i_duration
= (int64_t)( p_sys
->p_sectors
[i
+1] - p_sys
->p_sectors
[i
] ) *
507 CDDA_DATA_SIZE
* 1000000 / 44100 / 2 / 2;
508 p_input_item
= input_item_NewWithType( VLC_OBJECT( p_access
),
509 psz_uri
, psz_name
, 0, NULL
, 0, i_duration
,
511 input_item_CopyOptions( p_current
, p_input_item
);
512 input_item_AddOption( p_input_item
, psz_first
, VLC_INPUT_OPTION_TRUSTED
);
513 input_item_AddOption( p_input_item
, psz_last
, VLC_INPUT_OPTION_TRUSTED
);
514 input_item_AddOption( p_input_item
, psz_opt
, VLC_INPUT_OPTION_TRUSTED
);
516 const char *psz_track_title
= NULL
;
517 const char *psz_track_artist
= NULL
;
518 const char *psz_track_genre
= NULL
;
519 const char *psz_track_description
= NULL
;
522 /* Retreive CDDB information */
525 cddb_track_t
*t
= cddb_disc_get_track( p_disc
, i
);
528 psz_track_title
= cddb_track_get_title( t
);
529 psz_track_artist
= cddb_track_get_artist( t
);
534 /* Retreive CD-TEXT information but prefer CDDB */
535 if( i
+1 < i_cd_text
&& pp_cd_text
[i
+1] )
537 const vlc_meta_t
*t
= pp_cd_text
[i
+1];
539 ON_EMPTY( psz_track_title
, vlc_meta_Get( t
, vlc_meta_Title
) );
540 ON_EMPTY( psz_track_artist
, vlc_meta_Get( t
, vlc_meta_Artist
) );
541 ON_EMPTY( psz_track_genre
, vlc_meta_Get( t
, vlc_meta_Genre
) );
542 ON_EMPTY( psz_track_description
, vlc_meta_Get( t
, vlc_meta_Description
) );
546 ON_EMPTY( psz_track_artist
, psz_artist
);
547 ON_EMPTY( psz_track_genre
, psz_genre
);
548 ON_EMPTY( psz_track_description
, psz_description
);
551 if( NONEMPTY( psz_track_title
) )
553 input_item_SetName( p_input_item
, psz_track_title
);
554 input_item_SetTitle( p_input_item
, psz_track_title
);
557 if( NONEMPTY( psz_track_artist
) )
558 input_item_SetArtist( p_input_item
, psz_track_artist
);
560 if( NONEMPTY( psz_track_genre
) )
561 input_item_SetGenre( p_input_item
, psz_track_genre
);
563 if( NONEMPTY( psz_track_description
) )
564 input_item_SetDescription( p_input_item
, psz_track_description
);
566 if( NONEMPTY( psz_album
) )
567 input_item_SetAlbum( p_input_item
, psz_album
);
569 if( NONEMPTY( psz_year
) )
570 input_item_SetDate( p_input_item
, psz_year
);
573 snprintf( psz_num
, sizeof(psz_num
), "%d", 1+i
);
574 input_item_SetTrackNum( p_input_item
, psz_num
);
576 input_item_node_AppendItem( p_root
, p_input_item
);
577 vlc_gc_decref( p_input_item
);
578 free( psz_uri
); free( psz_opt
); free( psz_name
);
579 free( psz_first
); free( psz_last
);
584 input_item_node_PostAndDelete( p_root
);
587 for( int i
= 0; i
< i_cd_text
; i
++ )
589 vlc_meta_t
*p_meta
= pp_cd_text
[i
];
592 vlc_meta_Delete( p_meta
);
598 cddb_disc_destroy( p_disc
);
604 static cddb_disc_t
*GetCDDBInfo( access_t
*p_access
, int i_titles
, int *p_sectors
)
606 if( var_InheritInteger( p_access
, "album-art" ) == ALBUM_ART_WHEN_ASKED
)
610 cddb_conn_t
*p_cddb
= cddb_new();
613 msg_Warn( p_access
, "unable to use CDDB" );
618 char *psz_tmp
= var_InheritString( p_access
, "cddb-server" );
621 cddb_set_server_name( p_cddb
, psz_tmp
);
625 cddb_set_server_port( p_cddb
, var_InheritInteger( p_access
, "cddb-port" ) );
627 cddb_set_email_address( p_cddb
, "vlc@videolan.org" );
630 cddb_cache_disable( p_cddb
);
632 // cddb_cache_set_dir( p_cddb,
633 // var_InheritString( p_access,
634 // MODULE_STRING "-cddb-cachedir") );
636 cddb_set_timeout( p_cddb
, 10 );
639 cddb_http_disable( p_cddb
);
642 cddb_disc_t
*p_disc
= cddb_disc_new();
645 msg_Err( p_access
, "unable to create CDDB disc structure." );
649 int64_t i_length
= 0;
650 for( int i
= 0; i
< i_titles
; i
++ )
652 cddb_track_t
*t
= cddb_track_new();
653 cddb_track_set_frame_offset( t
, p_sectors
[i
] );
654 cddb_disc_add_track( p_disc
, t
);
655 const int64_t i_size
= ( p_sectors
[i
+1] - p_sectors
[i
] ) *
656 (int64_t)CDDA_DATA_SIZE
;
657 i_length
+= INT64_C(1000000) * i_size
/ 44100 / 4 ;
660 cddb_disc_set_length( p_disc
, (int)(i_length
/1000000) );
662 if( !cddb_disc_calc_discid( p_disc
) )
664 msg_Err( p_access
, "CDDB disc ID calculation failed" );
668 const int i_matches
= cddb_query( p_cddb
, p_disc
);
671 msg_Warn( p_access
, "CDDB error: %s", cddb_error_str(errno
) );
674 else if( i_matches
== 0 )
676 msg_Dbg( p_access
, "Couldn't find any matches in CDDB." );
679 else if( i_matches
> 1 )
680 msg_Warn( p_access
, "found %d matches in CDDB. Using first one.", i_matches
);
682 cddb_read( p_cddb
, p_disc
);
684 cddb_destroy( p_cddb
);
689 cddb_disc_destroy( p_disc
);
690 cddb_destroy( p_cddb
);
693 #endif /*HAVE_LIBCDDB*/