comparison src/audio/mint/SDL_mintaudio_xbios.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
58 } 58 }
59 #else 59 #else
60 #define DEBUG_PRINT(what) 60 #define DEBUG_PRINT(what)
61 #endif 61 #endif
62 62
63 /*--- Static variables ---*/ 63 static unsigned long cookie_snd = 0;
64 64
65 static unsigned long cookie_snd; 65 static void
66 66 MINTXBIOS_LockDevice(_THIS)
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 SDL_MintAudio_mint_present = SDL_FALSE;
88
89 /* We can't use XBIOS in interrupt with Magic, don't know about thread */
90 if (Getcookie(C_MagX, &dummy) == C_FOUND) {
91 return (0);
92 }
93
94 /* Check if user asked a different audio driver */
95 if ((envr) && (SDL_strcmp(envr, MINT_AUDIO_DRIVER_NAME) != 0)) {
96 DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
97 return (0);
98 }
99
100 /* Cookie _SND present ? if not, assume ST machine */
101 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
102 cookie_snd = SND_PSG;
103 }
104
105 /* Check if we have 16 bits audio */
106 if ((cookie_snd & SND_16BIT) == 0) {
107 DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
108 return (0);
109 }
110
111 /* Check if audio is lockable */
112 if (Locksnd() != 1) {
113 DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
114 return (0);
115 }
116
117 Unlocksnd();
118
119 DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n"));
120 return (1);
121 }
122
123 static void
124 Audio_DeleteDevice(SDL_AudioDevice * device)
125 {
126 SDL_free(device->hidden);
127 SDL_free(device);
128 }
129
130 static SDL_AudioDevice *
131 Audio_CreateDevice(int devindex)
132 {
133 SDL_AudioDevice *this;
134
135 /* Initialize all variables that we clean on shutdown */
136 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
137 if (this) {
138 SDL_memset(this, 0, (sizeof *this));
139 this->hidden = (struct SDL_PrivateAudioData *)
140 SDL_malloc((sizeof *this->hidden));
141 }
142 if ((this == NULL) || (this->hidden == NULL)) {
143 SDL_OutOfMemory();
144 if (this) {
145 SDL_free(this);
146 }
147 return (0);
148 }
149 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
150
151 /* Set the function pointers */
152 this->OpenAudio = Mint_OpenAudio;
153 this->CloseAudio = Mint_CloseAudio;
154 this->LockAudio = Mint_LockAudio;
155 this->UnlockAudio = Mint_UnlockAudio;
156 this->free = Audio_DeleteDevice;
157
158 return this;
159 }
160
161 AudioBootStrap MINTAUDIO_XBIOS_bootstrap = {
162 MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver",
163 Audio_Available, Audio_CreateDevice
164 };
165
166 static void
167 Mint_LockAudio(_THIS)
168 { 67 {
169 /* Stop replay */ 68 /* Stop replay */
170 Buffoper(0); 69 Buffoper(0);
171 } 70 }
172 71
173 static void 72 static void
174 Mint_UnlockAudio(_THIS) 73 MINTXBIOS_UnlockDevice(_THIS)
175 { 74 {
176 /* Restart replay */ 75 /* Restart replay */
177 Buffoper(SB_PLA_ENA | SB_PLA_RPT); 76 Buffoper(SB_PLA_ENA | SB_PLA_RPT);
178 } 77 }
179 78
180 static void 79 static void
181 Mint_CloseAudio(_THIS) 80 MINTXBIOS_CloseDevice(_THIS)
182 { 81 {
183 /* Stop replay */ 82 if (this->hidden != NULL) {
184 SDL_MintAudio_WaitThread(); 83 /* Stop replay */
185 Buffoper(0); 84 SDL_MintAudio_WaitThread();
186 85 Buffoper(0);
187 if (!SDL_MintAudio_mint_present) { 86
188 /* Uninstall interrupt */ 87 if (!SDL_MintAudio_mint_present) {
189 Jdisint(MFP_DMASOUND); 88 /* Uninstall interrupt */
190 } 89 Jdisint(MFP_DMASOUND);
191 90 }
192 /* Wait if currently playing sound */ 91
193 while (SDL_MintAudio_mutex != 0) { 92 /* Wait if currently playing sound */
194 } 93 while (SDL_MintAudio_mutex != 0) {}
195 94
196 /* Clear buffers */ 95 /* Clear buffers */
197 if (SDL_MintAudio_audiobuf[0]) { 96 if (SDL_MintAudio_audiobuf[0]) {
198 Mfree(SDL_MintAudio_audiobuf[0]); 97 Mfree(SDL_MintAudio_audiobuf[0]);
199 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL; 98 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
200 } 99 }
201 100
202 /* Unlock sound system */ 101 /* Unlock sound system */
203 Unlocksnd(); 102 Unlocksnd();
103
104 SDL_free(this->hidden);
105 this->hidden = NULL;
106 }
204 } 107 }
205 108
206 /* Falcon XBIOS implementation of Devconnect() is buggy with external clock */ 109 /* Falcon XBIOS implementation of Devconnect() is buggy with external clock */
207 static void 110 static void
208 Devconnect2(int src, int dst, int sclk, int pre) 111 Devconnect2(int src, int dst, int sclk, int pre)
267 170
268 Super(oldstack); 171 Super(oldstack);
269 } 172 }
270 173
271 static void 174 static void
272 Mint_CheckExternalClock(_THIS) 175 MINTXBIOS_CheckExternalClock(_THIS)
273 { 176 {
274 #define SIZE_BUF_CLOCK_MEASURE (44100/10) 177 #define SIZE_BUF_CLOCK_MEASURE (44100/10)
275 178
276 unsigned long cookie_snd; 179 unsigned long cookie_snd;
277 char *buffer; 180 char *buffer;
353 256
354 Mfree(buffer); 257 Mfree(buffer);
355 } 258 }
356 259
357 static int 260 static int
358 Mint_CheckAudio(_THIS, SDL_AudioSpec * spec) 261 MINTXBIOS_CheckAudio(_THIS)
359 { 262 {
360 int i; 263 int i;
361 Uint32 extclock; 264 Uint32 extclock;
362 265
363 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ", 266 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",
364 SDL_AUDIO_BITSIZE(spec->format))); 267 SDL_AUDIO_BITSIZE(this->spec.format)));
365 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); 268 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
366 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); 269 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
367 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); 270 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
368 DEBUG_PRINT(("channels=%d, ", spec->channels)); 271 DEBUG_PRINT(("channels=%d, ", this->spec.channels));
369 DEBUG_PRINT(("freq=%d\n", spec->freq)); 272 DEBUG_PRINT(("freq=%d\n", this->spec.freq));
370 273
371 spec->format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */ 274 this->spec.format |= SDL_AUDIO_MASK_SIGNED; /* Audio is always signed */
372 275
373 /* clamp out int32/float32 */ 276 /* clamp out int32/float32 */
374 if (SDL_AUDIO_BITSIZE(spec->format) >= 16) { 277 if (SDL_AUDIO_BITSIZE(this->spec.format) >= 16) {
375 spec->format = AUDIO_S16MSB; /* Audio is always big endian */ 278 this->spec.format = AUDIO_S16MSB; /* Audio is always big endian */
376 spec->channels = 2; /* 16 bits always stereo */ 279 this->spec.channels = 2; /* 16 bits always stereo */
377 } else if (spec->channels > 2) { 280 } else if (this->spec.channels > 2) {
378 spec->channels = 2; /* no more than stereo! */ 281 this->spec.channels = 2; /* no more than stereo! */
379 } 282 }
380 283
381 MINTAUDIO_freqcount = 0; 284 MINTAUDIO_freqcount = 0;
382 285
383 /* Add external clocks if present */ 286 /* Add external clocks if present */
384 Mint_CheckExternalClock(this); 287 MINTXBIOS_CheckExternalClock(this);
385 288
386 /* Standard clocks */ 289 /* Standard clocks */
387 for (i = 1; i < 12; i++) { 290 for (i = 1; i < 12; i++) {
388 /* Remove unusable Falcon codec predivisors */ 291 /* Remove unusable Falcon codec predivisors */
389 if ((i == 6) || (i == 8) || (i == 10)) { 292 if ((i == 6) || (i == 8) || (i == 10)) {
402 MINTAUDIO_frequencies[i].masterclock, 305 MINTAUDIO_frequencies[i].masterclock,
403 MINTAUDIO_frequencies[i].predivisor)); 306 MINTAUDIO_frequencies[i].predivisor));
404 } 307 }
405 #endif 308 #endif
406 309
407 MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, spec->freq); 310 MINTAUDIO_numfreq = SDL_MintAudio_SearchFrequency(this, this->spec.freq);
408 spec->freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency; 311 this->spec.freq = MINTAUDIO_frequencies[MINTAUDIO_numfreq].frequency;
409 312
410 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ", 313 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",
411 SDL_AUDIO_BITSIZE(spec->format))); 314 SDL_AUDIO_BITSIZE(this->spec.format)));
412 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(spec->format))); 315 DEBUG_PRINT(("float=%d, ", SDL_AUDIO_ISFLOAT(this->spec.format)));
413 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(spec->format))); 316 DEBUG_PRINT(("signed=%d, ", SDL_AUDIO_ISSIGNED(this->spec.format)));
414 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(spec->format))); 317 DEBUG_PRINT(("big endian=%d, ", SDL_AUDIO_ISBIGENDIAN(this->spec.format)));
415 DEBUG_PRINT(("channels=%d, ", spec->channels)); 318 DEBUG_PRINT(("channels=%d, ", this->spec.channels));
416 DEBUG_PRINT(("freq=%d\n", spec->freq)); 319 DEBUG_PRINT(("freq=%d\n", this->spec.freq));
417 320
418 return 0; 321 return 0;
419 } 322 }
420 323
421 static void 324 static void
422 Mint_InitAudio(_THIS, SDL_AudioSpec * spec) 325 MINTXBIOS_InitAudio(_THIS)
423 { 326 {
424 int channels_mode, dmaclock, prediv; 327 int channels_mode, dmaclock, prediv;
425 void *buffer; 328 void *buffer;
426 329
427 /* Stop currently playing sound */ 330 /* Stop currently playing sound */
434 Settracks(0, 0); 337 Settracks(0, 0);
435 Setmontracks(0); 338 Setmontracks(0);
436 339
437 /* Select replay format */ 340 /* Select replay format */
438 channels_mode = STEREO16; 341 channels_mode = STEREO16;
439 switch (SDL_AUDIO_BITSIZE(spec->format)) { 342 switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
440 case 8: 343 case 8:
441 if (spec->channels == 2) { 344 if (this->spec.channels == 2) {
442 channels_mode = STEREO8; 345 channels_mode = STEREO8;
443 } else { 346 } else {
444 channels_mode = MONO8; 347 channels_mode = MONO8;
445 } 348 }
446 break; 349 break;
459 Devconnect2(DMAPLAY, DAC, CLK25M, prediv); 362 Devconnect2(DMAPLAY, DAC, CLK25M, prediv);
460 } 363 }
461 364
462 /* Set buffer */ 365 /* Set buffer */
463 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf]; 366 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
464 if (Setbuffer(0, buffer, buffer + spec->size) < 0) { 367 if (Setbuffer(0, buffer, buffer + this->spec.size) < 0) {
465 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n")); 368 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
466 } 369 }
467 370
468 if (SDL_MintAudio_mint_present) { 371 if (SDL_MintAudio_mint_present) {
469 SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0); 372 SDL_MintAudio_thread_pid = tfork(SDL_MintAudio_Thread, 0);
483 Buffoper(SB_PLA_ENA | SB_PLA_RPT); 386 Buffoper(SB_PLA_ENA | SB_PLA_RPT);
484 DEBUG_PRINT((DEBUG_NAME "hardware initialized\n")); 387 DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
485 } 388 }
486 389
487 static int 390 static int
488 Mint_OpenAudio(_THIS, SDL_AudioSpec * spec) 391 MINTXBIOS_OpenDevice(_THIS, const char *devname, int iscapture)
489 { 392 {
490 /* Lock sound system */ 393 /* Lock sound system */
491 if (Locksnd() != 1) { 394 if (Locksnd() != 1) {
492 SDL_SetError("Mint_OpenAudio: Audio system already in use"); 395 SDL_SetError("MINTXBIOS_OpenAudio: Audio system already in use");
493 return (-1); 396 return 0;
494 } 397 }
495 398
496 SDL_MintAudio_device = this; 399 SDL_MintAudio_device = this;
497 400
498 /* Check audio capabilities */ 401 /* Check audio capabilities */
499 if (Mint_CheckAudio(this, spec) == -1) { 402 if (MINTXBIOS_CheckAudio(this) == -1) {
500 return -1; 403 return 0;
501 } 404 }
502 405
503 SDL_CalculateAudioSpec(spec); 406 /* Initialize all variables that we clean on shutdown */
407 this->hidden = (struct SDL_PrivateAudioData *)
408 SDL_malloc((sizeof *this->hidden));
409 if (this->hidden == NULL) {
410 SDL_OutOfMemory();
411 return 0;
412 }
413 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
414
415 SDL_CalculateAudioSpec(&this->spec);
504 416
505 /* Allocate memory for audio buffers in DMA-able RAM */ 417 /* Allocate memory for audio buffers in DMA-able RAM */
506 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size)); 418 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", this->spec.size));
507 419
508 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size * 2, MX_STRAM); 420 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(this->spec.size * 2, MX_STRAM);
509 if (SDL_MintAudio_audiobuf[0] == NULL) { 421 if (SDL_MintAudio_audiobuf[0] == NULL) {
510 SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer"); 422 SDL_free(this->hidden);
511 return (-1); 423 this->hidden = NULL;
512 } 424 SDL_OutOfMemory();
513 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size; 425 return 0;
426 }
427 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + this->spec.size;
514 SDL_MintAudio_numbuf = 0; 428 SDL_MintAudio_numbuf = 0;
515 SDL_memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size * 2); 429 SDL_memset(SDL_MintAudio_audiobuf[0],this->spec.silence,this->spec.size*2);
516 SDL_MintAudio_audiosize = spec->size; 430 SDL_MintAudio_audiosize = this->spec.size;
517 SDL_MintAudio_mutex = 0; 431 SDL_MintAudio_mutex = 0;
518 432
519 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", 433 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n",
520 SDL_MintAudio_audiobuf[0])); 434 SDL_MintAudio_audiobuf[0]));
521 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", 435 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n",
522 SDL_MintAudio_audiobuf[1])); 436 SDL_MintAudio_audiobuf[1]));
523 437
524 SDL_MintAudio_CheckFpu(); 438 SDL_MintAudio_CheckFpu();
525 439
526 /* Setup audio hardware */ 440 /* Setup audio hardware */
527 Mint_InitAudio(this, spec); 441 MINTXBIOS_InitAudio(this);
528 442
529 return (1); /* We don't use SDL threaded audio */ 443 return 1; /* good to go. */
530 } 444 }
445
446 static int
447 MINTXBIOS_Init(SDL_AudioDriverImpl *impl)
448 {
449 unsigned long dummy = 0;
450 /*SDL_MintAudio_mint_present = (Getcookie(C_MiNT, &dummy) == C_FOUND); */
451 SDL_MintAudio_mint_present = SDL_FALSE;
452
453 /* We can't use XBIOS in interrupt with Magic, don't know about thread */
454 if (Getcookie(C_MagX, &dummy) == C_FOUND) {
455 return (0);
456 }
457
458 /* Cookie _SND present ? if not, assume ST machine */
459 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
460 cookie_snd = SND_PSG;
461 }
462
463 /* Check if we have 16 bits audio */
464 if ((cookie_snd & SND_16BIT) == 0) {
465 SDL_SetError(DEBUG_NAME "no 16-bit sound");
466 return (0);
467 }
468
469 /* Check if audio is lockable */
470 if (Locksnd() != 1) {
471 SDL_SetError(DEBUG_NAME "audio locked by other application");
472 return (0);
473 }
474
475 Unlocksnd();
476
477 DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n"));
478
479 /* Set the function pointers */
480 impl->OpenDevice = MINTXBIOS_OpenDevice;
481 impl->CloseDevice = MINTXBIOS_CloseDevice;
482 impl->LockAudio = MINTXBIOS_LockAudio;
483 impl->UnlockAudio = MINTXBIOS_UnlockAudio;
484 impl->OnlyHasDefaultOutputDevice = 1;
485 impl->ProvidesOwnCallbackThread = 1;
486 impl->SkipMixerLock = 1;
487
488 return 1;
489 }
490
491 AudioBootStrap MINTAUDIO_XBIOS_bootstrap = {
492 MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver", MINTXBIOS_Init, 0
493 };
531 494
532 /* vi: set ts=4 sw=4 expandtab: */ 495 /* vi: set ts=4 sw=4 expandtab: */