• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8 
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12 
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22 
23 /* Allow access to a raw mixing buffer */
24 
25 #include "SDL.h"
26 #include "SDL_audio.h"
27 #include "SDL_audio_c.h"
28 #include "SDL_sysaudio.h"
29 #include "../thread/SDL_systhread.h"
30 
31 #define _THIS SDL_AudioDevice *_this
32 
33 static SDL_AudioDriver current_audio;
34 static SDL_AudioDevice *open_devices[16];
35 
36 /*
37  * Not all of these will be compiled and linked in, but it's convenient
38  *  to have a complete list here and saves yet-another block of #ifdefs...
39  *  Please see bootstrap[], below, for the actual #ifdef mess.
40  */
41 extern AudioBootStrap PULSEAUDIO_bootstrap;
42 extern AudioBootStrap ALSA_bootstrap;
43 extern AudioBootStrap SNDIO_bootstrap;
44 extern AudioBootStrap BSD_AUDIO_bootstrap;
45 extern AudioBootStrap DSP_bootstrap;
46 extern AudioBootStrap QSAAUDIO_bootstrap;
47 extern AudioBootStrap SUNAUDIO_bootstrap;
48 extern AudioBootStrap ARTS_bootstrap;
49 extern AudioBootStrap ESD_bootstrap;
50 extern AudioBootStrap NACLAUDIO_bootstrap;
51 extern AudioBootStrap NAS_bootstrap;
52 extern AudioBootStrap XAUDIO2_bootstrap;
53 extern AudioBootStrap DSOUND_bootstrap;
54 extern AudioBootStrap WINMM_bootstrap;
55 extern AudioBootStrap PAUDIO_bootstrap;
56 extern AudioBootStrap HAIKUAUDIO_bootstrap;
57 extern AudioBootStrap COREAUDIO_bootstrap;
58 extern AudioBootStrap DISKAUDIO_bootstrap;
59 extern AudioBootStrap DUMMYAUDIO_bootstrap;
60 extern AudioBootStrap FUSIONSOUND_bootstrap;
61 extern AudioBootStrap ANDROIDAUDIO_bootstrap;
62 extern AudioBootStrap PSPAUDIO_bootstrap;
63 extern AudioBootStrap SNDIO_bootstrap;
64 extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
65 
66 /* Available audio drivers */
67 static const AudioBootStrap *const bootstrap[] = {
68 #if SDL_AUDIO_DRIVER_PULSEAUDIO
69     &PULSEAUDIO_bootstrap,
70 #endif
71 #if SDL_AUDIO_DRIVER_ALSA
72     &ALSA_bootstrap,
73 #endif
74 #if SDL_AUDIO_DRIVER_SNDIO
75     &SNDIO_bootstrap,
76 #endif
77 #if SDL_AUDIO_DRIVER_BSD
78     &BSD_AUDIO_bootstrap,
79 #endif
80 #if SDL_AUDIO_DRIVER_OSS
81     &DSP_bootstrap,
82 #endif
83 #if SDL_AUDIO_DRIVER_QSA
84     &QSAAUDIO_bootstrap,
85 #endif
86 #if SDL_AUDIO_DRIVER_SUNAUDIO
87     &SUNAUDIO_bootstrap,
88 #endif
89 #if SDL_AUDIO_DRIVER_ARTS
90     &ARTS_bootstrap,
91 #endif
92 #if SDL_AUDIO_DRIVER_ESD
93     &ESD_bootstrap,
94 #endif
95 #if SDL_AUDIO_DRIVER_NACL
96     &NACLAUDIO_bootstrap,
97 #endif
98 #if SDL_AUDIO_DRIVER_NAS
99     &NAS_bootstrap,
100 #endif
101 #if SDL_AUDIO_DRIVER_XAUDIO2
102     &XAUDIO2_bootstrap,
103 #endif
104 #if SDL_AUDIO_DRIVER_DSOUND
105     &DSOUND_bootstrap,
106 #endif
107 #if SDL_AUDIO_DRIVER_WINMM
108     &WINMM_bootstrap,
109 #endif
110 #if SDL_AUDIO_DRIVER_PAUDIO
111     &PAUDIO_bootstrap,
112 #endif
113 #if SDL_AUDIO_DRIVER_HAIKU
114     &HAIKUAUDIO_bootstrap,
115 #endif
116 #if SDL_AUDIO_DRIVER_COREAUDIO
117     &COREAUDIO_bootstrap,
118 #endif
119 #if SDL_AUDIO_DRIVER_DISK
120     &DISKAUDIO_bootstrap,
121 #endif
122 #if SDL_AUDIO_DRIVER_DUMMY
123     &DUMMYAUDIO_bootstrap,
124 #endif
125 #if SDL_AUDIO_DRIVER_FUSIONSOUND
126     &FUSIONSOUND_bootstrap,
127 #endif
128 #if SDL_AUDIO_DRIVER_ANDROID
129     &ANDROIDAUDIO_bootstrap,
130 #endif
131 #if SDL_AUDIO_DRIVER_PSP
132     &PSPAUDIO_bootstrap,
133 #endif
134 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
135     &EMSCRIPTENAUDIO_bootstrap,
136 #endif
137     NULL
138 };
139 
140 static SDL_AudioDevice *
get_audio_device(SDL_AudioDeviceID id)141 get_audio_device(SDL_AudioDeviceID id)
142 {
143     id--;
144     if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
145         SDL_SetError("Invalid audio device ID");
146         return NULL;
147     }
148 
149     return open_devices[id];
150 }
151 
152 
153 /* stubs for audio drivers that don't need a specific entry point... */
154 static void
SDL_AudioDetectDevices_Default(void)155 SDL_AudioDetectDevices_Default(void)
156 {
157     /* you have to write your own implementation if these assertions fail. */
158     SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
159     SDL_assert(current_audio.impl.OnlyHasDefaultCaptureDevice || !current_audio.impl.HasCaptureSupport);
160 
161     SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
162     if (current_audio.impl.HasCaptureSupport) {
163         SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
164     }
165 }
166 
167 static void
SDL_AudioThreadInit_Default(_THIS)168 SDL_AudioThreadInit_Default(_THIS)
169 {                               /* no-op. */
170 }
171 
172 static void
SDL_AudioWaitDevice_Default(_THIS)173 SDL_AudioWaitDevice_Default(_THIS)
174 {                               /* no-op. */
175 }
176 
177 static void
SDL_AudioPlayDevice_Default(_THIS)178 SDL_AudioPlayDevice_Default(_THIS)
179 {                               /* no-op. */
180 }
181 
182 static int
SDL_AudioGetPendingBytes_Default(_THIS)183 SDL_AudioGetPendingBytes_Default(_THIS)
184 {
185     return 0;
186 }
187 
188 static Uint8 *
SDL_AudioGetDeviceBuf_Default(_THIS)189 SDL_AudioGetDeviceBuf_Default(_THIS)
190 {
191     return NULL;
192 }
193 
194 static int
SDL_AudioCaptureFromDevice_Default(_THIS,void * buffer,int buflen)195 SDL_AudioCaptureFromDevice_Default(_THIS, void *buffer, int buflen)
196 {
197     return -1;  /* just fail immediately. */
198 }
199 
200 static void
SDL_AudioFlushCapture_Default(_THIS)201 SDL_AudioFlushCapture_Default(_THIS)
202 {                               /* no-op. */
203 }
204 
205 static void
SDL_AudioPrepareToClose_Default(_THIS)206 SDL_AudioPrepareToClose_Default(_THIS)
207 {                               /* no-op. */
208 }
209 
210 static void
SDL_AudioCloseDevice_Default(_THIS)211 SDL_AudioCloseDevice_Default(_THIS)
212 {                               /* no-op. */
213 }
214 
215 static void
SDL_AudioDeinitialize_Default(void)216 SDL_AudioDeinitialize_Default(void)
217 {                               /* no-op. */
218 }
219 
220 static void
SDL_AudioFreeDeviceHandle_Default(void * handle)221 SDL_AudioFreeDeviceHandle_Default(void *handle)
222 {                               /* no-op. */
223 }
224 
225 
226 static int
SDL_AudioOpenDevice_Default(_THIS,void * handle,const char * devname,int iscapture)227 SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
228 {
229     return SDL_Unsupported();
230 }
231 
232 static SDL_INLINE SDL_bool
is_in_audio_device_thread(SDL_AudioDevice * device)233 is_in_audio_device_thread(SDL_AudioDevice * device)
234 {
235     /* The device thread locks the same mutex, but not through the public API.
236        This check is in case the application, in the audio callback,
237        tries to lock the thread that we've already locked from the
238        device thread...just in case we only have non-recursive mutexes. */
239     if (device->thread && (SDL_ThreadID() == device->threadid)) {
240         return SDL_TRUE;
241     }
242 
243     return SDL_FALSE;
244 }
245 
246 static void
SDL_AudioLockDevice_Default(SDL_AudioDevice * device)247 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
248 {
249     if (!is_in_audio_device_thread(device)) {
250         SDL_LockMutex(device->mixer_lock);
251     }
252 }
253 
254 static void
SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)255 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
256 {
257     if (!is_in_audio_device_thread(device)) {
258         SDL_UnlockMutex(device->mixer_lock);
259     }
260 }
261 
262 static void
SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice * device)263 SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice * device)
264 {
265 }
266 
267 static void
finish_audio_entry_points_init(void)268 finish_audio_entry_points_init(void)
269 {
270     /*
271      * Fill in stub functions for unused driver entry points. This lets us
272      *  blindly call them without having to check for validity first.
273      */
274 
275     if (current_audio.impl.SkipMixerLock) {
276         if (current_audio.impl.LockDevice == NULL) {
277             current_audio.impl.LockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
278         }
279         if (current_audio.impl.UnlockDevice == NULL) {
280             current_audio.impl.UnlockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
281         }
282     }
283 
284 #define FILL_STUB(x) \
285         if (current_audio.impl.x == NULL) { \
286             current_audio.impl.x = SDL_Audio##x##_Default; \
287         }
288     FILL_STUB(DetectDevices);
289     FILL_STUB(OpenDevice);
290     FILL_STUB(ThreadInit);
291     FILL_STUB(WaitDevice);
292     FILL_STUB(PlayDevice);
293     FILL_STUB(GetPendingBytes);
294     FILL_STUB(GetDeviceBuf);
295     FILL_STUB(CaptureFromDevice);
296     FILL_STUB(FlushCapture);
297     FILL_STUB(PrepareToClose);
298     FILL_STUB(CloseDevice);
299     FILL_STUB(LockDevice);
300     FILL_STUB(UnlockDevice);
301     FILL_STUB(FreeDeviceHandle);
302     FILL_STUB(Deinitialize);
303 #undef FILL_STUB
304 }
305 
306 
307 /* device hotplug support... */
308 
309 static int
add_audio_device(const char * name,void * handle,SDL_AudioDeviceItem ** devices,int * devCount)310 add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
311 {
312     int retval = -1;
313     const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
314     SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
315     if (item == NULL) {
316         return -1;
317     }
318 
319     SDL_assert(handle != NULL);  /* we reserve NULL, audio backends can't use it. */
320 
321     item->handle = handle;
322     SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
323 
324     SDL_LockMutex(current_audio.detectionLock);
325     item->next = *devices;
326     *devices = item;
327     retval = (*devCount)++;
328     SDL_UnlockMutex(current_audio.detectionLock);
329 
330     return retval;
331 }
332 
333 static SDL_INLINE int
add_capture_device(const char * name,void * handle)334 add_capture_device(const char *name, void *handle)
335 {
336     SDL_assert(current_audio.impl.HasCaptureSupport);
337     return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
338 }
339 
340 static SDL_INLINE int
add_output_device(const char * name,void * handle)341 add_output_device(const char *name, void *handle)
342 {
343     return add_audio_device(name, handle, &current_audio.outputDevices, &current_audio.outputDeviceCount);
344 }
345 
346 static void
free_device_list(SDL_AudioDeviceItem ** devices,int * devCount)347 free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
348 {
349     SDL_AudioDeviceItem *item, *next;
350     for (item = *devices; item != NULL; item = next) {
351         next = item->next;
352         if (item->handle != NULL) {
353             current_audio.impl.FreeDeviceHandle(item->handle);
354         }
355         SDL_free(item);
356     }
357     *devices = NULL;
358     *devCount = 0;
359 }
360 
361 
362 /* The audio backends call this when a new device is plugged in. */
363 void
SDL_AddAudioDevice(const int iscapture,const char * name,void * handle)364 SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
365 {
366     const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
367     if (device_index != -1) {
368         /* Post the event, if desired */
369         if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
370             SDL_Event event;
371             SDL_zero(event);
372             event.adevice.type = SDL_AUDIODEVICEADDED;
373             event.adevice.which = device_index;
374             event.adevice.iscapture = iscapture;
375             SDL_PushEvent(&event);
376         }
377     }
378 }
379 
380 /* The audio backends call this when a currently-opened device is lost. */
SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice * device)381 void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
382 {
383     SDL_assert(get_audio_device(device->id) == device);
384 
385     if (!SDL_AtomicGet(&device->enabled)) {
386         return;
387     }
388 
389     /* Ends the audio callback and mark the device as STOPPED, but the
390        app still needs to close the device to free resources. */
391     current_audio.impl.LockDevice(device);
392     SDL_AtomicSet(&device->enabled, 0);
393     current_audio.impl.UnlockDevice(device);
394 
395     /* Post the event, if desired */
396     if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
397         SDL_Event event;
398         SDL_zero(event);
399         event.adevice.type = SDL_AUDIODEVICEREMOVED;
400         event.adevice.which = device->id;
401         event.adevice.iscapture = device->iscapture ? 1 : 0;
402         SDL_PushEvent(&event);
403     }
404 }
405 
406 static void
mark_device_removed(void * handle,SDL_AudioDeviceItem * devices,SDL_bool * removedFlag)407 mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
408 {
409     SDL_AudioDeviceItem *item;
410     SDL_assert(handle != NULL);
411     for (item = devices; item != NULL; item = item->next) {
412         if (item->handle == handle) {
413             item->handle = NULL;
414             *removedFlag = SDL_TRUE;
415             return;
416         }
417     }
418 }
419 
420 /* The audio backends call this when a device is removed from the system. */
421 void
SDL_RemoveAudioDevice(const int iscapture,void * handle)422 SDL_RemoveAudioDevice(const int iscapture, void *handle)
423 {
424     int device_index;
425     SDL_AudioDevice *device = NULL;
426 
427     SDL_LockMutex(current_audio.detectionLock);
428     if (iscapture) {
429         mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
430     } else {
431         mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
432     }
433     for (device_index = 0; device_index < SDL_arraysize(open_devices); device_index++)
434     {
435         device = open_devices[device_index];
436         if (device != NULL && device->handle == handle)
437         {
438             SDL_OpenedAudioDeviceDisconnected(device);
439             break;
440         }
441     }
442     SDL_UnlockMutex(current_audio.detectionLock);
443 
444     current_audio.impl.FreeDeviceHandle(handle);
445 }
446 
447 
448 
449 /* buffer queueing support... */
450 
451 /* this expects that you managed thread safety elsewhere. */
452 static void
free_audio_queue(SDL_AudioBufferQueue * packet)453 free_audio_queue(SDL_AudioBufferQueue *packet)
454 {
455     while (packet) {
456         SDL_AudioBufferQueue *next = packet->next;
457         SDL_free(packet);
458         packet = next;
459     }
460 }
461 
462 /* NOTE: This assumes you'll hold the mixer lock before calling! */
463 static int
queue_audio_to_device(SDL_AudioDevice * device,const Uint8 * data,Uint32 len)464 queue_audio_to_device(SDL_AudioDevice *device, const Uint8 *data, Uint32 len)
465 {
466     SDL_AudioBufferQueue *orighead;
467     SDL_AudioBufferQueue *origtail;
468     Uint32 origlen;
469     Uint32 datalen;
470 
471     orighead = device->buffer_queue_head;
472     origtail = device->buffer_queue_tail;
473     origlen = origtail ? origtail->datalen : 0;
474 
475     while (len > 0) {
476         SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
477         SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
478         if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
479             /* tail packet missing or completely full; we need a new packet. */
480             packet = device->buffer_queue_pool;
481             if (packet != NULL) {
482                 /* we have one available in the pool. */
483                 device->buffer_queue_pool = packet->next;
484             } else {
485                 /* Have to allocate a new one! */
486                 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
487                 if (packet == NULL) {
488                     /* uhoh, reset so we've queued nothing new, free what we can. */
489                     if (!origtail) {
490                         packet = device->buffer_queue_head;  /* whole queue. */
491                     } else {
492                         packet = origtail->next;  /* what we added to existing queue. */
493                         origtail->next = NULL;
494                         origtail->datalen = origlen;
495                     }
496                     device->buffer_queue_head = orighead;
497                     device->buffer_queue_tail = origtail;
498                     device->buffer_queue_pool = NULL;
499 
500                     free_audio_queue(packet);  /* give back what we can. */
501 
502                     return SDL_OutOfMemory();
503                 }
504             }
505             packet->datalen = 0;
506             packet->startpos = 0;
507             packet->next = NULL;
508 
509             SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
510             if (device->buffer_queue_tail == NULL) {
511                 device->buffer_queue_head = packet;
512             } else {
513                 device->buffer_queue_tail->next = packet;
514             }
515             device->buffer_queue_tail = packet;
516         }
517 
518         datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
519         SDL_memcpy(packet->data + packet->datalen, data, datalen);
520         data += datalen;
521         len -= datalen;
522         packet->datalen += datalen;
523         device->queued_bytes += datalen;
524     }
525 
526     return 0;
527 }
528 
529 /* NOTE: This assumes you'll hold the mixer lock before calling! */
530 static Uint32
dequeue_audio_from_device(SDL_AudioDevice * device,Uint8 * stream,Uint32 len)531 dequeue_audio_from_device(SDL_AudioDevice *device, Uint8 *stream, Uint32 len)
532 {
533     SDL_AudioBufferQueue *packet;
534     Uint8 *ptr = stream;
535 
536     while ((len > 0) && ((packet = device->buffer_queue_head) != NULL)) {
537         const Uint32 avail = packet->datalen - packet->startpos;
538         const Uint32 cpy = SDL_min(len, avail);
539         SDL_assert(device->queued_bytes >= avail);
540 
541         SDL_memcpy(ptr, packet->data + packet->startpos, cpy);
542         packet->startpos += cpy;
543         ptr += cpy;
544         device->queued_bytes -= cpy;
545         len -= cpy;
546 
547         if (packet->startpos == packet->datalen) {  /* packet is done, put it in the pool. */
548             device->buffer_queue_head = packet->next;
549             SDL_assert((packet->next != NULL) || (packet == device->buffer_queue_tail));
550             packet->next = device->buffer_queue_pool;
551             device->buffer_queue_pool = packet;
552         }
553     }
554 
555     SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
556 
557     if (device->buffer_queue_head == NULL) {
558         device->buffer_queue_tail = NULL;  /* in case we drained the queue entirely. */
559     }
560 
561     return (Uint32) (ptr - stream);
562 }
563 
564 static void SDLCALL
SDL_BufferQueueDrainCallback(void * userdata,Uint8 * stream,int len)565 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int len)
566 {
567     /* this function always holds the mixer lock before being called. */
568     SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
569     Uint32 written;
570 
571     SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
572     SDL_assert(!device->iscapture);  /* this shouldn't ever happen, right?! */
573     SDL_assert(len >= 0);  /* this shouldn't ever happen, right?! */
574 
575     written = dequeue_audio_from_device(device, stream, (Uint32) len);
576     stream += written;
577     len -= (int) written;
578 
579     if (len > 0) {  /* fill any remaining space in the stream with silence. */
580         SDL_assert(device->buffer_queue_head == NULL);
581         SDL_memset(stream, device->spec.silence, len);
582     }
583 }
584 
585 static void SDLCALL
SDL_BufferQueueFillCallback(void * userdata,Uint8 * stream,int len)586 SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
587 {
588     /* this function always holds the mixer lock before being called. */
589     SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
590 
591     SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
592     SDL_assert(device->iscapture);  /* this shouldn't ever happen, right?! */
593     SDL_assert(len >= 0);  /* this shouldn't ever happen, right?! */
594 
595     /* note that if this needs to allocate more space and run out of memory,
596        we have no choice but to quietly drop the data and hope it works out
597        later, but you probably have bigger problems in this case anyhow. */
598     queue_audio_to_device(device, stream, (Uint32) len);
599 }
600 
601 int
SDL_QueueAudio(SDL_AudioDeviceID devid,const void * data,Uint32 len)602 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *data, Uint32 len)
603 {
604     SDL_AudioDevice *device = get_audio_device(devid);
605     int rc = 0;
606 
607     if (!device) {
608         return -1;  /* get_audio_device() will have set the error state */
609     } else if (device->iscapture) {
610         return SDL_SetError("This is a capture device, queueing not allowed");
611     } else if (device->spec.callback != SDL_BufferQueueDrainCallback) {
612         return SDL_SetError("Audio device has a callback, queueing not allowed");
613     }
614 
615     if (len > 0) {
616         current_audio.impl.LockDevice(device);
617         rc = queue_audio_to_device(device, data, len);
618         current_audio.impl.UnlockDevice(device);
619     }
620 
621     return rc;
622 }
623 
624 Uint32
SDL_DequeueAudio(SDL_AudioDeviceID devid,void * data,Uint32 len)625 SDL_DequeueAudio(SDL_AudioDeviceID devid, void *data, Uint32 len)
626 {
627     SDL_AudioDevice *device = get_audio_device(devid);
628     Uint32 rc;
629 
630     if ( (len == 0) ||  /* nothing to do? */
631          (!device) ||  /* called with bogus device id */
632          (!device->iscapture) ||  /* playback devices can't dequeue */
633          (device->spec.callback != SDL_BufferQueueFillCallback) ) { /* not set for queueing */
634         return 0;  /* just report zero bytes dequeued. */
635     }
636 
637     current_audio.impl.LockDevice(device);
638     rc = dequeue_audio_from_device(device, data, len);
639     current_audio.impl.UnlockDevice(device);
640     return rc;
641 }
642 
643 Uint32
SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)644 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
645 {
646     Uint32 retval = 0;
647     SDL_AudioDevice *device = get_audio_device(devid);
648 
649     if (!device) {
650         return 0;
651     }
652 
653     /* Nothing to do unless we're set up for queueing. */
654     if (device->spec.callback == SDL_BufferQueueDrainCallback) {
655         current_audio.impl.LockDevice(device);
656         retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
657         current_audio.impl.UnlockDevice(device);
658     } else if (device->spec.callback == SDL_BufferQueueFillCallback) {
659         current_audio.impl.LockDevice(device);
660         retval = device->queued_bytes;
661         current_audio.impl.UnlockDevice(device);
662     }
663 
664     return retval;
665 }
666 
667 void
SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)668 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
669 {
670     SDL_AudioDevice *device = get_audio_device(devid);
671     SDL_AudioBufferQueue *packet;
672 
673     if (!device) {
674         return;  /* nothing to do. */
675     }
676 
677     /* Blank out the device and release the mutex. Free it afterwards. */
678     current_audio.impl.LockDevice(device);
679 
680     /* merge the available pool and the current queue into one list. */
681     packet = device->buffer_queue_head;
682     if (packet) {
683         device->buffer_queue_tail->next = device->buffer_queue_pool;
684     } else {
685         packet = device->buffer_queue_pool;
686     }
687 
688     /* Remove the queued packets from the device. */
689     device->buffer_queue_tail = NULL;
690     device->buffer_queue_head = NULL;
691     device->queued_bytes = 0;
692     device->buffer_queue_pool = packet;
693 
694     /* Keep up to two packets in the pool to reduce future malloc pressure. */
695     if (packet) {
696         if (!packet->next) {
697             packet = NULL;  /* one packet (the only one) for the pool. */
698         } else {
699             SDL_AudioBufferQueue *next = packet->next->next;
700             packet->next->next = NULL;  /* two packets for the pool. */
701             packet = next;  /* rest will be freed. */
702         }
703     }
704 
705     current_audio.impl.UnlockDevice(device);
706 
707     /* free any extra packets we didn't keep in the pool. */
708     free_audio_queue(packet);
709 }
710 
711 
712 /* The general mixing thread function */
713 static int SDLCALL
SDL_RunAudio(void * devicep)714 SDL_RunAudio(void *devicep)
715 {
716     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
717     const int silence = (int) device->spec.silence;
718     const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
719     const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
720     Uint8 *stream;
721     void *udata = device->spec.userdata;
722     void (SDLCALL *callback) (void *, Uint8 *, int) = device->spec.callback;
723 
724     SDL_assert(!device->iscapture);
725 
726     /* The audio mixing is always a high priority thread */
727     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
728 
729     /* Perform any thread setup */
730     device->threadid = SDL_ThreadID();
731     current_audio.impl.ThreadInit(device);
732 
733     /* Loop, filling the audio buffers */
734     while (!SDL_AtomicGet(&device->shutdown)) {
735         /* Fill the current buffer with sound */
736         if (device->convert.needed) {
737             stream = device->convert.buf;
738         } else if (SDL_AtomicGet(&device->enabled)) {
739             stream = current_audio.impl.GetDeviceBuf(device);
740         } else {
741             /* if the device isn't enabled, we still write to the
742                fake_stream, so the app's callback will fire with
743                a regular frequency, in case they depend on that
744                for timing or progress. They can use hotplug
745                now to know if the device failed. */
746             stream = NULL;
747         }
748 
749         if (stream == NULL) {
750             stream = device->fake_stream;
751         }
752 
753         /* !!! FIXME: this should be LockDevice. */
754         if ( SDL_AtomicGet(&device->enabled) ) {
755             SDL_LockMutex(device->mixer_lock);
756             if (SDL_AtomicGet(&device->paused)) {
757                 SDL_memset(stream, silence, stream_len);
758             } else {
759                 (*callback) (udata, stream, stream_len);
760             }
761             SDL_UnlockMutex(device->mixer_lock);
762         }
763 
764         /* Convert the audio if necessary */
765         if (device->convert.needed && SDL_AtomicGet(&device->enabled)) {
766             SDL_ConvertAudio(&device->convert);
767             stream = current_audio.impl.GetDeviceBuf(device);
768             if (stream == NULL) {
769                 stream = device->fake_stream;
770             } else {
771                 SDL_memcpy(stream, device->convert.buf,
772                            device->convert.len_cvt);
773             }
774         }
775 
776         /* Ready current buffer for play and change current buffer */
777         if (stream == device->fake_stream) {
778             SDL_Delay(delay);
779         } else {
780             current_audio.impl.PlayDevice(device);
781             current_audio.impl.WaitDevice(device);
782         }
783     }
784 
785     current_audio.impl.PrepareToClose(device);
786 
787     /* Wait for the audio to drain. */
788     SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
789 
790     return 0;
791 }
792 
793 /* The general capture thread function */
794 static int SDLCALL
SDL_CaptureAudio(void * devicep)795 SDL_CaptureAudio(void *devicep)
796 {
797     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
798     const int silence = (int) device->spec.silence;
799     const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
800     const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
801     Uint8 *stream;
802     void *udata = device->spec.userdata;
803     void (SDLCALL *callback) (void *, Uint8 *, int) = device->spec.callback;
804 
805     SDL_assert(device->iscapture);
806 
807     /* The audio mixing is always a high priority thread */
808     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
809 
810     /* Perform any thread setup */
811     device->threadid = SDL_ThreadID();
812     current_audio.impl.ThreadInit(device);
813 
814     /* Loop, filling the audio buffers */
815     while (!SDL_AtomicGet(&device->shutdown)) {
816         int still_need;
817         Uint8 *ptr;
818 
819         if (!SDL_AtomicGet(&device->enabled) || SDL_AtomicGet(&device->paused)) {
820             SDL_Delay(delay);  /* just so we don't cook the CPU. */
821             current_audio.impl.FlushCapture(device);  /* dump anything pending. */
822             continue;
823         }
824 
825         /* Fill the current buffer with sound */
826         still_need = stream_len;
827         if (device->convert.needed) {
828             ptr = stream = device->convert.buf;
829         } else {
830             /* just use the "fake" stream to hold data read from the device. */
831             ptr = stream = device->fake_stream;
832         }
833 
834         /* We still read from the device when "paused" to keep the state sane,
835            and block when there isn't data so this thread isn't eating CPU.
836            But we don't process it further or call the app's callback. */
837 
838         while (still_need > 0) {
839             const int rc = current_audio.impl.CaptureFromDevice(device, ptr, still_need);
840             SDL_assert(rc <= still_need);  /* device should not overflow buffer. :) */
841             if (rc > 0) {
842                 still_need -= rc;
843                 ptr += rc;
844             } else {  /* uhoh, device failed for some reason! */
845                 SDL_OpenedAudioDeviceDisconnected(device);
846                 break;
847             }
848         }
849 
850         if (still_need > 0) {
851             /* Keep any data we already read, silence the rest. */
852             SDL_memset(ptr, silence, still_need);
853         }
854 
855         if (device->convert.needed) {
856             SDL_ConvertAudio(&device->convert);
857         }
858 
859         /* !!! FIXME: this should be LockDevice. */
860         SDL_LockMutex(device->mixer_lock);
861         if (SDL_AtomicGet(&device->paused)) {
862             current_audio.impl.FlushCapture(device);  /* one snuck in! */
863         } else {
864             (*callback)(udata, stream, stream_len);
865         }
866         SDL_UnlockMutex(device->mixer_lock);
867     }
868 
869     current_audio.impl.FlushCapture(device);
870 
871     return 0;
872 }
873 
874 
875 static SDL_AudioFormat
SDL_ParseAudioFormat(const char * string)876 SDL_ParseAudioFormat(const char *string)
877 {
878 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
879     CHECK_FMT_STRING(U8);
880     CHECK_FMT_STRING(S8);
881     CHECK_FMT_STRING(U16LSB);
882     CHECK_FMT_STRING(S16LSB);
883     CHECK_FMT_STRING(U16MSB);
884     CHECK_FMT_STRING(S16MSB);
885     CHECK_FMT_STRING(U16SYS);
886     CHECK_FMT_STRING(S16SYS);
887     CHECK_FMT_STRING(U16);
888     CHECK_FMT_STRING(S16);
889     CHECK_FMT_STRING(S32LSB);
890     CHECK_FMT_STRING(S32MSB);
891     CHECK_FMT_STRING(S32SYS);
892     CHECK_FMT_STRING(S32);
893     CHECK_FMT_STRING(F32LSB);
894     CHECK_FMT_STRING(F32MSB);
895     CHECK_FMT_STRING(F32SYS);
896     CHECK_FMT_STRING(F32);
897 #undef CHECK_FMT_STRING
898     return 0;
899 }
900 
901 int
SDL_GetNumAudioDrivers(void)902 SDL_GetNumAudioDrivers(void)
903 {
904     return SDL_arraysize(bootstrap) - 1;
905 }
906 
907 const char *
SDL_GetAudioDriver(int index)908 SDL_GetAudioDriver(int index)
909 {
910     if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
911         return bootstrap[index]->name;
912     }
913     return NULL;
914 }
915 
916 int
SDL_AudioInit(const char * driver_name)917 SDL_AudioInit(const char *driver_name)
918 {
919     int i = 0;
920     int initialized = 0;
921     int tried_to_init = 0;
922 
923     if (SDL_WasInit(SDL_INIT_AUDIO)) {
924         SDL_AudioQuit();        /* shutdown driver if already running. */
925     }
926 
927     SDL_zero(current_audio);
928     SDL_zero(open_devices);
929 
930     /* Select the proper audio driver */
931     if (driver_name == NULL) {
932         driver_name = SDL_getenv("SDL_AUDIODRIVER");
933     }
934 
935     for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
936         /* make sure we should even try this driver before doing so... */
937         const AudioBootStrap *backend = bootstrap[i];
938         if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
939             (!driver_name && backend->demand_only)) {
940             continue;
941         }
942 
943         tried_to_init = 1;
944         SDL_zero(current_audio);
945         current_audio.name = backend->name;
946         current_audio.desc = backend->desc;
947         initialized = backend->init(&current_audio.impl);
948     }
949 
950     if (!initialized) {
951         /* specific drivers will set the error message if they fail... */
952         if (!tried_to_init) {
953             if (driver_name) {
954                 SDL_SetError("Audio target '%s' not available", driver_name);
955             } else {
956                 SDL_SetError("No available audio device");
957             }
958         }
959 
960         SDL_zero(current_audio);
961         return -1;            /* No driver was available, so fail. */
962     }
963 
964     current_audio.detectionLock = SDL_CreateMutex();
965 
966     finish_audio_entry_points_init();
967 
968     /* Make sure we have a list of devices available at startup. */
969     current_audio.impl.DetectDevices();
970 
971     return 0;
972 }
973 
974 /*
975  * Get the current audio driver name
976  */
977 const char *
SDL_GetCurrentAudioDriver()978 SDL_GetCurrentAudioDriver()
979 {
980     return current_audio.name;
981 }
982 
983 /* Clean out devices that we've removed but had to keep around for stability. */
984 static void
clean_out_device_list(SDL_AudioDeviceItem ** devices,int * devCount,SDL_bool * removedFlag)985 clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
986 {
987     SDL_AudioDeviceItem *item = *devices;
988     SDL_AudioDeviceItem *prev = NULL;
989     int total = 0;
990 
991     while (item) {
992         SDL_AudioDeviceItem *next = item->next;
993         if (item->handle != NULL) {
994             total++;
995             prev = item;
996         } else {
997             if (prev) {
998                 prev->next = next;
999             } else {
1000                 *devices = next;
1001             }
1002             SDL_free(item);
1003         }
1004         item = next;
1005     }
1006 
1007     *devCount = total;
1008     *removedFlag = SDL_FALSE;
1009 }
1010 
1011 
1012 int
SDL_GetNumAudioDevices(int iscapture)1013 SDL_GetNumAudioDevices(int iscapture)
1014 {
1015     int retval = 0;
1016 
1017     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1018         return -1;
1019     }
1020 
1021     SDL_LockMutex(current_audio.detectionLock);
1022     if (iscapture && current_audio.captureDevicesRemoved) {
1023         clean_out_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount, &current_audio.captureDevicesRemoved);
1024     }
1025 
1026     if (!iscapture && current_audio.outputDevicesRemoved) {
1027         clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_audio.outputDevicesRemoved);
1028         current_audio.outputDevicesRemoved = SDL_FALSE;
1029     }
1030 
1031     retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
1032     SDL_UnlockMutex(current_audio.detectionLock);
1033 
1034     return retval;
1035 }
1036 
1037 
1038 const char *
SDL_GetAudioDeviceName(int index,int iscapture)1039 SDL_GetAudioDeviceName(int index, int iscapture)
1040 {
1041     const char *retval = NULL;
1042 
1043     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1044         SDL_SetError("Audio subsystem is not initialized");
1045         return NULL;
1046     }
1047 
1048     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
1049         SDL_SetError("No capture support");
1050         return NULL;
1051     }
1052 
1053     if (index >= 0) {
1054         SDL_AudioDeviceItem *item;
1055         int i;
1056 
1057         SDL_LockMutex(current_audio.detectionLock);
1058         item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
1059         i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
1060         if (index < i) {
1061             for (i--; i > index; i--, item = item->next) {
1062                 SDL_assert(item != NULL);
1063             }
1064             SDL_assert(item != NULL);
1065             retval = item->name;
1066         }
1067         SDL_UnlockMutex(current_audio.detectionLock);
1068     }
1069 
1070     if (retval == NULL) {
1071         SDL_SetError("No such device");
1072     }
1073 
1074     return retval;
1075 }
1076 
1077 
1078 static void
close_audio_device(SDL_AudioDevice * device)1079 close_audio_device(SDL_AudioDevice * device)
1080 {
1081     if (!device) {
1082         return;
1083     }
1084 
1085     if (device->id > 0) {
1086         SDL_AudioDevice *opendev = open_devices[device->id - 1];
1087         SDL_assert((opendev == device) || (opendev == NULL));
1088         if (opendev == device) {
1089             open_devices[device->id - 1] = NULL;
1090         }
1091     }
1092 
1093     SDL_AtomicSet(&device->shutdown, 1);
1094     SDL_AtomicSet(&device->enabled, 0);
1095     if (device->thread != NULL) {
1096         SDL_WaitThread(device->thread, NULL);
1097     }
1098     if (device->mixer_lock != NULL) {
1099         SDL_DestroyMutex(device->mixer_lock);
1100     }
1101     SDL_free(device->fake_stream);
1102     if (device->convert.needed) {
1103         SDL_free(device->convert.buf);
1104     }
1105     if (device->hidden != NULL) {
1106         current_audio.impl.CloseDevice(device);
1107     }
1108 
1109     free_audio_queue(device->buffer_queue_head);
1110     free_audio_queue(device->buffer_queue_pool);
1111 
1112     SDL_free(device);
1113 }
1114 
1115 
1116 /*
1117  * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
1118  *  Fills in a sanitized copy in (prepared).
1119  *  Returns non-zero if okay, zero on fatal parameters in (orig).
1120  */
1121 static int
prepare_audiospec(const SDL_AudioSpec * orig,SDL_AudioSpec * prepared)1122 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
1123 {
1124     SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
1125 
1126     if (orig->freq == 0) {
1127         const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
1128         if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
1129             prepared->freq = 22050;     /* a reasonable default */
1130         }
1131     }
1132 
1133     if (orig->format == 0) {
1134         const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
1135         if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
1136             prepared->format = AUDIO_S16;       /* a reasonable default */
1137         }
1138     }
1139 
1140     switch (orig->channels) {
1141     case 0:{
1142             const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
1143             if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
1144                 prepared->channels = 2; /* a reasonable default */
1145             }
1146             break;
1147         }
1148     case 1:                    /* Mono */
1149     case 2:                    /* Stereo */
1150     case 4:                    /* surround */
1151     case 6:                    /* surround with center and lfe */
1152         break;
1153     default:
1154         SDL_SetError("Unsupported number of audio channels.");
1155         return 0;
1156     }
1157 
1158     if (orig->samples == 0) {
1159         const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
1160         if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
1161             /* Pick a default of ~46 ms at desired frequency */
1162             /* !!! FIXME: remove this when the non-Po2 resampling is in. */
1163             const int samples = (prepared->freq / 1000) * 46;
1164             int power2 = 1;
1165             while (power2 < samples) {
1166                 power2 *= 2;
1167             }
1168             prepared->samples = power2;
1169         }
1170     }
1171 
1172     /* Calculate the silence and size of the audio specification */
1173     SDL_CalculateAudioSpec(prepared);
1174 
1175     return 1;
1176 }
1177 
1178 static SDL_AudioDeviceID
open_audio_device(const char * devname,int iscapture,const SDL_AudioSpec * desired,SDL_AudioSpec * obtained,int allowed_changes,int min_id)1179 open_audio_device(const char *devname, int iscapture,
1180                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1181                   int allowed_changes, int min_id)
1182 {
1183     const SDL_bool is_internal_thread = (desired->callback != NULL);
1184     SDL_AudioDeviceID id = 0;
1185     SDL_AudioSpec _obtained;
1186     SDL_AudioDevice *device;
1187     SDL_bool build_cvt;
1188     void *handle = NULL;
1189     int i = 0;
1190 
1191     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1192         SDL_SetError("Audio subsystem is not initialized");
1193         return 0;
1194     }
1195 
1196     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
1197         SDL_SetError("No capture support");
1198         return 0;
1199     }
1200 
1201     /* !!! FIXME: there is a race condition here if two devices open from two threads at once. */
1202     /* Find an available device ID... */
1203     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
1204         if (open_devices[id] == NULL) {
1205             break;
1206         }
1207     }
1208 
1209     if (id == SDL_arraysize(open_devices)) {
1210         SDL_SetError("Too many open audio devices");
1211         return 0;
1212     }
1213 
1214     if (!obtained) {
1215         obtained = &_obtained;
1216     }
1217     if (!prepare_audiospec(desired, obtained)) {
1218         return 0;
1219     }
1220 
1221     /* If app doesn't care about a specific device, let the user override. */
1222     if (devname == NULL) {
1223         devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
1224     }
1225 
1226     /*
1227      * Catch device names at the high level for the simple case...
1228      * This lets us have a basic "device enumeration" for systems that
1229      *  don't have multiple devices, but makes sure the device name is
1230      *  always NULL when it hits the low level.
1231      *
1232      * Also make sure that the simple case prevents multiple simultaneous
1233      *  opens of the default system device.
1234      */
1235 
1236     if ((iscapture) && (current_audio.impl.OnlyHasDefaultCaptureDevice)) {
1237         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
1238             SDL_SetError("No such device");
1239             return 0;
1240         }
1241         devname = NULL;
1242 
1243         for (i = 0; i < SDL_arraysize(open_devices); i++) {
1244             if ((open_devices[i]) && (open_devices[i]->iscapture)) {
1245                 SDL_SetError("Audio device already open");
1246                 return 0;
1247             }
1248         }
1249     } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
1250         if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
1251             SDL_SetError("No such device");
1252             return 0;
1253         }
1254         devname = NULL;
1255 
1256         for (i = 0; i < SDL_arraysize(open_devices); i++) {
1257             if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
1258                 SDL_SetError("Audio device already open");
1259                 return 0;
1260             }
1261         }
1262     } else if (devname != NULL) {
1263         /* if the app specifies an exact string, we can pass the backend
1264            an actual device handle thingey, which saves them the effort of
1265            figuring out what device this was (such as, reenumerating
1266            everything again to find the matching human-readable name).
1267            It might still need to open a device based on the string for,
1268            say, a network audio server, but this optimizes some cases. */
1269         SDL_AudioDeviceItem *item;
1270         SDL_LockMutex(current_audio.detectionLock);
1271         for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
1272             if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
1273                 handle = item->handle;
1274                 break;
1275             }
1276         }
1277         SDL_UnlockMutex(current_audio.detectionLock);
1278     }
1279 
1280     if (!current_audio.impl.AllowsArbitraryDeviceNames) {
1281         /* has to be in our device list, or the default device. */
1282         if ((handle == NULL) && (devname != NULL)) {
1283             SDL_SetError("No such device.");
1284             return 0;
1285         }
1286     }
1287 
1288     device = (SDL_AudioDevice *) SDL_calloc(1, sizeof (SDL_AudioDevice));
1289     if (device == NULL) {
1290         SDL_OutOfMemory();
1291         return 0;
1292     }
1293     device->id = id + 1;
1294     device->spec = *obtained;
1295     device->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
1296     device->handle = handle;
1297 
1298     SDL_AtomicSet(&device->shutdown, 0);  /* just in case. */
1299     SDL_AtomicSet(&device->paused, 1);
1300     SDL_AtomicSet(&device->enabled, 1);
1301 
1302     /* Create a mutex for locking the sound buffers */
1303     if (!current_audio.impl.SkipMixerLock) {
1304         device->mixer_lock = SDL_CreateMutex();
1305         if (device->mixer_lock == NULL) {
1306             close_audio_device(device);
1307             SDL_SetError("Couldn't create mixer lock");
1308             return 0;
1309         }
1310     }
1311 
1312     if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
1313         close_audio_device(device);
1314         return 0;
1315     }
1316 
1317     /* if your target really doesn't need it, set it to 0x1 or something. */
1318     /* otherwise, close_audio_device() won't call impl.CloseDevice(). */
1319     SDL_assert(device->hidden != NULL);
1320 
1321     /* See if we need to do any conversion */
1322     build_cvt = SDL_FALSE;
1323     if (obtained->freq != device->spec.freq) {
1324         if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
1325             obtained->freq = device->spec.freq;
1326         } else {
1327             build_cvt = SDL_TRUE;
1328         }
1329     }
1330     if (obtained->format != device->spec.format) {
1331         if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
1332             obtained->format = device->spec.format;
1333         } else {
1334             build_cvt = SDL_TRUE;
1335         }
1336     }
1337     if (obtained->channels != device->spec.channels) {
1338         if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
1339             obtained->channels = device->spec.channels;
1340         } else {
1341             build_cvt = SDL_TRUE;
1342         }
1343     }
1344 
1345     /* If the audio driver changes the buffer size, accept it.
1346        This needs to be done after the format is modified above,
1347        otherwise it might not have the correct buffer size.
1348      */
1349     if (device->spec.samples != obtained->samples) {
1350         obtained->samples = device->spec.samples;
1351         SDL_CalculateAudioSpec(obtained);
1352     }
1353 
1354     if (build_cvt) {
1355         /* Build an audio conversion block */
1356         if (SDL_BuildAudioCVT(&device->convert,
1357                               obtained->format, obtained->channels,
1358                               obtained->freq,
1359                               device->spec.format, device->spec.channels,
1360                               device->spec.freq) < 0) {
1361             close_audio_device(device);
1362             return 0;
1363         }
1364         if (device->convert.needed) {
1365             device->convert.len = (int) (((double) device->spec.size) /
1366                                          device->convert.len_ratio);
1367 
1368             device->convert.buf =
1369                 (Uint8 *) SDL_malloc(device->convert.len *
1370                                             device->convert.len_mult);
1371             if (device->convert.buf == NULL) {
1372                 close_audio_device(device);
1373                 SDL_OutOfMemory();
1374                 return 0;
1375             }
1376         }
1377     }
1378 
1379     if (device->spec.callback == NULL) {  /* use buffer queueing? */
1380         /* pool a few packets to start. Enough for two callbacks. */
1381         const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
1382         const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
1383         const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
1384         for (i = 0; i < wantpackets; i++) {
1385             SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
1386             if (packet) { /* don't care if this fails, we'll deal later. */
1387                 packet->datalen = 0;
1388                 packet->startpos = 0;
1389                 packet->next = device->buffer_queue_pool;
1390                 device->buffer_queue_pool = packet;
1391             }
1392         }
1393 
1394         device->spec.callback = iscapture ? SDL_BufferQueueFillCallback : SDL_BufferQueueDrainCallback;
1395         device->spec.userdata = device;
1396     }
1397 
1398     /* add it to our list of open devices. */
1399     open_devices[id] = device;
1400 
1401     /* Start the audio thread if necessary */
1402     if (!current_audio.impl.ProvidesOwnCallbackThread) {
1403         /* Start the audio thread */
1404         /* !!! FIXME: we don't force the audio thread stack size here if it calls into user code, but maybe we should? */
1405         /* buffer queueing callback only needs a few bytes, so make the stack tiny. */
1406         const size_t stacksize = is_internal_thread ? 64 * 1024 : 0;
1407         char threadname[64];
1408 
1409         /* Allocate a fake audio buffer; only used by our internal threads. */
1410         Uint32 stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
1411         if (device->spec.size > stream_len) {
1412             stream_len = device->spec.size;
1413         }
1414         SDL_assert(stream_len > 0);
1415 
1416         device->fake_stream = (Uint8 *) SDL_malloc(stream_len);
1417         if (device->fake_stream == NULL) {
1418             close_audio_device(device);
1419             SDL_OutOfMemory();
1420             return 0;
1421         }
1422 
1423         SDL_snprintf(threadname, sizeof (threadname), "SDLAudioDev%d", (int) device->id);
1424         device->thread = SDL_CreateThreadInternal(iscapture ? SDL_CaptureAudio : SDL_RunAudio, threadname, stacksize, device);
1425 
1426         if (device->thread == NULL) {
1427             close_audio_device(device);
1428             SDL_SetError("Couldn't create audio thread");
1429             return 0;
1430         }
1431     }
1432 
1433     return device->id;
1434 }
1435 
1436 
1437 int
SDL_OpenAudio(SDL_AudioSpec * desired,SDL_AudioSpec * obtained)1438 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
1439 {
1440     SDL_AudioDeviceID id = 0;
1441 
1442     /* Start up the audio driver, if necessary. This is legacy behaviour! */
1443     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1444         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
1445             return -1;
1446         }
1447     }
1448 
1449     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
1450     if (open_devices[0] != NULL) {
1451         SDL_SetError("Audio device is already opened");
1452         return -1;
1453     }
1454 
1455     if (obtained) {
1456         id = open_audio_device(NULL, 0, desired, obtained,
1457                                SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
1458     } else {
1459         id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
1460     }
1461 
1462     SDL_assert((id == 0) || (id == 1));
1463     return (id == 0) ? -1 : 0;
1464 }
1465 
1466 SDL_AudioDeviceID
SDL_OpenAudioDevice(const char * device,int iscapture,const SDL_AudioSpec * desired,SDL_AudioSpec * obtained,int allowed_changes)1467 SDL_OpenAudioDevice(const char *device, int iscapture,
1468                     const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1469                     int allowed_changes)
1470 {
1471     return open_audio_device(device, iscapture, desired, obtained,
1472                              allowed_changes, 2);
1473 }
1474 
1475 SDL_AudioStatus
SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)1476 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
1477 {
1478     SDL_AudioDevice *device = get_audio_device(devid);
1479     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
1480     if (device && SDL_AtomicGet(&device->enabled)) {
1481         if (SDL_AtomicGet(&device->paused)) {
1482             status = SDL_AUDIO_PAUSED;
1483         } else {
1484             status = SDL_AUDIO_PLAYING;
1485         }
1486     }
1487     return status;
1488 }
1489 
1490 
1491 SDL_AudioStatus
SDL_GetAudioStatus(void)1492 SDL_GetAudioStatus(void)
1493 {
1494     return SDL_GetAudioDeviceStatus(1);
1495 }
1496 
1497 void
SDL_PauseAudioDevice(SDL_AudioDeviceID devid,int pause_on)1498 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
1499 {
1500     SDL_AudioDevice *device = get_audio_device(devid);
1501     if (device) {
1502         current_audio.impl.LockDevice(device);
1503         SDL_AtomicSet(&device->paused, pause_on ? 1 : 0);
1504         current_audio.impl.UnlockDevice(device);
1505     }
1506 }
1507 
1508 void
SDL_PauseAudio(int pause_on)1509 SDL_PauseAudio(int pause_on)
1510 {
1511     SDL_PauseAudioDevice(1, pause_on);
1512 }
1513 
1514 
1515 void
SDL_LockAudioDevice(SDL_AudioDeviceID devid)1516 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
1517 {
1518     /* Obtain a lock on the mixing buffers */
1519     SDL_AudioDevice *device = get_audio_device(devid);
1520     if (device) {
1521         current_audio.impl.LockDevice(device);
1522     }
1523 }
1524 
1525 void
SDL_LockAudio(void)1526 SDL_LockAudio(void)
1527 {
1528     SDL_LockAudioDevice(1);
1529 }
1530 
1531 void
SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)1532 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
1533 {
1534     /* Obtain a lock on the mixing buffers */
1535     SDL_AudioDevice *device = get_audio_device(devid);
1536     if (device) {
1537         current_audio.impl.UnlockDevice(device);
1538     }
1539 }
1540 
1541 void
SDL_UnlockAudio(void)1542 SDL_UnlockAudio(void)
1543 {
1544     SDL_UnlockAudioDevice(1);
1545 }
1546 
1547 void
SDL_CloseAudioDevice(SDL_AudioDeviceID devid)1548 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
1549 {
1550     close_audio_device(get_audio_device(devid));
1551 }
1552 
1553 void
SDL_CloseAudio(void)1554 SDL_CloseAudio(void)
1555 {
1556     SDL_CloseAudioDevice(1);
1557 }
1558 
1559 void
SDL_AudioQuit(void)1560 SDL_AudioQuit(void)
1561 {
1562     SDL_AudioDeviceID i;
1563 
1564     if (!current_audio.name) {  /* not initialized?! */
1565         return;
1566     }
1567 
1568     for (i = 0; i < SDL_arraysize(open_devices); i++) {
1569         close_audio_device(open_devices[i]);
1570     }
1571 
1572     free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
1573     free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
1574 
1575     /* Free the driver data */
1576     current_audio.impl.Deinitialize();
1577 
1578     SDL_DestroyMutex(current_audio.detectionLock);
1579 
1580     SDL_zero(current_audio);
1581     SDL_zero(open_devices);
1582 }
1583 
1584 #define NUM_FORMATS 10
1585 static int format_idx;
1586 static int format_idx_sub;
1587 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
1588     {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1589      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1590     {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1591      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1592     {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
1593      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1594     {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
1595      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1596     {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
1597      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1598     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
1599      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1600     {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
1601      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1602     {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
1603      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1604     {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
1605      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1606     {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
1607      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1608 };
1609 
1610 SDL_AudioFormat
SDL_FirstAudioFormat(SDL_AudioFormat format)1611 SDL_FirstAudioFormat(SDL_AudioFormat format)
1612 {
1613     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
1614         if (format_list[format_idx][0] == format) {
1615             break;
1616         }
1617     }
1618     format_idx_sub = 0;
1619     return SDL_NextAudioFormat();
1620 }
1621 
1622 SDL_AudioFormat
SDL_NextAudioFormat(void)1623 SDL_NextAudioFormat(void)
1624 {
1625     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
1626         return 0;
1627     }
1628     return format_list[format_idx][format_idx_sub++];
1629 }
1630 
1631 void
SDL_CalculateAudioSpec(SDL_AudioSpec * spec)1632 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
1633 {
1634     switch (spec->format) {
1635     case AUDIO_U8:
1636         spec->silence = 0x80;
1637         break;
1638     default:
1639         spec->silence = 0x00;
1640         break;
1641     }
1642     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
1643     spec->size *= spec->channels;
1644     spec->size *= spec->samples;
1645 }
1646 
1647 
1648 /*
1649  * Moved here from SDL_mixer.c, since it relies on internals of an opened
1650  *  audio device (and is deprecated, by the way!).
1651  */
1652 void
SDL_MixAudio(Uint8 * dst,const Uint8 * src,Uint32 len,int volume)1653 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
1654 {
1655     /* Mix the user-level audio format */
1656     SDL_AudioDevice *device = get_audio_device(1);
1657     if (device != NULL) {
1658         SDL_AudioFormat format;
1659         if (device->convert.needed) {
1660             format = device->convert.src_format;
1661         } else {
1662             format = device->spec.format;
1663         }
1664         SDL_MixAudioFormat(dst, src, format, len, volume);
1665     }
1666 }
1667 
1668 /* vi: set ts=4 sw=4 expandtab: */
1669