SDL_audiodev.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2022 Sam Lantinga <[email protected]>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "../SDL_internal.h"
  19. /* Get the name of the audio device we use for output */
  20. #if SDL_AUDIO_DRIVER_NETBSD || SDL_AUDIO_DRIVER_OSS || SDL_AUDIO_DRIVER_SUNAUDIO
  21. #include <fcntl.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <unistd.h> /* For close() */
  25. #include "SDL_stdinc.h"
  26. #include "SDL_audiodev_c.h"
  27. #ifndef _PATH_DEV_DSP
  28. #if defined(__NETBSD__) || defined(__OPENBSD__)
  29. #define _PATH_DEV_DSP "/dev/audio"
  30. #else
  31. #define _PATH_DEV_DSP "/dev/dsp"
  32. #endif
  33. #endif
  34. #ifndef _PATH_DEV_DSP24
  35. #define _PATH_DEV_DSP24 "/dev/sound/dsp"
  36. #endif
  37. #ifndef _PATH_DEV_AUDIO
  38. #define _PATH_DEV_AUDIO "/dev/audio"
  39. #endif
  40. static void
  41. test_device(const int iscapture, const char *fname, int flags, int (*test) (int fd))
  42. {
  43. struct stat sb;
  44. if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) {
  45. const int audio_fd = open(fname, flags | O_CLOEXEC, 0);
  46. if (audio_fd >= 0) {
  47. const int okay = test(audio_fd);
  48. close(audio_fd);
  49. if (okay) {
  50. static size_t dummyhandle = 0;
  51. dummyhandle++;
  52. SDL_assert(dummyhandle != 0);
  53. /* Note that spec is NULL; while we are opening the device
  54. * endpoint here, the endpoint does not provide any mix format
  55. * information, making this information inaccessible at
  56. * enumeration time
  57. */
  58. SDL_AddAudioDevice(iscapture, fname, NULL, (void *) (uintptr_t) dummyhandle);
  59. }
  60. }
  61. }
  62. }
  63. static int
  64. test_stub(int fd)
  65. {
  66. return 1;
  67. }
  68. static void
  69. SDL_EnumUnixAudioDevices_Internal(const int iscapture, const int classic, int (*test)(int))
  70. {
  71. const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
  72. const char *audiodev;
  73. char audiopath[1024];
  74. if (test == NULL)
  75. test = test_stub;
  76. /* Figure out what our audio device is */
  77. if (((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) &&
  78. ((audiodev = SDL_getenv("AUDIODEV")) == NULL)) {
  79. if (classic) {
  80. audiodev = _PATH_DEV_AUDIO;
  81. } else {
  82. struct stat sb;
  83. /* Added support for /dev/sound/\* in Linux 2.4 */
  84. if (((stat("/dev/sound", &sb) == 0) && S_ISDIR(sb.st_mode))
  85. && ((stat(_PATH_DEV_DSP24, &sb) == 0)
  86. && S_ISCHR(sb.st_mode))) {
  87. audiodev = _PATH_DEV_DSP24;
  88. } else {
  89. audiodev = _PATH_DEV_DSP;
  90. }
  91. }
  92. }
  93. test_device(iscapture, audiodev, flags, test);
  94. if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) {
  95. int instance = 0;
  96. while (instance <= 64) {
  97. SDL_snprintf(audiopath, SDL_arraysize(audiopath),
  98. "%s%d", audiodev, instance);
  99. instance++;
  100. test_device(iscapture, audiopath, flags, test);
  101. }
  102. }
  103. }
  104. void
  105. SDL_EnumUnixAudioDevices(const int classic, int (*test)(int))
  106. {
  107. SDL_EnumUnixAudioDevices_Internal(SDL_TRUE, classic, test);
  108. SDL_EnumUnixAudioDevices_Internal(SDL_FALSE, classic, test);
  109. }
  110. #endif /* Audio driver selection */
  111. /* vi: set ts=4 sw=4 expandtab: */