1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2021 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 | #ifndef SDL_sysaudio_h_ |
24 | #define SDL_sysaudio_h_ |
25 | |
26 | #include "SDL_mutex.h" |
27 | #include "SDL_thread.h" |
28 | #include "../SDL_dataqueue.h" |
29 | #include "./SDL_audio_c.h" |
30 | |
31 | /* !!! FIXME: These are wordy and unlocalized... */ |
32 | #define DEFAULT_OUTPUT_DEVNAME "System audio output device" |
33 | #define DEFAULT_INPUT_DEVNAME "System audio capture device" |
34 | |
35 | /* The SDL audio driver */ |
36 | typedef struct SDL_AudioDevice SDL_AudioDevice; |
37 | #define _THIS SDL_AudioDevice *_this |
38 | |
39 | /* Audio targets should call this as devices are added to the system (such as |
40 | a USB headset being plugged in), and should also be called for |
41 | for every device found during DetectDevices(). */ |
42 | extern void SDL_AddAudioDevice(const int iscapture, const char *name, SDL_AudioSpec *spec, void *handle); |
43 | |
44 | /* Audio targets should call this as devices are removed, so SDL can update |
45 | its list of available devices. */ |
46 | extern void SDL_RemoveAudioDevice(const int iscapture, void *handle); |
47 | |
48 | /* Audio targets should call this if an opened audio device is lost while |
49 | being used. This can happen due to i/o errors, or a device being unplugged, |
50 | etc. If the device is totally gone, please also call SDL_RemoveAudioDevice() |
51 | as appropriate so SDL's list of devices is accurate. */ |
52 | extern void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device); |
53 | |
54 | /* This is the size of a packet when using SDL_QueueAudio(). We allocate |
55 | these as necessary and pool them, under the assumption that we'll |
56 | eventually end up with a handful that keep recycling, meeting whatever |
57 | the app needs. We keep packing data tightly as more arrives to avoid |
58 | wasting space, and if we get a giant block of data, we'll split them |
59 | into multiple packets behind the scenes. My expectation is that most |
60 | apps will have 2-3 of these in the pool. 8k should cover most needs, but |
61 | if this is crippling for some embedded system, we can #ifdef this. |
62 | The system preallocates enough packets for 2 callbacks' worth of data. */ |
63 | #define SDL_AUDIOBUFFERQUEUE_PACKETLEN (8 * 1024) |
64 | |
65 | typedef struct SDL_AudioDriverImpl |
66 | { |
67 | void (*DetectDevices) (void); |
68 | int (*OpenDevice) (_THIS, void *handle, const char *devname, int iscapture); |
69 | void (*ThreadInit) (_THIS); /* Called by audio thread at start */ |
70 | void (*ThreadDeinit) (_THIS); /* Called by audio thread at end */ |
71 | void (*BeginLoopIteration)(_THIS); /* Called by audio thread at top of loop */ |
72 | void (*WaitDevice) (_THIS); |
73 | void (*PlayDevice) (_THIS); |
74 | Uint8 *(*GetDeviceBuf) (_THIS); |
75 | int (*CaptureFromDevice) (_THIS, void *buffer, int buflen); |
76 | void (*FlushCapture) (_THIS); |
77 | void (*PrepareToClose) (_THIS); /**< Called between run and draining wait for playback devices */ |
78 | void (*CloseDevice) (_THIS); |
79 | void (*LockDevice) (_THIS); |
80 | void (*UnlockDevice) (_THIS); |
81 | void (*FreeDeviceHandle) (void *handle); /**< SDL is done with handle from SDL_AddAudioDevice() */ |
82 | void (*Deinitialize) (void); |
83 | |
84 | /* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */ |
85 | |
86 | /* Some flags to push duplicate code into the core and reduce #ifdefs. */ |
87 | /* !!! FIXME: these should be SDL_bool */ |
88 | int ProvidesOwnCallbackThread; |
89 | int SkipMixerLock; |
90 | int HasCaptureSupport; |
91 | int OnlyHasDefaultOutputDevice; |
92 | int OnlyHasDefaultCaptureDevice; |
93 | int AllowsArbitraryDeviceNames; |
94 | } SDL_AudioDriverImpl; |
95 | |
96 | |
97 | typedef struct SDL_AudioDeviceItem |
98 | { |
99 | void *handle; |
100 | char *name; |
101 | char *original_name; |
102 | SDL_AudioSpec spec; |
103 | int dupenum; |
104 | struct SDL_AudioDeviceItem *next; |
105 | } SDL_AudioDeviceItem; |
106 | |
107 | |
108 | typedef struct SDL_AudioDriver |
109 | { |
110 | /* * * */ |
111 | /* The name of this audio driver */ |
112 | const char *name; |
113 | |
114 | /* * * */ |
115 | /* The description of this audio driver */ |
116 | const char *desc; |
117 | |
118 | SDL_AudioDriverImpl impl; |
119 | |
120 | /* A mutex for device detection */ |
121 | SDL_mutex *detectionLock; |
122 | SDL_bool captureDevicesRemoved; |
123 | SDL_bool outputDevicesRemoved; |
124 | int outputDeviceCount; |
125 | int inputDeviceCount; |
126 | SDL_AudioDeviceItem *outputDevices; |
127 | SDL_AudioDeviceItem *inputDevices; |
128 | } SDL_AudioDriver; |
129 | |
130 | |
131 | /* Define the SDL audio driver structure */ |
132 | struct SDL_AudioDevice |
133 | { |
134 | /* * * */ |
135 | /* Data common to all devices */ |
136 | SDL_AudioDeviceID id; |
137 | |
138 | /* The device's current audio specification */ |
139 | SDL_AudioSpec spec; |
140 | |
141 | /* The callback's expected audio specification (converted vs device's spec). */ |
142 | SDL_AudioSpec callbackspec; |
143 | |
144 | /* Stream that converts and resamples. NULL if not needed. */ |
145 | SDL_AudioStream *stream; |
146 | |
147 | /* Current state flags */ |
148 | SDL_atomic_t shutdown; /* true if we are signaling the play thread to end. */ |
149 | SDL_atomic_t enabled; /* true if device is functioning and connected. */ |
150 | SDL_atomic_t paused; |
151 | SDL_bool iscapture; |
152 | |
153 | /* Scratch buffer used in the bridge between SDL and the user callback. */ |
154 | Uint8 *work_buffer; |
155 | |
156 | /* Size, in bytes, of work_buffer. */ |
157 | Uint32 work_buffer_len; |
158 | |
159 | /* A mutex for locking the mixing buffers */ |
160 | SDL_mutex *mixer_lock; |
161 | |
162 | /* A thread to feed the audio device */ |
163 | SDL_Thread *thread; |
164 | SDL_threadID threadid; |
165 | |
166 | /* Queued buffers (if app not using callback). */ |
167 | SDL_DataQueue *buffer_queue; |
168 | |
169 | /* * * */ |
170 | /* Data private to this driver */ |
171 | struct SDL_PrivateAudioData *hidden; |
172 | |
173 | void *handle; |
174 | }; |
175 | #undef _THIS |
176 | |
177 | typedef struct AudioBootStrap |
178 | { |
179 | const char *name; |
180 | const char *desc; |
181 | int (*init) (SDL_AudioDriverImpl * impl); |
182 | int demand_only; /* 1==request explicitly, or it won't be available. */ |
183 | } AudioBootStrap; |
184 | |
185 | /* Not all of these are available in a given build. Use #ifdefs, etc. */ |
186 | extern AudioBootStrap PIPEWIRE_bootstrap; |
187 | extern AudioBootStrap PULSEAUDIO_bootstrap; |
188 | extern AudioBootStrap ALSA_bootstrap; |
189 | extern AudioBootStrap JACK_bootstrap; |
190 | extern AudioBootStrap SNDIO_bootstrap; |
191 | extern AudioBootStrap NETBSDAUDIO_bootstrap; |
192 | extern AudioBootStrap DSP_bootstrap; |
193 | extern AudioBootStrap QSAAUDIO_bootstrap; |
194 | extern AudioBootStrap SUNAUDIO_bootstrap; |
195 | extern AudioBootStrap ARTS_bootstrap; |
196 | extern AudioBootStrap ESD_bootstrap; |
197 | extern AudioBootStrap NACLAUDIO_bootstrap; |
198 | extern AudioBootStrap NAS_bootstrap; |
199 | extern AudioBootStrap WASAPI_bootstrap; |
200 | extern AudioBootStrap DSOUND_bootstrap; |
201 | extern AudioBootStrap WINMM_bootstrap; |
202 | extern AudioBootStrap PAUDIO_bootstrap; |
203 | extern AudioBootStrap HAIKUAUDIO_bootstrap; |
204 | extern AudioBootStrap COREAUDIO_bootstrap; |
205 | extern AudioBootStrap DISKAUDIO_bootstrap; |
206 | extern AudioBootStrap DUMMYAUDIO_bootstrap; |
207 | extern AudioBootStrap FUSIONSOUND_bootstrap; |
208 | extern AudioBootStrap aaudio_bootstrap; |
209 | extern AudioBootStrap openslES_bootstrap; |
210 | extern AudioBootStrap ANDROIDAUDIO_bootstrap; |
211 | extern AudioBootStrap PSPAUDIO_bootstrap; |
212 | extern AudioBootStrap VITAAUD_bootstrap; |
213 | extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap; |
214 | extern AudioBootStrap OS2AUDIO_bootstrap; |
215 | |
216 | #endif /* SDL_sysaudio_h_ */ |
217 | |
218 | /* vi: set ts=4 sw=4 expandtab: */ |
219 | |