1 /* --------------------------------------------------------------------------
2 
3    MusicBrainz -- The Internet music metadatabase
4 
5    Copyright (C) 2000 Robert Kaye
6    Copyright (C) 1999 Marc E E van Woerkom
7    Copyright (C) 1999 Ben Wong
8 
9    This library is free software; you can redistribute it and/or
10    modify it under the terms of the GNU Lesser General Public
11    License as published by the Free Software Foundation; either
12    version 2.1 of the License, or (at your option) any later version.
13 
14    This library is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    Lesser General Public License for more details.
18 
19    You should have received a copy of the GNU Lesser General Public
20    License along with this library; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 
23      $Id: mb_irix.cpp,v 1.2 2000/09/22 14:15:02 robert Exp $
24 
25 ----------------------------------------------------------------------------*/
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <sys/ioctl.h>
33 #include <sys/socket.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <assert.h>
38 
39 #include <netinet/in.h>
40 #include <signal.h>
41 
42 #include "mb.h"
43 #include "diskid.h"
44 #include "config.h"
45 
46 
47 // Irix will just magically find the CD-ROM when told to open NULL.
48 MUSICBRAINZ_DEVICE DEFAULT_DEVICE = 0;
49 
50 
ReadTOCHeader(CDPLAYER * fd,int & first,int & last)51 int ReadTOCHeader(CDPLAYER* fd,
52                   int& first,
53                   int& last)
54 {
55     CDSTATUS tochdr;
56 
57     // CDgetstatus returns 0 on error but we return 0 on success.
58     int ret = !CDgetstatus(fd, &tochdr);
59 
60     if (!ret)
61     {
62         first = tochdr.first;
63         last  = tochdr.last;
64     }
65 
66     return ret;
67 }
68 
69 
ReadTOCEntry(CDPLAYER * fd,int track,int & lba)70 int ReadTOCEntry(CDPLAYER* fd,
71                  int track,
72                  int& lba)
73 {
74     CDTRACKINFO trackinfo;
75 
76     // CDgettrackinfo returns 0 on error but we return 0 on success.
77     int ret = !CDgettrackinfo(fd, track, &trackinfo);
78 
79     if (!ret)
80     {
81         // trackinfo has Min/Sec/Frame but we want a Logical Block Address.
82         lba = CDmsftoblock(fd,
83                            trackinfo.start_min,
84                            trackinfo.start_sec,
85                            trackinfo.start_frame);
86     }
87 
88     return ret;
89 }
90 
91 
92 // Return one past the *end* of the track requested instead of the
93 // start. (Equivalent to "start of the next track" but works even when
94 // the next track doesn't exist).
95 
ReadTOCEntryEnd(CDPLAYER * fd,int track,int & lba)96 int ReadTOCEntryEnd(CDPLAYER* fd,
97                     int track,
98                     int &lba)
99 {
100     CDTRACKINFO trackinfo;
101 
102     // CDgettrackinfo returns 0 on error but we return 0 on success.
103     int ret = !CDgettrackinfo(fd, track, &trackinfo);
104     if (!ret)
105     {
106         // trackinfo has Min/Sec/Frame but we want a Logical Block Address.
107         lba = CDmsftoblock(fd,
108                            trackinfo.start_min+trackinfo.total_min,
109                            trackinfo.start_sec+trackinfo.total_sec,
110                            trackinfo.start_frame+trackinfo.total_frame)+1;
111     }
112 
113     return ret;
114 }
115 
116 
ReadTOC(MUSICBRAINZ_DEVICE device,MUSICBRAINZ_CDINFO & cdinfo)117 bool DiskId::ReadTOC(MUSICBRAINZ_DEVICE device,
118                      MUSICBRAINZ_CDINFO& cdinfo)
119 {
120    CDSTATUS status;
121    CDPLAYER *fd = CDopen(device, "r");
122    int first, last;
123    int lba, i;
124    char err[256];
125 
126    if (!fd || !CDgetstatus(fd, &status))
127    {
128        sprintf(err, "Cannot open %s",
129               device ? device : "any CD-ROM");
130 
131        if (!fd)
132            sprintf(err + strlen(err), ": %s", strerror(errno));
133 
134        ReportError(err);
135 
136        return false;
137    }
138 
139    // Check if the CD-ROM is ready, has a disk in it, isn't already playing.
140    if (status.state != CD_READY)
141    {
142        strcpy(err, "The CD-ROM isn't ready. Reason: ");
143 
144        switch (status.state) {
145        case CD_NODISC:
146            strcat(err, "The drive does not have a CD loaded.");
147            break;
148 
149        case CD_CDROM:
150            strcat(err, "The drive is loaded with a CD-ROM.  Subsequent ");
151            strcat(err, "play or read operations will return I/O errors.");
152            break;
153 
154        case CD_ERROR:
155            strcat(err, "An error occurred while trying to read the disc or");
156            strcat(err, " it table of contents.");
157            break;
158 
159        case CD_PLAYING:
160            strcat(err, "The drive is in CD player mode playing an audio ");
161            strcat(err, "CD through its audio jacks.");
162            break;
163 
164        case CD_PAUSED:
165        case CD_STILL:
166            strcat(err, "The drive is in CD player mode with play paused.");
167            break;
168 
169        default:
170            strcat(err, "An unknown error occured.");
171        }
172        ReportError(err);
173 
174        return false;
175    }
176 
177    // Initialize cdinfo to all zeroes.
178    memset(&cdinfo, 0, sizeof(MUSICBRAINZ_CDINFO));
179 
180    // Find the number of the first track (usually 1) and the last track.
181    if (ReadTOCHeader(fd, first, last))
182    {
183       ReportError("Cannot read table of contents.");
184       CDclose(fd);
185       return false;
186    }
187 
188    // Do some basic error checking.
189    if (last==0)
190    {
191       ReportError("This disk has no tracks.");
192       CDclose(fd);
193       return false;
194    }
195 
196    // Get the block address for the end of the audio data.
197    // The "LEADOUT" track is the track beyond the final audio track
198    // so we're looking for the block address of the LEADOUT track.
199    ReadTOCEntryEnd(fd, last, lba);
200    cdinfo.FrameOffset[0] = lba + 150;
201 
202    // Now, for every track, find out the block address where it starts.
203    for (i = first; i <= last; i++)
204    {
205       ReadTOCEntry(fd, i, lba);
206       cdinfo.FrameOffset[i] = lba + 150;
207    }
208 
209    cdinfo.FirstTrack = first;
210    cdinfo.LastTrack = last;
211 
212    CDclose(fd);
213 
214    return true;
215 }
216 
217