comparison src/audio/mint/SDL_mintaudio_mcsn.c @ 2049:5f6550e5184f

Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
author Ryan C. Gordon <icculus@icculus.org>
date Tue, 17 Oct 2006 09:15:21 +0000
parents adf732f1f016
children 866052b01ee5
comparison
equal deleted inserted replaced
2048:6067c7f9a672 2049:5f6550e5184f
59 #define DEBUG_PRINT(what) 59 #define DEBUG_PRINT(what)
60 #endif 60 #endif
61 61
62 /*--- Static variables ---*/ 62 /*--- Static variables ---*/
63 63
64 static unsigned long cookie_snd, cookie_mch; 64 static unsigned long cookie_snd = 0;
65 static cookie_mcsn_t *cookie_mcsn; 65 static unsigned long cookie_mch = 0;
66 66 static cookie_mcsn_t *cookie_mcsn = NULL;
67 /*--- Audio driver functions ---*/
68
69 static void Mint_CloseAudio(_THIS);
70 static int Mint_OpenAudio(_THIS, SDL_AudioSpec * spec);
71 static void Mint_LockAudio(_THIS);
72 static void Mint_UnlockAudio(_THIS);
73
74 /* To check/init hardware audio */
75 static int Mint_CheckAudio(_THIS, SDL_AudioSpec * spec);
76 static void Mint_InitAudio(_THIS, SDL_AudioSpec * spec);
77
78 /*--- Audio driver bootstrap functions ---*/
79
80 static int
81 Audio_Available(void)
82 {
83 unsigned long dummy;
84 const char *envr = SDL_getenv("SDL_AUDIODRIVER");
85
86 SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
87
88 /* We can't use XBIOS in interrupt with Magic, don't know about thread */
89 if (Getcookie(C_MagX, &dummy) == C_FOUND) {
90 return (0);
91 }
92
93 /* Check if user asked a different audio driver */
94 if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) {
95 DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
96 return (0);
97 }
98
99 /* Cookie _MCH present ? if not, assume ST machine */
100 if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
101 cookie_mch = MCH_ST;
102 }
103
104 /* Cookie _SND present ? if not, assume ST machine */
105 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
106 cookie_snd = SND_PSG;
107 }
108
109 /* Check if we have 16 bits audio */
110 if ((cookie_snd & SND_16BIT) == 0) {
111 DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
112 return (0);
113 }
114
115 /* Cookie MCSN present ? */
116 if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) {
117 DEBUG_PRINT((DEBUG_NAME "no MCSN audio\n"));
118 return (0);
119 }
120
121 /* Check if interrupt at end of replay */
122 if (cookie_mcsn->pint == 0) {
123 DEBUG_PRINT((DEBUG_NAME "no interrupt at end of replay\n"));
124 return (0);
125 }
126
127 /* Check if audio is lockable */
128 if (Locksnd() != 1) {
129 DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
130 return (0);
131 }
132
133 Unlocksnd();
134
135 DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n"));
136 return (1);
137 }
138 67
139 static void 68 static void
140 Audio_DeleteDevice(SDL_AudioDevice * device) 69 MINTMCSN_LockDevice(_THIS)
141 {
142 SDL_free(device->hidden);
143 SDL_free(device);
144 }
145
146 static SDL_AudioDevice *
147 Audio_CreateDevice(int devindex)
148 {
149 SDL_AudioDevice *this;
150
151 /* Initialize all variables that we clean on shutdown */
152 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
153 if (this) {
154 SDL_memset(this, 0, (sizeof *this));
155 this->hidden = (struct SDL_PrivateAudioData *)
156 SDL_malloc((sizeof *this->hidden));
157 }
158 if ((this == NULL) || (this->hidden == NULL)) {
159 SDL_OutOfMemory();
160 if (this) {
161 SDL_free(this);
162 }
163 return (0);
164 }
165 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
166
167 /* Set the function pointers */
168 this->OpenAudio = Mint_OpenAudio;
169 this->CloseAudio = Mint_CloseAudio;
170 this->LockAudio = Mint_LockAudio;
171 this->UnlockAudio = Mint_UnlockAudio;
172 this->free = Audio_DeleteDevice;
173
174 return this;
175 }
176
177 AudioBootStrap MINTAUDIO_MCSN_bootstrap = {
178 MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver",
179 Audio_Available, Audio_CreateDevice
180 };
181
182 static void
183 Mint_LockAudio(_THIS)
184 { 70 {
185 /* Stop replay */ 71 /* Stop replay */
186 Buffoper(0); 72 Buffoper(0);
187 } 73 }
188 74
189 static void 75 static void
190 Mint_UnlockAudio(_THIS) 76 MINTMCSN_UnlockDevice(_THIS)
191 { 77 {
192 /* Restart replay */ 78 /* Restart replay */
193 Buffoper(SB_PLA_ENA | SB_PLA_RPT); 79 Buffoper(SB_PLA_ENA | SB_PLA_RPT);
194 } 80 }
195 81
196 static void 82 static void
197 Mint_CloseAudio(_THIS) 83 MINTMCSN_CloseDevice(_THIS)
198 { 84 {
199 /* Stop replay */ 85 if (this->hidden != NULL) {
200 SDL_MintAudio_WaitThread(); 86 /* Stop replay */
201 Buffoper(0); 87 SDL_MintAudio_WaitThread();
202 88 Buffoper(0);
203 if (!SDL_MintAudio_mint_present) { 89
204 /* Uninstall interrupt */ 90 if (!SDL_MintAudio_mint_present) {
205 Jdisint(MFP_DMASOUND); 91 /* Uninstall interrupt */
206 } 92 Jdisint(MFP_DMASOUND);
207 93 }
208 /* Wait if currently playing sound */ 94
209 while (SDL_MintAudio_mutex != 0) { 95 /* Wait if currently playing sound */
210 } 96 while (SDL_MintAudio_mutex != 0) {}
211 97
212 /* Clear buffers */ 98 /* Clear buffers */
213 if (SDL_MintAudio_audiobuf[0]) { 99 if (SDL_MintAudio_audiobuf[0]) {
214 Mfree(SDL_MintAudio_audiobuf[0]); 100 Mfree(SDL_MintAudio_audiobuf[0]);
215 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; 101 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
216 } 102 }
217 103
218 /* Unlock sound system */ 104 /* Unlock sound system */
219 Unlocksnd(); 105 Unlocksnd();
106
107 SDL_free(this->hidden);
108 this->hidden = NULL;
109 }
220 } 110 }
221 111
222 static int 112 static int
223 Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) 113 MINTMCSN_CheckAudio(_THIS)
224 { 114 {
225 int i; 115 int i;
226 unsigned long masterclock, masterprediv; 116 unsigned long masterclock, masterprediv;
227 117
228 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", 118 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",
229 SDL_AUDIO_BITSIZE(spec->format))); 119 SDL_AUDIO_BITSIZE(this->spec.format)));
230 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); 120 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
231 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); 121 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
232 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); 122 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
233 DEBUG_PRINT(("channels=%d, ", spec->channels)); 123 DEBUG_PRINT(("channels=%d, ", this->spec.channels));
234 DEBUG_PRINT(("freq=%d\n", spec->freq)); 124 DEBUG_PRINT(("freq=%d\n", this->spec.freq));
235 125
236 if (spec->channels > 2) { 126 if (this->spec.channels > 2) {
237 spec->channels = 2; /* no more than stereo! */ 127 this->spec.channels = 2; /* no more than stereo! */
238 } 128 }
239 129
240 /* Check formats available */ 130 /* Check formats available */
241 MINTAUDIO_freqcount = 0; 131 MINTAUDIO_freqcount = 0;
242 switch (cookie_mcsn->play) { 132 switch (cookie_mcsn->play) {
243 case MCSN_ST: 133 case MCSN_ST:
244 spec->channels = 1; 134 this->spec.channels = 1;
245 spec->format = AUDIO_S8; /* FIXME: is it signed or unsigned ? */ 135 this->spec.format = AUDIO_S8; /* FIXME: is it signed or unsigned ? */
246 SDL_MintAudio_AddFrequency(this, 12500, 0, 0, -1); 136 SDL_MintAudio_AddFrequency(this, 12500, 0, 0, -1);
247 break; 137 break;
248 case MCSN_TT: /* Also STE, Mega STE */ 138 case MCSN_TT: /* Also STE, Mega STE */
249 spec->format = AUDIO_S8; 139 this->spec.format = AUDIO_S8;
250 masterclock = MASTERCLOCK_STE; 140 masterclock = MASTERCLOCK_STE;
251 masterprediv = MASTERPREDIV_STE; 141 masterprediv = MASTERPREDIV_STE;
252 if ((cookie_mch >> 16) == MCH_TT) { 142 if ((cookie_mch >> 16) == MCH_TT) {
253 masterclock = MASTERCLOCK_TT; 143 masterclock = MASTERCLOCK_TT;
254 masterprediv = MASTERPREDIV_TT; 144 masterprediv = MASTERPREDIV_TT;
278 (MASTERPREDIV_FALCON * 168 (MASTERPREDIV_FALCON *
279 (1 << i)), CLKEXT, 169 (1 << i)), CLKEXT,
280 (1 << i) - 1, -1); 170 (1 << i) - 1, -1);
281 } 171 }
282 } 172 }
283 spec->format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */ 173 this->spec.format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */
284 if ((SDL_AUDIO_BITSIZE(spec->format)) == 16) { 174 if ((SDL_AUDIO_BITSIZE(this->spec.format)) == 16) {
285 spec->format |= SDL_AUDIO_MASK_ENDIAN; /* Audio is always big endian */ 175 this->spec.format |= SDL_AUDIO_MASK_ENDIAN; /* Audio is always big endian */
286 spec->channels = 2; /* 16 bits always stereo */ 176 this->spec.channels = 2; /* 16 bits always stereo */
287 } 177 }
288 break; 178 break;
289 } 179 }
290 180
291 #if 1 181 #if 1
295 MINTAUDIO_frequencies[i].masterclock, 185 MINTAUDIO_frequencies[i].masterclock,
296 MINTAUDIO_frequencies[i].predivisor)); 186 MINTAUDIO_frequencies[i].predivisor));
297 } 187 }
298 #endif 188 #endif
299 189
300 MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq); 190 MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq);
301 spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; 191 this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
302 192
303 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ", 193 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
304 SDL_AUDIO_BITSIZE(spec->format))); 194 SDL_AUDIO_BITSIZE(this->spec.format)));
305 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); 195 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
306 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); 196 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
307 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); 197 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
308 DEBUG_PRINT(("channels=%d, ", spec->channels)); 198 DEBUG_PRINT(("channels=%d, ", this->spec.channels));
309 DEBUG_PRINT(("freq=%d\n", spec->freq)); 199 DEBUG_PRINT(("freq=%d\n", this->spec.freq));
310 200
311 return 0; 201 return 0;
312 } 202 }
313 203
314 static void 204 static void
315 Mint_InitAudio(_THIS, SDL_AudioSpec * spec) 205 MINTMCSN_InitAudio(_THIS)
316 { 206 {
317 int channels_mode, prediv, dmaclock; 207 int channels_mode, prediv, dmaclock;
318 void *buffer; 208 void *buffer;
319 209
320 /* Stop currently playing sound */ 210 /* Stop currently playing sound */
327 Settracks(0, 0); 217 Settracks(0, 0);
328 Setmontracks(0); 218 Setmontracks(0);
329 219
330 /* Select replay format */ 220 /* Select replay format */
331 channels_mode = STEREO16; 221 channels_mode = STEREO16;
332 switch (SDL_AUDIO_BITSIZE(spec->format)) { 222 switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
333 case 8: 223 case 8:
334 if (spec->channels == 2) { 224 if (this->spec.channels == 2) {
335 channels_mode = STEREO8; 225 channels_mode = STEREO8;
336 } else { 226 } else {
337 channels_mode = MONO8; 227 channels_mode = MONO8;
338 } 228 }
339 break; 229 break;
356 break; 246 break;
357 } 247 }
358 248
359 /* Set buffer */ 249 /* Set buffer */
360 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; 250 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
361 if (Setbuffer(0, buffer, buffer + spec->size) < 0) { 251 if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) {
362 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); 252 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
363 } 253 }
364 254
365 if (SDL_MintAudio_mint_present) { 255 if (SDL_MintAudio_mint_present) {
366 SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0); 256 SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0);
379 Buffoper(SB_PLA_ENA | SB_PLA_RPT); 269 Buffoper(SB_PLA_ENA | SB_PLA_RPT);
380 DEBUG_PRINT((DEBUG_NAME "hardware initialized\n")); 270 DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
381 } 271 }
382 272
383 static int 273 static int
384 Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) 274 MINTMCSN_OpenDevice(_THIS, const char *devname, int iscapture)
385 { 275 {
386 /* Lock sound system */ 276 /* Lock sound system */
387 if (Locksnd() != 1) { 277 if (Locksnd() != 1) {
388 SDL_SetError("Mint_OpenAudio: Audio system already in use"); 278 SDL_SetError("MINTMCSN_OpenDevice: Audio system already in use");
389 return (-1); 279 return 0;
390 } 280 }
391 281
392 SDL_MintAudio_device = this; 282 SDL_MintAudio_device = this;
393 283
394 /* Check audio capabilities */ 284 /* Check audio capabilities */
395 if (Mint_CheckAudio(this, spec) == -1) { 285 if (MINTMCSN_CheckAudio(this) == -1) {
396 return -1; 286 return 0;
397 } 287 }
398 288
399 SDL_CalculateAudioSpec(spec); 289 /* Initialize all variables that we clean on shutdown */
290 this->hidden = (struct SDL_PrivateAudioData *)
291 SDL_malloc((sizeof *this->hidden));
292 if (this->hidden == NULL) {
293 SDL_OutOfMemory();
294 return 0;
295 }
296 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
297
298 SDL_CalculateAudioSpec(&this->spec);
400 299
401 /* Allocate memory for audio buffers in DMA-able RAM */ 300 /* Allocate memory for audio buffers in DMA-able RAM */
402 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); 301 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size));
403 302
404 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM); 303 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM);
405 if (SDL_MintAudio_audiobuf[0] == NULL) { 304 if (SDL_MintAudio_audiobuf[0] == NULL) {
406 SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); 305 SDL_free(this->hidden);
407 return (-1); 306 this->hidden = NULL;
408 } 307 SDL_OutOfMemory();
409 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size; 308 return 0;
309 }
310 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size;
410 SDL_MintAudio_numbuf = 0; 311 SDL_MintAudio_numbuf = 0;
411 SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2); 312 SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2);
412 SDL_MintAudio_audiosize = spec->size; 313 SDL_MintAudio_audiosize = this->spec.size;
413 SDL_MintAudio_mutex = 0; 314 SDL_MintAudio_mutex = 0;
414 315
415 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", 316 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n",
416 SDL_MintAudio_audiobuf[0])); 317 SDL_MintAudio_audiobuf[0]));
417 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", 318 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n",
418 SDL_MintAudio_audiobuf[1])); 319 SDL_MintAudio_audiobuf[1]));
419 320
420 SDL_MintAudio_CheckFpu(); 321 SDL_MintAudio_CheckFpu();
421 322
422 /* Setup audio hardware */ 323 /* Setup audio hardware */
423 Mint_InitAudio(this, spec); 324 MINTMCSN_InitAudio(this);
424 325
425 return (1); /* We don't use SDL threaded audio */ 326 return 1; /* good to go. */
426 } 327 }
328
329 static int
330 MINTMCSN_Init(SDL_AudioDriverImpl *impl)
331 {
332 unsigned long dummy = 0;
333
334 SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND);
335
336 /* We can't use XBIOS in interrupt with Magic, don't know about thread */
337 if (Getcookie(C_MagX, &dummy) == C_FOUND) {
338 return 0;
339 }
340
341 /* Cookie _MCH present ? if not, assume ST machine */
342 if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
343 cookie_mch = MCH_ST;
344 }
345
346 /* Cookie _SND present ? if not, assume ST machine */
347 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
348 cookie_snd = SND_PSG;
349 }
350
351 /* Check if we have 16 bits audio */
352 if ((cookie_snd & SND_16BIT) == 0) {
353 SDL_SetError(DEBUG_NAME "no 16-bit sound");
354 return 0;
355 }
356
357 /* Cookie MCSN present ? */
358 if (Getcookie(C_McSn, (long *) &cookie_mcsn) != C_FOUND) {
359 SDL_SetError(DEBUG_NAME "no MCSN audio");
360 return 0;
361 }
362
363 /* Check if interrupt at end of replay */
364 if (cookie_mcsn->pint == 0) {
365 SDL_SetError(DEBUG_NAME "no interrupt at end of replay");
366 return 0;
367 }
368
369 /* Check if audio is lockable */
370 if (Locksnd() != 1) {
371 SDL_SetError(DEBUG_NAME "audio locked by other application");
372 return 0;
373 }
374
375 Unlocksnd();
376
377 DEBUG_PRINT((DEBUG_NAME "MCSN audio available!\n"));
378
379 /* Set the function pointers */
380 impl->OpenDevice = MINTMCSN_OpenDevice;
381 impl->CloseDevice = MINTMCSN_CloseDevice;
382 impl->LockAudio = MINTMCSN_LockAudio;
383 impl->UnlockAudio = MINTMCSN_UnlockAudio;
384 impl->OnlyHasDefaultOutputDevice = 1;
385 impl->ProvidesOwnCallbackThread = 1;
386 impl->SkipMixerLock = 1;
387
388 return 1;
389 }
390
391 AudioBootStrap MINTAUDIO_MCSN_bootstrap = {
392 MINT_AUDIO_DRIVER_NAME, "MiNT MCSN audio driver", MINTMCSN_Init, 0
393 };
427 394
428 /* vi: set ts=4 sw=4 expandtab: */ 395 /* vi: set ts=4 sw=4 expandtab: */