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", NULL
, 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" );
148 if( !psz_name
|| !*psz_name
)
154 else psz_name
= ToLocaleDup( p_access
->psz_filepath
);
157 if( psz_name
[0] && psz_name
[1] == ':' &&
158 psz_name
[2] == '\\' && psz_name
[3] == '\0' ) psz_name
[2] = '\0';
162 if( (vcddev
= ioctl_Open( VLC_OBJECT(p_access
), psz_name
) ) == NULL
)
164 msg_Warn( p_access
, "could not open %s", psz_name
);
170 /* Set up p_access */
171 STANDARD_BLOCK_ACCESS_INIT
172 p_sys
->vcddev
= vcddev
;
174 /* Do we play a single track ? */
175 p_sys
->i_track
= var_InheritInteger( p_access
, "cdda-track" ) - 1;
177 if( p_sys
->i_track
< 0 )
179 /* We only do separate items if the whole disc is requested */
180 input_thread_t
*p_input
= access_GetParentInput( p_access
);
185 input_item_t
*p_current
= input_GetItem( p_input
);
187 i_ret
= GetTracks( p_access
, p_current
);
189 vlc_object_release( p_input
);
196 /* Build a WAV header for the output data */
197 memset( &p_sys
->waveheader
, 0, sizeof(WAVEHEADER
) );
198 SetWLE( &p_sys
->waveheader
.Format
, 1 ); /*WAVE_FORMAT_PCM*/
199 SetWLE( &p_sys
->waveheader
.BitsPerSample
, 16);
200 p_sys
->waveheader
.MainChunkID
= VLC_FOURCC('R', 'I', 'F', 'F');
201 p_sys
->waveheader
.Length
= 0; /* we just don't know */
202 p_sys
->waveheader
.ChunkTypeID
= VLC_FOURCC('W', 'A', 'V', 'E');
203 p_sys
->waveheader
.SubChunkID
= VLC_FOURCC('f', 'm', 't', ' ');
204 SetDWLE( &p_sys
->waveheader
.SubChunkLength
, 16);
205 SetWLE( &p_sys
->waveheader
.Modus
, 2);
206 SetDWLE( &p_sys
->waveheader
.SampleFreq
, 44100);
207 SetWLE( &p_sys
->waveheader
.BytesPerSample
,
208 2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
209 SetDWLE( &p_sys
->waveheader
.BytesPerSec
,
210 2*16/8 /*BytesPerSample*/ * 44100 /*SampleFreq*/ );
211 p_sys
->waveheader
.DataChunkID
= VLC_FOURCC('d', 'a', 't', 'a');
212 p_sys
->waveheader
.DataLength
= 0; /* we just don't know */
214 p_sys
->i_first_sector
= var_InheritInteger( p_access
,
215 "cdda-first-sector" );
216 p_sys
->i_last_sector
= var_InheritInteger( p_access
,
217 "cdda-last-sector" );
218 /* Tracknumber in MRL */
219 if( p_sys
->i_first_sector
< 0 || p_sys
->i_last_sector
< 0 )
221 const int i_titles
= ioctl_GetTracksMap( VLC_OBJECT(p_access
),
222 p_sys
->vcddev
, &p_sys
->p_sectors
);
223 if( p_sys
->i_track
>= i_titles
)
225 msg_Err( p_access
, "invalid track number" );
228 p_sys
->i_first_sector
= p_sys
->p_sectors
[p_sys
->i_track
];
229 p_sys
->i_last_sector
= p_sys
->p_sectors
[p_sys
->i_track
+1];
232 p_sys
->i_sector
= p_sys
->i_first_sector
;
233 p_access
->info
.i_size
= (p_sys
->i_last_sector
- p_sys
->i_first_sector
)
234 * (int64_t)CDDA_DATA_SIZE
;
238 var_Create( p_access
, "cdda-caching", VLC_VAR_INTEGER
|VLC_VAR_DOINHERIT
);
243 free( p_sys
->p_sectors
);
244 ioctl_Close( VLC_OBJECT(p_access
), p_sys
->vcddev
);
249 /*****************************************************************************
251 *****************************************************************************/
252 static void Close( vlc_object_t
*p_this
)
254 access_t
*p_access
= (access_t
*)p_this
;
255 access_sys_t
*p_sys
= p_access
->p_sys
;
257 free( p_sys
->p_sectors
);
258 ioctl_Close( p_this
, p_sys
->vcddev
);
262 /*****************************************************************************
263 * Block: read data (CDDA_DATA_ONCE)
264 *****************************************************************************/
265 static block_t
*Block( access_t
*p_access
)
267 access_sys_t
*p_sys
= p_access
->p_sys
;
268 int i_blocks
= CDDA_BLOCKS_ONCE
;
271 if( p_sys
->i_track
< 0 ) p_access
->info
.b_eof
= true;
273 /* Check end of file */
274 if( p_access
->info
.b_eof
) return NULL
;
276 if( !p_sys
->b_header
)
278 /* Return only the header */
279 p_block
= block_New( p_access
, sizeof( WAVEHEADER
) );
280 memcpy( p_block
->p_buffer
, &p_sys
->waveheader
, sizeof(WAVEHEADER
) );
281 p_sys
->b_header
= true;
285 if( p_sys
->i_sector
>= p_sys
->i_last_sector
)
287 p_access
->info
.b_eof
= true;
291 /* Don't read too far */
292 if( p_sys
->i_sector
+ i_blocks
>= p_sys
->i_last_sector
)
293 i_blocks
= p_sys
->i_last_sector
- p_sys
->i_sector
;
295 /* Do the actual reading */
296 if( !( p_block
= block_New( p_access
, i_blocks
* CDDA_DATA_SIZE
) ) )
298 msg_Err( p_access
, "cannot get a new block of size: %i",
299 i_blocks
* CDDA_DATA_SIZE
);
303 if( ioctl_ReadSectors( VLC_OBJECT(p_access
), p_sys
->vcddev
,
304 p_sys
->i_sector
, p_block
->p_buffer
, i_blocks
, CDDA_TYPE
) < 0 )
306 msg_Err( p_access
, "cannot read sector %i", p_sys
->i_sector
);
307 block_Release( p_block
);
309 /* Try to skip one sector (in case of bad sectors) */
311 p_access
->info
.i_pos
+= CDDA_DATA_SIZE
;
315 /* Update a few values */
316 p_sys
->i_sector
+= i_blocks
;
317 p_access
->info
.i_pos
+= p_block
->i_buffer
;
322 /****************************************************************************
324 ****************************************************************************/
325 static int Seek( access_t
*p_access
, uint64_t i_pos
)
327 access_sys_t
*p_sys
= p_access
->p_sys
;
329 /* Next sector to read */
330 p_sys
->i_sector
= p_sys
->i_first_sector
+ i_pos
/ CDDA_DATA_SIZE
;
331 assert( p_sys
->i_sector
>= 0 );
332 p_access
->info
.i_pos
= i_pos
;
337 /*****************************************************************************
339 *****************************************************************************/
340 static int Control( access_t
*p_access
, int i_query
, va_list args
)
344 case ACCESS_CAN_SEEK
:
345 case ACCESS_CAN_FASTSEEK
:
346 case ACCESS_CAN_PAUSE
:
347 case ACCESS_CAN_CONTROL_PACE
:
348 *va_arg( args
, bool* ) = true;
351 case ACCESS_GET_PTS_DELAY
:
352 *va_arg( args
, int64_t * ) =
353 var_GetInteger( p_access
, "cdda-caching" ) * INT64_C(1000);
356 case ACCESS_SET_PAUSE_STATE
:
359 case ACCESS_GET_TITLE_INFO
:
360 case ACCESS_SET_TITLE
:
361 case ACCESS_GET_META
:
362 case ACCESS_SET_SEEKPOINT
:
363 case ACCESS_SET_PRIVATE_ID_STATE
:
364 case ACCESS_GET_CONTENT_TYPE
:
368 msg_Warn( p_access
, "unimplemented query in control" );
374 static int GetTracks( access_t
*p_access
, input_item_t
*p_current
)
376 access_sys_t
*p_sys
= p_access
->p_sys
;
378 const int i_titles
= ioctl_GetTracksMap( VLC_OBJECT(p_access
),
379 p_sys
->vcddev
, &p_sys
->p_sectors
);
383 msg_Err( p_access
, "unable to count tracks" );
384 else if( i_titles
<= 0 )
385 msg_Err( p_access
, "no audio tracks found" );
386 return VLC_EGENERIC
;;
390 input_item_SetName( p_current
, "Audio CD" );
392 const char *psz_album
= NULL
;
393 const char *psz_year
= NULL
;
394 const char *psz_genre
= NULL
;
395 const char *psz_artist
= NULL
;
396 const char *psz_description
= NULL
;
398 /* Return true if the given string is not NULL and not empty */
399 #define NONEMPTY( psz ) ( (psz) && *(psz) )
400 /* If the given string is NULL or empty, fill it by the return value of 'code' */
401 #define ON_EMPTY( psz, code ) do { if( !NONEMPTY( psz) ) { (psz) = code; } } while(0)
403 /* Retreive CDDB information */
405 char psz_year_buffer
[4+1];
406 msg_Dbg( p_access
, "fetching infos with CDDB" );
407 cddb_disc_t
*p_disc
= GetCDDBInfo( p_access
, i_titles
, p_sys
->p_sectors
);
410 psz_album
= cddb_disc_get_title( p_disc
);
411 psz_genre
= cddb_disc_get_genre( p_disc
);
414 const unsigned i_year
= cddb_disc_get_year( p_disc
);
417 psz_year
= psz_year_buffer
;
418 snprintf( psz_year_buffer
, sizeof(psz_year_buffer
), "%u", i_year
);
421 /* Set artist only if unique */
422 for( int i
= 0; i
< i_titles
; i
++ )
424 cddb_track_t
*t
= cddb_disc_get_track( p_disc
, i
);
427 const char *psz_track_artist
= cddb_track_get_artist( t
);
428 if( psz_artist
&& psz_track_artist
&&
429 strcmp( psz_artist
, psz_track_artist
) )
434 psz_artist
= psz_track_artist
;
440 vlc_meta_t
**pp_cd_text
;
443 if( ioctl_GetCdText( VLC_OBJECT(p_access
), p_sys
->vcddev
, &pp_cd_text
, &i_cd_text
) )
445 msg_Dbg( p_access
, "CD-TEXT information missing" );
450 /* Retrieve CD-TEXT information but prefer CDDB */
451 if( i_cd_text
> 0 && pp_cd_text
[0] )
453 const vlc_meta_t
*p_disc
= pp_cd_text
[0];
454 ON_EMPTY( psz_album
, vlc_meta_Get( p_disc
, vlc_meta_Album
) );
455 ON_EMPTY( psz_genre
, vlc_meta_Get( p_disc
, vlc_meta_Genre
) );
456 ON_EMPTY( psz_artist
, vlc_meta_Get( p_disc
, vlc_meta_Artist
) );
457 ON_EMPTY( psz_description
, vlc_meta_Get( p_disc
, vlc_meta_Description
) );
460 if( NONEMPTY( psz_album
) )
462 input_item_SetName( p_current
, psz_album
);
463 input_item_SetAlbum( p_current
, psz_album
);
466 if( NONEMPTY( psz_genre
) )
467 input_item_SetGenre( p_current
, psz_genre
);
469 if( NONEMPTY( psz_artist
) )
470 input_item_SetArtist( p_current
, psz_artist
);
472 if( NONEMPTY( psz_year
) )
473 input_item_SetDate( p_current
, psz_year
);
475 if( NONEMPTY( psz_description
) )
476 input_item_SetDescription( p_current
, psz_description
);
478 const mtime_t i_duration
= (int64_t)( p_sys
->p_sectors
[i_titles
] - p_sys
->p_sectors
[0] ) *
479 CDDA_DATA_SIZE
* 1000000 / 44100 / 2 / 2;
480 input_item_SetDuration( p_current
, i_duration
);
482 input_item_node_t
*p_root
= input_item_node_Create( p_current
);
484 /* Build title table */
485 for( int i
= 0; i
< i_titles
; i
++ )
487 input_item_t
*p_input_item
;
489 char *psz_uri
, *psz_opt
, *psz_first
, *psz_last
;
492 msg_Dbg( p_access
, "track[%d] start=%d", i
, p_sys
->p_sectors
[i
] );
495 if( asprintf( &psz_uri
, "cdda://%s", p_access
->psz_location
) == -1 )
497 if( asprintf( &psz_opt
, "cdda-track=%i", i
+1 ) == -1 )
499 if( asprintf( &psz_first
, "cdda-first-sector=%i",p_sys
->p_sectors
[i
] ) == -1 )
501 if( asprintf( &psz_last
, "cdda-last-sector=%i", p_sys
->p_sectors
[i
+1] ) == -1 )
504 /* Define a "default name" */
505 if( asprintf( &psz_name
, _("Audio CD - Track %02i"), (i
+1) ) == -1 )
508 /* Create playlist items */
509 const mtime_t i_duration
= (int64_t)( p_sys
->p_sectors
[i
+1] - p_sys
->p_sectors
[i
] ) *
510 CDDA_DATA_SIZE
* 1000000 / 44100 / 2 / 2;
511 p_input_item
= input_item_NewWithType( VLC_OBJECT( p_access
),
512 psz_uri
, psz_name
, 0, NULL
, 0, i_duration
,
514 input_item_CopyOptions( p_current
, p_input_item
);
515 input_item_AddOption( p_input_item
, psz_first
, VLC_INPUT_OPTION_TRUSTED
);
516 input_item_AddOption( p_input_item
, psz_last
, VLC_INPUT_OPTION_TRUSTED
);
517 input_item_AddOption( p_input_item
, psz_opt
, VLC_INPUT_OPTION_TRUSTED
);
519 const char *psz_track_title
= NULL
;
520 const char *psz_track_artist
= NULL
;
521 const char *psz_track_genre
= NULL
;
522 const char *psz_track_description
= NULL
;
525 /* Retreive CDDB information */
528 cddb_track_t
*t
= cddb_disc_get_track( p_disc
, i
);
531 psz_track_title
= cddb_track_get_title( t
);
532 psz_track_artist
= cddb_track_get_artist( t
);
537 /* Retreive CD-TEXT information but prefer CDDB */
538 if( i
+1 < i_cd_text
&& pp_cd_text
[i
+1] )
540 const vlc_meta_t
*t
= pp_cd_text
[i
+1];
542 ON_EMPTY( psz_track_title
, vlc_meta_Get( t
, vlc_meta_Title
) );
543 ON_EMPTY( psz_track_artist
, vlc_meta_Get( t
, vlc_meta_Artist
) );
544 ON_EMPTY( psz_track_genre
, vlc_meta_Get( t
, vlc_meta_Genre
) );
545 ON_EMPTY( psz_track_description
, vlc_meta_Get( t
, vlc_meta_Description
) );
549 ON_EMPTY( psz_track_artist
, psz_artist
);
550 ON_EMPTY( psz_track_genre
, psz_genre
);
551 ON_EMPTY( psz_track_description
, psz_description
);
554 if( NONEMPTY( psz_track_title
) )
556 input_item_SetName( p_input_item
, psz_track_title
);
557 input_item_SetTitle( p_input_item
, psz_track_title
);
560 if( NONEMPTY( psz_track_artist
) )
561 input_item_SetArtist( p_input_item
, psz_track_artist
);
563 if( NONEMPTY( psz_track_genre
) )
564 input_item_SetGenre( p_input_item
, psz_track_genre
);
566 if( NONEMPTY( psz_track_description
) )
567 input_item_SetDescription( p_input_item
, psz_track_description
);
569 if( NONEMPTY( psz_album
) )
570 input_item_SetAlbum( p_input_item
, psz_album
);
572 if( NONEMPTY( psz_year
) )
573 input_item_SetDate( p_input_item
, psz_year
);
576 snprintf( psz_num
, sizeof(psz_num
), "%d", 1+i
);
577 input_item_SetTrackNum( p_input_item
, psz_num
);
579 input_item_node_AppendItem( p_root
, p_input_item
);
580 vlc_gc_decref( p_input_item
);
581 free( psz_uri
); free( psz_opt
); free( psz_name
);
582 free( psz_first
); free( psz_last
);
587 input_item_node_PostAndDelete( p_root
);
590 for( int i
= 0; i
< i_cd_text
; i
++ )
592 vlc_meta_t
*p_meta
= pp_cd_text
[i
];
595 vlc_meta_Delete( p_meta
);
601 cddb_disc_destroy( p_disc
);
607 static cddb_disc_t
*GetCDDBInfo( access_t
*p_access
, int i_titles
, int *p_sectors
)
609 if( var_InheritInteger( p_access
, "album-art" ) == ALBUM_ART_WHEN_ASKED
)
613 cddb_conn_t
*p_cddb
= cddb_new();
616 msg_Warn( p_access
, "unable to use CDDB" );
621 char *psz_tmp
= var_InheritString( p_access
, "cddb-server" );
624 cddb_set_server_name( p_cddb
, psz_tmp
);
628 cddb_set_server_port( p_cddb
, var_InheritInteger( p_access
, "cddb-port" ) );
630 cddb_set_email_address( p_cddb
, "vlc@videolan.org" );
633 cddb_cache_disable( p_cddb
);
635 // cddb_cache_set_dir( p_cddb,
636 // var_InheritString( p_access,
637 // MODULE_STRING "-cddb-cachedir") );
639 cddb_set_timeout( p_cddb
, 10 );
642 cddb_http_disable( p_cddb
);
645 cddb_disc_t
*p_disc
= cddb_disc_new();
648 msg_Err( p_access
, "unable to create CDDB disc structure." );
652 int64_t i_length
= 0;
653 for( int i
= 0; i
< i_titles
; i
++ )
655 cddb_track_t
*t
= cddb_track_new();
656 cddb_track_set_frame_offset( t
, p_sectors
[i
] );
657 cddb_disc_add_track( p_disc
, t
);
658 const int64_t i_size
= ( p_sectors
[i
+1] - p_sectors
[i
] ) *
659 (int64_t)CDDA_DATA_SIZE
;
660 i_length
+= INT64_C(1000000) * i_size
/ 44100 / 4 ;
663 cddb_disc_set_length( p_disc
, (int)(i_length
/1000000) );
665 if( !cddb_disc_calc_discid( p_disc
) )
667 msg_Err( p_access
, "CDDB disc ID calculation failed" );
671 const int i_matches
= cddb_query( p_cddb
, p_disc
);
674 msg_Warn( p_access
, "CDDB error: %s", cddb_error_str(errno
) );
677 else if( i_matches
== 0 )
679 msg_Dbg( p_access
, "Couldn't find any matches in CDDB." );
682 else if( i_matches
> 1 )
683 msg_Warn( p_access
, "found %d matches in CDDB. Using first one.", i_matches
);
685 cddb_read( p_cddb
, p_disc
);
687 cddb_destroy( p_cddb
);
692 cddb_disc_destroy( p_disc
);
693 cddb_destroy( p_cddb
);
696 #endif /*HAVE_LIBCDDB*/