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
* );
62 set_shortname( N_("Audio CD") )
63 set_description( N_("Audio CD input") )
64 set_capability( "access", 10 )
65 set_category( CAT_INPUT
)
66 set_subcategory( SUBCAT_INPUT_ACCESS
)
67 set_callbacks( Open
, Close
)
69 add_usage_hint( N_("[cdda:][device][@[track]]") )
70 add_integer( "cdda-track", 0 , NULL
, NULL
, true )
72 add_integer( "cdda-first-sector", -1, NULL
, NULL
, true )
74 add_integer( "cdda-last-sector", -1, NULL
, NULL
, true )
78 add_string( "cddb-server", "freedb.freedb.org", N_( "CDDB Server" ),
79 N_( "Address of the CDDB server to use." ), true )
80 add_integer( "cddb-port", 8880, N_( "CDDB port" ),
81 N_( "CDDB Server port to use." ), true )
84 add_shortcut( "cdda", "cddasimple" )
88 /* how many blocks VCDRead will read in each loop */
89 #define CDDA_BLOCKS_ONCE 20
90 #define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDDA_DATA_SIZE)
92 /*****************************************************************************
93 * Access: local prototypes
94 *****************************************************************************/
97 vcddev_t
*vcddev
; /* vcd device descriptor */
99 /* Current position */
100 int i_sector
; /* Current Sector */
101 int *p_sectors
; /* Track sectors */
103 /* Wave header for the output data */
104 WAVEHEADER waveheader
;
112 static block_t
*Block( access_t
* );
113 static int Seek( access_t
*, uint64_t );
114 static int Control( access_t
*, int, va_list );
116 static int GetTracks( access_t
*p_access
, input_item_t
*p_current
);
119 static cddb_disc_t
*GetCDDBInfo( access_t
*p_access
, int i_titles
, int *p_sectors
);
122 /*****************************************************************************
124 *****************************************************************************/
125 static int Open( vlc_object_t
*p_this
)
127 access_t
*p_access
= (access_t
*)p_this
;
132 if( !p_access
->psz_filepath
|| !*p_access
->psz_filepath
)
134 /* Only when selected */
135 if( !p_access
->psz_access
|| !*p_access
->psz_access
)
138 psz_name
= var_InheritString( p_this
, "cd-audio" );
142 else psz_name
= ToLocaleDup( p_access
->psz_filepath
);
144 #if defined( WIN32 ) || defined( __OS2__ )
145 if( psz_name
[0] && psz_name
[1] == ':' &&
146 psz_name
[2] == '\\' && psz_name
[3] == '\0' ) psz_name
[2] = '\0';
150 if( (vcddev
= ioctl_Open( VLC_OBJECT(p_access
), psz_name
) ) == NULL
)
152 msg_Warn( p_access
, "could not open %s", psz_name
);
158 /* Set up p_access */
159 STANDARD_BLOCK_ACCESS_INIT
160 p_sys
->vcddev
= vcddev
;
162 /* Do we play a single track ? */
163 p_sys
->i_track
= var_InheritInteger( p_access
, "cdda-track" ) - 1;
165 if( p_sys
->i_track
< 0 )
167 /* We only do separate items if the whole disc is requested */
168 input_thread_t
*p_input
= access_GetParentInput( p_access
);
173 input_item_t
*p_current
= input_GetItem( p_input
);
175 i_ret
= GetTracks( p_access
, p_current
);
177 vlc_object_release( p_input
);
184 /* Build a WAV header for the output data */
185 memset( &p_sys
->waveheader
, 0, sizeof(WAVEHEADER
) );
186 SetWLE( &p_sys
->waveheader
.Format
, 1 ); /*WAVE_FORMAT_PCM*/
187 SetWLE( &p_sys
->waveheader
.BitsPerSample
, 16);
188 p_sys
->waveheader
.MainChunkID
= VLC_FOURCC('R', 'I', 'F', 'F');
189 p_sys
->waveheader
.Length
= 0; /* we just don't know */
190 p_sys
->waveheader
.ChunkTypeID
= VLC_FOURCC('W', 'A', 'V', 'E');
191 p_sys
->waveheader
.SubChunkID
= VLC_FOURCC('f', 'm', 't', ' ');
192 SetDWLE( &p_sys
->waveheader
.SubChunkLength
, 16);
193 SetWLE( &p_sys
->waveheader
.Modus
, 2);
194 SetDWLE( &p_sys
->waveheader
.SampleFreq
, 44100);
195 SetWLE( &p_sys
->waveheader
.BytesPerSample
,
196 2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
197 SetDWLE( &p_sys
->waveheader
.BytesPerSec
,
198 2*16/8 /*BytesPerSample*/ * 44100 /*SampleFreq*/ );
199 p_sys
->waveheader
.DataChunkID
= VLC_FOURCC('d', 'a', 't', 'a');
200 p_sys
->waveheader
.DataLength
= 0; /* we just don't know */
202 p_sys
->i_first_sector
= var_InheritInteger( p_access
,
203 "cdda-first-sector" );
204 p_sys
->i_last_sector
= var_InheritInteger( p_access
,
205 "cdda-last-sector" );
206 /* Tracknumber in MRL */
207 if( p_sys
->i_first_sector
< 0 || p_sys
->i_last_sector
< 0 )
209 const int i_titles
= ioctl_GetTracksMap( VLC_OBJECT(p_access
),
210 p_sys
->vcddev
, &p_sys
->p_sectors
);
211 if( p_sys
->i_track
>= i_titles
)
213 msg_Err( p_access
, "invalid track number" );
216 p_sys
->i_first_sector
= p_sys
->p_sectors
[p_sys
->i_track
];
217 p_sys
->i_last_sector
= p_sys
->p_sectors
[p_sys
->i_track
+1];
220 p_sys
->i_sector
= p_sys
->i_first_sector
;
221 p_access
->info
.i_size
= (p_sys
->i_last_sector
- p_sys
->i_first_sector
)
222 * (int64_t)CDDA_DATA_SIZE
;
228 free( p_sys
->p_sectors
);
229 ioctl_Close( VLC_OBJECT(p_access
), p_sys
->vcddev
);
234 /*****************************************************************************
236 *****************************************************************************/
237 static void Close( vlc_object_t
*p_this
)
239 access_t
*p_access
= (access_t
*)p_this
;
240 access_sys_t
*p_sys
= p_access
->p_sys
;
242 free( p_sys
->p_sectors
);
243 ioctl_Close( p_this
, p_sys
->vcddev
);
247 /*****************************************************************************
248 * Block: read data (CDDA_DATA_ONCE)
249 *****************************************************************************/
250 static block_t
*Block( access_t
*p_access
)
252 access_sys_t
*p_sys
= p_access
->p_sys
;
253 int i_blocks
= CDDA_BLOCKS_ONCE
;
256 if( p_sys
->i_track
< 0 ) p_access
->info
.b_eof
= true;
258 /* Check end of file */
259 if( p_access
->info
.b_eof
) return NULL
;
261 if( !p_sys
->b_header
)
263 /* Return only the header */
264 p_block
= block_New( p_access
, sizeof( WAVEHEADER
) );
265 memcpy( p_block
->p_buffer
, &p_sys
->waveheader
, sizeof(WAVEHEADER
) );
266 p_sys
->b_header
= true;
270 if( p_sys
->i_sector
>= p_sys
->i_last_sector
)
272 p_access
->info
.b_eof
= true;
276 /* Don't read too far */
277 if( p_sys
->i_sector
+ i_blocks
>= p_sys
->i_last_sector
)
278 i_blocks
= p_sys
->i_last_sector
- p_sys
->i_sector
;
280 /* Do the actual reading */
281 if( !( p_block
= block_New( p_access
, i_blocks
* CDDA_DATA_SIZE
) ) )
283 msg_Err( p_access
, "cannot get a new block of size: %i",
284 i_blocks
* CDDA_DATA_SIZE
);
288 if( ioctl_ReadSectors( VLC_OBJECT(p_access
), p_sys
->vcddev
,
289 p_sys
->i_sector
, p_block
->p_buffer
, i_blocks
, CDDA_TYPE
) < 0 )
291 msg_Err( p_access
, "cannot read sector %i", p_sys
->i_sector
);
292 block_Release( p_block
);
294 /* Try to skip one sector (in case of bad sectors) */
296 p_access
->info
.i_pos
+= CDDA_DATA_SIZE
;
300 /* Update a few values */
301 p_sys
->i_sector
+= i_blocks
;
302 p_access
->info
.i_pos
+= p_block
->i_buffer
;
307 /****************************************************************************
309 ****************************************************************************/
310 static int Seek( access_t
*p_access
, uint64_t i_pos
)
312 access_sys_t
*p_sys
= p_access
->p_sys
;
314 /* Next sector to read */
315 p_sys
->i_sector
= p_sys
->i_first_sector
+ i_pos
/ CDDA_DATA_SIZE
;
316 assert( p_sys
->i_sector
>= 0 );
317 p_access
->info
.i_pos
= i_pos
;
322 /*****************************************************************************
324 *****************************************************************************/
325 static int Control( access_t
*p_access
, int i_query
, va_list args
)
329 case ACCESS_CAN_SEEK
:
330 case ACCESS_CAN_FASTSEEK
:
331 case ACCESS_CAN_PAUSE
:
332 case ACCESS_CAN_CONTROL_PACE
:
333 *va_arg( args
, bool* ) = true;
336 case ACCESS_GET_PTS_DELAY
:
337 *va_arg( args
, int64_t * ) =
338 INT64_C(1000) * var_InheritInteger( p_access
, "disc-caching" );
341 case ACCESS_SET_PAUSE_STATE
:
344 case ACCESS_GET_TITLE_INFO
:
345 case ACCESS_SET_TITLE
:
346 case ACCESS_GET_META
:
347 case ACCESS_SET_SEEKPOINT
:
348 case ACCESS_SET_PRIVATE_ID_STATE
:
349 case ACCESS_GET_CONTENT_TYPE
:
353 msg_Warn( p_access
, "unimplemented query in control" );
359 static int GetTracks( access_t
*p_access
, input_item_t
*p_current
)
361 access_sys_t
*p_sys
= p_access
->p_sys
;
363 const int i_titles
= ioctl_GetTracksMap( VLC_OBJECT(p_access
),
364 p_sys
->vcddev
, &p_sys
->p_sectors
);
368 msg_Err( p_access
, "unable to count tracks" );
369 else if( i_titles
<= 0 )
370 msg_Err( p_access
, "no audio tracks found" );
371 return VLC_EGENERIC
;;
375 input_item_SetName( p_current
, "Audio CD" );
377 const char *psz_album
= NULL
;
378 const char *psz_year
= NULL
;
379 const char *psz_genre
= NULL
;
380 const char *psz_artist
= NULL
;
381 const char *psz_description
= NULL
;
383 /* Return true if the given string is not NULL and not empty */
384 #define NONEMPTY( psz ) ( (psz) && *(psz) )
385 /* If the given string is NULL or empty, fill it by the return value of 'code' */
386 #define ON_EMPTY( psz, code ) do { if( !NONEMPTY( psz) ) { (psz) = code; } } while(0)
388 /* Retreive CDDB information */
390 char psz_year_buffer
[4+1];
391 msg_Dbg( p_access
, "fetching infos with CDDB" );
392 cddb_disc_t
*p_disc
= GetCDDBInfo( p_access
, i_titles
, p_sys
->p_sectors
);
395 psz_album
= cddb_disc_get_title( p_disc
);
396 psz_genre
= cddb_disc_get_genre( p_disc
);
399 const unsigned i_year
= cddb_disc_get_year( p_disc
);
402 psz_year
= psz_year_buffer
;
403 snprintf( psz_year_buffer
, sizeof(psz_year_buffer
), "%u", i_year
);
406 /* Set artist only if unique */
407 for( int i
= 0; i
< i_titles
; i
++ )
409 cddb_track_t
*t
= cddb_disc_get_track( p_disc
, i
);
412 const char *psz_track_artist
= cddb_track_get_artist( t
);
413 if( psz_artist
&& psz_track_artist
&&
414 strcmp( psz_artist
, psz_track_artist
) )
419 psz_artist
= psz_track_artist
;
425 vlc_meta_t
**pp_cd_text
;
428 if( ioctl_GetCdText( VLC_OBJECT(p_access
), p_sys
->vcddev
, &pp_cd_text
, &i_cd_text
) )
430 msg_Dbg( p_access
, "CD-TEXT information missing" );
435 /* Retrieve CD-TEXT information but prefer CDDB */
436 if( i_cd_text
> 0 && pp_cd_text
[0] )
438 const vlc_meta_t
*p_disc
= pp_cd_text
[0];
439 ON_EMPTY( psz_album
, vlc_meta_Get( p_disc
, vlc_meta_Album
) );
440 ON_EMPTY( psz_genre
, vlc_meta_Get( p_disc
, vlc_meta_Genre
) );
441 ON_EMPTY( psz_artist
, vlc_meta_Get( p_disc
, vlc_meta_Artist
) );
442 ON_EMPTY( psz_description
, vlc_meta_Get( p_disc
, vlc_meta_Description
) );
445 if( NONEMPTY( psz_album
) )
447 input_item_SetName( p_current
, psz_album
);
448 input_item_SetAlbum( p_current
, psz_album
);
451 if( NONEMPTY( psz_genre
) )
452 input_item_SetGenre( p_current
, psz_genre
);
454 if( NONEMPTY( psz_artist
) )
455 input_item_SetArtist( p_current
, psz_artist
);
457 if( NONEMPTY( psz_year
) )
458 input_item_SetDate( p_current
, psz_year
);
460 if( NONEMPTY( psz_description
) )
461 input_item_SetDescription( p_current
, psz_description
);
463 const mtime_t i_duration
= (int64_t)( p_sys
->p_sectors
[i_titles
] - p_sys
->p_sectors
[0] ) *
464 CDDA_DATA_SIZE
* 1000000 / 44100 / 2 / 2;
465 input_item_SetDuration( p_current
, i_duration
);
467 input_item_node_t
*p_root
= input_item_node_Create( p_current
);
469 /* Build title table */
470 for( int i
= 0; i
< i_titles
; i
++ )
472 input_item_t
*p_input_item
;
474 char *psz_uri
, *psz_opt
, *psz_first
, *psz_last
;
477 msg_Dbg( p_access
, "track[%d] start=%d", i
, p_sys
->p_sectors
[i
] );
480 if( asprintf( &psz_uri
, "cdda://%s", p_access
->psz_location
) == -1 )
482 if( asprintf( &psz_opt
, "cdda-track=%i", i
+1 ) == -1 )
484 if( asprintf( &psz_first
, "cdda-first-sector=%i",p_sys
->p_sectors
[i
] ) == -1 )
486 if( asprintf( &psz_last
, "cdda-last-sector=%i", p_sys
->p_sectors
[i
+1] ) == -1 )
489 /* Define a "default name" */
490 if( asprintf( &psz_name
, _("Audio CD - Track %02i"), (i
+1) ) == -1 )
493 /* Create playlist items */
494 const mtime_t i_duration
= (int64_t)( p_sys
->p_sectors
[i
+1] - p_sys
->p_sectors
[i
] ) *
495 CDDA_DATA_SIZE
* 1000000 / 44100 / 2 / 2;
496 p_input_item
= input_item_NewWithType( psz_uri
, psz_name
, 0, NULL
, 0,
497 i_duration
, ITEM_TYPE_DISC
);
498 input_item_CopyOptions( p_current
, p_input_item
);
499 input_item_AddOption( p_input_item
, psz_first
, VLC_INPUT_OPTION_TRUSTED
);
500 input_item_AddOption( p_input_item
, psz_last
, VLC_INPUT_OPTION_TRUSTED
);
501 input_item_AddOption( p_input_item
, psz_opt
, VLC_INPUT_OPTION_TRUSTED
);
503 const char *psz_track_title
= NULL
;
504 const char *psz_track_artist
= NULL
;
505 const char *psz_track_genre
= NULL
;
506 const char *psz_track_description
= NULL
;
509 /* Retreive CDDB information */
512 cddb_track_t
*t
= cddb_disc_get_track( p_disc
, i
);
515 psz_track_title
= cddb_track_get_title( t
);
516 psz_track_artist
= cddb_track_get_artist( t
);
521 /* Retreive CD-TEXT information but prefer CDDB */
522 if( i
+1 < i_cd_text
&& pp_cd_text
[i
+1] )
524 const vlc_meta_t
*t
= pp_cd_text
[i
+1];
526 ON_EMPTY( psz_track_title
, vlc_meta_Get( t
, vlc_meta_Title
) );
527 ON_EMPTY( psz_track_artist
, vlc_meta_Get( t
, vlc_meta_Artist
) );
528 ON_EMPTY( psz_track_genre
, vlc_meta_Get( t
, vlc_meta_Genre
) );
529 ON_EMPTY( psz_track_description
, vlc_meta_Get( t
, vlc_meta_Description
) );
533 ON_EMPTY( psz_track_artist
, psz_artist
);
534 ON_EMPTY( psz_track_genre
, psz_genre
);
535 ON_EMPTY( psz_track_description
, psz_description
);
538 if( NONEMPTY( psz_track_title
) )
540 input_item_SetName( p_input_item
, psz_track_title
);
541 input_item_SetTitle( p_input_item
, psz_track_title
);
544 if( NONEMPTY( psz_track_artist
) )
545 input_item_SetArtist( p_input_item
, psz_track_artist
);
547 if( NONEMPTY( psz_track_genre
) )
548 input_item_SetGenre( p_input_item
, psz_track_genre
);
550 if( NONEMPTY( psz_track_description
) )
551 input_item_SetDescription( p_input_item
, psz_track_description
);
553 if( NONEMPTY( psz_album
) )
554 input_item_SetAlbum( p_input_item
, psz_album
);
556 if( NONEMPTY( psz_year
) )
557 input_item_SetDate( p_input_item
, psz_year
);
560 snprintf( psz_num
, sizeof(psz_num
), "%d", 1+i
);
561 input_item_SetTrackNum( p_input_item
, psz_num
);
563 input_item_node_AppendItem( p_root
, p_input_item
);
564 vlc_gc_decref( p_input_item
);
565 free( psz_uri
); free( psz_opt
); free( psz_name
);
566 free( psz_first
); free( psz_last
);
571 input_item_node_PostAndDelete( p_root
);
574 for( int i
= 0; i
< i_cd_text
; i
++ )
576 vlc_meta_t
*p_meta
= pp_cd_text
[i
];
579 vlc_meta_Delete( p_meta
);
585 cddb_disc_destroy( p_disc
);
591 static cddb_disc_t
*GetCDDBInfo( access_t
*p_access
, int i_titles
, int *p_sectors
)
593 if( var_InheritInteger( p_access
, "album-art" ) == ALBUM_ART_WHEN_ASKED
)
597 cddb_conn_t
*p_cddb
= cddb_new();
600 msg_Warn( p_access
, "unable to use CDDB" );
605 char *psz_tmp
= var_InheritString( p_access
, "cddb-server" );
608 cddb_set_server_name( p_cddb
, psz_tmp
);
612 cddb_set_server_port( p_cddb
, var_InheritInteger( p_access
, "cddb-port" ) );
614 cddb_set_email_address( p_cddb
, "vlc@videolan.org" );
617 cddb_cache_disable( p_cddb
);
619 // cddb_cache_set_dir( p_cddb,
620 // var_InheritString( p_access,
621 // MODULE_STRING "-cddb-cachedir") );
623 cddb_set_timeout( p_cddb
, 10 );
626 cddb_http_disable( p_cddb
);
629 cddb_disc_t
*p_disc
= cddb_disc_new();
632 msg_Err( p_access
, "unable to create CDDB disc structure." );
636 int64_t i_length
= 0;
637 for( int i
= 0; i
< i_titles
; i
++ )
639 cddb_track_t
*t
= cddb_track_new();
640 cddb_track_set_frame_offset( t
, p_sectors
[i
] );
641 cddb_disc_add_track( p_disc
, t
);
642 const int64_t i_size
= ( p_sectors
[i
+1] - p_sectors
[i
] ) *
643 (int64_t)CDDA_DATA_SIZE
;
644 i_length
+= INT64_C(1000000) * i_size
/ 44100 / 4 ;
647 cddb_disc_set_length( p_disc
, (int)(i_length
/1000000) );
649 if( !cddb_disc_calc_discid( p_disc
) )
651 msg_Err( p_access
, "CDDB disc ID calculation failed" );
655 const int i_matches
= cddb_query( p_cddb
, p_disc
);
658 msg_Warn( p_access
, "CDDB error: %s", cddb_error_str(errno
) );
661 else if( i_matches
== 0 )
663 msg_Dbg( p_access
, "Couldn't find any matches in CDDB." );
666 else if( i_matches
> 1 )
667 msg_Warn( p_access
, "found %d matches in CDDB. Using first one.", i_matches
);
669 cddb_read( p_cddb
, p_disc
);
671 cddb_destroy( p_cddb
);
676 cddb_disc_destroy( p_disc
);
677 cddb_destroy( p_cddb
);
680 #endif /*HAVE_LIBCDDB*/