diff options
author | Franklin Wei <git@fwei.tk> | 2018-02-07 20:04:46 -0500 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2018-03-12 20:52:01 -0400 |
commit | 6039eb05ba6d82ef56f2868c96654c552d117bf9 (patch) | |
tree | 9db7016bcbf66cfdf7b9bc998d84c6eaff9c8378 /apps/plugins/sdl/src/cdrom/macosx | |
parent | ef373c03b96b0be08babca581d9f10bccfd4931f (diff) | |
download | rockbox-6039eb05ba6d82ef56f2868c96654c552d117bf9.tar.gz rockbox-6039eb05ba6d82ef56f2868c96654c552d117bf9.zip |
sdl: remove non-rockbox drivers
We never use any of these other drivers, so having them around just takes
up space.
Change-Id: Iced812162df1fef3fd55522b7e700acb6c3bcd41
Diffstat (limited to 'apps/plugins/sdl/src/cdrom/macosx')
-rw-r--r-- | apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.c | 360 | ||||
-rw-r--r-- | apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.h | 178 | ||||
-rw-r--r-- | apps/plugins/sdl/src/cdrom/macosx/AudioFileReaderThread.c | 610 | ||||
-rw-r--r-- | apps/plugins/sdl/src/cdrom/macosx/CDPlayer.c | 636 | ||||
-rw-r--r-- | apps/plugins/sdl/src/cdrom/macosx/CDPlayer.h | 69 | ||||
-rw-r--r-- | apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.c | 199 | ||||
-rw-r--r-- | apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.h | 116 | ||||
-rw-r--r-- | apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom.c | 514 | ||||
-rw-r--r-- | apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom_c.h | 136 |
9 files changed, 0 insertions, 2818 deletions
diff --git a/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.c b/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.c deleted file mode 100644 index 97cb9b2874..0000000000 --- a/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.c +++ /dev/null | |||
@@ -1,360 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | |||
22 | This file based on Apple sample code. We haven't changed the file name, | ||
23 | so if you want to see the original search for it on apple.com/developer | ||
24 | */ | ||
25 | #include "SDL_config.h" | ||
26 | #include "SDL_endian.h" | ||
27 | |||
28 | /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
29 | AudioFilePlayer.cpp | ||
30 | */ | ||
31 | #include "AudioFilePlayer.h" | ||
32 | |||
33 | /* | ||
34 | void ThrowResult (OSStatus result, const char* str) | ||
35 | { | ||
36 | SDL_SetError ("Error: %s %d", str, result); | ||
37 | throw result; | ||
38 | } | ||
39 | */ | ||
40 | |||
41 | #if DEBUG | ||
42 | static void PrintStreamDesc (AudioStreamBasicDescription *inDesc) | ||
43 | { | ||
44 | if (!inDesc) { | ||
45 | printf ("Can't print a NULL desc!\n"); | ||
46 | return; | ||
47 | } | ||
48 | |||
49 | printf ("- - - - - - - - - - - - - - - - - - - -\n"); | ||
50 | printf (" Sample Rate:%f\n", inDesc->mSampleRate); | ||
51 | printf (" Format ID:%s\n", (char*)&inDesc->mFormatID); | ||
52 | printf (" Format Flags:%lX\n", inDesc->mFormatFlags); | ||
53 | printf (" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket); | ||
54 | printf (" Frames per Packet:%ld\n", inDesc->mFramesPerPacket); | ||
55 | printf (" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame); | ||
56 | printf (" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame); | ||
57 | printf (" Bits per Channel:%ld\n", inDesc->mBitsPerChannel); | ||
58 | printf ("- - - - - - - - - - - - - - - - - - - -\n"); | ||
59 | } | ||
60 | #endif | ||
61 | |||
62 | |||
63 | static int AudioFilePlayer_SetDestination (AudioFilePlayer *afp, AudioUnit *inDestUnit) | ||
64 | { | ||
65 | /*if (afp->mConnected) throw static_cast<OSStatus>(-1);*/ /* can't set dest if already engaged */ | ||
66 | if (afp->mConnected) | ||
67 | return 0 ; | ||
68 | |||
69 | SDL_memcpy(&afp->mPlayUnit, inDestUnit, sizeof (afp->mPlayUnit)); | ||
70 | |||
71 | OSStatus result = noErr; | ||
72 | |||
73 | |||
74 | /* we can "down" cast a component instance to a component */ | ||
75 | ComponentDescription desc; | ||
76 | result = GetComponentInfo ((Component)*inDestUnit, &desc, 0, 0, 0); | ||
77 | if (result) return 0; /*THROW_RESULT("GetComponentInfo")*/ | ||
78 | |||
79 | /* we're going to use this to know which convert routine to call | ||
80 | a v1 audio unit will have a type of 'aunt' | ||
81 | a v2 audio unit will have one of several different types. */ | ||
82 | if (desc.componentType != kAudioUnitType_Output) { | ||
83 | result = badComponentInstance; | ||
84 | /*THROW_RESULT("BAD COMPONENT")*/ | ||
85 | if (result) return 0; | ||
86 | } | ||
87 | |||
88 | /* Set the input format of the audio unit. */ | ||
89 | result = AudioUnitSetProperty (*inDestUnit, | ||
90 | kAudioUnitProperty_StreamFormat, | ||
91 | kAudioUnitScope_Input, | ||
92 | 0, | ||
93 | &afp->mFileDescription, | ||
94 | sizeof (afp->mFileDescription)); | ||
95 | /*THROW_RESULT("AudioUnitSetProperty")*/ | ||
96 | if (result) return 0; | ||
97 | return 1; | ||
98 | } | ||
99 | |||
100 | static void AudioFilePlayer_SetNotifier(AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon) | ||
101 | { | ||
102 | afp->mNotifier = inNotifier; | ||
103 | afp->mRefCon = inRefCon; | ||
104 | } | ||
105 | |||
106 | static int AudioFilePlayer_IsConnected(AudioFilePlayer *afp) | ||
107 | { | ||
108 | return afp->mConnected; | ||
109 | } | ||
110 | |||
111 | static AudioUnit AudioFilePlayer_GetDestUnit(AudioFilePlayer *afp) | ||
112 | { | ||
113 | return afp->mPlayUnit; | ||
114 | } | ||
115 | |||
116 | static void AudioFilePlayer_Print(AudioFilePlayer *afp) | ||
117 | { | ||
118 | #if DEBUG | ||
119 | printf ("Is Connected:%s\n", (IsConnected() ? "true" : "false")); | ||
120 | printf ("- - - - - - - - - - - - - - \n"); | ||
121 | #endif | ||
122 | } | ||
123 | |||
124 | static void AudioFilePlayer_SetStartFrame (AudioFilePlayer *afp, int frame) | ||
125 | { | ||
126 | SInt64 position = frame * 2352; | ||
127 | |||
128 | afp->mStartFrame = frame; | ||
129 | afp->mAudioFileManager->SetPosition (afp->mAudioFileManager, position); | ||
130 | } | ||
131 | |||
132 | |||
133 | static int AudioFilePlayer_GetCurrentFrame (AudioFilePlayer *afp) | ||
134 | { | ||
135 | return afp->mStartFrame + (afp->mAudioFileManager->GetByteCounter(afp->mAudioFileManager) / 2352); | ||
136 | } | ||
137 | |||
138 | static void AudioFilePlayer_SetStopFrame (AudioFilePlayer *afp, int frame) | ||
139 | { | ||
140 | SInt64 position = frame * 2352; | ||
141 | |||
142 | afp->mAudioFileManager->SetEndOfFile (afp->mAudioFileManager, position); | ||
143 | } | ||
144 | |||
145 | void delete_AudioFilePlayer(AudioFilePlayer *afp) | ||
146 | { | ||
147 | if (afp != NULL) | ||
148 | { | ||
149 | afp->Disconnect(afp); | ||
150 | |||
151 | if (afp->mAudioFileManager) { | ||
152 | delete_AudioFileManager(afp->mAudioFileManager); | ||
153 | afp->mAudioFileManager = 0; | ||
154 | } | ||
155 | |||
156 | if (afp->mForkRefNum) { | ||
157 | FSCloseFork (afp->mForkRefNum); | ||
158 | afp->mForkRefNum = 0; | ||
159 | } | ||
160 | SDL_free(afp); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | static int AudioFilePlayer_Connect(AudioFilePlayer *afp) | ||
165 | { | ||
166 | #if DEBUG | ||
167 | printf ("Connect:%x, engaged=%d\n", (int)afp->mPlayUnit, (afp->mConnected ? 1 : 0)); | ||
168 | #endif | ||
169 | if (!afp->mConnected) | ||
170 | { | ||
171 | if (!afp->mAudioFileManager->DoConnect(afp->mAudioFileManager)) | ||
172 | return 0; | ||
173 | |||
174 | /* set the render callback for the file data to be supplied to the sound converter AU */ | ||
175 | afp->mInputCallback.inputProc = afp->mAudioFileManager->FileInputProc; | ||
176 | afp->mInputCallback.inputProcRefCon = afp->mAudioFileManager; | ||
177 | |||
178 | OSStatus result = AudioUnitSetProperty (afp->mPlayUnit, | ||
179 | kAudioUnitProperty_SetRenderCallback, | ||
180 | kAudioUnitScope_Input, | ||
181 | 0, | ||
182 | &afp->mInputCallback, | ||
183 | sizeof(afp->mInputCallback)); | ||
184 | if (result) return 0; /*THROW_RESULT("AudioUnitSetProperty")*/ | ||
185 | afp->mConnected = 1; | ||
186 | } | ||
187 | |||
188 | return 1; | ||
189 | } | ||
190 | |||
191 | /* warning noted, now please go away ;-) */ | ||
192 | /* #warning This should redirect the calling of notification code to some other thread */ | ||
193 | static void AudioFilePlayer_DoNotification (AudioFilePlayer *afp, OSStatus inStatus) | ||
194 | { | ||
195 | if (afp->mNotifier) { | ||
196 | (*afp->mNotifier) (afp->mRefCon, inStatus); | ||
197 | } else { | ||
198 | SDL_SetError ("Notification posted with no notifier in place"); | ||
199 | |||
200 | if (inStatus == kAudioFilePlay_FileIsFinished) | ||
201 | afp->Disconnect(afp); | ||
202 | else if (inStatus != kAudioFilePlayErr_FilePlayUnderrun) | ||
203 | afp->Disconnect(afp); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static void AudioFilePlayer_Disconnect (AudioFilePlayer *afp) | ||
208 | { | ||
209 | #if DEBUG | ||
210 | printf ("Disconnect:%x,%ld, engaged=%d\n", (int)afp->mPlayUnit, 0, (afp->mConnected ? 1 : 0)); | ||
211 | #endif | ||
212 | if (afp->mConnected) | ||
213 | { | ||
214 | afp->mConnected = 0; | ||
215 | |||
216 | afp->mInputCallback.inputProc = 0; | ||
217 | afp->mInputCallback.inputProcRefCon = 0; | ||
218 | OSStatus result = AudioUnitSetProperty (afp->mPlayUnit, | ||
219 | kAudioUnitProperty_SetRenderCallback, | ||
220 | kAudioUnitScope_Input, | ||
221 | 0, | ||
222 | &afp->mInputCallback, | ||
223 | sizeof(afp->mInputCallback)); | ||
224 | if (result) | ||
225 | SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result); | ||
226 | |||
227 | afp->mAudioFileManager->Disconnect(afp->mAudioFileManager); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | typedef struct { | ||
232 | UInt32 offset; | ||
233 | UInt32 blockSize; | ||
234 | } SSNDData; | ||
235 | |||
236 | static int AudioFilePlayer_OpenFile (AudioFilePlayer *afp, const FSRef *inRef, SInt64 *outFileDataSize) | ||
237 | { | ||
238 | ContainerChunk chunkHeader; | ||
239 | ChunkHeader chunk; | ||
240 | SSNDData ssndData; | ||
241 | |||
242 | OSErr result; | ||
243 | HFSUniStr255 dfName; | ||
244 | ByteCount actual; | ||
245 | SInt64 offset; | ||
246 | |||
247 | /* Open the data fork of the input file */ | ||
248 | result = FSGetDataForkName(&dfName); | ||
249 | if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName")*/ | ||
250 | |||
251 | result = FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm, &afp->mForkRefNum); | ||
252 | if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork")*/ | ||
253 | |||
254 | /* Read the file header, and check if it's indeed an AIFC file */ | ||
255 | result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(chunkHeader), &chunkHeader, &actual); | ||
256 | if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/ | ||
257 | |||
258 | if (SDL_SwapBE32(chunkHeader.ckID) != 'FORM') { | ||
259 | result = -1; | ||
260 | if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'");*/ | ||
261 | } | ||
262 | |||
263 | if (SDL_SwapBE32(chunkHeader.formType) != 'AIFC') { | ||
264 | result = -1; | ||
265 | if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): file format is not 'AIFC'");*/ | ||
266 | } | ||
267 | |||
268 | /* Search for the SSND chunk. We ignore all compression etc. information | ||
269 | in other chunks. Of course that is kind of evil, but for now we are lazy | ||
270 | and rely on the cdfs to always give us the same fixed format. | ||
271 | TODO: Parse the COMM chunk we currently skip to fill in mFileDescription. | ||
272 | */ | ||
273 | offset = 0; | ||
274 | do { | ||
275 | result = FSReadFork(afp->mForkRefNum, fsFromMark, offset, sizeof(chunk), &chunk, &actual); | ||
276 | if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/ | ||
277 | |||
278 | chunk.ckID = SDL_SwapBE32(chunk.ckID); | ||
279 | chunk.ckSize = SDL_SwapBE32(chunk.ckSize); | ||
280 | |||
281 | /* Skip the chunk data */ | ||
282 | offset = chunk.ckSize; | ||
283 | } while (chunk.ckID != 'SSND'); | ||
284 | |||
285 | /* Read the header of the SSND chunk. After this, we are positioned right | ||
286 | at the start of the audio data. */ | ||
287 | result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(ssndData), &ssndData, &actual); | ||
288 | if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/ | ||
289 | |||
290 | ssndData.offset = SDL_SwapBE32(ssndData.offset); | ||
291 | |||
292 | result = FSSetForkPosition(afp->mForkRefNum, fsFromMark, ssndData.offset); | ||
293 | if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSSetForkPosition")*/ | ||
294 | |||
295 | /* Data size */ | ||
296 | *outFileDataSize = chunk.ckSize - ssndData.offset - 8; | ||
297 | |||
298 | /* File format */ | ||
299 | afp->mFileDescription.mSampleRate = 44100; | ||
300 | afp->mFileDescription.mFormatID = kAudioFormatLinearPCM; | ||
301 | afp->mFileDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger; | ||
302 | afp->mFileDescription.mBytesPerPacket = 4; | ||
303 | afp->mFileDescription.mFramesPerPacket = 1; | ||
304 | afp->mFileDescription.mBytesPerFrame = 4; | ||
305 | afp->mFileDescription.mChannelsPerFrame = 2; | ||
306 | afp->mFileDescription.mBitsPerChannel = 16; | ||
307 | |||
308 | return 1; | ||
309 | } | ||
310 | |||
311 | AudioFilePlayer *new_AudioFilePlayer (const FSRef *inFileRef) | ||
312 | { | ||
313 | SInt64 fileDataSize = 0; | ||
314 | |||
315 | AudioFilePlayer *afp = (AudioFilePlayer *) SDL_malloc(sizeof (AudioFilePlayer)); | ||
316 | if (afp == NULL) | ||
317 | return NULL; | ||
318 | SDL_memset(afp, '\0', sizeof (*afp)); | ||
319 | |||
320 | #define SET_AUDIOFILEPLAYER_METHOD(m) afp->m = AudioFilePlayer_##m | ||
321 | SET_AUDIOFILEPLAYER_METHOD(SetDestination); | ||
322 | SET_AUDIOFILEPLAYER_METHOD(SetNotifier); | ||
323 | SET_AUDIOFILEPLAYER_METHOD(SetStartFrame); | ||
324 | SET_AUDIOFILEPLAYER_METHOD(GetCurrentFrame); | ||
325 | SET_AUDIOFILEPLAYER_METHOD(SetStopFrame); | ||
326 | SET_AUDIOFILEPLAYER_METHOD(Connect); | ||
327 | SET_AUDIOFILEPLAYER_METHOD(Disconnect); | ||
328 | SET_AUDIOFILEPLAYER_METHOD(DoNotification); | ||
329 | SET_AUDIOFILEPLAYER_METHOD(IsConnected); | ||
330 | SET_AUDIOFILEPLAYER_METHOD(GetDestUnit); | ||
331 | SET_AUDIOFILEPLAYER_METHOD(Print); | ||
332 | SET_AUDIOFILEPLAYER_METHOD(OpenFile); | ||
333 | #undef SET_AUDIOFILEPLAYER_METHOD | ||
334 | |||
335 | if (!afp->OpenFile (afp, inFileRef, &fileDataSize)) | ||
336 | { | ||
337 | SDL_free(afp); | ||
338 | return NULL; | ||
339 | } | ||
340 | |||
341 | /* we want about 4 seconds worth of data for the buffer */ | ||
342 | int bytesPerSecond = (UInt32) (4 * afp->mFileDescription.mSampleRate * afp->mFileDescription.mBytesPerFrame); | ||
343 | |||
344 | #if DEBUG | ||
345 | printf("File format:\n"); | ||
346 | PrintStreamDesc (&afp->mFileDescription); | ||
347 | #endif | ||
348 | |||
349 | afp->mAudioFileManager = new_AudioFileManager(afp, afp->mForkRefNum, | ||
350 | fileDataSize, | ||
351 | bytesPerSecond); | ||
352 | if (afp->mAudioFileManager == NULL) | ||
353 | { | ||
354 | delete_AudioFilePlayer(afp); | ||
355 | return NULL; | ||
356 | } | ||
357 | |||
358 | return afp; | ||
359 | } | ||
360 | |||
diff --git a/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.h b/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.h deleted file mode 100644 index 886d017a59..0000000000 --- a/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.h +++ /dev/null | |||
@@ -1,178 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | |||
22 | This file based on Apple sample code. We haven't changed the file name, | ||
23 | so if you want to see the original search for it on apple.com/developer | ||
24 | */ | ||
25 | #include "SDL_config.h" | ||
26 | |||
27 | /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
28 | AudioFilePlayer.h | ||
29 | */ | ||
30 | #ifndef __AudioFilePlayer_H__ | ||
31 | #define __AudioFilePlayer_H__ | ||
32 | |||
33 | #include <CoreServices/CoreServices.h> | ||
34 | |||
35 | #include <AudioUnit/AudioUnit.h> | ||
36 | #if MAC_OS_X_VERSION_MAX_ALLOWED <= 1050 | ||
37 | #include <AudioUnit/AUNTComponent.h> | ||
38 | #endif | ||
39 | |||
40 | #if (MAC_OS_X_VERSION_MAX_ALLOWED < 1050) | ||
41 | typedef SInt16 FSIORefNum; | ||
42 | #endif | ||
43 | |||
44 | #include "SDL_error.h" | ||
45 | |||
46 | const char* AudioFilePlayerErrorStr (OSStatus error); | ||
47 | |||
48 | /* | ||
49 | void ThrowResult (OSStatus result, const char *str); | ||
50 | |||
51 | #define THROW_RESULT(str) \ | ||
52 | if (result) { \ | ||
53 | ThrowResult (result, str); \ | ||
54 | } | ||
55 | */ | ||
56 | |||
57 | typedef void (*AudioFilePlayNotifier)(void *inRefCon, | ||
58 | OSStatus inStatus); | ||
59 | |||
60 | enum { | ||
61 | kAudioFilePlayErr_FilePlayUnderrun = -10000, | ||
62 | kAudioFilePlay_FileIsFinished = -10001, | ||
63 | kAudioFilePlay_PlayerIsUninitialized = -10002 | ||
64 | }; | ||
65 | |||
66 | |||
67 | struct S_AudioFileManager; | ||
68 | |||
69 | #pragma mark __________ AudioFilePlayer | ||
70 | typedef struct S_AudioFilePlayer | ||
71 | { | ||
72 | /*public:*/ | ||
73 | int (*SetDestination)(struct S_AudioFilePlayer *afp, AudioUnit *inDestUnit); | ||
74 | void (*SetNotifier)(struct S_AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon); | ||
75 | void (*SetStartFrame)(struct S_AudioFilePlayer *afp, int frame); /* seek in the file */ | ||
76 | int (*GetCurrentFrame)(struct S_AudioFilePlayer *afp); /* get the current frame position */ | ||
77 | void (*SetStopFrame)(struct S_AudioFilePlayer *afp, int frame); /* set limit in the file */ | ||
78 | int (*Connect)(struct S_AudioFilePlayer *afp); | ||
79 | void (*Disconnect)(struct S_AudioFilePlayer *afp); | ||
80 | void (*DoNotification)(struct S_AudioFilePlayer *afp, OSStatus inError); | ||
81 | int (*IsConnected)(struct S_AudioFilePlayer *afp); | ||
82 | AudioUnit (*GetDestUnit)(struct S_AudioFilePlayer *afp); | ||
83 | void (*Print)(struct S_AudioFilePlayer *afp); | ||
84 | |||
85 | /*private:*/ | ||
86 | AudioUnit mPlayUnit; | ||
87 | FSIORefNum mForkRefNum; | ||
88 | |||
89 | AURenderCallbackStruct mInputCallback; | ||
90 | |||
91 | AudioStreamBasicDescription mFileDescription; | ||
92 | |||
93 | int mConnected; | ||
94 | |||
95 | struct S_AudioFileManager* mAudioFileManager; | ||
96 | |||
97 | AudioFilePlayNotifier mNotifier; | ||
98 | void* mRefCon; | ||
99 | |||
100 | int mStartFrame; | ||
101 | |||
102 | #pragma mark __________ Private_Methods | ||
103 | |||
104 | int (*OpenFile)(struct S_AudioFilePlayer *afp, const FSRef *inRef, SInt64 *outFileSize); | ||
105 | } AudioFilePlayer; | ||
106 | |||
107 | |||
108 | AudioFilePlayer *new_AudioFilePlayer(const FSRef *inFileRef); | ||
109 | void delete_AudioFilePlayer(AudioFilePlayer *afp); | ||
110 | |||
111 | |||
112 | |||
113 | #pragma mark __________ AudioFileManager | ||
114 | typedef struct S_AudioFileManager | ||
115 | { | ||
116 | /*public:*/ | ||
117 | /* this method should NOT be called by an object of this class | ||
118 | as it is called by the parent's Disconnect() method */ | ||
119 | void (*Disconnect)(struct S_AudioFileManager *afm); | ||
120 | int (*DoConnect)(struct S_AudioFileManager *afm); | ||
121 | OSStatus (*Read)(struct S_AudioFileManager *afm, char *buffer, ByteCount *len); | ||
122 | const char* (*GetFileBuffer)(struct S_AudioFileManager *afm); | ||
123 | const AudioFilePlayer *(*GetParent)(struct S_AudioFileManager *afm); | ||
124 | void (*SetPosition)(struct S_AudioFileManager *afm, SInt64 pos); /* seek/rewind in the file */ | ||
125 | int (*GetByteCounter)(struct S_AudioFileManager *afm); /* return actual bytes streamed to audio hardware */ | ||
126 | void (*SetEndOfFile)(struct S_AudioFileManager *afm, SInt64 pos); /* set the "EOF" (will behave just like it reached eof) */ | ||
127 | |||
128 | /*protected:*/ | ||
129 | AudioFilePlayer* mParent; | ||
130 | SInt16 mForkRefNum; | ||
131 | SInt64 mAudioDataOffset; | ||
132 | |||
133 | char* mFileBuffer; | ||
134 | |||
135 | int mByteCounter; | ||
136 | |||
137 | int mReadFromFirstBuffer; | ||
138 | int mLockUnsuccessful; | ||
139 | int mIsEngaged; | ||
140 | |||
141 | int mNumTimesAskedSinceFinished; | ||
142 | |||
143 | |||
144 | void* mTmpBuffer; | ||
145 | UInt32 mBufferSize; | ||
146 | UInt32 mBufferOffset; | ||
147 | /*public:*/ | ||
148 | UInt32 mChunkSize; | ||
149 | SInt64 mFileLength; | ||
150 | SInt64 mReadFilePosition; | ||
151 | int mWriteToFirstBuffer; | ||
152 | int mFinishedReadingData; | ||
153 | |||
154 | /*protected:*/ | ||
155 | OSStatus (*Render)(struct S_AudioFileManager *afm, AudioBufferList *ioData); | ||
156 | OSStatus (*GetFileData)(struct S_AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize); | ||
157 | void (*AfterRender)(struct S_AudioFileManager *afm); | ||
158 | |||
159 | /*public:*/ | ||
160 | /*static*/ | ||
161 | OSStatus (*FileInputProc)(void *inRefCon, | ||
162 | AudioUnitRenderActionFlags *ioActionFlags, | ||
163 | const AudioTimeStamp *inTimeStamp, | ||
164 | UInt32 inBusNumber, | ||
165 | UInt32 inNumberFrames, | ||
166 | AudioBufferList *ioData); | ||
167 | } AudioFileManager; | ||
168 | |||
169 | |||
170 | AudioFileManager *new_AudioFileManager (AudioFilePlayer *inParent, | ||
171 | SInt16 inForkRefNum, | ||
172 | SInt64 inFileLength, | ||
173 | UInt32 inChunkSize); | ||
174 | |||
175 | void delete_AudioFileManager(AudioFileManager *afm); | ||
176 | |||
177 | #endif | ||
178 | |||
diff --git a/apps/plugins/sdl/src/cdrom/macosx/AudioFileReaderThread.c b/apps/plugins/sdl/src/cdrom/macosx/AudioFileReaderThread.c deleted file mode 100644 index 0007c07f61..0000000000 --- a/apps/plugins/sdl/src/cdrom/macosx/AudioFileReaderThread.c +++ /dev/null | |||
@@ -1,610 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | |||
22 | This file based on Apple sample code. We haven't changed the file name, | ||
23 | so if you want to see the original search for it on apple.com/developer | ||
24 | */ | ||
25 | #include "SDL_config.h" | ||
26 | |||
27 | /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
28 | AudioFileManager.cpp | ||
29 | */ | ||
30 | #include "AudioFilePlayer.h" | ||
31 | #include <mach/mach.h> /* used for setting policy of thread */ | ||
32 | #include "SDLOSXCAGuard.h" | ||
33 | #include <pthread.h> | ||
34 | |||
35 | /*#include <list>*/ | ||
36 | |||
37 | /*typedef void *FileData;*/ | ||
38 | typedef struct S_FileData | ||
39 | { | ||
40 | AudioFileManager *obj; | ||
41 | struct S_FileData *next; | ||
42 | } FileData; | ||
43 | |||
44 | |||
45 | typedef struct S_FileReaderThread { | ||
46 | /*public:*/ | ||
47 | SDLOSXCAGuard* (*GetGuard)(struct S_FileReaderThread *frt); | ||
48 | void (*AddReader)(struct S_FileReaderThread *frt); | ||
49 | void (*RemoveReader)(struct S_FileReaderThread *frt, AudioFileManager* inItem); | ||
50 | int (*TryNextRead)(struct S_FileReaderThread *frt, AudioFileManager* inItem); | ||
51 | |||
52 | int mThreadShouldDie; | ||
53 | |||
54 | /*private:*/ | ||
55 | /*typedef std::list<AudioFileManager*> FileData;*/ | ||
56 | |||
57 | SDLOSXCAGuard *mGuard; | ||
58 | UInt32 mThreadPriority; | ||
59 | |||
60 | int mNumReaders; | ||
61 | FileData *mFileData; | ||
62 | |||
63 | |||
64 | void (*ReadNextChunk)(struct S_FileReaderThread *frt); | ||
65 | int (*StartFixedPriorityThread)(struct S_FileReaderThread *frt); | ||
66 | /*static*/ | ||
67 | UInt32 (*GetThreadBasePriority)(pthread_t inThread); | ||
68 | /*static*/ | ||
69 | void* (*DiskReaderEntry)(void *inRefCon); | ||
70 | } FileReaderThread; | ||
71 | |||
72 | |||
73 | static SDLOSXCAGuard* FileReaderThread_GetGuard(FileReaderThread *frt) | ||
74 | { | ||
75 | return frt->mGuard; | ||
76 | } | ||
77 | |||
78 | /* returns 1 if succeeded */ | ||
79 | static int FileReaderThread_TryNextRead (FileReaderThread *frt, AudioFileManager* inItem) | ||
80 | { | ||
81 | int didLock = 0; | ||
82 | int succeeded = 0; | ||
83 | if (frt->mGuard->Try(frt->mGuard, &didLock)) | ||
84 | { | ||
85 | /*frt->mFileData.push_back (inItem);*/ | ||
86 | /* !!! FIXME: this could be faster with a "tail" member. --ryan. */ | ||
87 | FileData *i = frt->mFileData; | ||
88 | FileData *prev = NULL; | ||
89 | |||
90 | FileData *newfd = (FileData *) SDL_malloc(sizeof (FileData)); | ||
91 | newfd->obj = inItem; | ||
92 | newfd->next = NULL; | ||
93 | |||
94 | while (i != NULL) { prev = i; i = i->next; } | ||
95 | if (prev == NULL) | ||
96 | frt->mFileData = newfd; | ||
97 | else | ||
98 | prev->next = newfd; | ||
99 | |||
100 | frt->mGuard->Notify(frt->mGuard); | ||
101 | succeeded = 1; | ||
102 | |||
103 | if (didLock) | ||
104 | frt->mGuard->Unlock(frt->mGuard); | ||
105 | } | ||
106 | |||
107 | return succeeded; | ||
108 | } | ||
109 | |||
110 | static void FileReaderThread_AddReader(FileReaderThread *frt) | ||
111 | { | ||
112 | if (frt->mNumReaders == 0) | ||
113 | { | ||
114 | frt->mThreadShouldDie = 0; | ||
115 | frt->StartFixedPriorityThread (frt); | ||
116 | } | ||
117 | frt->mNumReaders++; | ||
118 | } | ||
119 | |||
120 | static void FileReaderThread_RemoveReader (FileReaderThread *frt, AudioFileManager* inItem) | ||
121 | { | ||
122 | if (frt->mNumReaders > 0) | ||
123 | { | ||
124 | int bNeedsRelease = frt->mGuard->Lock(frt->mGuard); | ||
125 | |||
126 | /*frt->mFileData.remove (inItem);*/ | ||
127 | FileData *i = frt->mFileData; | ||
128 | FileData *prev = NULL; | ||
129 | while (i != NULL) | ||
130 | { | ||
131 | FileData *next = i->next; | ||
132 | if (i->obj != inItem) | ||
133 | prev = i; | ||
134 | else | ||
135 | { | ||
136 | if (prev == NULL) | ||
137 | frt->mFileData = next; | ||
138 | else | ||
139 | prev->next = next; | ||
140 | SDL_free(i); | ||
141 | } | ||
142 | i = next; | ||
143 | } | ||
144 | |||
145 | if (--frt->mNumReaders == 0) { | ||
146 | frt->mThreadShouldDie = 1; | ||
147 | frt->mGuard->Notify(frt->mGuard); /* wake up thread so it will quit */ | ||
148 | frt->mGuard->Wait(frt->mGuard); /* wait for thread to die */ | ||
149 | } | ||
150 | |||
151 | if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static int FileReaderThread_StartFixedPriorityThread (FileReaderThread *frt) | ||
156 | { | ||
157 | pthread_attr_t theThreadAttrs; | ||
158 | pthread_t pThread; | ||
159 | |||
160 | OSStatus result = pthread_attr_init(&theThreadAttrs); | ||
161 | if (result) return 0; /*THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")*/ | ||
162 | |||
163 | result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED); | ||
164 | if (result) return 0; /*THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")*/ | ||
165 | |||
166 | result = pthread_create (&pThread, &theThreadAttrs, frt->DiskReaderEntry, frt); | ||
167 | if (result) return 0; /*THROW_RESULT("pthread_create - Create and start the thread.")*/ | ||
168 | |||
169 | pthread_attr_destroy(&theThreadAttrs); | ||
170 | |||
171 | /* we've now created the thread and started it | ||
172 | we'll now set the priority of the thread to the nominated priority | ||
173 | and we'll also make the thread fixed */ | ||
174 | thread_extended_policy_data_t theFixedPolicy; | ||
175 | thread_precedence_policy_data_t thePrecedencePolicy; | ||
176 | SInt32 relativePriority; | ||
177 | |||
178 | /* make thread fixed */ | ||
179 | theFixedPolicy.timeshare = 0; /* set to 1 for a non-fixed thread */ | ||
180 | result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); | ||
181 | if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")*/ | ||
182 | /* set priority */ | ||
183 | /* precedency policy's "importance" value is relative to spawning thread's priority */ | ||
184 | relativePriority = frt->mThreadPriority - frt->GetThreadBasePriority(pthread_self()); | ||
185 | |||
186 | thePrecedencePolicy.importance = relativePriority; | ||
187 | result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); | ||
188 | if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread priority.")*/ | ||
189 | |||
190 | return 1; | ||
191 | } | ||
192 | |||
193 | static UInt32 FileReaderThread_GetThreadBasePriority (pthread_t inThread) | ||
194 | { | ||
195 | thread_basic_info_data_t threadInfo; | ||
196 | policy_info_data_t thePolicyInfo; | ||
197 | unsigned int count; | ||
198 | |||
199 | /* get basic info */ | ||
200 | count = THREAD_BASIC_INFO_COUNT; | ||
201 | thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count); | ||
202 | |||
203 | switch (threadInfo.policy) { | ||
204 | case POLICY_TIMESHARE: | ||
205 | count = POLICY_TIMESHARE_INFO_COUNT; | ||
206 | thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count); | ||
207 | return thePolicyInfo.ts.base_priority; | ||
208 | break; | ||
209 | |||
210 | case POLICY_FIFO: | ||
211 | count = POLICY_FIFO_INFO_COUNT; | ||
212 | thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count); | ||
213 | if (thePolicyInfo.fifo.depressed) { | ||
214 | return thePolicyInfo.fifo.depress_priority; | ||
215 | } else { | ||
216 | return thePolicyInfo.fifo.base_priority; | ||
217 | } | ||
218 | break; | ||
219 | |||
220 | case POLICY_RR: | ||
221 | count = POLICY_RR_INFO_COUNT; | ||
222 | thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count); | ||
223 | if (thePolicyInfo.rr.depressed) { | ||
224 | return thePolicyInfo.rr.depress_priority; | ||
225 | } else { | ||
226 | return thePolicyInfo.rr.base_priority; | ||
227 | } | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static void *FileReaderThread_DiskReaderEntry (void *inRefCon) | ||
235 | { | ||
236 | FileReaderThread *frt = (FileReaderThread *)inRefCon; | ||
237 | frt->ReadNextChunk(frt); | ||
238 | #if DEBUG | ||
239 | printf ("finished with reading file\n"); | ||
240 | #endif | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static void FileReaderThread_ReadNextChunk (FileReaderThread *frt) | ||
246 | { | ||
247 | OSStatus result; | ||
248 | ByteCount dataChunkSize; | ||
249 | AudioFileManager* theItem = 0; | ||
250 | |||
251 | for (;;) | ||
252 | { | ||
253 | { /* this is a scoped based lock */ | ||
254 | int bNeedsRelease = frt->mGuard->Lock(frt->mGuard); | ||
255 | |||
256 | if (frt->mThreadShouldDie) { | ||
257 | frt->mGuard->Notify(frt->mGuard); | ||
258 | if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard); | ||
259 | return; | ||
260 | } | ||
261 | |||
262 | /*if (frt->mFileData.empty())*/ | ||
263 | if (frt->mFileData == NULL) | ||
264 | { | ||
265 | frt->mGuard->Wait(frt->mGuard); | ||
266 | } | ||
267 | |||
268 | /* kill thread */ | ||
269 | if (frt->mThreadShouldDie) { | ||
270 | |||
271 | frt->mGuard->Notify(frt->mGuard); | ||
272 | if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard); | ||
273 | return; | ||
274 | } | ||
275 | |||
276 | /*theItem = frt->mFileData.front();*/ | ||
277 | /*frt->mFileData.pop_front();*/ | ||
278 | theItem = NULL; | ||
279 | if (frt->mFileData != NULL) | ||
280 | { | ||
281 | FileData *next = frt->mFileData->next; | ||
282 | theItem = frt->mFileData->obj; | ||
283 | SDL_free(frt->mFileData); | ||
284 | frt->mFileData = next; | ||
285 | } | ||
286 | |||
287 | if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard); | ||
288 | } | ||
289 | |||
290 | if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize) | ||
291 | dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition; | ||
292 | else | ||
293 | dataChunkSize = theItem->mChunkSize; | ||
294 | |||
295 | /* this is the exit condition for the thread */ | ||
296 | if (dataChunkSize <= 0) { | ||
297 | theItem->mFinishedReadingData = 1; | ||
298 | continue; | ||
299 | } | ||
300 | /* construct pointer */ | ||
301 | char* writePtr = (char *) (theItem->GetFileBuffer(theItem) + | ||
302 | (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize)); | ||
303 | |||
304 | /* read data */ | ||
305 | result = theItem->Read(theItem, writePtr, &dataChunkSize); | ||
306 | if (result != noErr && result != eofErr) { | ||
307 | AudioFilePlayer *afp = (AudioFilePlayer *) theItem->GetParent(theItem); | ||
308 | afp->DoNotification(afp, result); | ||
309 | continue; | ||
310 | } | ||
311 | |||
312 | if (dataChunkSize != theItem->mChunkSize) | ||
313 | { | ||
314 | writePtr += dataChunkSize; | ||
315 | |||
316 | /* can't exit yet.. we still have to pass the partial buffer back */ | ||
317 | SDL_memset(writePtr, 0, (theItem->mChunkSize - dataChunkSize)); | ||
318 | } | ||
319 | |||
320 | theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; /* switch buffers */ | ||
321 | |||
322 | if (result == eofErr) | ||
323 | theItem->mReadFilePosition = theItem->mFileLength; | ||
324 | else | ||
325 | theItem->mReadFilePosition += dataChunkSize; /* increment count */ | ||
326 | } | ||
327 | } | ||
328 | |||
329 | void delete_FileReaderThread(FileReaderThread *frt) | ||
330 | { | ||
331 | if (frt != NULL) | ||
332 | { | ||
333 | delete_SDLOSXCAGuard(frt->mGuard); | ||
334 | SDL_free(frt); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | FileReaderThread *new_FileReaderThread () | ||
339 | { | ||
340 | FileReaderThread *frt = (FileReaderThread *) SDL_malloc(sizeof (FileReaderThread)); | ||
341 | if (frt == NULL) | ||
342 | return NULL; | ||
343 | SDL_memset(frt, '\0', sizeof (*frt)); | ||
344 | |||
345 | frt->mGuard = new_SDLOSXCAGuard(); | ||
346 | if (frt->mGuard == NULL) | ||
347 | { | ||
348 | SDL_free(frt); | ||
349 | return NULL; | ||
350 | } | ||
351 | |||
352 | #define SET_FILEREADERTHREAD_METHOD(m) frt->m = FileReaderThread_##m | ||
353 | SET_FILEREADERTHREAD_METHOD(GetGuard); | ||
354 | SET_FILEREADERTHREAD_METHOD(AddReader); | ||
355 | SET_FILEREADERTHREAD_METHOD(RemoveReader); | ||
356 | SET_FILEREADERTHREAD_METHOD(TryNextRead); | ||
357 | SET_FILEREADERTHREAD_METHOD(ReadNextChunk); | ||
358 | SET_FILEREADERTHREAD_METHOD(StartFixedPriorityThread); | ||
359 | SET_FILEREADERTHREAD_METHOD(GetThreadBasePriority); | ||
360 | SET_FILEREADERTHREAD_METHOD(DiskReaderEntry); | ||
361 | #undef SET_FILEREADERTHREAD_METHOD | ||
362 | |||
363 | frt->mThreadPriority = 62; | ||
364 | return frt; | ||
365 | } | ||
366 | |||
367 | |||
368 | static FileReaderThread *sReaderThread; | ||
369 | |||
370 | |||
371 | static int AudioFileManager_DoConnect (AudioFileManager *afm) | ||
372 | { | ||
373 | if (!afm->mIsEngaged) | ||
374 | { | ||
375 | OSStatus result; | ||
376 | |||
377 | /*afm->mReadFilePosition = 0;*/ | ||
378 | afm->mFinishedReadingData = 0; | ||
379 | |||
380 | afm->mNumTimesAskedSinceFinished = 0; | ||
381 | afm->mLockUnsuccessful = 0; | ||
382 | |||
383 | ByteCount dataChunkSize; | ||
384 | |||
385 | if ((afm->mFileLength - afm->mReadFilePosition) < afm->mChunkSize) | ||
386 | dataChunkSize = afm->mFileLength - afm->mReadFilePosition; | ||
387 | else | ||
388 | dataChunkSize = afm->mChunkSize; | ||
389 | |||
390 | result = afm->Read(afm, afm->mFileBuffer, &dataChunkSize); | ||
391 | if (result) return 0; /*THROW_RESULT("AudioFileManager::DoConnect(): Read")*/ | ||
392 | |||
393 | afm->mReadFilePosition += dataChunkSize; | ||
394 | |||
395 | afm->mWriteToFirstBuffer = 0; | ||
396 | afm->mReadFromFirstBuffer = 1; | ||
397 | |||
398 | sReaderThread->AddReader(sReaderThread); | ||
399 | |||
400 | afm->mIsEngaged = 1; | ||
401 | } | ||
402 | /* | ||
403 | else | ||
404 | throw static_cast<OSStatus>(-1); */ /* thread has already been started */ | ||
405 | |||
406 | return 1; | ||
407 | } | ||
408 | |||
409 | static void AudioFileManager_Disconnect (AudioFileManager *afm) | ||
410 | { | ||
411 | if (afm->mIsEngaged) | ||
412 | { | ||
413 | sReaderThread->RemoveReader (sReaderThread, afm); | ||
414 | afm->mIsEngaged = 0; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | static OSStatus AudioFileManager_Read(AudioFileManager *afm, char *buffer, ByteCount *len) | ||
419 | { | ||
420 | return FSReadFork (afm->mForkRefNum, | ||
421 | fsFromStart, | ||
422 | afm->mReadFilePosition + afm->mAudioDataOffset, | ||
423 | *len, | ||
424 | buffer, | ||
425 | len); | ||
426 | } | ||
427 | |||
428 | static OSStatus AudioFileManager_GetFileData (AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize) | ||
429 | { | ||
430 | if (afm->mFinishedReadingData) | ||
431 | { | ||
432 | ++afm->mNumTimesAskedSinceFinished; | ||
433 | *inOutDataSize = 0; | ||
434 | *inOutData = 0; | ||
435 | return noErr; | ||
436 | } | ||
437 | |||
438 | if (afm->mReadFromFirstBuffer == afm->mWriteToFirstBuffer) { | ||
439 | #if DEBUG | ||
440 | printf ("* * * * * * * Can't keep up with reading file\n"); | ||
441 | #endif | ||
442 | |||
443 | afm->mParent->DoNotification (afm->mParent, kAudioFilePlayErr_FilePlayUnderrun); | ||
444 | *inOutDataSize = 0; | ||
445 | *inOutData = 0; | ||
446 | } else { | ||
447 | *inOutDataSize = afm->mChunkSize; | ||
448 | *inOutData = afm->mReadFromFirstBuffer ? afm->mFileBuffer : (afm->mFileBuffer + afm->mChunkSize); | ||
449 | } | ||
450 | |||
451 | afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm); | ||
452 | |||
453 | afm->mReadFromFirstBuffer = !afm->mReadFromFirstBuffer; | ||
454 | |||
455 | return noErr; | ||
456 | } | ||
457 | |||
458 | static void AudioFileManager_AfterRender (AudioFileManager *afm) | ||
459 | { | ||
460 | if (afm->mNumTimesAskedSinceFinished > 0) | ||
461 | { | ||
462 | int didLock = 0; | ||
463 | SDLOSXCAGuard *guard = sReaderThread->GetGuard(sReaderThread); | ||
464 | if (guard->Try(guard, &didLock)) { | ||
465 | afm->mParent->DoNotification (afm->mParent, kAudioFilePlay_FileIsFinished); | ||
466 | if (didLock) | ||
467 | guard->Unlock(guard); | ||
468 | } | ||
469 | } | ||
470 | |||
471 | if (afm->mLockUnsuccessful) | ||
472 | afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm); | ||
473 | } | ||
474 | |||
475 | static void AudioFileManager_SetPosition (AudioFileManager *afm, SInt64 pos) | ||
476 | { | ||
477 | if (pos < 0 || pos >= afm->mFileLength) { | ||
478 | SDL_SetError ("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n", | ||
479 | (unsigned int)pos, (unsigned int)afm->mFileLength); | ||
480 | pos = 0; | ||
481 | } | ||
482 | |||
483 | afm->mReadFilePosition = pos; | ||
484 | } | ||
485 | |||
486 | static void AudioFileManager_SetEndOfFile (AudioFileManager *afm, SInt64 pos) | ||
487 | { | ||
488 | if (pos <= 0 || pos > afm->mFileLength) { | ||
489 | SDL_SetError ("AudioFileManager::SetEndOfFile - position beyond actual eof\n"); | ||
490 | pos = afm->mFileLength; | ||
491 | } | ||
492 | |||
493 | afm->mFileLength = pos; | ||
494 | } | ||
495 | |||
496 | static const char *AudioFileManager_GetFileBuffer(AudioFileManager *afm) | ||
497 | { | ||
498 | return afm->mFileBuffer; | ||
499 | } | ||
500 | |||
501 | const AudioFilePlayer *AudioFileManager_GetParent(AudioFileManager *afm) | ||
502 | { | ||
503 | return afm->mParent; | ||
504 | } | ||
505 | |||
506 | static int AudioFileManager_GetByteCounter(AudioFileManager *afm) | ||
507 | { | ||
508 | return afm->mByteCounter; | ||
509 | } | ||
510 | |||
511 | static OSStatus AudioFileManager_FileInputProc (void *inRefCon, | ||
512 | AudioUnitRenderActionFlags *ioActionFlags, | ||
513 | const AudioTimeStamp *inTimeStamp, | ||
514 | UInt32 inBusNumber, | ||
515 | UInt32 inNumberFrames, | ||
516 | AudioBufferList *ioData) | ||
517 | { | ||
518 | AudioFileManager* afm = (AudioFileManager*)inRefCon; | ||
519 | return afm->Render(afm, ioData); | ||
520 | } | ||
521 | |||
522 | static OSStatus AudioFileManager_Render (AudioFileManager *afm, AudioBufferList *ioData) | ||
523 | { | ||
524 | OSStatus result = noErr; | ||
525 | AudioBuffer *abuf; | ||
526 | UInt32 i; | ||
527 | |||
528 | for (i = 0; i < ioData->mNumberBuffers; i++) { | ||
529 | abuf = &ioData->mBuffers[i]; | ||
530 | if (afm->mBufferOffset >= afm->mBufferSize) { | ||
531 | result = afm->GetFileData(afm, &afm->mTmpBuffer, &afm->mBufferSize); | ||
532 | if (result) { | ||
533 | SDL_SetError ("AudioConverterFillBuffer:%ld\n", result); | ||
534 | afm->mParent->DoNotification(afm->mParent, result); | ||
535 | return result; | ||
536 | } | ||
537 | |||
538 | afm->mBufferOffset = 0; | ||
539 | } | ||
540 | |||
541 | if (abuf->mDataByteSize > afm->mBufferSize - afm->mBufferOffset) | ||
542 | abuf->mDataByteSize = afm->mBufferSize - afm->mBufferOffset; | ||
543 | abuf->mData = (char *)afm->mTmpBuffer + afm->mBufferOffset; | ||
544 | afm->mBufferOffset += abuf->mDataByteSize; | ||
545 | |||
546 | afm->mByteCounter += abuf->mDataByteSize; | ||
547 | afm->AfterRender(afm); | ||
548 | } | ||
549 | return result; | ||
550 | } | ||
551 | |||
552 | |||
553 | void delete_AudioFileManager (AudioFileManager *afm) | ||
554 | { | ||
555 | if (afm != NULL) { | ||
556 | if (afm->mFileBuffer) { | ||
557 | free(afm->mFileBuffer); | ||
558 | } | ||
559 | |||
560 | SDL_free(afm); | ||
561 | } | ||
562 | } | ||
563 | |||
564 | |||
565 | AudioFileManager *new_AudioFileManager(AudioFilePlayer *inParent, | ||
566 | SInt16 inForkRefNum, | ||
567 | SInt64 inFileLength, | ||
568 | UInt32 inChunkSize) | ||
569 | { | ||
570 | AudioFileManager *afm; | ||
571 | |||
572 | if (sReaderThread == NULL) | ||
573 | { | ||
574 | sReaderThread = new_FileReaderThread(); | ||
575 | if (sReaderThread == NULL) | ||
576 | return NULL; | ||
577 | } | ||
578 | |||
579 | afm = (AudioFileManager *) SDL_malloc(sizeof (AudioFileManager)); | ||
580 | if (afm == NULL) | ||
581 | return NULL; | ||
582 | SDL_memset(afm, '\0', sizeof (*afm)); | ||
583 | |||
584 | #define SET_AUDIOFILEMANAGER_METHOD(m) afm->m = AudioFileManager_##m | ||
585 | SET_AUDIOFILEMANAGER_METHOD(Disconnect); | ||
586 | SET_AUDIOFILEMANAGER_METHOD(DoConnect); | ||
587 | SET_AUDIOFILEMANAGER_METHOD(Read); | ||
588 | SET_AUDIOFILEMANAGER_METHOD(GetFileBuffer); | ||
589 | SET_AUDIOFILEMANAGER_METHOD(GetParent); | ||
590 | SET_AUDIOFILEMANAGER_METHOD(SetPosition); | ||
591 | SET_AUDIOFILEMANAGER_METHOD(GetByteCounter); | ||
592 | SET_AUDIOFILEMANAGER_METHOD(SetEndOfFile); | ||
593 | SET_AUDIOFILEMANAGER_METHOD(Render); | ||
594 | SET_AUDIOFILEMANAGER_METHOD(GetFileData); | ||
595 | SET_AUDIOFILEMANAGER_METHOD(AfterRender); | ||
596 | SET_AUDIOFILEMANAGER_METHOD(FileInputProc); | ||
597 | #undef SET_AUDIOFILEMANAGER_METHOD | ||
598 | |||
599 | afm->mParent = inParent; | ||
600 | afm->mForkRefNum = inForkRefNum; | ||
601 | afm->mBufferSize = inChunkSize; | ||
602 | afm->mBufferOffset = inChunkSize; | ||
603 | afm->mChunkSize = inChunkSize; | ||
604 | afm->mFileLength = inFileLength; | ||
605 | afm->mFileBuffer = (char*) SDL_malloc(afm->mChunkSize * 2); | ||
606 | FSGetForkPosition(afm->mForkRefNum, &afm->mAudioDataOffset); | ||
607 | assert (afm->mFileBuffer != NULL); | ||
608 | return afm; | ||
609 | } | ||
610 | |||
diff --git a/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.c b/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.c deleted file mode 100644 index beb87cd85b..0000000000 --- a/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.c +++ /dev/null | |||
@@ -1,636 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #include "CDPlayer.h" | ||
25 | #include "AudioFilePlayer.h" | ||
26 | #include "SDLOSXCAGuard.h" | ||
27 | |||
28 | /* we're exporting these functions into C land for SDL_syscdrom.c */ | ||
29 | /*extern "C" {*/ | ||
30 | |||
31 | /*/////////////////////////////////////////////////////////////////////////// | ||
32 | Constants | ||
33 | //////////////////////////////////////////////////////////////////////////*/ | ||
34 | |||
35 | #define kAudioCDFilesystemID (UInt16)(('J' << 8) | 'H') /* 'JH'; this avoids compiler warning */ | ||
36 | |||
37 | /* XML PList keys */ | ||
38 | #define kRawTOCDataString "Format 0x02 TOC Data" | ||
39 | #define kSessionsString "Sessions" | ||
40 | #define kSessionTypeString "Session Type" | ||
41 | #define kTrackArrayString "Track Array" | ||
42 | #define kFirstTrackInSessionString "First Track" | ||
43 | #define kLastTrackInSessionString "Last Track" | ||
44 | #define kLeadoutBlockString "Leadout Block" | ||
45 | #define kDataKeyString "Data" | ||
46 | #define kPointKeyString "Point" | ||
47 | #define kSessionNumberKeyString "Session Number" | ||
48 | #define kStartBlockKeyString "Start Block" | ||
49 | |||
50 | /*/////////////////////////////////////////////////////////////////////////// | ||
51 | Globals | ||
52 | //////////////////////////////////////////////////////////////////////////*/ | ||
53 | |||
54 | #pragma mark -- Globals -- | ||
55 | |||
56 | static int playBackWasInit = 0; | ||
57 | static AudioUnit theUnit; | ||
58 | static AudioFilePlayer* thePlayer = NULL; | ||
59 | static CDPlayerCompletionProc completionProc = NULL; | ||
60 | static SDL_mutex *apiMutex = NULL; | ||
61 | static SDL_sem *callbackSem; | ||
62 | static SDL_CD* theCDROM; | ||
63 | |||
64 | /*/////////////////////////////////////////////////////////////////////////// | ||
65 | Prototypes | ||
66 | //////////////////////////////////////////////////////////////////////////*/ | ||
67 | |||
68 | #pragma mark -- Prototypes -- | ||
69 | |||
70 | static OSStatus CheckInit (); | ||
71 | |||
72 | static void FilePlayNotificationHandler (void* inRefCon, OSStatus inStatus); | ||
73 | |||
74 | static int RunCallBackThread (void* inRefCon); | ||
75 | |||
76 | |||
77 | #pragma mark -- Public Functions -- | ||
78 | |||
79 | void Lock () | ||
80 | { | ||
81 | if (!apiMutex) { | ||
82 | apiMutex = SDL_CreateMutex(); | ||
83 | } | ||
84 | SDL_mutexP(apiMutex); | ||
85 | } | ||
86 | |||
87 | void Unlock () | ||
88 | { | ||
89 | SDL_mutexV(apiMutex); | ||
90 | } | ||
91 | |||
92 | int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes) | ||
93 | { | ||
94 | int volumeIndex; | ||
95 | int cdVolumeCount = 0; | ||
96 | OSStatus result = noErr; | ||
97 | |||
98 | for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++) | ||
99 | { | ||
100 | FSVolumeRefNum actualVolume; | ||
101 | FSVolumeInfo volumeInfo; | ||
102 | |||
103 | memset (&volumeInfo, 0, sizeof(volumeInfo)); | ||
104 | |||
105 | result = FSGetVolumeInfo (kFSInvalidVolumeRefNum, | ||
106 | volumeIndex, | ||
107 | &actualVolume, | ||
108 | kFSVolInfoFSInfo, | ||
109 | &volumeInfo, | ||
110 | NULL, | ||
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) | ||
118 | volumes[cdVolumeCount] = actualVolume; | ||
119 | |||
120 | cdVolumeCount++; | ||
121 | } | ||
122 | } | ||
123 | else | ||
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; | ||
131 | } | ||
132 | |||
133 | int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD) | ||
134 | { | ||
135 | HFSUniStr255 dataForkName; | ||
136 | OSStatus theErr; | ||
137 | FSIORefNum forkRefNum; | ||
138 | SInt64 forkSize; | ||
139 | Ptr forkData = 0; | ||
140 | ByteCount actualRead; | ||
141 | CFDataRef dataRef = 0; | ||
142 | CFPropertyListRef propertyListRef = 0; | ||
143 | FSRefParam fsRefPB; | ||
144 | FSRef tocPlistFSRef; | ||
145 | FSRef rootRef; | ||
146 | const char* error = "Unspecified Error"; | ||
147 | const UniChar uniName[] = { '.','T','O','C','.','p','l','i','s','t' }; | ||
148 | |||
149 | theErr = FSGetVolumeInfo(theVolume, 0, 0, kFSVolInfoNone, 0, 0, &rootRef); | ||
150 | if(theErr != noErr) { | ||
151 | error = "FSGetVolumeInfo"; | ||
152 | goto bail; | ||
153 | } | ||
154 | |||
155 | SDL_memset(&fsRefPB, '\0', sizeof (fsRefPB)); | ||
156 | |||
157 | /* get stuff from .TOC.plist */ | ||
158 | fsRefPB.ref = &rootRef; | ||
159 | fsRefPB.newRef = &tocPlistFSRef; | ||
160 | fsRefPB.nameLength = sizeof (uniName) / sizeof (uniName[0]); | ||
161 | fsRefPB.name = uniName; | ||
162 | fsRefPB.textEncodingHint = kTextEncodingUnknown; | ||
163 | |||
164 | theErr = PBMakeFSRefUnicodeSync (&fsRefPB); | ||
165 | if(theErr != noErr) { | ||
166 | error = "PBMakeFSRefUnicodeSync"; | ||
167 | goto bail; | ||
168 | } | ||
169 | |||
170 | /* Load and parse the TOC XML data */ | ||
171 | |||
172 | theErr = FSGetDataForkName (&dataForkName); | ||
173 | if (theErr != noErr) { | ||
174 | error = "FSGetDataForkName"; | ||
175 | goto bail; | ||
176 | } | ||
177 | |||
178 | theErr = FSOpenFork (&tocPlistFSRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &forkRefNum); | ||
179 | if (theErr != noErr) { | ||
180 | error = "FSOpenFork"; | ||
181 | goto bail; | ||
182 | } | ||
183 | |||
184 | theErr = FSGetForkSize (forkRefNum, &forkSize); | ||
185 | if (theErr != noErr) { | ||
186 | error = "FSGetForkSize"; | ||
187 | goto bail; | ||
188 | } | ||
189 | |||
190 | /* Allocate some memory for the XML data */ | ||
191 | forkData = NewPtr (forkSize); | ||
192 | if(forkData == NULL) { | ||
193 | error = "NewPtr"; | ||
194 | goto bail; | ||
195 | } | ||
196 | |||
197 | theErr = FSReadFork (forkRefNum, fsFromStart, 0 /* offset location */, forkSize, forkData, &actualRead); | ||
198 | if(theErr != noErr) { | ||
199 | error = "FSReadFork"; | ||
200 | goto bail; | ||
201 | } | ||
202 | |||
203 | dataRef = CFDataCreate (kCFAllocatorDefault, (UInt8 *)forkData, forkSize); | ||
204 | if(dataRef == 0) { | ||
205 | error = "CFDataCreate"; | ||
206 | goto bail; | ||
207 | } | ||
208 | |||
209 | propertyListRef = CFPropertyListCreateFromXMLData (kCFAllocatorDefault, | ||
210 | dataRef, | ||
211 | kCFPropertyListImmutable, | ||
212 | NULL); | ||
213 | if (propertyListRef == NULL) { | ||
214 | error = "CFPropertyListCreateFromXMLData"; | ||
215 | goto bail; | ||
216 | } | ||
217 | |||
218 | /* Now we got the Property List in memory. Parse it. */ | ||
219 | |||
220 | /* First, make sure the root item is a CFDictionary. If not, release and bail. */ | ||
221 | if(CFGetTypeID(propertyListRef)== CFDictionaryGetTypeID()) | ||
222 | { | ||
223 | CFDictionaryRef dictRef = (CFDictionaryRef)propertyListRef; | ||
224 | |||
225 | CFDataRef theRawTOCDataRef; | ||
226 | CFArrayRef theSessionArrayRef; | ||
227 | CFIndex numSessions; | ||
228 | CFIndex index; | ||
229 | |||
230 | /* This is how we get the Raw TOC Data */ | ||
231 | theRawTOCDataRef = (CFDataRef)CFDictionaryGetValue (dictRef, CFSTR(kRawTOCDataString)); | ||
232 | |||
233 | /* Get the session array info. */ | ||
234 | theSessionArrayRef = (CFArrayRef)CFDictionaryGetValue (dictRef, CFSTR(kSessionsString)); | ||
235 | |||
236 | /* Find out how many sessions there are. */ | ||
237 | numSessions = CFArrayGetCount (theSessionArrayRef); | ||
238 | |||
239 | /* Initialize the total number of tracks to 0 */ | ||
240 | theCD->numtracks = 0; | ||
241 | |||
242 | /* Iterate over all sessions, collecting the track data */ | ||
243 | for(index = 0; index < numSessions; index++) | ||
244 | { | ||
245 | CFDictionaryRef theSessionDict; | ||
246 | CFNumberRef leadoutBlock; | ||
247 | CFArrayRef trackArray; | ||
248 | CFIndex numTracks; | ||
249 | CFIndex trackIndex; | ||
250 | UInt32 value = 0; | ||
251 | |||
252 | theSessionDict = (CFDictionaryRef) CFArrayGetValueAtIndex (theSessionArrayRef, index); | ||
253 | leadoutBlock = (CFNumberRef) CFDictionaryGetValue (theSessionDict, CFSTR(kLeadoutBlockString)); | ||
254 | |||
255 | trackArray = (CFArrayRef)CFDictionaryGetValue (theSessionDict, CFSTR(kTrackArrayString)); | ||
256 | |||
257 | numTracks = CFArrayGetCount (trackArray); | ||
258 | |||
259 | for(trackIndex = 0; trackIndex < numTracks; trackIndex++) { | ||
260 | |||
261 | CFDictionaryRef theTrackDict; | ||
262 | CFNumberRef trackNumber; | ||
263 | CFNumberRef sessionNumber; | ||
264 | CFNumberRef startBlock; | ||
265 | CFBooleanRef isDataTrack; | ||
266 | UInt32 value; | ||
267 | |||
268 | theTrackDict = (CFDictionaryRef) CFArrayGetValueAtIndex (trackArray, trackIndex); | ||
269 | |||
270 | trackNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kPointKeyString)); | ||
271 | sessionNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kSessionNumberKeyString)); | ||
272 | startBlock = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kStartBlockKeyString)); | ||
273 | isDataTrack = (CFBooleanRef) CFDictionaryGetValue (theTrackDict, CFSTR(kDataKeyString)); | ||
274 | |||
275 | /* Fill in the SDL_CD struct */ | ||
276 | int idx = theCD->numtracks++; | ||
277 | |||
278 | CFNumberGetValue (trackNumber, kCFNumberSInt32Type, &value); | ||
279 | theCD->track[idx].id = value; | ||
280 | |||
281 | CFNumberGetValue (startBlock, kCFNumberSInt32Type, &value); | ||
282 | theCD->track[idx].offset = value; | ||
283 | |||
284 | theCD->track[idx].type = (isDataTrack == kCFBooleanTrue) ? SDL_DATA_TRACK : SDL_AUDIO_TRACK; | ||
285 | |||
286 | /* Since the track lengths are not stored in .TOC.plist we compute them. */ | ||
287 | if (trackIndex > 0) { | ||
288 | theCD->track[idx-1].length = theCD->track[idx].offset - theCD->track[idx-1].offset; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | /* Compute the length of the last track */ | ||
293 | CFNumberGetValue (leadoutBlock, kCFNumberSInt32Type, &value); | ||
294 | |||
295 | theCD->track[theCD->numtracks-1].length = | ||
296 | value - theCD->track[theCD->numtracks-1].offset; | ||
297 | |||
298 | /* Set offset to leadout track */ | ||
299 | theCD->track[theCD->numtracks].offset = value; | ||
300 | } | ||
301 | |||
302 | } | ||
303 | |||
304 | theErr = 0; | ||
305 | goto cleanup; | ||
306 | bail: | ||
307 | SDL_SetError ("ReadTOCData: %s returned %d", error, theErr); | ||
308 | theErr = -1; | ||
309 | cleanup: | ||
310 | |||
311 | if (propertyListRef != NULL) | ||
312 | CFRelease(propertyListRef); | ||
313 | if (dataRef != NULL) | ||
314 | CFRelease(dataRef); | ||
315 | if (forkData != NULL) | ||
316 | DisposePtr(forkData); | ||
317 | |||
318 | FSCloseFork (forkRefNum); | ||
319 | |||
320 | return theErr; | ||
321 | } | ||
322 | |||
323 | int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks) | ||
324 | { | ||
325 | OSStatus result = -1; | ||
326 | FSIterator iterator; | ||
327 | ItemCount actualObjects; | ||
328 | FSRef rootDirectory; | ||
329 | FSRef ref; | ||
330 | HFSUniStr255 nameStr; | ||
331 | |||
332 | result = FSGetVolumeInfo (theVolume, | ||
333 | 0, | ||
334 | NULL, | ||
335 | kFSVolInfoFSInfo, | ||
336 | NULL, | ||
337 | NULL, | ||
338 | &rootDirectory); | ||
339 | |||
340 | if (result != noErr) { | ||
341 | SDL_SetError ("ListTrackFiles: FSGetVolumeInfo returned %d", result); | ||
342 | return result; | ||
343 | } | ||
344 | |||
345 | result = FSOpenIterator (&rootDirectory, kFSIterateFlat, &iterator); | ||
346 | if (result == noErr) { | ||
347 | do | ||
348 | { | ||
349 | result = FSGetCatalogInfoBulk (iterator, 1, &actualObjects, | ||
350 | NULL, kFSCatInfoNone, NULL, &ref, NULL, &nameStr); | ||
351 | if (result == noErr) { | ||
352 | |||
353 | CFStringRef name; | ||
354 | name = CFStringCreateWithCharacters (NULL, nameStr.unicode, nameStr.length); | ||
355 | |||
356 | /* Look for .aiff extension */ | ||
357 | if (CFStringHasSuffix (name, CFSTR(".aiff")) || | ||
358 | CFStringHasSuffix (name, CFSTR(".cdda"))) { | ||
359 | |||
360 | /* Extract the track id from the filename */ | ||
361 | int trackID = 0, i = 0; | ||
362 | while (i < nameStr.length && !isdigit(nameStr.unicode[i])) { | ||
363 | ++i; | ||
364 | } | ||
365 | while (i < nameStr.length && isdigit(nameStr.unicode[i])) { | ||
366 | trackID = 10 * trackID +(nameStr.unicode[i] - '0'); | ||
367 | ++i; | ||
368 | } | ||
369 | |||
370 | #if DEBUG_CDROM | ||
371 | printf("Found AIFF for track %d: '%s'\n", trackID, | ||
372 | CFStringGetCStringPtr (name, CFStringGetSystemEncoding())); | ||
373 | #endif | ||
374 | |||
375 | /* Track ID's start at 1, but we want to start at 0 */ | ||
376 | trackID--; | ||
377 | |||
378 | assert(0 <= trackID && trackID <= SDL_MAX_TRACKS); | ||
379 | |||
380 | if (trackID < numTracks) | ||
381 | memcpy (&trackFiles[trackID], &ref, sizeof(FSRef)); | ||
382 | } | ||
383 | CFRelease (name); | ||
384 | } | ||
385 | } while(noErr == result); | ||
386 | FSCloseIterator (iterator); | ||
387 | } | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | int LoadFile (const FSRef *ref, int startFrame, int stopFrame) | ||
393 | { | ||
394 | int error = -1; | ||
395 | |||
396 | if (CheckInit () < 0) | ||
397 | goto bail; | ||
398 | |||
399 | /* release any currently playing file */ | ||
400 | if (ReleaseFile () < 0) | ||
401 | goto bail; | ||
402 | |||
403 | #if DEBUG_CDROM | ||
404 | printf ("LoadFile: %d %d\n", startFrame, stopFrame); | ||
405 | #endif | ||
406 | |||
407 | /*try {*/ | ||
408 | |||
409 | /* create a new player, and attach to the audio unit */ | ||
410 | |||
411 | thePlayer = new_AudioFilePlayer(ref); | ||
412 | if (thePlayer == NULL) { | ||
413 | SDL_SetError ("LoadFile: Could not create player"); | ||
414 | return -3; /*throw (-3);*/ | ||
415 | } | ||
416 | |||
417 | if (!thePlayer->SetDestination(thePlayer, &theUnit)) | ||
418 | goto bail; | ||
419 | |||
420 | if (startFrame >= 0) | ||
421 | thePlayer->SetStartFrame (thePlayer, startFrame); | ||
422 | |||
423 | if (stopFrame >= 0 && stopFrame > startFrame) | ||
424 | thePlayer->SetStopFrame (thePlayer, stopFrame); | ||
425 | |||
426 | /* we set the notifier later */ | ||
427 | /*thePlayer->SetNotifier(thePlayer, FilePlayNotificationHandler, NULL);*/ | ||
428 | |||
429 | if (!thePlayer->Connect(thePlayer)) | ||
430 | goto bail; | ||
431 | |||
432 | #if DEBUG_CDROM | ||
433 | thePlayer->Print(thePlayer); | ||
434 | fflush (stdout); | ||
435 | #endif | ||
436 | /*} | ||
437 | catch (...) | ||
438 | { | ||
439 | goto bail; | ||
440 | }*/ | ||
441 | |||
442 | error = 0; | ||
443 | |||
444 | bail: | ||
445 | return error; | ||
446 | } | ||
447 | |||
448 | int ReleaseFile () | ||
449 | { | ||
450 | int error = -1; | ||
451 | |||
452 | /* (Don't see any way that the original C++ code could throw here.) --ryan. */ | ||
453 | /*try {*/ | ||
454 | if (thePlayer != NULL) { | ||
455 | |||
456 | thePlayer->Disconnect(thePlayer); | ||
457 | |||
458 | delete_AudioFilePlayer(thePlayer); | ||
459 | |||
460 | thePlayer = NULL; | ||
461 | } | ||
462 | /*} | ||
463 | catch (...) | ||
464 | { | ||
465 | goto bail; | ||
466 | }*/ | ||
467 | |||
468 | error = 0; | ||
469 | |||
470 | /* bail: */ | ||
471 | return error; | ||
472 | } | ||
473 | |||
474 | int PlayFile () | ||
475 | { | ||
476 | OSStatus result = -1; | ||
477 | |||
478 | if (CheckInit () < 0) | ||
479 | goto bail; | ||
480 | |||
481 | /*try {*/ | ||
482 | |||
483 | // start processing of the audio unit | ||
484 | result = AudioOutputUnitStart (theUnit); | ||
485 | if (result) goto bail; //THROW_RESULT("PlayFile: AudioOutputUnitStart") | ||
486 | |||
487 | /*} | ||
488 | catch (...) | ||
489 | { | ||
490 | goto bail; | ||
491 | }*/ | ||
492 | |||
493 | result = 0; | ||
494 | |||
495 | bail: | ||
496 | return result; | ||
497 | } | ||
498 | |||
499 | int PauseFile () | ||
500 | { | ||
501 | OSStatus result = -1; | ||
502 | |||
503 | if (CheckInit () < 0) | ||
504 | goto bail; | ||
505 | |||
506 | /*try {*/ | ||
507 | |||
508 | /* stop processing the audio unit */ | ||
509 | result = AudioOutputUnitStop (theUnit); | ||
510 | if (result) goto bail; /*THROW_RESULT("PauseFile: AudioOutputUnitStop")*/ | ||
511 | /*} | ||
512 | catch (...) | ||
513 | { | ||
514 | goto bail; | ||
515 | }*/ | ||
516 | |||
517 | result = 0; | ||
518 | bail: | ||
519 | return result; | ||
520 | } | ||
521 | |||
522 | void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom) | ||
523 | { | ||
524 | assert(thePlayer != NULL); | ||
525 | |||
526 | theCDROM = cdrom; | ||
527 | completionProc = proc; | ||
528 | thePlayer->SetNotifier (thePlayer, FilePlayNotificationHandler, cdrom); | ||
529 | } | ||
530 | |||
531 | int GetCurrentFrame () | ||
532 | { | ||
533 | int frame; | ||
534 | |||
535 | if (thePlayer == NULL) | ||
536 | frame = 0; | ||
537 | else | ||
538 | frame = thePlayer->GetCurrentFrame (thePlayer); | ||
539 | |||
540 | return frame; | ||
541 | } | ||
542 | |||
543 | |||
544 | #pragma mark -- Private Functions -- | ||
545 | |||
546 | static OSStatus CheckInit () | ||
547 | { | ||
548 | if (playBackWasInit) | ||
549 | return 0; | ||
550 | |||
551 | OSStatus result = noErr; | ||
552 | |||
553 | /* Create the callback semaphore */ | ||
554 | callbackSem = SDL_CreateSemaphore(0); | ||
555 | |||
556 | /* Start callback thread */ | ||
557 | SDL_CreateThread(RunCallBackThread, NULL); | ||
558 | |||
559 | { /*try {*/ | ||
560 | ComponentDescription desc; | ||
561 | |||
562 | desc.componentType = kAudioUnitType_Output; | ||
563 | desc.componentSubType = kAudioUnitSubType_DefaultOutput; | ||
564 | desc.componentManufacturer = kAudioUnitManufacturer_Apple; | ||
565 | desc.componentFlags = 0; | ||
566 | desc.componentFlagsMask = 0; | ||
567 | |||
568 | Component comp = FindNextComponent (NULL, &desc); | ||
569 | if (comp == NULL) { | ||
570 | SDL_SetError ("CheckInit: FindNextComponent returned NULL"); | ||
571 | if (result) return -1; //throw(internalComponentErr); | ||
572 | } | ||
573 | |||
574 | result = OpenAComponent (comp, &theUnit); | ||
575 | if (result) return -1; //THROW_RESULT("CheckInit: OpenAComponent") | ||
576 | |||
577 | // you need to initialize the output unit before you set it as a destination | ||
578 | result = AudioUnitInitialize (theUnit); | ||
579 | if (result) return -1; //THROW_RESULT("CheckInit: AudioUnitInitialize") | ||
580 | |||
581 | |||
582 | playBackWasInit = true; | ||
583 | } | ||
584 | /*catch (...) | ||
585 | { | ||
586 | return -1; | ||
587 | }*/ | ||
588 | |||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | static void FilePlayNotificationHandler(void * inRefCon, OSStatus inStatus) | ||
593 | { | ||
594 | if (inStatus == kAudioFilePlay_FileIsFinished) { | ||
595 | |||
596 | /* notify non-CA thread to perform the callback */ | ||
597 | SDL_SemPost(callbackSem); | ||
598 | |||
599 | } else if (inStatus == kAudioFilePlayErr_FilePlayUnderrun) { | ||
600 | |||
601 | SDL_SetError ("CDPlayer Notification: buffer underrun"); | ||
602 | } else if (inStatus == kAudioFilePlay_PlayerIsUninitialized) { | ||
603 | |||
604 | SDL_SetError ("CDPlayer Notification: player is uninitialized"); | ||
605 | } else { | ||
606 | |||
607 | SDL_SetError ("CDPlayer Notification: unknown error %ld", inStatus); | ||
608 | } | ||
609 | } | ||
610 | |||
611 | static int RunCallBackThread (void *param) | ||
612 | { | ||
613 | for (;;) { | ||
614 | |||
615 | SDL_SemWait(callbackSem); | ||
616 | |||
617 | if (completionProc && theCDROM) { | ||
618 | #if DEBUG_CDROM | ||
619 | printf ("callback!\n"); | ||
620 | #endif | ||
621 | (*completionProc)(theCDROM); | ||
622 | } else { | ||
623 | #if DEBUG_CDROM | ||
624 | printf ("callback?\n"); | ||
625 | #endif | ||
626 | } | ||
627 | } | ||
628 | |||
629 | #if DEBUG_CDROM | ||
630 | printf ("thread dying now...\n"); | ||
631 | #endif | ||
632 | |||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | /*}; // extern "C" */ | ||
diff --git a/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.h b/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.h deleted file mode 100644 index be1ac1826a..0000000000 --- a/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.h +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #ifndef __CDPlayer__H__ | ||
25 | #define __CDPlayer__H__ 1 | ||
26 | |||
27 | #include <string.h> | ||
28 | |||
29 | #include <Carbon/Carbon.h> | ||
30 | #include <CoreFoundation/CoreFoundation.h> | ||
31 | #include <AudioUnit/AudioUnit.h> | ||
32 | |||
33 | #include "SDL.h" | ||
34 | #include "SDL_thread.h" | ||
35 | #include "SDL_mutex.h" | ||
36 | |||
37 | #ifdef __cplusplus | ||
38 | extern "C" { | ||
39 | #endif | ||
40 | |||
41 | typedef void (*CDPlayerCompletionProc)(SDL_CD *cdrom) ; | ||
42 | |||
43 | void Lock (); | ||
44 | |||
45 | void Unlock(); | ||
46 | |||
47 | int LoadFile (const FSRef *ref, int startFrame, int endFrame); /* pass -1 to do nothing */ | ||
48 | |||
49 | int ReleaseFile (); | ||
50 | |||
51 | int PlayFile (); | ||
52 | |||
53 | int PauseFile (); | ||
54 | |||
55 | void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom); | ||
56 | |||
57 | int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD); | ||
58 | |||
59 | int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks); | ||
60 | |||
61 | int DetectAudioCDVolumes (FSVolumeRefNum *volumes, int numVolumes); | ||
62 | |||
63 | int GetCurrentFrame (); | ||
64 | |||
65 | #ifdef __cplusplus | ||
66 | }; | ||
67 | #endif | ||
68 | |||
69 | #endif /* __CD_Player__H__ */ | ||
diff --git a/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.c b/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.c deleted file mode 100644 index e8caf1bf10..0000000000 --- a/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.c +++ /dev/null | |||
@@ -1,199 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | /* | ||
25 | Note: This file hasn't been modified so technically we have to keep the disclaimer :-( | ||
26 | |||
27 | Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved. | ||
28 | |||
29 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. | ||
30 | ("Apple") in consideration of your agreement to the following terms, and your | ||
31 | use, installation, modification or redistribution of this Apple software | ||
32 | constitutes acceptance of these terms. If you do not agree with these terms, | ||
33 | please do not use, install, modify or redistribute this Apple software. | ||
34 | |||
35 | In consideration of your agreement to abide by the following terms, and subject | ||
36 | to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs | ||
37 | copyrights in this original Apple software (the "Apple Software"), to use, | ||
38 | reproduce, modify and redistribute the Apple Software, with or without | ||
39 | modifications, in source and/or binary forms; provided that if you redistribute | ||
40 | the Apple Software in its entirety and without modifications, you must retain | ||
41 | this notice and the following text and disclaimers in all such redistributions of | ||
42 | the Apple Software. Neither the name, trademarks, service marks or logos of | ||
43 | Apple Computer, Inc. may be used to endorse or promote products derived from the | ||
44 | Apple Software without specific prior written permission from Apple. Except as | ||
45 | expressly stated in this notice, no other rights or licenses, express or implied, | ||
46 | are granted by Apple herein, including but not limited to any patent rights that | ||
47 | may be infringed by your derivative works or by other works in which the Apple | ||
48 | Software may be incorporated. | ||
49 | |||
50 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO | ||
51 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED | ||
52 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
53 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN | ||
54 | COMBINATION WITH YOUR PRODUCTS. | ||
55 | |||
56 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR | ||
57 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | ||
58 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
59 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION | ||
60 | OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT | ||
61 | (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN | ||
62 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
63 | */ | ||
64 | /*============================================================================= | ||
65 | CAGuard.cp | ||
66 | |||
67 | =============================================================================*/ | ||
68 | |||
69 | /*============================================================================= | ||
70 | Includes | ||
71 | =============================================================================*/ | ||
72 | |||
73 | /* | ||
74 | #include <stdio.h> | ||
75 | #include <stdlib.h> | ||
76 | #include <string.h> | ||
77 | */ | ||
78 | #include "SDL_stdinc.h" | ||
79 | |||
80 | /*#define NDEBUG 1*/ | ||
81 | /* | ||
82 | #include <assert.h> | ||
83 | */ | ||
84 | #define assert(X) | ||
85 | |||
86 | |||
87 | #include "SDLOSXCAGuard.h" | ||
88 | |||
89 | /*#warning Need a try-based Locker too*/ | ||
90 | /*============================================================================= | ||
91 | SDLOSXCAGuard | ||
92 | =============================================================================*/ | ||
93 | |||
94 | static int SDLOSXCAGuard_Lock(SDLOSXCAGuard *cag) | ||
95 | { | ||
96 | int theAnswer = 0; | ||
97 | |||
98 | if(pthread_self() != cag->mOwner) | ||
99 | { | ||
100 | OSStatus theError = pthread_mutex_lock(&cag->mMutex); | ||
101 | (void)theError; | ||
102 | assert(theError == 0); | ||
103 | cag->mOwner = pthread_self(); | ||
104 | theAnswer = 1; | ||
105 | } | ||
106 | |||
107 | return theAnswer; | ||
108 | } | ||
109 | |||
110 | static void SDLOSXCAGuard_Unlock(SDLOSXCAGuard *cag) | ||
111 | { | ||
112 | OSStatus theError; | ||
113 | assert(pthread_self() == cag->mOwner); | ||
114 | |||
115 | cag->mOwner = 0; | ||
116 | theError = pthread_mutex_unlock(&cag->mMutex); | ||
117 | (void)theError; | ||
118 | assert(theError == 0); | ||
119 | } | ||
120 | |||
121 | static int SDLOSXCAGuard_Try (SDLOSXCAGuard *cag, int *outWasLocked) | ||
122 | { | ||
123 | int theAnswer = 0; | ||
124 | *outWasLocked = 0; | ||
125 | |||
126 | if (pthread_self() == cag->mOwner) { | ||
127 | theAnswer = 1; | ||
128 | *outWasLocked = 0; | ||
129 | } else { | ||
130 | OSStatus theError = pthread_mutex_trylock(&cag->mMutex); | ||
131 | if (theError == 0) { | ||
132 | cag->mOwner = pthread_self(); | ||
133 | theAnswer = 1; | ||
134 | *outWasLocked = 1; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | return theAnswer; | ||
139 | } | ||
140 | |||
141 | static void SDLOSXCAGuard_Wait(SDLOSXCAGuard *cag) | ||
142 | { | ||
143 | OSStatus theError; | ||
144 | assert(pthread_self() == cag->mOwner); | ||
145 | |||
146 | cag->mOwner = 0; | ||
147 | |||
148 | theError = pthread_cond_wait(&cag->mCondVar, &cag->mMutex); | ||
149 | (void)theError; | ||
150 | assert(theError == 0); | ||
151 | cag->mOwner = pthread_self(); | ||
152 | } | ||
153 | |||
154 | static void SDLOSXCAGuard_Notify(SDLOSXCAGuard *cag) | ||
155 | { | ||
156 | OSStatus theError = pthread_cond_signal(&cag->mCondVar); | ||
157 | (void)theError; | ||
158 | assert(theError == 0); | ||
159 | } | ||
160 | |||
161 | |||
162 | SDLOSXCAGuard *new_SDLOSXCAGuard(void) | ||
163 | { | ||
164 | OSStatus theError; | ||
165 | SDLOSXCAGuard *cag = (SDLOSXCAGuard *) SDL_malloc(sizeof (SDLOSXCAGuard)); | ||
166 | if (cag == NULL) | ||
167 | return NULL; | ||
168 | SDL_memset(cag, '\0', sizeof (*cag)); | ||
169 | |||
170 | #define SET_SDLOSXCAGUARD_METHOD(m) cag->m = SDLOSXCAGuard_##m | ||
171 | SET_SDLOSXCAGUARD_METHOD(Lock); | ||
172 | SET_SDLOSXCAGUARD_METHOD(Unlock); | ||
173 | SET_SDLOSXCAGUARD_METHOD(Try); | ||
174 | SET_SDLOSXCAGUARD_METHOD(Wait); | ||
175 | SET_SDLOSXCAGUARD_METHOD(Notify); | ||
176 | #undef SET_SDLOSXCAGUARD_METHOD | ||
177 | |||
178 | theError = pthread_mutex_init(&cag->mMutex, NULL); | ||
179 | (void)theError; | ||
180 | assert(theError == 0); | ||
181 | |||
182 | theError = pthread_cond_init(&cag->mCondVar, NULL); | ||
183 | (void)theError; | ||
184 | assert(theError == 0); | ||
185 | |||
186 | cag->mOwner = 0; | ||
187 | return cag; | ||
188 | } | ||
189 | |||
190 | void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag) | ||
191 | { | ||
192 | if (cag != NULL) | ||
193 | { | ||
194 | pthread_mutex_destroy(&cag->mMutex); | ||
195 | pthread_cond_destroy(&cag->mCondVar); | ||
196 | SDL_free(cag); | ||
197 | } | ||
198 | } | ||
199 | |||
diff --git a/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.h b/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.h deleted file mode 100644 index f22c6956fe..0000000000 --- a/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.h +++ /dev/null | |||
@@ -1,116 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | /* | ||
25 | Note: This file hasn't been modified so technically we have to keep the disclaimer :-( | ||
26 | |||
27 | |||
28 | Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved. | ||
29 | |||
30 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. | ||
31 | ("Apple") in consideration of your agreement to the following terms, and your | ||
32 | use, installation, modification or redistribution of this Apple software | ||
33 | constitutes acceptance of these terms. If you do not agree with these terms, | ||
34 | please do not use, install, modify or redistribute this Apple software. | ||
35 | |||
36 | In consideration of your agreement to abide by the following terms, and subject | ||
37 | to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs | ||
38 | copyrights in this original Apple software (the "Apple Software"), to use, | ||
39 | reproduce, modify and redistribute the Apple Software, with or without | ||
40 | modifications, in source and/or binary forms; provided that if you redistribute | ||
41 | the Apple Software in its entirety and without modifications, you must retain | ||
42 | this notice and the following text and disclaimers in all such redistributions of | ||
43 | the Apple Software. Neither the name, trademarks, service marks or logos of | ||
44 | Apple Computer, Inc. may be used to endorse or promote products derived from the | ||
45 | Apple Software without specific prior written permission from Apple. Except as | ||
46 | expressly stated in this notice, no other rights or licenses, express or implied, | ||
47 | are granted by Apple herein, including but not limited to any patent rights that | ||
48 | may be infringed by your derivative works or by other works in which the Apple | ||
49 | Software may be incorporated. | ||
50 | |||
51 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO | ||
52 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED | ||
53 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
54 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN | ||
55 | COMBINATION WITH YOUR PRODUCTS. | ||
56 | |||
57 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR | ||
58 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | ||
59 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
60 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION | ||
61 | OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT | ||
62 | (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN | ||
63 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
64 | */ | ||
65 | /*============================================================================= | ||
66 | CAGuard.h | ||
67 | |||
68 | =============================================================================*/ | ||
69 | #if !defined(__CAGuard_h__) | ||
70 | #define __CAGuard_h__ | ||
71 | |||
72 | /*============================================================================= | ||
73 | Includes | ||
74 | =============================================================================*/ | ||
75 | |||
76 | #include <CoreAudio/CoreAudioTypes.h> | ||
77 | #include <pthread.h> | ||
78 | |||
79 | |||
80 | /*============================================================================= | ||
81 | CAGuard | ||
82 | |||
83 | This is your typical mutex with signalling implemented via pthreads. | ||
84 | Lock() will return true if and only if the guard is locked on that call. | ||
85 | A thread that already has the guard will receive 'false' if it locks it | ||
86 | again. Use of the stack-based CAGuard::Locker class is highly recommended | ||
87 | to properly manage the recursive nesting. The Wait calls with timeouts | ||
88 | will return true if and only if the timeout period expired. They will | ||
89 | return false if they receive notification any other way. | ||
90 | =============================================================================*/ | ||
91 | |||
92 | typedef struct S_SDLOSXCAGuard | ||
93 | { | ||
94 | |||
95 | /* Construction/Destruction */ | ||
96 | /*public:*/ | ||
97 | /* Actions */ | ||
98 | /*public:*/ | ||
99 | int (*Lock)(struct S_SDLOSXCAGuard *cag); | ||
100 | void (*Unlock)(struct S_SDLOSXCAGuard *cag); | ||
101 | int (*Try)(struct S_SDLOSXCAGuard *cag, int *outWasLocked); /* returns true if lock is free, false if not */ | ||
102 | void (*Wait)(struct S_SDLOSXCAGuard *cag); | ||
103 | void (*Notify)(struct S_SDLOSXCAGuard *cag); | ||
104 | |||
105 | /* Implementation */ | ||
106 | /*protected:*/ | ||
107 | pthread_mutex_t mMutex; | ||
108 | pthread_cond_t mCondVar; | ||
109 | pthread_t mOwner; | ||
110 | } SDLOSXCAGuard; | ||
111 | |||
112 | SDLOSXCAGuard *new_SDLOSXCAGuard(void); | ||
113 | void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag); | ||
114 | |||
115 | #endif | ||
116 | |||
diff --git a/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom.c deleted file mode 100644 index 5018750222..0000000000 --- a/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom.c +++ /dev/null | |||
@@ -1,514 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | #ifdef SDL_CDROM_MACOSX | ||
25 | |||
26 | #include "SDL_syscdrom_c.h" | ||
27 | |||
28 | #pragma mark -- Globals -- | ||
29 | |||
30 | static FSRef** tracks; | ||
31 | static FSVolumeRefNum* volumes; | ||
32 | static CDstatus status; | ||
33 | static int nextTrackFrame; | ||
34 | static int nextTrackFramesRemaining; | ||
35 | static int fakeCD; | ||
36 | static int currentTrack; | ||
37 | static int didReadTOC; | ||
38 | static int cacheTOCNumTracks; | ||
39 | static int currentDrive; /* Only allow 1 drive in use at a time */ | ||
40 | |||
41 | #pragma mark -- Prototypes -- | ||
42 | |||
43 | static const char *SDL_SYS_CDName (int drive); | ||
44 | static int SDL_SYS_CDOpen (int drive); | ||
45 | static int SDL_SYS_CDGetTOC (SDL_CD *cdrom); | ||
46 | static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position); | ||
47 | static int SDL_SYS_CDPlay (SDL_CD *cdrom, int start, int length); | ||
48 | static int SDL_SYS_CDPause (SDL_CD *cdrom); | ||
49 | static int SDL_SYS_CDResume (SDL_CD *cdrom); | ||
50 | static int SDL_SYS_CDStop (SDL_CD *cdrom); | ||
51 | static int SDL_SYS_CDEject (SDL_CD *cdrom); | ||
52 | static void SDL_SYS_CDClose (SDL_CD *cdrom); | ||
53 | |||
54 | #pragma mark -- Helper Functions -- | ||
55 | |||
56 | /* Read a list of tracks from the volume */ | ||
57 | static int LoadTracks (SDL_CD *cdrom) | ||
58 | { | ||
59 | /* Check if tracks are already loaded */ | ||
60 | if ( tracks[cdrom->id] != NULL ) | ||
61 | return 0; | ||
62 | |||
63 | /* Allocate memory for tracks */ | ||
64 | tracks[cdrom->id] = (FSRef*) SDL_calloc (1, sizeof(**tracks) * cdrom->numtracks); | ||
65 | if (tracks[cdrom->id] == NULL) { | ||
66 | SDL_OutOfMemory (); | ||
67 | return -1; | ||
68 | } | ||
69 | |||
70 | /* Load tracks */ | ||
71 | if (ListTrackFiles (volumes[cdrom->id], tracks[cdrom->id], cdrom->numtracks) < 0) | ||
72 | return -1; | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | /* Find a file for a given start frame and length */ | ||
78 | static FSRef* GetFileForOffset (SDL_CD *cdrom, int start, int length, int *outStartFrame, int *outStopFrame) | ||
79 | { | ||
80 | int i; | ||
81 | |||
82 | for (i = 0; i < cdrom->numtracks; i++) { | ||
83 | |||
84 | if (cdrom->track[i].offset <= start && | ||
85 | start < (cdrom->track[i].offset + cdrom->track[i].length)) | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | if (i == cdrom->numtracks) | ||
90 | return NULL; | ||
91 | |||
92 | currentTrack = i; | ||
93 | |||
94 | *outStartFrame = start - cdrom->track[i].offset; | ||
95 | |||
96 | if ((*outStartFrame + length) < cdrom->track[i].length) { | ||
97 | *outStopFrame = *outStartFrame + length; | ||
98 | length = 0; | ||
99 | nextTrackFrame = -1; | ||
100 | nextTrackFramesRemaining = -1; | ||
101 | } | ||
102 | else { | ||
103 | *outStopFrame = -1; | ||
104 | length -= cdrom->track[i].length - *outStartFrame; | ||
105 | nextTrackFrame = cdrom->track[i+1].offset; | ||
106 | nextTrackFramesRemaining = length; | ||
107 | } | ||
108 | |||
109 | return &tracks[cdrom->id][i]; | ||
110 | } | ||
111 | |||
112 | /* Setup another file for playback, or stop playback (called from another thread) */ | ||
113 | static void CompletionProc (SDL_CD *cdrom) | ||
114 | { | ||
115 | |||
116 | Lock (); | ||
117 | |||
118 | if (nextTrackFrame > 0 && nextTrackFramesRemaining > 0) { | ||
119 | |||
120 | /* Load the next file to play */ | ||
121 | int startFrame, stopFrame; | ||
122 | FSRef *file; | ||
123 | |||
124 | PauseFile (); | ||
125 | ReleaseFile (); | ||
126 | |||
127 | file = GetFileForOffset (cdrom, nextTrackFrame, | ||
128 | nextTrackFramesRemaining, &startFrame, &stopFrame); | ||
129 | |||
130 | if (file == NULL) { | ||
131 | status = CD_STOPPED; | ||
132 | Unlock (); | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | LoadFile (file, startFrame, stopFrame); | ||
137 | |||
138 | SetCompletionProc (CompletionProc, cdrom); | ||
139 | |||
140 | PlayFile (); | ||
141 | } | ||
142 | else { | ||
143 | |||
144 | /* Release the current file */ | ||
145 | PauseFile (); | ||
146 | ReleaseFile (); | ||
147 | status = CD_STOPPED; | ||
148 | } | ||
149 | |||
150 | Unlock (); | ||
151 | } | ||
152 | |||
153 | |||
154 | #pragma mark -- Driver Functions -- | ||
155 | |||
156 | /* Initialize */ | ||
157 | int SDL_SYS_CDInit (void) | ||
158 | { | ||
159 | /* Initialize globals */ | ||
160 | volumes = NULL; | ||
161 | tracks = NULL; | ||
162 | status = CD_STOPPED; | ||
163 | nextTrackFrame = -1; | ||
164 | nextTrackFramesRemaining = -1; | ||
165 | fakeCD = SDL_FALSE; | ||
166 | currentTrack = -1; | ||
167 | didReadTOC = SDL_FALSE; | ||
168 | cacheTOCNumTracks = -1; | ||
169 | currentDrive = -1; | ||
170 | |||
171 | /* Fill in function pointers */ | ||
172 | SDL_CDcaps.Name = SDL_SYS_CDName; | ||
173 | SDL_CDcaps.Open = SDL_SYS_CDOpen; | ||
174 | SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; | ||
175 | SDL_CDcaps.Status = SDL_SYS_CDStatus; | ||
176 | SDL_CDcaps.Play = SDL_SYS_CDPlay; | ||
177 | SDL_CDcaps.Pause = SDL_SYS_CDPause; | ||
178 | SDL_CDcaps.Resume = SDL_SYS_CDResume; | ||
179 | SDL_CDcaps.Stop = SDL_SYS_CDStop; | ||
180 | SDL_CDcaps.Eject = SDL_SYS_CDEject; | ||
181 | SDL_CDcaps.Close = SDL_SYS_CDClose; | ||
182 | |||
183 | /* | ||
184 | Read the list of "drives" | ||
185 | |||
186 | This is currently a hack that infers drives from | ||
187 | mounted audio CD volumes, rather than | ||
188 | actual CD-ROM devices - which means it may not | ||
189 | act as expected sometimes. | ||
190 | */ | ||
191 | |||
192 | /* Find out how many cd volumes are mounted */ | ||
193 | SDL_numcds = DetectAudioCDVolumes (NULL, 0); | ||
194 | |||
195 | /* | ||
196 | If there are no volumes, fake a cd device | ||
197 | so tray empty can be reported. | ||
198 | */ | ||
199 | if (SDL_numcds == 0) { | ||
200 | |||
201 | fakeCD = SDL_TRUE; | ||
202 | SDL_numcds = 1; | ||
203 | status = CD_TRAYEMPTY; | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | /* Allocate space for volumes */ | ||
209 | volumes = (FSVolumeRefNum*) SDL_calloc (1, sizeof(*volumes) * SDL_numcds); | ||
210 | if (volumes == NULL) { | ||
211 | SDL_OutOfMemory (); | ||
212 | return -1; | ||
213 | } | ||
214 | |||
215 | /* Allocate space for tracks */ | ||
216 | tracks = (FSRef**) SDL_calloc (1, sizeof(*tracks) * (SDL_numcds + 1)); | ||
217 | if (tracks == NULL) { | ||
218 | SDL_OutOfMemory (); | ||
219 | return -1; | ||
220 | } | ||
221 | |||
222 | /* Mark the end of the tracks array */ | ||
223 | tracks[ SDL_numcds ] = (FSRef*)-1; | ||
224 | |||
225 | /* | ||
226 | Redetect, now save all volumes for later | ||
227 | Update SDL_numcds just in case it changed | ||
228 | */ | ||
229 | { | ||
230 | int numVolumes = SDL_numcds; | ||
231 | |||
232 | SDL_numcds = DetectAudioCDVolumes (volumes, numVolumes); | ||
233 | |||
234 | /* If more cds suddenly show up, ignore them */ | ||
235 | if (SDL_numcds > numVolumes) { | ||
236 | SDL_SetError ("Some CD's were added but they will be ignored"); | ||
237 | SDL_numcds = numVolumes; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | /* Shutdown and cleanup */ | ||
245 | void SDL_SYS_CDQuit(void) | ||
246 | { | ||
247 | ReleaseFile(); | ||
248 | |||
249 | if (volumes != NULL) | ||
250 | free (volumes); | ||
251 | |||
252 | if (tracks != NULL) { | ||
253 | |||
254 | FSRef **ptr; | ||
255 | for (ptr = tracks; *ptr != (FSRef*)-1; ptr++) | ||
256 | if (*ptr != NULL) | ||
257 | free (*ptr); | ||
258 | |||
259 | free (tracks); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | /* Get the Unix disk name of the volume */ | ||
264 | static const char *SDL_SYS_CDName (int drive) | ||
265 | { | ||
266 | /* | ||
267 | * !!! FIXME: PBHGetVolParmsSync() is gone in 10.6, | ||
268 | * !!! FIXME: replaced with FSGetVolumeParms(), which | ||
269 | * !!! FIXME: isn't available before 10.5. :/ | ||
270 | */ | ||
271 | return "Mac OS X CD-ROM Device"; | ||
272 | |||
273 | #if 0 | ||
274 | OSStatus err = noErr; | ||
275 | HParamBlockRec pb; | ||
276 | GetVolParmsInfoBuffer volParmsInfo; | ||
277 | |||
278 | if (fakeCD) | ||
279 | return "Fake CD-ROM Device"; | ||
280 | |||
281 | pb.ioParam.ioNamePtr = NULL; | ||
282 | pb.ioParam.ioVRefNum = volumes[drive]; | ||
283 | pb.ioParam.ioBuffer = (Ptr)&volParmsInfo; | ||
284 | pb.ioParam.ioReqCount = (SInt32)sizeof(volParmsInfo); | ||
285 | err = PBHGetVolParmsSync(&pb); | ||
286 | |||
287 | if (err != noErr) { | ||
288 | SDL_SetError ("PBHGetVolParmsSync returned %d", err); | ||
289 | return NULL; | ||
290 | } | ||
291 | |||
292 | return volParmsInfo.vMDeviceID; | ||
293 | #endif | ||
294 | } | ||
295 | |||
296 | /* Open the "device" */ | ||
297 | static int SDL_SYS_CDOpen (int drive) | ||
298 | { | ||
299 | /* Only allow 1 device to be open */ | ||
300 | if (currentDrive >= 0) { | ||
301 | SDL_SetError ("Only one cdrom is supported"); | ||
302 | return -1; | ||
303 | } | ||
304 | else | ||
305 | currentDrive = drive; | ||
306 | |||
307 | return drive; | ||
308 | } | ||
309 | |||
310 | /* Get the table of contents */ | ||
311 | static int SDL_SYS_CDGetTOC (SDL_CD *cdrom) | ||
312 | { | ||
313 | if (fakeCD) { | ||
314 | SDL_SetError (kErrorFakeDevice); | ||
315 | return -1; | ||
316 | } | ||
317 | |||
318 | if (didReadTOC) { | ||
319 | cdrom->numtracks = cacheTOCNumTracks; | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | |||
324 | ReadTOCData (volumes[cdrom->id], cdrom); | ||
325 | didReadTOC = SDL_TRUE; | ||
326 | cacheTOCNumTracks = cdrom->numtracks; | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | /* Get CD-ROM status */ | ||
332 | static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position) | ||
333 | { | ||
334 | if (position) { | ||
335 | int trackFrame; | ||
336 | |||
337 | Lock (); | ||
338 | trackFrame = GetCurrentFrame (); | ||
339 | Unlock (); | ||
340 | |||
341 | *position = cdrom->track[currentTrack].offset + trackFrame; | ||
342 | } | ||
343 | |||
344 | return status; | ||
345 | } | ||
346 | |||
347 | /* Start playback */ | ||
348 | static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) | ||
349 | { | ||
350 | int startFrame, stopFrame; | ||
351 | FSRef *ref; | ||
352 | |||
353 | if (fakeCD) { | ||
354 | SDL_SetError (kErrorFakeDevice); | ||
355 | return -1; | ||
356 | } | ||
357 | |||
358 | Lock(); | ||
359 | |||
360 | if (LoadTracks (cdrom) < 0) | ||
361 | return -2; | ||
362 | |||
363 | if (PauseFile () < 0) | ||
364 | return -3; | ||
365 | |||
366 | if (ReleaseFile () < 0) | ||
367 | return -4; | ||
368 | |||
369 | ref = GetFileForOffset (cdrom, start, length, &startFrame, &stopFrame); | ||
370 | if (ref == NULL) { | ||
371 | SDL_SetError ("SDL_SYS_CDPlay: No file for start=%d, length=%d", start, length); | ||
372 | return -5; | ||
373 | } | ||
374 | |||
375 | if (LoadFile (ref, startFrame, stopFrame) < 0) | ||
376 | return -6; | ||
377 | |||
378 | SetCompletionProc (CompletionProc, cdrom); | ||
379 | |||
380 | if (PlayFile () < 0) | ||
381 | return -7; | ||
382 | |||
383 | status = CD_PLAYING; | ||
384 | |||
385 | Unlock(); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | /* Pause playback */ | ||
391 | static int SDL_SYS_CDPause(SDL_CD *cdrom) | ||
392 | { | ||
393 | if (fakeCD) { | ||
394 | SDL_SetError (kErrorFakeDevice); | ||
395 | return -1; | ||
396 | } | ||
397 | |||
398 | Lock (); | ||
399 | |||
400 | if (PauseFile () < 0) { | ||
401 | Unlock (); | ||
402 | return -2; | ||
403 | } | ||
404 | |||
405 | status = CD_PAUSED; | ||
406 | |||
407 | Unlock (); | ||
408 | |||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | /* Resume playback */ | ||
413 | static int SDL_SYS_CDResume(SDL_CD *cdrom) | ||
414 | { | ||
415 | if (fakeCD) { | ||
416 | SDL_SetError (kErrorFakeDevice); | ||
417 | return -1; | ||
418 | } | ||
419 | |||
420 | Lock (); | ||
421 | |||
422 | if (PlayFile () < 0) { | ||
423 | Unlock (); | ||
424 | return -2; | ||
425 | } | ||
426 | |||
427 | status = CD_PLAYING; | ||
428 | |||
429 | Unlock (); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | /* Stop playback */ | ||
435 | static int SDL_SYS_CDStop(SDL_CD *cdrom) | ||
436 | { | ||
437 | if (fakeCD) { | ||
438 | SDL_SetError (kErrorFakeDevice); | ||
439 | return -1; | ||
440 | } | ||
441 | |||
442 | Lock (); | ||
443 | |||
444 | if (PauseFile () < 0) { | ||
445 | Unlock (); | ||
446 | return -2; | ||
447 | } | ||
448 | |||
449 | if (ReleaseFile () < 0) { | ||
450 | Unlock (); | ||
451 | return -3; | ||
452 | } | ||
453 | |||
454 | status = CD_STOPPED; | ||
455 | |||
456 | Unlock (); | ||
457 | |||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | /* Eject the CD-ROM (Unmount the volume) */ | ||
462 | static int SDL_SYS_CDEject(SDL_CD *cdrom) | ||
463 | { | ||
464 | OSStatus err; | ||
465 | pid_t dissenter; | ||
466 | |||
467 | if (fakeCD) { | ||
468 | SDL_SetError (kErrorFakeDevice); | ||
469 | return -1; | ||
470 | } | ||
471 | |||
472 | Lock (); | ||
473 | |||
474 | if (PauseFile () < 0) { | ||
475 | Unlock (); | ||
476 | return -2; | ||
477 | } | ||
478 | |||
479 | if (ReleaseFile () < 0) { | ||
480 | Unlock (); | ||
481 | return -3; | ||
482 | } | ||
483 | |||
484 | status = CD_STOPPED; | ||
485 | |||
486 | /* Eject the volume */ | ||
487 | err = FSEjectVolumeSync(volumes[cdrom->id], kNilOptions, &dissenter); | ||
488 | |||
489 | if (err != noErr) { | ||
490 | Unlock (); | ||
491 | SDL_SetError ("PBUnmountVol returned %d", err); | ||
492 | return -4; | ||
493 | } | ||
494 | |||
495 | status = CD_TRAYEMPTY; | ||
496 | |||
497 | /* Invalidate volume and track info */ | ||
498 | volumes[cdrom->id] = 0; | ||
499 | free (tracks[cdrom->id]); | ||
500 | tracks[cdrom->id] = NULL; | ||
501 | |||
502 | Unlock (); | ||
503 | |||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | /* Close the CD-ROM */ | ||
508 | static void SDL_SYS_CDClose(SDL_CD *cdrom) | ||
509 | { | ||
510 | currentDrive = -1; | ||
511 | return; | ||
512 | } | ||
513 | |||
514 | #endif /* SDL_CDROM_MACOSX */ | ||
diff --git a/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom_c.h b/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom_c.h deleted file mode 100644 index 589c5897e6..0000000000 --- a/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom_c.h +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* | ||
2 | SDL - Simple DirectMedia Layer | ||
3 | Copyright (C) 1997-2012 Sam Lantinga | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with this library; if not, write to the Free | ||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | |||
19 | Sam Lantinga | ||
20 | slouken@libsdl.org | ||
21 | */ | ||
22 | #include "SDL_config.h" | ||
23 | |||
24 | /* This is the Mac OS X / CoreAudio specific header for the SDL CD-ROM API | ||
25 | Contributed by Darrell Walisser and Max Horn | ||
26 | */ | ||
27 | |||
28 | /*********************************************************************************** | ||
29 | Implementation Notes | ||
30 | ********************* | ||
31 | |||
32 | This code has several limitations currently (all of which are proabaly fixable): | ||
33 | |||
34 | 1. A CD-ROM device is inferred from a mounted cdfs volume, so device 0 is | ||
35 | not necessarily the first CD-ROM device on the system. (Somewhat easy to fix | ||
36 | by useing the device name from the volume id's to reorder the volumes) | ||
37 | |||
38 | 2. You can only open and control 1 CD-ROM device at a time. (Challenging to fix, | ||
39 | due to extensive code restructuring) | ||
40 | |||
41 | 3. The status reported by SDL_CDStatus only changes to from CD_PLAYING to CD_STOPPED in | ||
42 | 1-second intervals (because the audio is buffered in 1-second chunks) If | ||
43 | the audio data is less than 1 second, the remainder is filled with silence. | ||
44 | |||
45 | If you need to play sequences back-to-back that are less that 1 second long, | ||
46 | use the frame position to determine when to play the next sequence, instead | ||
47 | of SDL_CDStatus. | ||
48 | |||
49 | This may be possible to fix with a clever usage of the AudioUnit API. | ||
50 | |||
51 | 4. When new volumes are inserted, our volume information is not updated. The only way | ||
52 | to refresh this information is to reinit the CD-ROM subsystem of SDL. To fix this, | ||
53 | one would probably have to fix point 1 above first, then figure out how to register | ||
54 | for a notification when new media is mounted in order to perform an automatic | ||
55 | rescan for cdfs volumes. | ||
56 | |||
57 | |||
58 | |||
59 | So, here comes a description of how this all works. | ||
60 | |||
61 | < Initializing > | ||
62 | |||
63 | To get things rolling, we have to locate mounted volumes that contain | ||
64 | audio (since nearly all Macs don't have analog audio-in on the sound card). | ||
65 | That's easy, since these volumes have a flag that indicates this special | ||
66 | filesystem. See DetectAudioCDVolumes() in CDPlayer.cpp for this code. | ||
67 | |||
68 | Next, we parse the invisible .TOC.plist in the root of the volume, which gets us | ||
69 | the track information (number, offset, length, leadout, etc). See ReadTOCData() in | ||
70 | CDPlayer.cpp for the skinny on this. | ||
71 | |||
72 | |||
73 | < The Playback Loop > | ||
74 | |||
75 | Now come the tricky parts. Let's start with basic audio playback. When a frame | ||
76 | range to play is requested, we must first find the .aiff files on the volume, | ||
77 | hopefully in the right order. Since these files all begin with a number "1 Audio Track", | ||
78 | etc, this is used to determine the correct track order. | ||
79 | |||
80 | Once all files are determined, we have to find what file corresponds to the start | ||
81 | and length parameter to SDL_SYS_CDPlay(). Again, this is quite simple by walking the | ||
82 | cdrom's track list. At this point, we also save the offset to the next track and frames | ||
83 | remaining, if we're going to have to play another file after the first one. See | ||
84 | GetFileForOffset() for this code. | ||
85 | |||
86 | At this point we have all info needed to start playback, so we hand off to the LoadFile() | ||
87 | function, which proceeds to do its magic and plays back the file. | ||
88 | |||
89 | When the file is finished playing, CompletionProc() is invoked, at which time we can | ||
90 | play the next file if the previously saved next track and frames remaining | ||
91 | indicates that we should. | ||
92 | |||
93 | |||
94 | < Magic > | ||
95 | |||
96 | OK, so it's not really magic, but since I don't fully understand all the hidden details it | ||
97 | seems like it to me ;-) The API's involved are the AudioUnit and AudioFile API's. These | ||
98 | appear to be an extension of CoreAudio for creating modular playback and f/x entities. | ||
99 | The important thing is that CPU usage is very low and reliability is very high. You'd | ||
100 | be hard-pressed to find a way to stutter the playback with other CPU-intensive tasks. | ||
101 | |||
102 | One part of this magic is that it uses multiple threads, which carries the usual potential | ||
103 | for disaster if not handled carefully. Playback currently requires 4 additional threads: | ||
104 | 1. The coreaudio runloop thread | ||
105 | 2. The coreaudio device i/o thread | ||
106 | 3. The file streaming thread | ||
107 | 4. The notification/callback thread | ||
108 | |||
109 | The first 2 threads are necessary evil - CoreAudio creates this no matter what the situation | ||
110 | is (even the SDL sound implementation creates theses suckers). The last two are are created | ||
111 | by us. | ||
112 | |||
113 | The file is streamed from disk using a threaded double-buffer approach. | ||
114 | This way, the high latency operation of reading from disk can be performed without interrupting | ||
115 | the real-time device thread (which amounts to avoiding dropouts). The device thread grabs the | ||
116 | buffer that isn't being read and sends it to the CoreAudio mixer where it eventually gets | ||
117 | to the sound card. | ||
118 | |||
119 | The device thread posts a notification when the file streaming thread is out of data. This | ||
120 | notification must be handled in a separate thread to avoid potential deadlock in the | ||
121 | device thread. That's where the notification thread comes in. This thread is signaled | ||
122 | whenever a notification needs to be processed, so another file can be played back if need be. | ||
123 | |||
124 | The API in CDPlayer.cpp contains synchronization because otherwise both the notification thread | ||
125 | and main thread (or another other thread using the SDL CD api) can potentially call it at the same time. | ||
126 | |||
127 | ************************************************************************************/ | ||
128 | |||
129 | |||
130 | #include "SDL_cdrom.h" | ||
131 | #include "../SDL_syscdrom.h" | ||
132 | |||
133 | #include "CDPlayer.h" | ||
134 | |||
135 | #define kErrorFakeDevice "Error: Cannot proceed since we're faking a CD-ROM device. Reinit the CD-ROM subsystem to scan for new volumes." | ||
136 | |||