cdda.c 19.4 KB
Newer Older
gbazin's avatar
   
gbazin committed
1
2
3
/*****************************************************************************
 * cdda.c : CD digital audio input module for vlc
 *****************************************************************************
4
 * Copyright (C) 2000, 2003 the VideoLAN team
5
 * $Id$
gbazin's avatar
   
gbazin committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Gildas Bazin <gbazin@netcourrier.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
gbazin's avatar
   
gbazin committed
23
24
 *****************************************************************************/

25
26
27
28
29
30
/**
 * Todo:
 *   - Improve CDDB support (non-blocking, cache, ...)
 *   - Fix tracknumber in MRL
 */

gbazin's avatar
   
gbazin committed
31
32
33
/*****************************************************************************
 * Preamble
 *****************************************************************************/
dionoea's avatar
dionoea committed
34
#define _GNU_SOURCE
gbazin's avatar
   
gbazin committed
35
36
37
#include <stdlib.h>

#include <vlc/vlc.h>
zorglub's avatar
zorglub committed
38
39
#include <vlc_input.h>
#include <vlc_access.h>
gbazin's avatar
   
gbazin committed
40

zorglub's avatar
zorglub committed
41
#include <vlc_codecs.h> /* For WAVEHEADER */
gbazin's avatar
   
gbazin committed
42
43
#include "vcd/cdrom.h"

44
45
#include <vlc_playlist.h>

46
47
48
49
#ifdef HAVE_LIBCDDB
#include <cddb/cddb.h>
#endif

50
51
52
53
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif

gbazin's avatar
   
gbazin committed
54
/*****************************************************************************
Laurent Aimar's avatar
Laurent Aimar committed
55
 * Module descriptior
gbazin's avatar
   
gbazin committed
56
 *****************************************************************************/
57
58
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );
gbazin's avatar
   
gbazin committed
59
60
61

#define CACHING_TEXT N_("Caching value in ms")
#define CACHING_LONGTEXT N_( \
zorglub's avatar
zorglub committed
62
63
    "Default caching value for Audio CDs. This " \
    "value should be set in milliseconds." )
gbazin's avatar
   
gbazin committed
64
65

vlc_module_begin();
66
    set_shortname( _("Audio CD"));
Sam Hocevar's avatar
Sam Hocevar committed
67
    set_description( _("Audio CD input") );
68
    set_capability( "access2", 10 );
zorglub's avatar
zorglub committed
69
70
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_ACCESS );
71
    set_callbacks( Open, Close );
gbazin's avatar
   
gbazin committed
72

73
    add_usage_hint( N_("[cdda:][device][@[track]]") );
gbazin's avatar
   
gbazin committed
74
75
    add_integer( "cdda-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT,
                 CACHING_LONGTEXT, VLC_TRUE );
76

77
    add_integer( "cdda-track", -1 , NULL, NULL, NULL, VLC_TRUE );
78
        change_internal();
79
80
81
82
83
    add_integer( "cdda-first-sector", -1, NULL, NULL, NULL, VLC_TRUE );
        change_internal();
    add_integer( "cdda-last-sector", -1, NULL, NULL, NULL, VLC_TRUE );
        change_internal();

84
    add_string( "cddb-server", "freedb.freedb.org", NULL,
85
                N_( "CDDB Server" ), N_( "Address of the CDDB server to use." ),
86
87
                VLC_TRUE );
    add_integer( "cddb-port", 8880, NULL,
zorglub's avatar
zorglub committed
88
                N_( "CDDB port" ), N_( "CDDB Server port to use." ),
89
                VLC_TRUE );
gbazin's avatar
   
gbazin committed
90
    add_shortcut( "cdda" );
gbazin's avatar
   
gbazin committed
91
    add_shortcut( "cddasimple" );
gbazin's avatar
   
gbazin committed
92
93
vlc_module_end();

Laurent Aimar's avatar
Laurent Aimar committed
94
95
96
97
98
99
100
101
102
103
104

/* how many blocks VCDRead will read in each loop */
#define CDDA_BLOCKS_ONCE 20
#define CDDA_DATA_ONCE   (CDDA_BLOCKS_ONCE * CDDA_DATA_SIZE)

/*****************************************************************************
 * Access: local prototypes
 *****************************************************************************/
struct access_sys_t
{
    vcddev_t    *vcddev;                            /* vcd device descriptor */
105

106
    /* Current position */
Laurent Aimar's avatar
Laurent Aimar committed
107
108
109
    int         i_sector;                                  /* Current Sector */
    int *       p_sectors;                                  /* Track sectors */

110
111
    /* Wave header for the output data */
    WAVEHEADER  waveheader;
112
    vlc_bool_t  b_header;
113
114

    int         i_track;
115
116
    int         i_first_sector;
    int         i_last_sector;
117
118
119
120

#ifdef HAVE_LIBCDDB
    cddb_disc_t *p_disc;
#endif
Laurent Aimar's avatar
Laurent Aimar committed
121
122
};

123
124
125
static block_t *Block( access_t * );
static int      Seek( access_t *, int64_t );
static int      Control( access_t *, int, va_list );
Laurent Aimar's avatar
Laurent Aimar committed
126

127
128
static int GetTracks( access_t *p_access, playlist_t *p_playlist,
                      playlist_item_t *p_parent );
129

130
131
132
133
#ifdef HAVE_LIBCDDB
static void GetCDDBInfo( access_t *p_access, int i_titles, int *p_sectors );
#endif

gbazin's avatar
   
gbazin committed
134
/*****************************************************************************
135
 * Open: open cdda
gbazin's avatar
   
gbazin committed
136
 *****************************************************************************/
137
static int Open( vlc_object_t *p_this )
gbazin's avatar
   
gbazin committed
138
{
139
140
141
    access_t     *p_access = (access_t*)p_this;
    access_sys_t *p_sys;
    vcddev_t *vcddev;
142
    char *psz_name;
143
    int i_mrl_tracknum = -1;
144
145
146
147
148

    input_thread_t *p_input;
    playlist_item_t *p_item = NULL;
    playlist_t *p_playlist  = NULL;
    int i_ret;
149

150
    if( !p_access->psz_path || !*p_access->psz_path )
gbazin's avatar
   
gbazin committed
151
    {
152
        /* Only when selected */
153
        if( !p_this->b_force ) return VLC_EGENERIC;
154

155
156
        psz_name = var_CreateGetString( p_this, "cd-audio" );
        if( !psz_name || !*psz_name )
gbazin's avatar
   
gbazin committed
157
        {
158
            if( psz_name ) free( psz_name );
Laurent Aimar's avatar
Laurent Aimar committed
159
            return VLC_EGENERIC;
gbazin's avatar
   
gbazin committed
160
161
        }
    }
162
    else psz_name = strdup( p_access->psz_path );
gbazin's avatar
   
gbazin committed
163

164
165
166
167
168
#ifdef WIN32
    if( psz_name[0] && psz_name[1] == ':' &&
        psz_name[2] == '\\' && psz_name[3] == '\0' ) psz_name[2] = '\0';
#endif

gbazin's avatar
   
gbazin committed
169
    /* Open CDDA */
170
    if( (vcddev = ioctl_Open( VLC_OBJECT(p_access), psz_name )) == NULL )
gbazin's avatar
   
gbazin committed
171
    {
172
173
        msg_Warn( p_access, "could not open %s", psz_name );
        free( psz_name );
Laurent Aimar's avatar
Laurent Aimar committed
174
        return VLC_EGENERIC;
gbazin's avatar
   
gbazin committed
175
    }
176
    free( psz_name );
177
178

    /* Set up p_access */
179
    STANDARD_BLOCK_ACCESS_INIT
Laurent Aimar's avatar
Laurent Aimar committed
180
    p_sys->vcddev = vcddev;
181
182
183
184

    /* We only do separate items if the whole disc is requested -
     *  Dirty hack we access some private data ! */
    p_input = (input_thread_t *)( p_access->p_parent );
gbazin's avatar
   
gbazin committed
185

186
187
   /* Do we play a single track ? */
   p_sys->i_track = var_CreateGetInteger( p_access, "cdda-track" );
188

189
190
   if( p_sys->i_track < 0 && i_mrl_tracknum <= 0 )
   {
zorglub's avatar
zorglub committed
191
        p_playlist = pl_Yield( p_access );
192
        if( p_playlist->status.p_item->p_input ==
zorglub's avatar
zorglub committed
193
             input_GetItem( (input_thread_t *)p_access->p_parent))
194
195
196
            p_item = p_playlist->status.p_item;
        else
        {
zorglub's avatar
zorglub committed
197
198
            input_item_t *p_current = input_GetItem(
                                        (input_thread_t*)p_access->p_parent);
199
            p_item = playlist_ItemGetByInput( p_playlist, p_current, VLC_FALSE );
zorglub's avatar
Grmbl    
zorglub committed
200

201
202
203
            if( !p_item )
            {
                msg_Dbg( p_playlist, "unable to find item in playlist");
204
                return -1;
205
206
            }
        }
gbazin's avatar
   
gbazin committed
207

208
209
210
211
212
213
        i_ret = GetTracks( p_access, p_playlist, p_item );

        if( p_playlist ) vlc_object_release( p_playlist );
        if( i_ret < 0 ) goto error;
    }
    else
214
    {
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
        /* Build a WAV header for the output data */
        memset( &p_sys->waveheader, 0, sizeof(WAVEHEADER) );
        SetWLE( &p_sys->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
        SetWLE( &p_sys->waveheader.BitsPerSample, 16);
        p_sys->waveheader.MainChunkID = VLC_FOURCC('R', 'I', 'F', 'F');
        p_sys->waveheader.Length = 0;               /* we just don't know */
        p_sys->waveheader.ChunkTypeID = VLC_FOURCC('W', 'A', 'V', 'E');
        p_sys->waveheader.SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
        SetDWLE( &p_sys->waveheader.SubChunkLength, 16);
        SetWLE( &p_sys->waveheader.Modus, 2);
        SetDWLE( &p_sys->waveheader.SampleFreq, 44100);
        SetWLE( &p_sys->waveheader.BytesPerSample,
                    2 /*Modus*/ * 16 /*BitsPerSample*/ / 8 );
        SetDWLE( &p_sys->waveheader.BytesPerSec,
                    2*16/8 /*BytesPerSample*/ * 44100 /*SampleFreq*/ );
        p_sys->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
        p_sys->waveheader.DataLength = 0;           /* we just don't know */

        p_sys->i_first_sector = var_CreateGetInteger( p_access,
                                                      "cdda-first-sector" );
        p_sys->i_last_sector  = var_CreateGetInteger( p_access,
                                                      "cdda-last-sector" );
        /* Tracknumber in MRL */
        if( p_sys->i_first_sector < 0 || p_sys->i_last_sector < 0 )
239
        {
240
241
242
243
244
245
246
247
            int i_titles;
            if( i_mrl_tracknum <= 0 )
            {
                msg_Err( p_access, "wrong sector information" );
                goto error;
            }
            i_titles = ioctl_GetTracksMap( VLC_OBJECT(p_access),
                                            p_sys->vcddev, &p_sys->p_sectors );
248
        }
gbazin's avatar
   
gbazin committed
249

250

251
252
253
        p_sys->i_sector = p_sys->i_first_sector;
        p_access->info.i_size = (p_sys->i_last_sector - p_sys->i_first_sector)
                                     * (int64_t)CDDA_DATA_SIZE;
254
    }
255

256
257
    /* PTS delay */
    var_Create( p_access, "cdda-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
258

Laurent Aimar's avatar
Laurent Aimar committed
259
    return VLC_SUCCESS;
260
261
262
263

error:
    ioctl_Close( VLC_OBJECT(p_access), p_sys->vcddev );
    free( p_sys );
zorglub's avatar
zorglub committed
264
    if( p_playlist ) vlc_object_release( p_playlist );
265
    return VLC_EGENERIC;
gbazin's avatar
   
gbazin committed
266
267
268
}

/*****************************************************************************
269
 * Close: closes cdda
gbazin's avatar
   
gbazin committed
270
 *****************************************************************************/
271
static void Close( vlc_object_t *p_this )
gbazin's avatar
   
gbazin committed
272
{
273
274
    access_t     *p_access = (access_t *)p_this;
    access_sys_t *p_sys = p_access->p_sys;
Laurent Aimar's avatar
Laurent Aimar committed
275
276
    ioctl_Close( p_this, p_sys->vcddev );
    free( p_sys );
gbazin's avatar
   
gbazin committed
277
278
279
}

/*****************************************************************************
280
 * Block: read data (CDDA_DATA_ONCE)
gbazin's avatar
   
gbazin committed
281
 *****************************************************************************/
282
static block_t *Block( access_t *p_access )
gbazin's avatar
   
gbazin committed
283
{
284
    access_sys_t *p_sys = p_access->p_sys;
285
286
    int i_blocks = CDDA_BLOCKS_ONCE;
    block_t *p_block;
287

288
    if( p_sys->i_track < 0 ) p_access->info.b_eof = VLC_TRUE;
289

290
291
    /* Check end of file */
    if( p_access->info.b_eof ) return NULL;
gbazin's avatar
   
gbazin committed
292

293
    if( !p_sys->b_header )
gbazin's avatar
   
gbazin committed
294
    {
295
296
297
        /* Return only the header */
        p_block = block_New( p_access, sizeof( WAVEHEADER ) );
        memcpy( p_block->p_buffer, &p_sys->waveheader, sizeof(WAVEHEADER) );
298
        p_sys->b_header = VLC_TRUE;
299
        return p_block;
gbazin's avatar
   
gbazin committed
300
    }
gbazin's avatar
   
gbazin committed
301

302
    if( p_sys->i_sector >= p_sys->i_last_sector )
gbazin's avatar
   
gbazin committed
303
    {
304
305
        p_access->info.b_eof = VLC_TRUE;
        return NULL;
gbazin's avatar
   
gbazin committed
306
    }
307

308
309
310
    /* Don't read too far */
    if( p_sys->i_sector + i_blocks >= p_sys->i_last_sector )
        i_blocks = p_sys->i_last_sector - p_sys->i_sector;
gbazin's avatar
   
gbazin committed
311

312
313
    /* Do the actual reading */
    if( !( p_block = block_New( p_access, i_blocks * CDDA_DATA_SIZE ) ) )
314
    {
315
        msg_Err( p_access, "cannot get a new block of size: %i",
316
                 i_blocks * CDDA_DATA_SIZE );
317
        return NULL;
gbazin's avatar
   
gbazin committed
318
319
    }

320
321
    if( ioctl_ReadSectors( VLC_OBJECT(p_access), p_sys->vcddev,
            p_sys->i_sector, p_block->p_buffer, i_blocks, CDDA_TYPE ) < 0 )
gbazin's avatar
   
gbazin committed
322
    {
323
        msg_Err( p_access, "cannot read sector %i", p_sys->i_sector );
324
        block_Release( p_block );
325

326
327
328
        /* Try to skip one sector (in case of bad sectors) */
        p_sys->i_sector++;
        p_access->info.i_pos += CDDA_DATA_SIZE;
329
        return NULL;
gbazin's avatar
   
gbazin committed
330
331
    }

332
333
334
    /* Update a few values */
    p_sys->i_sector += i_blocks;
    p_access->info.i_pos += p_block->i_buffer;
335
336

    return p_block;
gbazin's avatar
   
gbazin committed
337
338
}

339
340
/****************************************************************************
 * Seek
gbazin's avatar
   
gbazin committed
341
 ****************************************************************************/
342
static int Seek( access_t *p_access, int64_t i_pos )
gbazin's avatar
   
gbazin committed
343
{
344
    access_sys_t *p_sys = p_access->p_sys;
gbazin's avatar
   
gbazin committed
345

346
    /* Next sector to read */
347
    p_sys->i_sector = p_sys->i_first_sector + i_pos / CDDA_DATA_SIZE;
348
    p_access->info.i_pos = i_pos;
gbazin's avatar
   
gbazin committed
349

350
351
    return VLC_SUCCESS;
}
gbazin's avatar
   
gbazin committed
352

353
354
355
356
357
358
359
360
/*****************************************************************************
 * Control:
 *****************************************************************************/
static int Control( access_t *p_access, int i_query, va_list args )
{
    vlc_bool_t   *pb_bool;
    int          *pi_int;
    int64_t      *pi_64;
gbazin's avatar
   
gbazin committed
361

362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
    switch( i_query )
    {
        case ACCESS_CAN_SEEK:
        case ACCESS_CAN_FASTSEEK:
        case ACCESS_CAN_PAUSE:
        case ACCESS_CAN_CONTROL_PACE:
            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
            *pb_bool = VLC_TRUE;
            break;

        case ACCESS_GET_MTU:
            pi_int = (int*)va_arg( args, int * );
            *pi_int = CDDA_DATA_ONCE;
            break;

        case ACCESS_GET_PTS_DELAY:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
379
            *pi_64 = var_GetInteger( p_access, "cdda-caching" ) * 1000;
380
381
382
383
384
            break;

        case ACCESS_SET_PAUSE_STATE:
        case ACCESS_GET_TITLE_INFO:
        case ACCESS_SET_TITLE:
385
        case ACCESS_GET_META:
386
        case ACCESS_SET_SEEKPOINT:
387
        case ACCESS_SET_PRIVATE_ID_STATE:
388
            return VLC_EGENERIC;
gbazin's avatar
   
gbazin committed
389

390
        default:
391
            msg_Warn( p_access, "unimplemented query in control" );
392
            return VLC_EGENERIC;
gbazin's avatar
   
gbazin committed
393

394
395
    }
    return VLC_SUCCESS;
gbazin's avatar
   
gbazin committed
396
}
397

398
static int GetTracks( access_t *p_access,
399
400
401
                      playlist_t *p_playlist, playlist_item_t *p_parent )
{
    access_sys_t *p_sys = p_access->p_sys;
402
    int i, i_titles;
403
    input_item_t *p_input_item;
404
    playlist_item_t *p_item_in_category;
405
    char *psz_name;
406
407
408
    i_titles = ioctl_GetTracksMap( VLC_OBJECT(p_access),
                                   p_sys->vcddev, &p_sys->p_sectors );
    if( i_titles < 0 )
409
410
411
412
    {
        msg_Err( p_access, "unable to count tracks" );
        return VLC_EGENERIC;;
    }
413
    else if( i_titles <= 0 )
414
415
416
417
418
    {
        msg_Err( p_access, "no audio tracks found" );
        return VLC_EGENERIC;
    }

419
    p_item_in_category = playlist_ItemToNode( p_playlist, p_parent, VLC_FALSE );
420
421
422
423
424
425
    psz_name = strdup( "Audio CD" );
    vlc_mutex_lock( &p_playlist->object_lock );
    playlist_ItemSetName( p_parent, psz_name );
    vlc_mutex_unlock( &p_playlist->object_lock );
    var_SetInteger( p_playlist, "item-change", p_parent->p_input->i_id );
    free( psz_name );
426
427

#ifdef HAVE_LIBCDDB
428
429
430
431
    GetCDDBInfo( p_access, i_titles, p_sys->p_sectors );
    if( p_sys->p_disc )
    {
        if( cddb_disc_get_title( p_sys->p_disc ) )
432
        {
433
434
435
436
437
438
439
            asprintf( &psz_name, "%s", cddb_disc_get_title( p_sys->p_disc ) );
            vlc_mutex_lock( &p_playlist->object_lock );
            playlist_ItemSetName( p_parent, psz_name );
            vlc_mutex_unlock( &p_playlist->object_lock );
            var_SetInteger( p_playlist, "item-change",
                            p_parent->p_input->i_id );
            free( psz_name );
440
        }
441
    }
442
#endif
443
444

    /* Build title table */
445
    for( i = 0; i < i_titles; i++ )
446
447
    {
        msg_Dbg( p_access, "track[%d] start=%d", i, p_sys->p_sectors[i] );
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
        char *psz_uri, *psz_opt, *psz_first, *psz_last;
        int i_path_len = p_access->psz_path ? strlen( p_access->psz_path ) : 0;

        psz_name = (char*)malloc( strlen( _("Audio CD - Track ") ) + 5 );
        psz_opt = (char*)malloc( strlen( "cdda-track=" ) + 3 );
        psz_first = (char*)malloc( strlen( "cdda-first-sector=" ) + 7 );
        psz_last = (char*)malloc( strlen( "cdda-last-sector=" ) + 7 );
        psz_uri = (char*)malloc( i_path_len + 13 );

        snprintf( psz_uri, i_path_len + 13, "cdda://%s",
                           p_access->psz_path ? p_access->psz_path : "" );
        sprintf( psz_opt, "cdda-track=%i", i+1 );
        sprintf( psz_first, "cdda-first-sector=%i",p_sys->p_sectors[i] );

//        if( i != i_titles -1 )
            sprintf( psz_last, "cdda-last-sector=%i", p_sys->p_sectors[i+1] );
//         else
//            sprintf( psz_last, "cdda-last-sector=%i", 1242 /* FIXME */);

        /* Define a "default name" */
        sprintf( psz_name, _("Audio CD - Track %i"), (i+1) );

        /* Create playlist items */
        p_input_item = input_ItemNewWithType( VLC_OBJECT( p_playlist ),
                                              psz_uri, psz_name, 0, NULL, -1,
                                              ITEM_TYPE_DISC );
474
475
476
        input_ItemAddOption( p_input_item, psz_first );
        input_ItemAddOption( p_input_item, psz_last );
        input_ItemAddOption( p_input_item, psz_opt );
477

478
#ifdef HAVE_LIBCDDB
479
480
481
        /* If we have CDDB info, change the name */
        if( p_sys->p_disc )
        {
hartman's avatar
hartman committed
482
            const char *psz_result;
483
484
            cddb_track_t *t = cddb_disc_get_track( p_sys->p_disc, i );
            if( t!= NULL )
485
            {
486
                if( cddb_track_get_title( t )  != NULL )
487
                {
488
                    input_ItemAddInfo( p_input_item, _(VLC_META_INFO_CAT),
489
                                            _(VLC_META_TITLE),
zorglub's avatar
zorglub committed
490
                                            cddb_track_get_title( t ) );
491
492
493
494
495
496
497
498
                    if( p_input_item->psz_name )
                        free( p_input_item->psz_name );
                    asprintf( &p_input_item->psz_name, "%s",
                              cddb_track_get_title( t ) );
                }
                psz_result = cddb_track_get_artist( t );
                if( psz_result )
                {
499
                    input_ItemAddInfo( p_input_item, _(VLC_META_INFO_CAT),
500
                                            _(VLC_META_ARTIST), psz_result );
501
502
                }
            }
503
        }
504
#endif
505
        playlist_BothAddInput( p_playlist, p_input_item, p_item_in_category,
506
                               PLAYLIST_APPEND, PLAYLIST_END, NULL, NULL );
507
508
        free( psz_uri ); free( psz_opt ); free( psz_name );
        free( psz_first ); free( psz_last );
509
    }
510
    return VLC_SUCCESS;
511
}
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545

#ifdef HAVE_LIBCDDB
static void GetCDDBInfo( access_t *p_access, int i_titles, int *p_sectors )
{
    int i, i_matches;
    int64_t  i_length = 0, i_size = 0;
    cddb_conn_t  *p_cddb = cddb_new();

    if( !p_cddb )
    {
        msg_Warn( p_access, "unable to use CDDB" );
        goto cddb_destroy;
    }

    cddb_set_email_address( p_cddb, "vlc@videolan.org" );
    cddb_set_server_name( p_cddb, config_GetPsz( p_access, "cddb-server" ) );
    cddb_set_server_port( p_cddb, config_GetInt( p_access, "cddb-port" ) );

    /// \todo
    cddb_cache_disable( p_cddb );

//    cddb_cache_set_dir( p_cddb,
//                     config_GetPsz( p_access,
//                                    MODULE_STRING "-cddb-cachedir") );

    cddb_set_timeout( p_cddb, 10 );

    /// \todo
    cddb_http_disable( p_cddb);

    p_access->p_sys->p_disc = cddb_disc_new();

    if(! p_access->p_sys->p_disc )
    {
546
        msg_Err( p_access, "unable to create CDDB disc structure." );
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
        goto cddb_end;
    }

    for(i = 0; i < i_titles ; i++ )
    {
        cddb_track_t *t = cddb_track_new();
        cddb_track_set_frame_offset(t, p_sectors[i] );
        cddb_disc_add_track( p_access->p_sys->p_disc, t );
        i_size = ( p_sectors[i+1] - p_sectors[i] ) *
                   (int64_t)CDDA_DATA_SIZE;
        i_length += I64C(1000000) * i_size / 44100 / 4  ;
    }

    cddb_disc_set_length( p_access->p_sys->p_disc, (int)(i_length/1000000) );

    if (!cddb_disc_calc_discid(p_access->p_sys->p_disc ))
    {
        msg_Err( p_access, "CDDB disc ID calculation failed" );
        goto cddb_destroy;
    }

    i_matches = cddb_query( p_cddb, p_access->p_sys->p_disc);

    if (i_matches > 0)
    {
        if (i_matches > 1)
573
             msg_Warn( p_access, "found %d matches in CDDB. Using first one.",
574
575
576
577
578
579
580
581
582
583
584
585
                                 i_matches);
        cddb_read( p_cddb, p_access->p_sys->p_disc );
    }
    else
        msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));

cddb_destroy:
    cddb_destroy( p_cddb);

cddb_end: ;
}
#endif /*HAVE_LIBCDDB*/