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 Stephen van Egmond
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_beos.cpp,v 1.3 2001/07/06 21:32:13 robert Exp $
24
25 ----------------------------------------------------------------------------*/
26
27 #include "mb.h"
28 #include "diskid.h"
29 #include "config.h"
30
31 // BeOS layer includes
32 #include <Path.h>
33 #include <Directory.h>
34 #include <String.h>
35 #include <scsi.h>
36 #include <Roster.h>
37
38 // POSIX layer includes
39 #include <string.h>
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <stdlib.h>
43 #include <assert.h>
44
45
46 // forward declarations
47 static void FindCDPlayerDevice();
48 static uint32 msf_to_lba(uint8 m, uint8 s, uint8 f);
49
50 // global variables
51 BString gCDPlayerDeviceName;
52 int gCDPlayerDevice;
53
54 // initializer -- call before using above globals
gConfigureGlobals()55 status_t gConfigureGlobals() {
56 gCDPlayerDevice = 0;
57
58 FindCDPlayerDevice();
59 if (gCDPlayerDevice == 0) {
60 return B_DEV_BAD_DRIVE_NUM;
61 }
62
63 return B_NO_ERROR;
64 }
65
ReadTOC(char * device,MUSICBRAINZ_CDINFO & cdinfo)66 bool DiskId::ReadTOC(char *device,
67 MUSICBRAINZ_CDINFO& cdinfo) {
68 // how does it get the device?
69 status_t rc = gConfigureGlobals();
70 if (rc != B_NO_ERROR) {
71 char err[255];
72 sprintf(err, "Error while accessing the CD drive: %s.",
73 strerror(rc));
74 ReportError(err);
75
76 return false;
77 }
78
79 scsi_toc toc;
80
81 rc = ioctl(gCDPlayerDevice, B_SCSI_GET_TOC, &toc);
82
83 if (rc != B_NO_ERROR) {
84 char err[255];
85 sprintf(err, "Error while accessing %s: %s.",
86 gCDPlayerDeviceName.String(), strerror(rc));
87 ReportError(err);
88
89 return false;
90 }
91
92 /*
93
94 typedef struct {
95 byte FirstTrack; // The first track on CD : normally 1
96 byte LastTrack; // The last track on CD: max number 99
97
98 dword FrameOffset[100]; // Track 2 is TrackFrameOffset[2] etc.
99
100 // Leadout Track will be TrackFrameOffset[0]
101
102 } MUSICBRAINZ_CDINFO, *PMUSICBRAINZ_CDINFO;
103
104 */
105
106
107 /*
108
109 SCSI toc format
110
111 http://www.symbios.com/t10
112
113 All multibyte values big-endian
114
115 uint16 data_length; // of following data, not including these 2 bytes
116 uint8 first_track;
117 uint8 last_track;
118
119 struct {
120 uint8 reserved;
121 uint8 flag_bits; // ADR and CONTROL, whatever
122 uint8 track_number;
123 uint8 reserved2;
124 uint32 logical_block_address;
125 } [n];
126
127 // where n fills out the data length
128 */
129
130
131 uint16 data_length = * ((uint16*)toc.toc_data);
132 data_length = B_BENDIAN_TO_HOST_INT16(data_length);
133 data_length += 2; // to include the length itself
134
135 cdinfo.FirstTrack = toc.toc_data[2];
136 cdinfo.LastTrack = toc.toc_data[3];
137 assert(cdinfo.FirstTrack >= 1 && cdinfo.FirstTrack<=99);
138 assert(cdinfo.LastTrack >= 1 && cdinfo.LastTrack<=99);
139
140 int indexer = 4;
141 while (indexer < data_length) {
142 indexer+=2;
143 int track_number = toc.toc_data[indexer];
144 indexer+=2;
145 uint32 lba = msf_to_lba(toc.toc_data[indexer+1],toc.toc_data[indexer+2],toc.toc_data[indexer+3]);
146
147 indexer+=4;
148
149 assert(track_number == 0xaa || (track_number>=1 && track_number <= cdinfo.LastTrack));
150 if (track_number == 0xaa)
151 track_number = 0;
152
153 cdinfo.FrameOffset[track_number] = lba + 150;
154 }
155
156 return true;
157 }
158
159
try_dir(const char * directory)160 static bool try_dir(const char *directory)
161 {
162 BDirectory dir;
163 dir.SetTo(directory);
164 if(dir.InitCheck() != B_NO_ERROR) {
165 return false;
166 }
167 dir.Rewind();
168 BEntry entry;
169 while(dir.GetNextEntry(&entry) >= 0) {
170 BPath path;
171 const char *name;
172 entry_ref e;
173
174 if(entry.GetPath(&path) != B_NO_ERROR)
175 continue;
176 name = path.Path();
177
178
179 if(entry.GetRef(&e) != B_NO_ERROR)
180 continue;
181
182 if(entry.IsDirectory()) {
183 if(strcmp(e.name, "floppy") == 0)
184 continue; // ignore floppy (it is not silent)
185 if (try_dir(name))
186 return true;
187 }
188 else {
189 int devfd;
190 device_geometry g;
191
192 if(strcmp(e.name, "raw") != 0)
193 continue; // ignore partitions
194
195 devfd = open(name, O_RDONLY);
196 if(devfd < 0)
197 continue;
198
199 if(ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) {
200 if(g.device_type == B_CD)
201 {
202 gCDPlayerDevice = devfd;
203 gCDPlayerDeviceName = name;
204 return true;
205 }
206 }
207 close(devfd);
208 }
209 }
210
211 return false;
212 }
213
214
FindCDPlayerDevice()215 static void FindCDPlayerDevice()
216 {
217 try_dir("/dev/disk");
218 }
219
220
msf_to_lba(uint8 m,uint8 s,uint8 f)221 static uint32 msf_to_lba(uint8 m, uint8 s, uint8 f)
222 {
223 return (((m * 60) + s) * 75 + f) - 150;
224 }
225