File: cd_access.c

package info (click to toggle)
libcddb 1.3.2-7.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,376 kB
  • sloc: sh: 10,958; ansic: 4,722; makefile: 44
file content (158 lines) | stat: -rw-r--r-- 5,196 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
    $Id: cd_access.c,v 1.14 2006/09/29 16:01:42 airborne Exp $

    Copyright (C) 2003, 2004, 2005 Kris Verbeeck <airborne@advalvas.be>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the
    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA  02111-1307, USA.
*/

#include <stdlib.h>
#include "main.h"

#ifdef HAVE_LIBCDIO
#include <cdio/cdio.h>
#endif

#define libcdio_error_exit(...) error_exit(GENERIC_ERROR, "libcdio: " __VA_ARGS__)


cddb_disc_t *cd_read(char *device)
{
    cddb_disc_t *disc = NULL;   /* libcddb disc structure */
    
#ifndef HAVE_LIBCDIO

    fprintf(stderr, "*** libcdio support missing, CD access failed ***\n");
    fprintf(stderr, "*** see http://www.gnu.org/software/libcdio/ ***\n");

#else

    CdIo_t *cdio;               /* libcdio CD access structure */
    track_t cnt, t;             /* track counters */
    lba_t lba;                  /* Logical Block Address */
    int *foffset = NULL;        /* list of frame offsets */

    /* Get the name of the default CD-ROM device. */
    if (!device) {
        device = cdio_get_default_device(NULL);
        if (!device) {
            libcdio_error_exit("unable to get default CD device");
        }
    }
    printf("CD-ROM device: %s\n", device);

    /* Load the appropriate driver and open the CD-ROM device for reading. */
    cdio = cdio_open(device, DRIVER_UNKNOWN);
    if (!cdio) {
        libcdio_error_exit("unable to open CD device");
    }

    /* Get the track count for the CD. */
    cnt = cdio_get_num_tracks(cdio);
    if (cnt == 0) {
        libcdio_error_exit("no audio tracks on CD");
    }
    printf("CD contains %d track(s)\n", cnt);

    /* Reserve some memory for the frame offsets. */
    foffset = calloc(cnt, sizeof(int));
    
    /* Now we go and fetch the track data. */
    for (t = 1; t <= cnt; t++) {

        /* We only want to process audio CDs. */
        if (cdio_get_track_format(cdio, t) != TRACK_FORMAT_AUDIO) {
            libcdio_error_exit("track %d is not an audio track", t);
        }

        /* Get frame offset of next track. */
        lba = cdio_get_track_lba(cdio, t);
        if (lba == CDIO_INVALID_LBA) {
            libcdio_error_exit("track %d has invalid Logical Block Address", t);
        }

        /* Add this offset to the list. */
        foffset[t - 1] = lba;
    }

    /* Now all we still have to do, is calculate the length of the
       disc in seconds.  We use the LEADOUT_TRACK for this. */
    lba = cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK);
    if (lba == CDIO_INVALID_LBA) {
        libcdio_error_exit("LEADOUT_TRACK has invalid Logical Block Address");
    }

    /* Now we have to create the libcddb disc structure. */
    disc = cd_create(FRAMES_TO_SECONDS(lba), cnt, foffset, 0);

    /* Free all resources held by libcdio CD access structure. */
    cdio_destroy(cdio);

    /* more clean up */
    FREE_NOT_NULL(foffset);
    FREE_NOT_NULL(device);

#endif

    return disc;
}

cddb_disc_t *cd_create(int dlength, int tcount, int *foffset, int use_time)
{
    int i;
    cddb_disc_t *disc;
    cddb_track_t *track;

    /* Create a new disc structure. */
    disc = cddb_disc_new();

    /* If the pointer is NULL then an error occured (out of memory).
       Otherwise we continue. */
    if (disc) { 
        /* Initialize the disc length in the structure. */
        cddb_disc_set_length(disc, dlength);

        /* Now we have to add the basic track data. */
        for (i = 0; i < tcount; i++) {
            /* Create a new libcddb track structure for this track. */
            track = cddb_track_new();

            /* If the pointer is NULL then an error occured (out of
               memory).  Otherwise we continue. */
            if (!track) { 
                /* Destroy the disc because we can not return half of
                   it.  Return NULL to signal failure. */
                cddb_disc_destroy(disc);
                return NULL;
            }

            /* First add the track to the disc. */
            cddb_disc_add_track(disc, track);

            if (use_time) {
                /* Set length in track structure.  Since this track is
                   already part of a disc, the frame offset for the
                   track will be calculated automatically when we set
                   its length. */
                cddb_track_set_length(track, foffset[i]);
            } else {
                /* Set frame offset in track structure. */
                cddb_track_set_frame_offset(track, foffset[i]);
            }
        }
    }
    return disc;
}