diff options
Diffstat (limited to 'contrib/SDL-3.2.8/src/audio/qnx')
| -rw-r--r-- | contrib/SDL-3.2.8/src/audio/qnx/SDL_qsa_audio.c | 451 | ||||
| -rw-r--r-- | contrib/SDL-3.2.8/src/audio/qnx/SDL_qsa_audio.h | 40 |
2 files changed, 491 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/audio/qnx/SDL_qsa_audio.c b/contrib/SDL-3.2.8/src/audio/qnx/SDL_qsa_audio.c new file mode 100644 index 0000000..a31bea4 --- /dev/null +++ b/contrib/SDL-3.2.8/src/audio/qnx/SDL_qsa_audio.c | |||
| @@ -0,0 +1,451 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | // !!! FIXME: can this target support hotplugging? | ||
| 23 | |||
| 24 | #include "../../SDL_internal.h" | ||
| 25 | |||
| 26 | #ifdef SDL_AUDIO_DRIVER_QNX | ||
| 27 | |||
| 28 | #include <errno.h> | ||
| 29 | #include <unistd.h> | ||
| 30 | #include <fcntl.h> | ||
| 31 | #include <signal.h> | ||
| 32 | #include <sys/types.h> | ||
| 33 | #include <sys/time.h> | ||
| 34 | #include <sched.h> | ||
| 35 | #include <sys/select.h> | ||
| 36 | #include <sys/neutrino.h> | ||
| 37 | #include <sys/asoundlib.h> | ||
| 38 | |||
| 39 | #include "SDL3/SDL_timer.h" | ||
| 40 | #include "SDL3/SDL_audio.h" | ||
| 41 | #include "../../core/unix/SDL_poll.h" | ||
| 42 | #include "../SDL_sysaudio.h" | ||
| 43 | #include "SDL_qsa_audio.h" | ||
| 44 | |||
| 45 | // default channel communication parameters | ||
| 46 | #define DEFAULT_CPARAMS_RATE 44100 | ||
| 47 | #define DEFAULT_CPARAMS_VOICES 1 | ||
| 48 | |||
| 49 | #define DEFAULT_CPARAMS_FRAG_SIZE 4096 | ||
| 50 | #define DEFAULT_CPARAMS_FRAGS_MIN 1 | ||
| 51 | #define DEFAULT_CPARAMS_FRAGS_MAX 1 | ||
| 52 | |||
| 53 | #define QSA_MAX_NAME_LENGTH 81+16 // Hardcoded in QSA, can't be changed | ||
| 54 | |||
| 55 | static bool QSA_SetError(const char *fn, int status) | ||
| 56 | { | ||
| 57 | return SDL_SetError("QSA: %s() failed: %s", fn, snd_strerror(status)); | ||
| 58 | } | ||
| 59 | |||
| 60 | // !!! FIXME: does this need to be here? Does the SDL version not work? | ||
| 61 | static void QSA_ThreadInit(SDL_AudioDevice *device) | ||
| 62 | { | ||
| 63 | // Increase default 10 priority to 25 to avoid jerky sound | ||
| 64 | struct sched_param param; | ||
| 65 | if (SchedGet(0, 0, ¶m) != -1) { | ||
| 66 | param.sched_priority = param.sched_curpriority + 15; | ||
| 67 | SchedSet(0, 0, SCHED_NOCHANGE, ¶m); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 71 | // PCM channel parameters initialize function | ||
| 72 | static void QSA_InitAudioParams(snd_pcm_channel_params_t * cpars) | ||
| 73 | { | ||
| 74 | SDL_zerop(cpars); | ||
| 75 | cpars->channel = SND_PCM_CHANNEL_PLAYBACK; | ||
| 76 | cpars->mode = SND_PCM_MODE_BLOCK; | ||
| 77 | cpars->start_mode = SND_PCM_START_DATA; | ||
| 78 | cpars->stop_mode = SND_PCM_STOP_STOP; | ||
| 79 | cpars->format.format = SND_PCM_SFMT_S16_LE; | ||
| 80 | cpars->format.interleave = 1; | ||
| 81 | cpars->format.rate = DEFAULT_CPARAMS_RATE; | ||
| 82 | cpars->format.voices = DEFAULT_CPARAMS_VOICES; | ||
| 83 | cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE; | ||
| 84 | cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; | ||
| 85 | cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; | ||
| 86 | } | ||
| 87 | |||
| 88 | // This function waits until it is possible to write a full sound buffer | ||
| 89 | static bool QSA_WaitDevice(SDL_AudioDevice *device) | ||
| 90 | { | ||
| 91 | // Setup timeout for playing one fragment equal to 2 seconds | ||
| 92 | // If timeout occurred than something wrong with hardware or driver | ||
| 93 | // For example, Vortex 8820 audio driver stucks on second DAC because | ||
| 94 | // it doesn't exist ! | ||
| 95 | const int result = SDL_IOReady(device->hidden->audio_fd, | ||
| 96 | device->recording ? SDL_IOR_READ : SDL_IOR_WRITE, | ||
| 97 | 2 * 1000); | ||
| 98 | switch (result) { | ||
| 99 | case -1: | ||
| 100 | SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "QSA: SDL_IOReady() failed: %s", strerror(errno)); | ||
| 101 | return false; | ||
| 102 | case 0: | ||
| 103 | device->hidden->timeout_on_wait = true; // !!! FIXME: Should we just disconnect the device in this case? | ||
| 104 | break; | ||
| 105 | default: | ||
| 106 | device->hidden->timeout_on_wait = false; | ||
| 107 | break; | ||
| 108 | } | ||
| 109 | |||
| 110 | return true; | ||
| 111 | } | ||
| 112 | |||
| 113 | static bool QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) | ||
| 114 | { | ||
| 115 | if (SDL_GetAtomicInt(&device->shutdown) || !device->hidden) { | ||
| 116 | return true; | ||
| 117 | } | ||
| 118 | |||
| 119 | int towrite = buflen; | ||
| 120 | |||
| 121 | // Write the audio data, checking for EAGAIN (buffer full) and underrun | ||
| 122 | while ((towrite > 0) && !SDL_GetAtomicInt(&device->shutdown)); | ||
| 123 | const int bw = snd_pcm_plugin_write(device->hidden->audio_handle, buffer, towrite); | ||
| 124 | if (bw != towrite) { | ||
| 125 | // Check if samples playback got stuck somewhere in hardware or in the audio device driver | ||
| 126 | if ((errno == EAGAIN) && (bw == 0)) { | ||
| 127 | if (device->hidden->timeout_on_wait) { | ||
| 128 | return true; // oh well, try again next time. !!! FIXME: Should we just disconnect the device in this case? | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | // Check for errors or conditions | ||
| 133 | if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { | ||
| 134 | SDL_Delay(1); // Let a little CPU time go by and try to write again | ||
| 135 | |||
| 136 | // if we wrote some data | ||
| 137 | towrite -= bw; | ||
| 138 | buffer += bw * device->spec.channels; | ||
| 139 | continue; | ||
| 140 | } else if ((errno == EINVAL) || (errno == EIO)) { | ||
| 141 | snd_pcm_channel_status_t cstatus; | ||
| 142 | SDL_zero(cstatus); | ||
| 143 | cstatus.channel = device->recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; | ||
| 144 | |||
| 145 | int status = snd_pcm_plugin_status(device->hidden->audio_handle, &cstatus); | ||
| 146 | if (status < 0) { | ||
| 147 | QSA_SetError("snd_pcm_plugin_status", status); | ||
| 148 | return false; | ||
| 149 | } else if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY)) { | ||
| 150 | status = snd_pcm_plugin_prepare(device->hidden->audio_handle, device->recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK); | ||
| 151 | if (status < 0) { | ||
| 152 | QSA_SetError("snd_pcm_plugin_prepare", status); | ||
| 153 | return false; | ||
| 154 | } | ||
| 155 | } | ||
| 156 | continue; | ||
| 157 | } else { | ||
| 158 | return false; | ||
| 159 | } | ||
| 160 | } else { | ||
| 161 | // we wrote all remaining data | ||
| 162 | towrite -= bw; | ||
| 163 | buffer += bw * device->spec.channels; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | // If we couldn't write, assume fatal error for now | ||
| 168 | return (towrite == 0); | ||
| 169 | } | ||
| 170 | |||
| 171 | static Uint8 *QSA_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) | ||
| 172 | { | ||
| 173 | return device->hidden->pcm_buf; | ||
| 174 | } | ||
| 175 | |||
| 176 | static void QSA_CloseDevice(SDL_AudioDevice *device) | ||
| 177 | { | ||
| 178 | if (device->hidden) { | ||
| 179 | if (device->hidden->audio_handle) { | ||
| 180 | #if _NTO_VERSION < 710 | ||
| 181 | // Finish playing available samples or cancel unread samples during recording | ||
| 182 | snd_pcm_plugin_flush(device->hidden->audio_handle, device->recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK); | ||
| 183 | #endif | ||
| 184 | snd_pcm_close(device->hidden->audio_handle); | ||
| 185 | } | ||
| 186 | |||
| 187 | SDL_free(device->hidden->pcm_buf); | ||
| 188 | SDL_free(device->hidden); | ||
| 189 | device->hidden = NULL; | ||
| 190 | } | ||
| 191 | } | ||
| 192 | |||
| 193 | static bool QSA_OpenDevice(SDL_AudioDevice *device) | ||
| 194 | { | ||
| 195 | if (device->recording) { | ||
| 196 | return SDL_SetError("SDL recording support isn't available on QNX atm"); // !!! FIXME: most of this code has support for recording devices, but there's no RecordDevice, etc functions. Fill them in! | ||
| 197 | } | ||
| 198 | |||
| 199 | SDL_assert(device->handle != NULL); // NULL used to mean "system default device" in SDL2; it does not mean that in SDL3. | ||
| 200 | const Uint32 sdlhandle = (Uint32) ((size_t) device->handle); | ||
| 201 | const uint32_t cardno = (uint32_t) (sdlhandle & 0xFFFF); | ||
| 202 | const uint32_t deviceno = (uint32_t) ((sdlhandle >> 16) & 0xFFFF); | ||
| 203 | const bool recording = device->recording; | ||
| 204 | int status = 0; | ||
| 205 | |||
| 206 | // Initialize all variables that we clean on shutdown | ||
| 207 | device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof (struct SDL_PrivateAudioData))); | ||
| 208 | if (device->hidden == NULL) { | ||
| 209 | return false; | ||
| 210 | } | ||
| 211 | |||
| 212 | // Initialize channel transfer parameters to default | ||
| 213 | snd_pcm_channel_params_t cparams; | ||
| 214 | QSA_InitAudioParams(&cparams); | ||
| 215 | |||
| 216 | // Open requested audio device | ||
| 217 | status = snd_pcm_open(&device->hidden->audio_handle, cardno, deviceno, recording ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK); | ||
| 218 | if (status < 0) { | ||
| 219 | device->hidden->audio_handle = NULL; | ||
| 220 | return QSA_SetError("snd_pcm_open", status); | ||
| 221 | } | ||
| 222 | |||
| 223 | // Try for a closest match on audio format | ||
| 224 | SDL_AudioFormat test_format = 0; | ||
| 225 | const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format); | ||
| 226 | while ((test_format = *(closefmts++)) != 0) { | ||
| 227 | // if match found set format to equivalent QSA format | ||
| 228 | switch (test_format) { | ||
| 229 | #define CHECKFMT(sdlfmt, qsafmt) case SDL_AUDIO_##sdlfmt: cparams.format.format = SND_PCM_SFMT_##qsafmt; break | ||
| 230 | CHECKFMT(U8, U8); | ||
| 231 | CHECKFMT(S8, S8); | ||
| 232 | CHECKFMT(S16LSB, S16_LE); | ||
| 233 | CHECKFMT(S16MSB, S16_BE); | ||
| 234 | CHECKFMT(S32LSB, S32_LE); | ||
| 235 | CHECKFMT(S32MSB, S32_BE); | ||
| 236 | CHECKFMT(F32LSB, FLOAT_LE); | ||
| 237 | CHECKFMT(F32MSB, FLOAT_BE); | ||
| 238 | #undef CHECKFMT | ||
| 239 | default: continue; | ||
| 240 | } | ||
| 241 | break; | ||
| 242 | } | ||
| 243 | |||
| 244 | // assumes test_format not 0 on success | ||
| 245 | if (test_format == 0) { | ||
| 246 | return SDL_SetError("QSA: Couldn't find any hardware audio formats"); | ||
| 247 | } | ||
| 248 | |||
| 249 | device->spec.format = test_format; | ||
| 250 | |||
| 251 | // Set mono/stereo/4ch/6ch/8ch audio | ||
| 252 | cparams.format.voices = device->spec.channels; | ||
| 253 | |||
| 254 | // Set rate | ||
| 255 | cparams.format.rate = device->spec.freq; | ||
| 256 | |||
| 257 | // Setup the transfer parameters according to cparams | ||
| 258 | status = snd_pcm_plugin_params(device->hidden->audio_handle, &cparams); | ||
| 259 | if (status < 0) { | ||
| 260 | return QSA_SetError("snd_pcm_plugin_params", status); | ||
| 261 | } | ||
| 262 | |||
| 263 | // Make sure channel is setup right one last time | ||
| 264 | snd_pcm_channel_setup_t csetup; | ||
| 265 | SDL_zero(csetup); | ||
| 266 | csetup.channel = recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; | ||
| 267 | if (snd_pcm_plugin_setup(device->hidden->audio_handle, &csetup) < 0) { | ||
| 268 | return SDL_SetError("QSA: Unable to setup channel"); | ||
| 269 | } | ||
| 270 | |||
| 271 | device->sample_frames = csetup.buf.block.frag_size; | ||
| 272 | |||
| 273 | // Calculate the final parameters for this audio specification | ||
| 274 | SDL_UpdatedAudioDeviceFormat(device); | ||
| 275 | |||
| 276 | device->hidden->pcm_buf = (Uint8 *) SDL_malloc(device->buffer_size); | ||
| 277 | if (device->hidden->pcm_buf == NULL) { | ||
| 278 | return false; | ||
| 279 | } | ||
| 280 | SDL_memset(device->hidden->pcm_buf, device->silence_value, device->buffer_size); | ||
| 281 | |||
| 282 | // get the file descriptor | ||
| 283 | device->hidden->audio_fd = snd_pcm_file_descriptor(device->hidden->audio_handle, csetup.channel); | ||
| 284 | if (device->hidden->audio_fd < 0) { | ||
| 285 | return QSA_SetError("snd_pcm_file_descriptor", device->hidden->audio_fd); | ||
| 286 | } | ||
| 287 | |||
| 288 | // Prepare an audio channel | ||
| 289 | status = snd_pcm_plugin_prepare(device->hidden->audio_handle, csetup.channel) | ||
| 290 | if (status < 0) { | ||
| 291 | return QSA_SetError("snd_pcm_plugin_prepare", status); | ||
| 292 | } | ||
| 293 | |||
| 294 | return true; // We're really ready to rock and roll. :-) | ||
| 295 | } | ||
| 296 | |||
| 297 | static SDL_AudioFormat QnxFormatToSDLFormat(const int32_t qnxfmt) | ||
| 298 | { | ||
| 299 | switch (qnxfmt) { | ||
| 300 | #define CHECKFMT(sdlfmt, qsafmt) case SND_PCM_SFMT_##qsafmt: return SDL_AUDIO_##sdlfmt | ||
| 301 | CHECKFMT(U8, U8); | ||
| 302 | CHECKFMT(S8, S8); | ||
| 303 | CHECKFMT(S16LSB, S16_LE); | ||
| 304 | CHECKFMT(S16MSB, S16_BE); | ||
| 305 | CHECKFMT(S32LSB, S32_LE); | ||
| 306 | CHECKFMT(S32MSB, S32_BE); | ||
| 307 | CHECKFMT(F32LSB, FLOAT_LE); | ||
| 308 | CHECKFMT(F32MSB, FLOAT_BE); | ||
| 309 | #undef CHECKFMT | ||
| 310 | default: break; | ||
| 311 | } | ||
| 312 | return SDL_AUDIO_S16; // oh well. | ||
| 313 | } | ||
| 314 | |||
| 315 | static void QSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) | ||
| 316 | { | ||
| 317 | // Detect amount of available devices | ||
| 318 | // this value can be changed in the runtime | ||
| 319 | int num_cards = 0; | ||
| 320 | (void) snd_cards_list(NULL, 0, &alloc_num_cards); | ||
| 321 | bool isstack = false; | ||
| 322 | int *cards = SDL_small_alloc(int, num_cards, &isstack); | ||
| 323 | if (!cards) { | ||
| 324 | return; // we're in trouble. | ||
| 325 | } | ||
| 326 | int overflow_cards = 0; | ||
| 327 | const int total_num_cards = snd_cards_list(cards, num_cards, &overflow_cards); | ||
| 328 | // if overflow_cards > 0 or total_num_cards > num_cards, it changed at the last moment; oh well, we lost some. | ||
| 329 | num_cards = SDL_min(num_cards, total_num_cards); // ...but make sure it didn't _shrink_. | ||
| 330 | |||
| 331 | // If io-audio manager is not running we will get 0 as number of available audio devices | ||
| 332 | if (num_cards == 0) { // not any available audio devices? | ||
| 333 | SDL_small_free(cards, isstack); | ||
| 334 | return; | ||
| 335 | } | ||
| 336 | |||
| 337 | // Find requested devices by type | ||
| 338 | for (int it = 0; it < num_cards; it++) { | ||
| 339 | const int card = cards[it]; | ||
| 340 | for (uint32_t deviceno = 0; ; deviceno++) { | ||
| 341 | int32_t status; | ||
| 342 | char name[QSA_MAX_NAME_LENGTH]; | ||
| 343 | |||
| 344 | status = snd_card_get_longname(card, name, sizeof (name)); | ||
| 345 | if (status == EOK) { | ||
| 346 | snd_pcm_t *handle; | ||
| 347 | |||
| 348 | // Add device number to device name | ||
| 349 | char fullname[QSA_MAX_NAME_LENGTH + 32]; | ||
| 350 | SDL_snprintf(fullname, sizeof (fullname), "%s d%d", name, (int) deviceno); | ||
| 351 | |||
| 352 | // Check if this device id could play anything | ||
| 353 | bool recording = false; | ||
| 354 | status = snd_pcm_open(&handle, card, deviceno, SND_PCM_OPEN_PLAYBACK); | ||
| 355 | if (status != EOK) { // no? See if it's a recording device instead. | ||
| 356 | #if 0 // !!! FIXME: most of this code has support for recording devices, but there's no RecordDevice, etc functions. Fill them in! | ||
| 357 | status = snd_pcm_open(&handle, card, deviceno, SND_PCM_OPEN_CAPTURE); | ||
| 358 | if (status == EOK) { | ||
| 359 | recording = true; | ||
| 360 | } | ||
| 361 | #endif | ||
| 362 | } | ||
| 363 | |||
| 364 | if (status == EOK) { | ||
| 365 | SDL_AudioSpec spec; | ||
| 366 | SDL_zero(spec); | ||
| 367 | SDL_AudioSpec *pspec = &spec; | ||
| 368 | snd_pcm_channel_setup_t csetup; | ||
| 369 | SDL_zero(csetup); | ||
| 370 | csetup.channel = recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; | ||
| 371 | |||
| 372 | if (snd_pcm_plugin_setup(device->hidden->audio_handle, &csetup) < 0) { | ||
| 373 | pspec = NULL; // go on without spec info. | ||
| 374 | } else { | ||
| 375 | spec.format = QnxFormatToSDLFormat(csetup.format.format); | ||
| 376 | spec.channels = csetup.format.channels; | ||
| 377 | spec.freq = csetup.format.rate; | ||
| 378 | } | ||
| 379 | |||
| 380 | status = snd_pcm_close(handle); | ||
| 381 | if (status == EOK) { | ||
| 382 | // !!! FIXME: I'm assuming each of these values are way less than 0xFFFF. Fix this if not. | ||
| 383 | SDL_assert(card <= 0xFFFF); | ||
| 384 | SDL_assert(deviceno <= 0xFFFF); | ||
| 385 | const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16); | ||
| 386 | SDL_AddAudioDevice(recording, fullname, pspec, (void *) ((size_t) sdlhandle)); | ||
| 387 | } | ||
| 388 | } else { | ||
| 389 | // Check if we got end of devices list | ||
| 390 | if (status == -ENOENT) { | ||
| 391 | break; | ||
| 392 | } | ||
| 393 | } | ||
| 394 | } else { | ||
| 395 | break; | ||
| 396 | } | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | SDL_small_free(cards, isstack); | ||
| 401 | |||
| 402 | // Try to open the "preferred" devices, which will tell us the card/device pairs for the default devices. | ||
| 403 | snd_pcm_t handle; | ||
| 404 | int cardno, deviceno; | ||
| 405 | if (snd_pcm_open_preferred(&handle, &cardno, &deviceno, SND_PCM_OPEN_PLAYBACK) == 0) { | ||
| 406 | snd_pcm_close(handle); | ||
| 407 | // !!! FIXME: I'm assuming each of these values are way less than 0xFFFF. Fix this if not. | ||
| 408 | SDL_assert(cardno <= 0xFFFF); | ||
| 409 | SDL_assert(deviceno <= 0xFFFF); | ||
| 410 | const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16); | ||
| 411 | *default_playback = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle)); | ||
| 412 | } | ||
| 413 | |||
| 414 | if (snd_pcm_open_preferred(&handle, &cardno, &deviceno, SND_PCM_OPEN_CAPTURE) == 0) { | ||
| 415 | snd_pcm_close(handle); | ||
| 416 | // !!! FIXME: I'm assuming each of these values are way less than 0xFFFF. Fix this if not. | ||
| 417 | SDL_assert(cardno <= 0xFFFF); | ||
| 418 | SDL_assert(deviceno <= 0xFFFF); | ||
| 419 | const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16); | ||
| 420 | *default_recording = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle)); | ||
| 421 | } | ||
| 422 | } | ||
| 423 | |||
| 424 | static void QSA_Deinitialize(void) | ||
| 425 | { | ||
| 426 | // nothing to do here atm. | ||
| 427 | } | ||
| 428 | |||
| 429 | static bool QSA_Init(SDL_AudioDriverImpl * impl) | ||
| 430 | { | ||
| 431 | impl->DetectDevices = QSA_DetectDevices; | ||
| 432 | impl->OpenDevice = QSA_OpenDevice; | ||
| 433 | impl->ThreadInit = QSA_ThreadInit; | ||
| 434 | impl->WaitDevice = QSA_WaitDevice; | ||
| 435 | impl->PlayDevice = QSA_PlayDevice; | ||
| 436 | impl->GetDeviceBuf = QSA_GetDeviceBuf; | ||
| 437 | impl->CloseDevice = QSA_CloseDevice; | ||
| 438 | impl->Deinitialize = QSA_Deinitialize; | ||
| 439 | |||
| 440 | // !!! FIXME: most of this code has support for recording devices, but there's no RecordDevice, etc functions. Fill them in! | ||
| 441 | //impl->HasRecordingSupport = true; | ||
| 442 | |||
| 443 | return true; | ||
| 444 | } | ||
| 445 | |||
| 446 | AudioBootStrap QSAAUDIO_bootstrap = { | ||
| 447 | "qsa", "QNX QSA Audio", QSA_Init, false, false | ||
| 448 | }; | ||
| 449 | |||
| 450 | #endif // SDL_AUDIO_DRIVER_QNX | ||
| 451 | |||
diff --git a/contrib/SDL-3.2.8/src/audio/qnx/SDL_qsa_audio.h b/contrib/SDL-3.2.8/src/audio/qnx/SDL_qsa_audio.h new file mode 100644 index 0000000..902752c --- /dev/null +++ b/contrib/SDL-3.2.8/src/audio/qnx/SDL_qsa_audio.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 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 | |||
| 22 | #include "../../SDL_internal.h" | ||
| 23 | |||
| 24 | #ifndef __SDL_QSA_AUDIO_H__ | ||
| 25 | #define __SDL_QSA_AUDIO_H__ | ||
| 26 | |||
| 27 | #include <sys/asoundlib.h> | ||
| 28 | |||
| 29 | #include "../SDL_sysaudio.h" | ||
| 30 | |||
| 31 | struct SDL_PrivateAudioData | ||
| 32 | { | ||
| 33 | snd_pcm_t *audio_handle; // The audio device handle | ||
| 34 | int audio_fd; // The audio file descriptor, for selecting on | ||
| 35 | bool timeout_on_wait; // Select timeout status | ||
| 36 | Uint8 *pcm_buf; // Raw mixing buffer | ||
| 37 | }; | ||
| 38 | |||
| 39 | #endif // __SDL_QSA_AUDIO_H__ | ||
| 40 | |||
