Mercurial > sdl-ios-xcode
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 */ |