Mercurial > sdl-ios-xcode
comparison src/cdrom/macosx/CDPlayer.c @ 1895:c121d94672cb
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 10 Jul 2006 21:04:37 +0000 |
parents | dc6b59e925a2 |
children | e27bdcc80744 |
comparison
equal
deleted
inserted
replaced
1894:c69cee13dd76 | 1895:c121d94672cb |
---|---|
30 | 30 |
31 /*/////////////////////////////////////////////////////////////////////////// | 31 /*/////////////////////////////////////////////////////////////////////////// |
32 Constants | 32 Constants |
33 //////////////////////////////////////////////////////////////////////////*/ | 33 //////////////////////////////////////////////////////////////////////////*/ |
34 | 34 |
35 #define kAudioCDFilesystemID (UInt16)(('J' << 8) | 'H') /* 'JH'; this avoids compiler warning */ | 35 #define kAudioCDFilesystemID (UInt16)(('J' << 8) | 'H') /* 'JH'; this avoids compiler warning */ |
36 | 36 |
37 /* XML PList keys */ | 37 /* XML PList keys */ |
38 #define kRawTOCDataString "Format 0x02 TOC Data" | 38 #define kRawTOCDataString "Format 0x02 TOC Data" |
39 #define kSessionsString "Sessions" | 39 #define kSessionsString "Sessions" |
40 #define kSessionTypeString "Session Type" | 40 #define kSessionTypeString "Session Type" |
43 #define kLastTrackInSessionString "Last Track" | 43 #define kLastTrackInSessionString "Last Track" |
44 #define kLeadoutBlockString "Leadout Block" | 44 #define kLeadoutBlockString "Leadout Block" |
45 #define kDataKeyString "Data" | 45 #define kDataKeyString "Data" |
46 #define kPointKeyString "Point" | 46 #define kPointKeyString "Point" |
47 #define kSessionNumberKeyString "Session Number" | 47 #define kSessionNumberKeyString "Session Number" |
48 #define kStartBlockKeyString "Start Block" | 48 #define kStartBlockKeyString "Start Block" |
49 | 49 |
50 /*/////////////////////////////////////////////////////////////////////////// | 50 /*/////////////////////////////////////////////////////////////////////////// |
51 Globals | 51 Globals |
52 //////////////////////////////////////////////////////////////////////////*/ | 52 //////////////////////////////////////////////////////////////////////////*/ |
53 | 53 |
54 #pragma mark -- Globals -- | 54 #pragma mark -- Globals -- |
55 | 55 |
56 static int playBackWasInit = 0; | 56 static int playBackWasInit = 0; |
57 static AudioUnit theUnit; | 57 static AudioUnit theUnit; |
58 static AudioFilePlayer* thePlayer = NULL; | 58 static AudioFilePlayer *thePlayer = NULL; |
59 static CDPlayerCompletionProc completionProc = NULL; | 59 static CDPlayerCompletionProc completionProc = NULL; |
60 static SDL_mutex *apiMutex = NULL; | 60 static SDL_mutex *apiMutex = NULL; |
61 static SDL_sem *callbackSem; | 61 static SDL_sem *callbackSem; |
62 static SDL_CD* theCDROM; | 62 static SDL_CD *theCDROM; |
63 | 63 |
64 /*/////////////////////////////////////////////////////////////////////////// | 64 /*/////////////////////////////////////////////////////////////////////////// |
65 Prototypes | 65 Prototypes |
66 //////////////////////////////////////////////////////////////////////////*/ | 66 //////////////////////////////////////////////////////////////////////////*/ |
67 | 67 |
68 #pragma mark -- Prototypes -- | 68 #pragma mark -- Prototypes -- |
69 | 69 |
70 static OSStatus CheckInit (); | 70 static OSStatus CheckInit(); |
71 | 71 |
72 static void FilePlayNotificationHandler (void* inRefCon, OSStatus inStatus); | 72 static void FilePlayNotificationHandler(void *inRefCon, OSStatus inStatus); |
73 | 73 |
74 static int RunCallBackThread (void* inRefCon); | 74 static int RunCallBackThread(void *inRefCon); |
75 | 75 |
76 | 76 |
77 #pragma mark -- Public Functions -- | 77 #pragma mark -- Public Functions -- |
78 | 78 |
79 void Lock () | 79 void |
80 Lock() | |
80 { | 81 { |
81 if (!apiMutex) { | 82 if (!apiMutex) { |
82 apiMutex = SDL_CreateMutex(); | 83 apiMutex = SDL_CreateMutex(); |
83 } | 84 } |
84 SDL_mutexP(apiMutex); | 85 SDL_mutexP(apiMutex); |
85 } | 86 } |
86 | 87 |
87 void Unlock () | 88 void |
89 Unlock() | |
88 { | 90 { |
89 SDL_mutexV(apiMutex); | 91 SDL_mutexV(apiMutex); |
90 } | 92 } |
91 | 93 |
92 int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes) | 94 int |
95 DetectAudioCDVolumes(FSVolumeRefNum * volumes, int numVolumes) | |
93 { | 96 { |
94 int volumeIndex; | 97 int volumeIndex; |
95 int cdVolumeCount = 0; | 98 int cdVolumeCount = 0; |
96 OSStatus result = noErr; | 99 OSStatus result = noErr; |
97 | 100 |
98 for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++) | 101 for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++) { |
99 { | 102 FSVolumeRefNum actualVolume; |
100 FSVolumeRefNum actualVolume; | 103 FSVolumeInfo volumeInfo; |
101 FSVolumeInfo volumeInfo; | 104 |
102 | 105 memset(&volumeInfo, 0, sizeof(volumeInfo)); |
103 memset (&volumeInfo, 0, sizeof(volumeInfo)); | 106 |
104 | 107 result = FSGetVolumeInfo(kFSInvalidVolumeRefNum, |
105 result = FSGetVolumeInfo (kFSInvalidVolumeRefNum, | 108 volumeIndex, |
106 volumeIndex, | 109 &actualVolume, |
107 &actualVolume, | 110 kFSVolInfoFSInfo, &volumeInfo, NULL, NULL); |
108 kFSVolInfoFSInfo, | 111 |
109 &volumeInfo, | 112 if (result == noErr) { |
110 NULL, | 113 if (volumeInfo.filesystemID == kAudioCDFilesystemID) { /* It's an audio CD */ |
111 NULL); | |
112 | |
113 if (result == noErr) | |
114 { | |
115 if (volumeInfo.filesystemID == kAudioCDFilesystemID) /* It's an audio CD */ | |
116 { | |
117 if (volumes != NULL && cdVolumeCount < numVolumes) | 114 if (volumes != NULL && cdVolumeCount < numVolumes) |
118 volumes[cdVolumeCount] = actualVolume; | 115 volumes[cdVolumeCount] = actualVolume; |
119 | 116 |
120 cdVolumeCount++; | 117 cdVolumeCount++; |
121 } | 118 } |
119 } else { | |
120 /* I'm commenting this out because it seems to be harmless */ | |
121 /*SDL_SetError ("DetectAudioCDVolumes: FSGetVolumeInfo returned %d", result); */ | |
122 } | 122 } |
123 else | 123 } |
124 { | 124 |
125 /* I'm commenting this out because it seems to be harmless */ | |
126 /*SDL_SetError ("DetectAudioCDVolumes: FSGetVolumeInfo returned %d", result);*/ | |
127 } | |
128 } | |
129 | |
130 return cdVolumeCount; | 125 return cdVolumeCount; |
131 } | 126 } |
132 | 127 |
133 int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD) | 128 int |
134 { | 129 ReadTOCData(FSVolumeRefNum theVolume, SDL_CD * theCD) |
135 HFSUniStr255 dataForkName; | 130 { |
136 OSStatus theErr; | 131 HFSUniStr255 dataForkName; |
137 SInt16 forkRefNum; | 132 OSStatus theErr; |
138 SInt64 forkSize; | 133 SInt16 forkRefNum; |
139 Ptr forkData = 0; | 134 SInt64 forkSize; |
140 ByteCount actualRead; | 135 Ptr forkData = 0; |
141 CFDataRef dataRef = 0; | 136 ByteCount actualRead; |
137 CFDataRef dataRef = 0; | |
142 CFPropertyListRef propertyListRef = 0; | 138 CFPropertyListRef propertyListRef = 0; |
143 | 139 |
144 FSRefParam fsRefPB; | 140 FSRefParam fsRefPB; |
145 FSRef tocPlistFSRef; | 141 FSRef tocPlistFSRef; |
146 | 142 |
147 const char* error = "Unspecified Error"; | 143 const char *error = "Unspecified Error"; |
148 | 144 |
149 /* get stuff from .TOC.plist */ | 145 /* get stuff from .TOC.plist */ |
150 fsRefPB.ioCompletion = NULL; | 146 fsRefPB.ioCompletion = NULL; |
151 fsRefPB.ioNamePtr = "\p.TOC.plist"; | 147 fsRefPB.ioNamePtr = "\p.TOC.plist"; |
152 fsRefPB.ioVRefNum = theVolume; | 148 fsRefPB.ioVRefNum = theVolume; |
153 fsRefPB.ioDirID = 0; | 149 fsRefPB.ioDirID = 0; |
154 fsRefPB.newRef = &tocPlistFSRef; | 150 fsRefPB.newRef = &tocPlistFSRef; |
155 | 151 |
156 theErr = PBMakeFSRefSync (&fsRefPB); | 152 theErr = PBMakeFSRefSync(&fsRefPB); |
157 if(theErr != noErr) { | 153 if (theErr != noErr) { |
158 error = "PBMakeFSRefSync"; | 154 error = "PBMakeFSRefSync"; |
159 goto bail; | 155 goto bail; |
160 } | 156 } |
161 | 157 |
162 /* Load and parse the TOC XML data */ | 158 /* Load and parse the TOC XML data */ |
163 | 159 |
164 theErr = FSGetDataForkName (&dataForkName); | 160 theErr = FSGetDataForkName(&dataForkName); |
165 if (theErr != noErr) { | 161 if (theErr != noErr) { |
166 error = "FSGetDataForkName"; | 162 error = "FSGetDataForkName"; |
167 goto bail; | 163 goto bail; |
168 } | 164 } |
169 | 165 |
170 theErr = FSOpenFork (&tocPlistFSRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &forkRefNum); | 166 theErr = |
167 FSOpenFork(&tocPlistFSRef, dataForkName.length, dataForkName.unicode, | |
168 fsRdPerm, &forkRefNum); | |
171 if (theErr != noErr) { | 169 if (theErr != noErr) { |
172 error = "FSOpenFork"; | 170 error = "FSOpenFork"; |
173 goto bail; | 171 goto bail; |
174 } | 172 } |
175 | 173 |
176 theErr = FSGetForkSize (forkRefNum, &forkSize); | 174 theErr = FSGetForkSize(forkRefNum, &forkSize); |
177 if (theErr != noErr) { | 175 if (theErr != noErr) { |
178 error = "FSGetForkSize"; | 176 error = "FSGetForkSize"; |
179 goto bail; | 177 goto bail; |
180 } | 178 } |
181 | 179 |
182 /* Allocate some memory for the XML data */ | 180 /* Allocate some memory for the XML data */ |
183 forkData = NewPtr (forkSize); | 181 forkData = NewPtr(forkSize); |
184 if(forkData == NULL) { | 182 if (forkData == NULL) { |
185 error = "NewPtr"; | 183 error = "NewPtr"; |
186 goto bail; | 184 goto bail; |
187 } | 185 } |
188 | 186 |
189 theErr = FSReadFork (forkRefNum, fsFromStart, 0 /* offset location */, forkSize, forkData, &actualRead); | 187 theErr = FSReadFork(forkRefNum, fsFromStart, 0 /* offset location */ , |
190 if(theErr != noErr) { | 188 forkSize, forkData, &actualRead); |
189 if (theErr != noErr) { | |
191 error = "FSReadFork"; | 190 error = "FSReadFork"; |
192 goto bail; | 191 goto bail; |
193 } | 192 } |
194 | 193 |
195 dataRef = CFDataCreate (kCFAllocatorDefault, (UInt8 *)forkData, forkSize); | 194 dataRef = CFDataCreate(kCFAllocatorDefault, (UInt8 *) forkData, forkSize); |
196 if(dataRef == 0) { | 195 if (dataRef == 0) { |
197 error = "CFDataCreate"; | 196 error = "CFDataCreate"; |
198 goto bail; | 197 goto bail; |
199 } | 198 } |
200 | 199 |
201 propertyListRef = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, | 200 propertyListRef = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, |
202 dataRef, | 201 dataRef, |
203 kCFPropertyListImmutable, | 202 kCFPropertyListImmutable, |
204 NULL); | 203 NULL); |
205 if (propertyListRef == NULL) { | 204 if (propertyListRef == NULL) { |
206 error = "CFPropertyListCreateFromXMLData"; | 205 error = "CFPropertyListCreateFromXMLData"; |
207 goto bail; | 206 goto bail; |
208 } | 207 } |
209 | 208 |
210 /* Now we got the Property List in memory. Parse it. */ | 209 /* Now we got the Property List in memory. Parse it. */ |
211 | 210 |
212 /* First, make sure the root item is a CFDictionary. If not, release and bail. */ | 211 /* First, make sure the root item is a CFDictionary. If not, release and bail. */ |
213 if(CFGetTypeID(propertyListRef)== CFDictionaryGetTypeID()) | 212 if (CFGetTypeID(propertyListRef) == CFDictionaryGetTypeID()) { |
214 { | 213 CFDictionaryRef dictRef = (CFDictionaryRef) propertyListRef; |
215 CFDictionaryRef dictRef = (CFDictionaryRef)propertyListRef; | 214 |
216 | 215 CFDataRef theRawTOCDataRef; |
217 CFDataRef theRawTOCDataRef; | 216 CFArrayRef theSessionArrayRef; |
218 CFArrayRef theSessionArrayRef; | 217 CFIndex numSessions; |
219 CFIndex numSessions; | 218 CFIndex index; |
220 CFIndex index; | 219 |
221 | |
222 /* This is how we get the Raw TOC Data */ | 220 /* This is how we get the Raw TOC Data */ |
223 theRawTOCDataRef = (CFDataRef)CFDictionaryGetValue (dictRef, CFSTR(kRawTOCDataString)); | 221 theRawTOCDataRef = |
224 | 222 (CFDataRef) CFDictionaryGetValue(dictRef, |
223 CFSTR(kRawTOCDataString)); | |
224 | |
225 /* Get the session array info. */ | 225 /* Get the session array info. */ |
226 theSessionArrayRef = (CFArrayRef)CFDictionaryGetValue (dictRef, CFSTR(kSessionsString)); | 226 theSessionArrayRef = |
227 | 227 (CFArrayRef) CFDictionaryGetValue(dictRef, |
228 CFSTR(kSessionsString)); | |
229 | |
228 /* Find out how many sessions there are. */ | 230 /* Find out how many sessions there are. */ |
229 numSessions = CFArrayGetCount (theSessionArrayRef); | 231 numSessions = CFArrayGetCount(theSessionArrayRef); |
230 | 232 |
231 /* Initialize the total number of tracks to 0 */ | 233 /* Initialize the total number of tracks to 0 */ |
232 theCD->numtracks = 0; | 234 theCD->numtracks = 0; |
233 | 235 |
234 /* Iterate over all sessions, collecting the track data */ | 236 /* Iterate over all sessions, collecting the track data */ |
235 for(index = 0; index < numSessions; index++) | 237 for (index = 0; index < numSessions; index++) { |
236 { | |
237 CFDictionaryRef theSessionDict; | 238 CFDictionaryRef theSessionDict; |
238 CFNumberRef leadoutBlock; | 239 CFNumberRef leadoutBlock; |
239 CFArrayRef trackArray; | 240 CFArrayRef trackArray; |
240 CFIndex numTracks; | 241 CFIndex numTracks; |
241 CFIndex trackIndex; | 242 CFIndex trackIndex; |
242 UInt32 value = 0; | 243 UInt32 value = 0; |
243 | 244 |
244 theSessionDict = (CFDictionaryRef) CFArrayGetValueAtIndex (theSessionArrayRef, index); | 245 theSessionDict = (CFDictionaryRef) |
245 leadoutBlock = (CFNumberRef) CFDictionaryGetValue (theSessionDict, CFSTR(kLeadoutBlockString)); | 246 CFArrayGetValueAtIndex(theSessionArrayRef, index); |
246 | 247 leadoutBlock = |
247 trackArray = (CFArrayRef)CFDictionaryGetValue (theSessionDict, CFSTR(kTrackArrayString)); | 248 (CFNumberRef) CFDictionaryGetValue(theSessionDict, |
248 | 249 CFSTR |
249 numTracks = CFArrayGetCount (trackArray); | 250 (kLeadoutBlockString)); |
250 | 251 |
251 for(trackIndex = 0; trackIndex < numTracks; trackIndex++) { | 252 trackArray = |
252 | 253 (CFArrayRef) CFDictionaryGetValue(theSessionDict, |
254 CFSTR(kTrackArrayString)); | |
255 | |
256 numTracks = CFArrayGetCount(trackArray); | |
257 | |
258 for (trackIndex = 0; trackIndex < numTracks; trackIndex++) { | |
259 | |
253 CFDictionaryRef theTrackDict; | 260 CFDictionaryRef theTrackDict; |
254 CFNumberRef trackNumber; | 261 CFNumberRef trackNumber; |
255 CFNumberRef sessionNumber; | 262 CFNumberRef sessionNumber; |
256 CFNumberRef startBlock; | 263 CFNumberRef startBlock; |
257 CFBooleanRef isDataTrack; | 264 CFBooleanRef isDataTrack; |
258 UInt32 value; | 265 UInt32 value; |
259 | 266 |
260 theTrackDict = (CFDictionaryRef) CFArrayGetValueAtIndex (trackArray, trackIndex); | 267 theTrackDict = (CFDictionaryRef) |
261 | 268 CFArrayGetValueAtIndex(trackArray, trackIndex); |
262 trackNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kPointKeyString)); | 269 |
263 sessionNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kSessionNumberKeyString)); | 270 trackNumber = |
264 startBlock = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kStartBlockKeyString)); | 271 (CFNumberRef) CFDictionaryGetValue(theTrackDict, |
265 isDataTrack = (CFBooleanRef) CFDictionaryGetValue (theTrackDict, CFSTR(kDataKeyString)); | 272 CFSTR |
266 | 273 (kPointKeyString)); |
274 sessionNumber = | |
275 (CFNumberRef) CFDictionaryGetValue(theTrackDict, | |
276 CFSTR | |
277 (kSessionNumberKeyString)); | |
278 startBlock = | |
279 (CFNumberRef) CFDictionaryGetValue(theTrackDict, | |
280 CFSTR | |
281 (kStartBlockKeyString)); | |
282 isDataTrack = | |
283 (CFBooleanRef) CFDictionaryGetValue(theTrackDict, | |
284 CFSTR | |
285 (kDataKeyString)); | |
286 | |
267 /* Fill in the SDL_CD struct */ | 287 /* Fill in the SDL_CD struct */ |
268 int idx = theCD->numtracks++; | 288 int idx = theCD->numtracks++; |
269 | 289 |
270 CFNumberGetValue (trackNumber, kCFNumberSInt32Type, &value); | 290 CFNumberGetValue(trackNumber, kCFNumberSInt32Type, &value); |
271 theCD->track[idx].id = value; | 291 theCD->track[idx].id = value; |
272 | 292 |
273 CFNumberGetValue (startBlock, kCFNumberSInt32Type, &value); | 293 CFNumberGetValue(startBlock, kCFNumberSInt32Type, &value); |
274 theCD->track[idx].offset = value; | 294 theCD->track[idx].offset = value; |
275 | 295 |
276 theCD->track[idx].type = (isDataTrack == kCFBooleanTrue) ? SDL_DATA_TRACK : SDL_AUDIO_TRACK; | 296 theCD->track[idx].type = |
297 (isDataTrack == | |
298 kCFBooleanTrue) ? SDL_DATA_TRACK : SDL_AUDIO_TRACK; | |
277 | 299 |
278 /* Since the track lengths are not stored in .TOC.plist we compute them. */ | 300 /* Since the track lengths are not stored in .TOC.plist we compute them. */ |
279 if (trackIndex > 0) { | 301 if (trackIndex > 0) { |
280 theCD->track[idx-1].length = theCD->track[idx].offset - theCD->track[idx-1].offset; | 302 theCD->track[idx - 1].length = |
303 theCD->track[idx].offset - theCD->track[idx - | |
304 1].offset; | |
281 } | 305 } |
282 } | 306 } |
283 | 307 |
284 /* Compute the length of the last track */ | 308 /* Compute the length of the last track */ |
285 CFNumberGetValue (leadoutBlock, kCFNumberSInt32Type, &value); | 309 CFNumberGetValue(leadoutBlock, kCFNumberSInt32Type, &value); |
286 | 310 |
287 theCD->track[theCD->numtracks-1].length = | 311 theCD->track[theCD->numtracks - 1].length = |
288 value - theCD->track[theCD->numtracks-1].offset; | 312 value - theCD->track[theCD->numtracks - 1].offset; |
289 | 313 |
290 /* Set offset to leadout track */ | 314 /* Set offset to leadout track */ |
291 theCD->track[theCD->numtracks].offset = value; | 315 theCD->track[theCD->numtracks].offset = value; |
292 } | 316 } |
293 | 317 |
294 } | 318 } |
295 | 319 |
296 theErr = 0; | 320 theErr = 0; |
297 goto cleanup; | 321 goto cleanup; |
298 bail: | 322 bail: |
299 SDL_SetError ("ReadTOCData: %s returned %d", error, theErr); | 323 SDL_SetError("ReadTOCData: %s returned %d", error, theErr); |
300 theErr = -1; | 324 theErr = -1; |
301 cleanup: | 325 cleanup: |
302 | 326 |
303 if (propertyListRef != NULL) | 327 if (propertyListRef != NULL) |
304 CFRelease(propertyListRef); | 328 CFRelease(propertyListRef); |
305 if (dataRef != NULL) | 329 if (dataRef != NULL) |
306 CFRelease(dataRef); | 330 CFRelease(dataRef); |
307 if (forkData != NULL) | 331 if (forkData != NULL) |
308 DisposePtr(forkData); | 332 DisposePtr(forkData); |
309 | 333 |
310 FSCloseFork (forkRefNum); | 334 FSCloseFork(forkRefNum); |
311 | 335 |
312 return theErr; | 336 return theErr; |
313 } | 337 } |
314 | 338 |
315 int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks) | 339 int |
316 { | 340 ListTrackFiles(FSVolumeRefNum theVolume, FSRef * trackFiles, int numTracks) |
317 OSStatus result = -1; | 341 { |
318 FSIterator iterator; | 342 OSStatus result = -1; |
319 ItemCount actualObjects; | 343 FSIterator iterator; |
320 FSRef rootDirectory; | 344 ItemCount actualObjects; |
321 FSRef ref; | 345 FSRef rootDirectory; |
322 HFSUniStr255 nameStr; | 346 FSRef ref; |
323 | 347 HFSUniStr255 nameStr; |
324 result = FSGetVolumeInfo (theVolume, | 348 |
325 0, | 349 result = FSGetVolumeInfo(theVolume, |
326 NULL, | 350 0, |
327 kFSVolInfoFSInfo, | 351 NULL, |
328 NULL, | 352 kFSVolInfoFSInfo, NULL, NULL, &rootDirectory); |
329 NULL, | 353 |
330 &rootDirectory); | |
331 | |
332 if (result != noErr) { | 354 if (result != noErr) { |
333 SDL_SetError ("ListTrackFiles: FSGetVolumeInfo returned %d", result); | 355 SDL_SetError("ListTrackFiles: FSGetVolumeInfo returned %d", result); |
334 return result; | 356 return result; |
335 } | 357 } |
336 | 358 |
337 result = FSOpenIterator (&rootDirectory, kFSIterateFlat, &iterator); | 359 result = FSOpenIterator(&rootDirectory, kFSIterateFlat, &iterator); |
338 if (result == noErr) { | 360 if (result == noErr) { |
339 do | 361 do { |
340 { | 362 result = FSGetCatalogInfoBulk(iterator, 1, &actualObjects, |
341 result = FSGetCatalogInfoBulk (iterator, 1, &actualObjects, | 363 NULL, kFSCatInfoNone, NULL, |
342 NULL, kFSCatInfoNone, NULL, &ref, NULL, &nameStr); | 364 &ref, NULL, &nameStr); |
343 if (result == noErr) { | 365 if (result == noErr) { |
344 | 366 |
345 CFStringRef name; | 367 CFStringRef name; |
346 name = CFStringCreateWithCharacters (NULL, nameStr.unicode, nameStr.length); | 368 name = |
347 | 369 CFStringCreateWithCharacters(NULL, nameStr.unicode, |
370 nameStr.length); | |
371 | |
348 /* Look for .aiff extension */ | 372 /* Look for .aiff extension */ |
349 if (CFStringHasSuffix (name, CFSTR(".aiff")) || | 373 if (CFStringHasSuffix(name, CFSTR(".aiff")) || |
350 CFStringHasSuffix (name, CFSTR(".cdda"))) { | 374 CFStringHasSuffix(name, CFSTR(".cdda"))) { |
351 | 375 |
352 /* Extract the track id from the filename */ | 376 /* Extract the track id from the filename */ |
353 int trackID = 0, i = 0; | 377 int trackID = 0, i = 0; |
354 while (i < nameStr.length && !isdigit(nameStr.unicode[i])) { | 378 while (i < nameStr.length && !isdigit(nameStr.unicode[i])) { |
355 ++i; | 379 ++i; |
356 } | 380 } |
357 while (i < nameStr.length && isdigit(nameStr.unicode[i])) { | 381 while (i < nameStr.length && isdigit(nameStr.unicode[i])) { |
358 trackID = 10 * trackID +(nameStr.unicode[i] - '0'); | 382 trackID = 10 * trackID + (nameStr.unicode[i] - '0'); |
359 ++i; | 383 ++i; |
360 } | 384 } |
361 | 385 |
362 #if DEBUG_CDROM | 386 #if DEBUG_CDROM |
363 printf("Found AIFF for track %d: '%s'\n", trackID, | 387 printf("Found AIFF for track %d: '%s'\n", |
364 CFStringGetCStringPtr (name, CFStringGetSystemEncoding())); | 388 trackID, CFStringGetCStringPtr(name, |
365 #endif | 389 CFStringGetSystemEncoding |
366 | 390 ())); |
391 #endif | |
392 | |
367 /* Track ID's start at 1, but we want to start at 0 */ | 393 /* Track ID's start at 1, but we want to start at 0 */ |
368 trackID--; | 394 trackID--; |
369 | 395 |
370 assert(0 <= trackID && trackID <= SDL_MAX_TRACKS); | 396 assert(0 <= trackID && trackID <= SDL_MAX_TRACKS); |
371 | 397 |
372 if (trackID < numTracks) | 398 if (trackID < numTracks) |
373 memcpy (&trackFiles[trackID], &ref, sizeof(FSRef)); | 399 memcpy(&trackFiles[trackID], &ref, sizeof(FSRef)); |
374 } | 400 } |
375 CFRelease (name); | 401 CFRelease(name); |
376 } | 402 } |
377 } while(noErr == result); | 403 } |
378 FSCloseIterator (iterator); | 404 while (noErr == result); |
379 } | 405 FSCloseIterator(iterator); |
380 | 406 } |
407 | |
381 return 0; | 408 return 0; |
382 } | 409 } |
383 | 410 |
384 int LoadFile (const FSRef *ref, int startFrame, int stopFrame) | 411 int |
412 LoadFile(const FSRef * ref, int startFrame, int stopFrame) | |
385 { | 413 { |
386 int error = -1; | 414 int error = -1; |
387 | 415 |
388 if (CheckInit () < 0) | 416 if (CheckInit() < 0) |
389 goto bail; | 417 goto bail; |
390 | 418 |
391 /* release any currently playing file */ | 419 /* release any currently playing file */ |
392 if (ReleaseFile () < 0) | 420 if (ReleaseFile() < 0) |
393 goto bail; | 421 goto bail; |
394 | 422 |
395 #if DEBUG_CDROM | 423 #if DEBUG_CDROM |
396 printf ("LoadFile: %d %d\n", startFrame, stopFrame); | 424 printf("LoadFile: %d %d\n", startFrame, stopFrame); |
397 #endif | 425 #endif |
398 | 426 |
399 /*try {*/ | 427 /*try { */ |
400 | 428 |
401 /* create a new player, and attach to the audio unit */ | 429 /* create a new player, and attach to the audio unit */ |
402 | 430 |
403 thePlayer = new_AudioFilePlayer(ref); | 431 thePlayer = new_AudioFilePlayer(ref); |
404 if (thePlayer == NULL) { | 432 if (thePlayer == NULL) { |
405 SDL_SetError ("LoadFile: Could not create player"); | 433 SDL_SetError("LoadFile: Could not create player"); |
406 return -3; /*throw (-3);*/ | 434 return -3; /*throw (-3); */ |
407 } | 435 } |
408 | 436 |
409 if (!thePlayer->SetDestination(thePlayer, &theUnit)) | 437 if (!thePlayer->SetDestination(thePlayer, &theUnit)) |
410 goto bail; | 438 goto bail; |
411 | 439 |
412 if (startFrame >= 0) | 440 if (startFrame >= 0) |
413 thePlayer->SetStartFrame (thePlayer, startFrame); | 441 thePlayer->SetStartFrame(thePlayer, startFrame); |
414 | 442 |
415 if (stopFrame >= 0 && stopFrame > startFrame) | 443 if (stopFrame >= 0 && stopFrame > startFrame) |
416 thePlayer->SetStopFrame (thePlayer, stopFrame); | 444 thePlayer->SetStopFrame(thePlayer, stopFrame); |
417 | 445 |
418 /* we set the notifier later */ | 446 /* we set the notifier later */ |
419 /*thePlayer->SetNotifier(thePlayer, FilePlayNotificationHandler, NULL);*/ | 447 /*thePlayer->SetNotifier(thePlayer, FilePlayNotificationHandler, NULL); */ |
420 | 448 |
421 if (!thePlayer->Connect(thePlayer)) | 449 if (!thePlayer->Connect(thePlayer)) |
422 goto bail; | 450 goto bail; |
423 | 451 |
424 #if DEBUG_CDROM | 452 #if DEBUG_CDROM |
425 thePlayer->Print(thePlayer); | 453 thePlayer->Print(thePlayer); |
426 fflush (stdout); | 454 fflush(stdout); |
427 #endif | 455 #endif |
428 /*} | 456 /*} |
429 catch (...) | 457 catch (...) |
430 { | 458 { |
431 goto bail; | 459 goto bail; |
432 }*/ | 460 } */ |
433 | 461 |
434 error = 0; | 462 error = 0; |
435 | 463 |
436 bail: | 464 bail: |
437 return error; | 465 return error; |
438 } | 466 } |
439 | 467 |
440 int ReleaseFile () | 468 int |
469 ReleaseFile() | |
441 { | 470 { |
442 int error = -1; | 471 int error = -1; |
443 | 472 |
444 /* (Don't see any way that the original C++ code could throw here.) --ryan. */ | 473 /* (Don't see any way that the original C++ code could throw here.) --ryan. */ |
445 /*try {*/ | 474 /*try { */ |
446 if (thePlayer != NULL) { | 475 if (thePlayer != NULL) { |
447 | 476 |
448 thePlayer->Disconnect(thePlayer); | 477 thePlayer->Disconnect(thePlayer); |
449 | 478 |
450 delete_AudioFilePlayer(thePlayer); | 479 delete_AudioFilePlayer(thePlayer); |
451 | 480 |
452 thePlayer = NULL; | 481 thePlayer = NULL; |
453 } | 482 } |
454 /*} | 483 /*} |
455 catch (...) | 484 catch (...) |
456 { | 485 { |
457 goto bail; | 486 goto bail; |
458 }*/ | 487 } */ |
459 | 488 |
460 error = 0; | 489 error = 0; |
461 | 490 |
462 /* bail: */ | 491 /* bail: */ |
463 return error; | 492 return error; |
464 } | 493 } |
465 | 494 |
466 int PlayFile () | 495 int |
496 PlayFile() | |
467 { | 497 { |
468 OSStatus result = -1; | 498 OSStatus result = -1; |
469 | 499 |
470 if (CheckInit () < 0) | 500 if (CheckInit() < 0) |
471 goto bail; | 501 goto bail; |
472 | 502 |
473 /*try {*/ | 503 /*try { */ |
474 | 504 |
475 // start processing of the audio unit | 505 // start processing of the audio unit |
476 result = AudioOutputUnitStart (theUnit); | 506 result = AudioOutputUnitStart(theUnit); |
477 if (result) goto bail; //THROW_RESULT("PlayFile: AudioOutputUnitStart") | 507 if (result) |
478 | 508 goto bail; //THROW_RESULT("PlayFile: AudioOutputUnitStart") |
509 | |
479 /*} | 510 /*} |
480 catch (...) | 511 catch (...) |
481 { | 512 { |
482 goto bail; | 513 goto bail; |
483 }*/ | 514 } */ |
484 | 515 |
485 result = 0; | 516 result = 0; |
486 | 517 |
487 bail: | 518 bail: |
488 return result; | 519 return result; |
489 } | 520 } |
490 | 521 |
491 int PauseFile () | 522 int |
523 PauseFile() | |
492 { | 524 { |
493 OSStatus result = -1; | 525 OSStatus result = -1; |
494 | 526 |
495 if (CheckInit () < 0) | 527 if (CheckInit() < 0) |
496 goto bail; | 528 goto bail; |
497 | 529 |
498 /*try {*/ | 530 /*try { */ |
499 | 531 |
500 /* stop processing the audio unit */ | 532 /* stop processing the audio unit */ |
501 result = AudioOutputUnitStop (theUnit); | 533 result = AudioOutputUnitStop(theUnit); |
502 if (result) goto bail; /*THROW_RESULT("PauseFile: AudioOutputUnitStop")*/ | 534 if (result) |
535 goto bail; /*THROW_RESULT("PauseFile: AudioOutputUnitStop") */ | |
503 /*} | 536 /*} |
504 catch (...) | 537 catch (...) |
505 { | 538 { |
506 goto bail; | 539 goto bail; |
507 }*/ | 540 } */ |
508 | 541 |
509 result = 0; | 542 result = 0; |
510 bail: | 543 bail: |
511 return result; | 544 return result; |
512 } | 545 } |
513 | 546 |
514 void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom) | 547 void |
548 SetCompletionProc(CDPlayerCompletionProc proc, SDL_CD * cdrom) | |
515 { | 549 { |
516 assert(thePlayer != NULL); | 550 assert(thePlayer != NULL); |
517 | 551 |
518 theCDROM = cdrom; | 552 theCDROM = cdrom; |
519 completionProc = proc; | 553 completionProc = proc; |
520 thePlayer->SetNotifier (thePlayer, FilePlayNotificationHandler, cdrom); | 554 thePlayer->SetNotifier(thePlayer, FilePlayNotificationHandler, cdrom); |
521 } | 555 } |
522 | 556 |
523 int GetCurrentFrame () | 557 int |
524 { | 558 GetCurrentFrame() |
559 { | |
525 int frame; | 560 int frame; |
526 | 561 |
527 if (thePlayer == NULL) | 562 if (thePlayer == NULL) |
528 frame = 0; | 563 frame = 0; |
529 else | 564 else |
530 frame = thePlayer->GetCurrentFrame (thePlayer); | 565 frame = thePlayer->GetCurrentFrame(thePlayer); |
531 | 566 |
532 return frame; | 567 return frame; |
533 } | 568 } |
534 | 569 |
535 | 570 |
536 #pragma mark -- Private Functions -- | 571 #pragma mark -- Private Functions -- |
537 | 572 |
538 static OSStatus CheckInit () | 573 static OSStatus |
539 { | 574 CheckInit() |
575 { | |
540 if (playBackWasInit) | 576 if (playBackWasInit) |
541 return 0; | 577 return 0; |
542 | 578 |
543 OSStatus result = noErr; | 579 OSStatus result = noErr; |
544 | 580 |
545 /* Create the callback semaphore */ | 581 /* Create the callback semaphore */ |
546 callbackSem = SDL_CreateSemaphore(0); | 582 callbackSem = SDL_CreateSemaphore(0); |
547 | 583 |
548 /* Start callback thread */ | 584 /* Start callback thread */ |
549 SDL_CreateThread(RunCallBackThread, NULL); | 585 SDL_CreateThread(RunCallBackThread, NULL); |
550 | 586 |
551 { /*try {*/ | 587 { /*try { */ |
552 ComponentDescription desc; | 588 ComponentDescription desc; |
553 | 589 |
554 desc.componentType = kAudioUnitComponentType; | 590 desc.componentType = kAudioUnitComponentType; |
555 desc.componentSubType = kAudioUnitSubType_Output; | 591 desc.componentSubType = kAudioUnitSubType_Output; |
556 desc.componentManufacturer = kAudioUnitID_DefaultOutput; | 592 desc.componentManufacturer = kAudioUnitID_DefaultOutput; |
557 desc.componentFlags = 0; | 593 desc.componentFlags = 0; |
558 desc.componentFlagsMask = 0; | 594 desc.componentFlagsMask = 0; |
559 | 595 |
560 Component comp = FindNextComponent (NULL, &desc); | 596 Component comp = FindNextComponent(NULL, &desc); |
561 if (comp == NULL) { | 597 if (comp == NULL) { |
562 SDL_SetError ("CheckInit: FindNextComponent returned NULL"); | 598 SDL_SetError("CheckInit: FindNextComponent returned NULL"); |
563 if (result) return -1; //throw(internalComponentErr); | 599 if (result) |
600 return -1; //throw(internalComponentErr); | |
564 } | 601 } |
565 | 602 |
566 result = OpenAComponent (comp, &theUnit); | 603 result = OpenAComponent(comp, &theUnit); |
567 if (result) return -1; //THROW_RESULT("CheckInit: OpenAComponent") | 604 if (result) |
568 | 605 return -1; //THROW_RESULT("CheckInit: OpenAComponent") |
606 | |
569 // you need to initialize the output unit before you set it as a destination | 607 // you need to initialize the output unit before you set it as a destination |
570 result = AudioUnitInitialize (theUnit); | 608 result = AudioUnitInitialize(theUnit); |
571 if (result) return -1; //THROW_RESULT("CheckInit: AudioUnitInitialize") | 609 if (result) |
572 | 610 return -1; //THROW_RESULT("CheckInit: AudioUnitInitialize") |
573 | 611 |
612 | |
574 playBackWasInit = true; | 613 playBackWasInit = true; |
575 } | 614 } |
576 /*catch (...) | 615 /*catch (...) |
577 { | 616 { |
578 return -1; | 617 return -1; |
579 }*/ | 618 } */ |
580 | 619 |
581 return 0; | 620 return 0; |
582 } | 621 } |
583 | 622 |
584 static void FilePlayNotificationHandler(void * inRefCon, OSStatus inStatus) | 623 static void |
624 FilePlayNotificationHandler(void *inRefCon, OSStatus inStatus) | |
585 { | 625 { |
586 if (inStatus == kAudioFilePlay_FileIsFinished) { | 626 if (inStatus == kAudioFilePlay_FileIsFinished) { |
587 | 627 |
588 /* notify non-CA thread to perform the callback */ | 628 /* notify non-CA thread to perform the callback */ |
589 SDL_SemPost(callbackSem); | 629 SDL_SemPost(callbackSem); |
590 | 630 |
591 } else if (inStatus == kAudioFilePlayErr_FilePlayUnderrun) { | 631 } else if (inStatus == kAudioFilePlayErr_FilePlayUnderrun) { |
592 | 632 |
593 SDL_SetError ("CDPlayer Notification: buffer underrun"); | 633 SDL_SetError("CDPlayer Notification: buffer underrun"); |
594 } else if (inStatus == kAudioFilePlay_PlayerIsUninitialized) { | 634 } else if (inStatus == kAudioFilePlay_PlayerIsUninitialized) { |
595 | 635 |
596 SDL_SetError ("CDPlayer Notification: player is uninitialized"); | 636 SDL_SetError("CDPlayer Notification: player is uninitialized"); |
597 } else { | 637 } else { |
598 | 638 |
599 SDL_SetError ("CDPlayer Notification: unknown error %ld", inStatus); | 639 SDL_SetError("CDPlayer Notification: unknown error %ld", inStatus); |
600 } | 640 } |
601 } | 641 } |
602 | 642 |
603 static int RunCallBackThread (void *param) | 643 static int |
644 RunCallBackThread(void *param) | |
604 { | 645 { |
605 for (;;) { | 646 for (;;) { |
606 | 647 |
607 SDL_SemWait(callbackSem); | 648 SDL_SemWait(callbackSem); |
608 | 649 |
609 if (completionProc && theCDROM) { | 650 if (completionProc && theCDROM) { |
610 #if DEBUG_CDROM | 651 #if DEBUG_CDROM |
611 printf ("callback!\n"); | 652 printf("callback!\n"); |
612 #endif | 653 #endif |
613 (*completionProc)(theCDROM); | 654 (*completionProc) (theCDROM); |
614 } else { | 655 } else { |
615 #if DEBUG_CDROM | 656 #if DEBUG_CDROM |
616 printf ("callback?\n"); | 657 printf("callback?\n"); |
617 #endif | 658 #endif |
618 } | 659 } |
619 } | 660 } |
620 | 661 |
621 #if DEBUG_CDROM | 662 #if DEBUG_CDROM |
622 printf ("thread dying now...\n"); | 663 printf("thread dying now...\n"); |
623 #endif | 664 #endif |
624 | 665 |
625 return 0; | 666 return 0; |
626 } | 667 } |
627 | 668 |
628 /*}; // extern "C" */ | 669 /*}; // extern "C" */ |
670 /* vi: set ts=4 sw=4 expandtab: */ |