comparison src/audio/dma/SDL_dmaaudio.c @ 3810:2c5387c0a642 SDL-ryan-multiple-audio-device

Multiple audio device code is now working for dsp and dma targets.
author Ryan C. Gordon <icculus@icculus.org>
date Thu, 05 Oct 2006 04:47:13 +0000
parents c8b3d3d13ed1
children 9d070c1a45fa
comparison
equal deleted inserted replaced
3809:7852b5b78af5 3810:2c5387c0a642
57 57
58 /* The tag name used by DMA audio */ 58 /* The tag name used by DMA audio */
59 #define DMA_DRIVER_NAME "dma" 59 #define DMA_DRIVER_NAME "dma"
60 60
61 /* Open the audio device for playback, and don't block if busy */ 61 /* Open the audio device for playback, and don't block if busy */
62 #define OPEN_FLAGS (O_RDWR|O_NONBLOCK) 62 #define OPEN_FLAGS_INPUT (O_RDWR|O_NONBLOCK)
63 #define OPEN_FLAGS_OUTPUT (O_RDWR|O_NONBLOCK)
63 64
64 /* Audio driver functions */ 65 /* Audio driver functions */
65 static int DMA_DetectDevices(int iscapture); 66 static int DMA_DetectDevices(int iscapture);
66 static const char *DMA_GetDeviceName(int index, int iscapture); 67 static const char *DMA_GetDeviceName(int index, int iscapture);
67 static int DMA_OpenDevice(_THIS, const char *devname, int iscapture); 68 static int DMA_OpenDevice(_THIS, const char *devname, int iscapture);
68 static void DMA_WaitDevice(_THIS); 69 static void DMA_WaitDevice(_THIS);
69 static void DMA_PlayDevice(_THIS); 70 static void DMA_PlayDevice(_THIS);
70 static Uint8 *DMA_GetDeviceBuf(_THIS); 71 static Uint8 *DMA_GetDeviceBuf(_THIS);
71 static void DMA_CloseDevice(_THIS); 72 static void DMA_CloseDevice(_THIS);
73 static void DMA_Deinitialize(void);
72 74
73 /* Audio driver bootstrap functions */ 75 /* Audio driver bootstrap functions */
74 76
77 static char **outputDevices = NULL;
78 static int outputDeviceCount = 0;
79 static char **inputDevices = NULL;
80 static int inputDeviceCount = 0;
81
82 static int
83 test_for_mmap(int fd)
84 {
85 int caps = 0;
86 struct audio_buf_info info;
87 if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) &&
88 (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
89 (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0))
90 {
91 size_t len = info.fragstotal * info.fragsize;
92 Uint8 *buf = (Uint8 *) mmap(NULL, len, PROT_WRITE, MAP_SHARED, fd, 0);
93 if (buf != MAP_FAILED) {
94 munmap(buf, len);
95 return 1;
96 }
97 }
98 return 0;
99 }
100
101
102 static inline void
103 free_device_list(char ***devs, int *count)
104 {
105 SDL_FreeUnixAudioDevices(devs, count);
106 }
107
108 static inline void
109 build_device_list(int iscapture, char ***devs, int *count)
110 {
111 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
112 free_device_list(devs, count);
113 SDL_EnumUnixAudioDevices(flags, 0, test_for_mmap, devs, count);
114 }
115
116 static inline void
117 build_device_lists(void)
118 {
119 build_device_list(0, &outputDevices, &outputDeviceCount);
120 build_device_list(1, &inputDevices, &inputDeviceCount);
121 }
122
123
124 static inline void
125 free_device_lists(void)
126 {
127 free_device_list(&outputDevices, &outputDeviceCount);
128 free_device_list(&inputDevices, &inputDeviceCount);
129 }
130
75 static int 131 static int
76 DMA_Available(void) 132 DMA_Available(void)
77 { 133 {
78 /* 134 int available = 0;
79 * !!! FIXME: maybe change this to always available, and move this to 135 build_device_lists();
80 * !!! FIXME: to device enumeration and opening? 136 available = ((outputDeviceCount > 0) || (inputDeviceCount > 0));
81 */ 137 free_device_lists();
82 int available; 138 return available;
83 int fd;
84
85 available = 0;
86
87 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
88 if (fd >= 0) {
89 int caps;
90 struct audio_buf_info info;
91
92 if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) &&
93 (caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
94 (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0)) {
95 available = 1;
96 }
97 close(fd);
98 }
99 return (available);
100 } 139 }
101 140
102 141
103 static int 142 static int
104 DMA_Init(SDL_AudioDriverImpl *impl) 143 DMA_Init(SDL_AudioDriverImpl *impl)
109 impl->OpenDevice = DMA_OpenDevice; 148 impl->OpenDevice = DMA_OpenDevice;
110 impl->WaitDevice = DMA_WaitDevice; 149 impl->WaitDevice = DMA_WaitDevice;
111 impl->PlayDevice = DMA_PlayDevice; 150 impl->PlayDevice = DMA_PlayDevice;
112 impl->GetDeviceBuf = DMA_GetDeviceBuf; 151 impl->GetDeviceBuf = DMA_GetDeviceBuf;
113 impl->CloseDevice = DMA_CloseDevice; 152 impl->CloseDevice = DMA_CloseDevice;
114 153 impl->Deinitialize = DMA_Deinitialize;
154
155 build_device_lists();
115 return 1; 156 return 1;
116 } 157 }
117 158
118 AudioBootStrap DMA_bootstrap = { 159 AudioBootStrap DMA_bootstrap = {
119 DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio", 160 DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio",
120 DMA_Available, DMA_Init, 0 161 DMA_Available, DMA_Init, 0
121 }; 162 };
122 163
164 static void DMA_Deinitialize(void)
165 {
166 free_device_lists();
167 }
123 168
124 static int 169 static int
125 DMA_DetectDevices(int iscapture) 170 DMA_DetectDevices(int iscapture)
126 { 171 {
127 return -1; /* !!! FIXME */ 172 if (iscapture) {
173 build_device_list(1, &inputDevices, &inputDeviceCount);
174 return inputDeviceCount;
175 } else {
176 build_device_list(0, &outputDevices, &outputDeviceCount);
177 return outputDeviceCount;
178 }
179
180 return 0; /* shouldn't ever hit this. */
128 } 181 }
129 182
130 183
131 static const char * 184 static const char *
132 DMA_GetDeviceName(int index, int iscapture) 185 DMA_GetDeviceName(int index, int iscapture)
133 { 186 {
134 SDL_SetError("No such device"); /* !!! FIXME */ 187 if ((iscapture) && (index < inputDeviceCount)) {
188 return inputDevices[index];
189 } else if ((!iscapture) && (index < outputDeviceCount)) {
190 return outputDevices[index];
191 }
192
193 SDL_SetError("No such device");
135 return NULL; 194 return NULL;
136 } 195 }
137 196
138 197
139 static int 198 static int
196 255
197 256
198 static int 257 static int
199 open_device_internal(_THIS, const char *devname, int iscapture) 258 open_device_internal(_THIS, const char *devname, int iscapture)
200 { 259 {
201 char audiodev[1024]; 260 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
202 int format; 261 int format;
203 int stereo; 262 int stereo;
204 int value; 263 int value;
205 SDL_AudioFormat test_format; 264 SDL_AudioFormat test_format;
206 struct audio_buf_info info; 265 struct audio_buf_info info;
207 266
267 /* We don't care what the devname is...we'll try to open anything. */
268 /* ...but default to first name in the list... */
269 if (devname == NULL) {
270 if ( ((iscapture) && (inputDeviceCount == 0)) ||
271 ((!iscapture) && (outputDeviceCount == 0)) ) {
272 SDL_SetError("No such audio device");
273 return 0;
274 }
275 devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
276 }
277
208 /* Initialize all variables that we clean on shutdown */ 278 /* Initialize all variables that we clean on shutdown */
209 this->hidden = (struct SDL_PrivateAudioData *) 279 this->hidden = (struct SDL_PrivateAudioData *)
210 SDL_malloc((sizeof *this->hidden)); 280 SDL_malloc((sizeof *this->hidden));
211 if (this->hidden == NULL) { 281 if (this->hidden == NULL) {
212 SDL_OutOfMemory(); 282 SDL_OutOfMemory();
213 return 0; 283 return 0;
214 } 284 }
215 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); 285 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
216 286
217 /* !!! FIXME: handle devname */
218 /* !!! FIXME: handle iscapture */
219 287
220 /* Open the audio device */ 288 /* Open the audio device */
221 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); 289 audio_fd = open(devname, flags, 0);
222 if (audio_fd < 0) { 290 if (audio_fd < 0) {
223 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); 291 SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
224 return 0; 292 return 0;
225 } 293 }
226 dma_buf = NULL; 294 dma_buf = NULL;
227 ioctl(audio_fd, SNDCTL_DSP_RESET, 0); 295 ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
228 296
302 370
303 /* Because some drivers don't allow setting the buffer size 371 /* Because some drivers don't allow setting the buffer size
304 after setting the format, we must re-open the audio device 372 after setting the format, we must re-open the audio device
305 once we know what format and channels are supported 373 once we know what format and channels are supported
306 */ 374 */
307 if (DMA_ReopenAudio(this, audiodev, format, stereo) < 0) { 375 if (DMA_ReopenAudio(this, devname, format, stereo) < 0) {
308 /* Error is set by DMA_ReopenAudio() */ 376 /* Error is set by DMA_ReopenAudio() */
309 return 0; 377 return 0;
310 } 378 }
311 379
312 /* Memory map the audio buffer */ 380 /* Memory map the audio buffer */