Mercurial > sdl-ios-xcode
comparison src/audio/dsp/SDL_dspaudio.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 |
---|---|
53 | 53 |
54 /* The tag name used by DSP audio */ | 54 /* The tag name used by DSP audio */ |
55 #define DSP_DRIVER_NAME "dsp" | 55 #define DSP_DRIVER_NAME "dsp" |
56 | 56 |
57 /* Open the audio device for playback, and don't block if busy */ | 57 /* Open the audio device for playback, and don't block if busy */ |
58 #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) | 58 #define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK) |
59 #define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK) | |
59 | 60 |
60 /* Audio driver functions */ | 61 /* Audio driver functions */ |
61 static int DSP_DetectDevices(int iscapture); | 62 static int DSP_DetectDevices(int iscapture); |
62 static const char *DSP_GetDeviceName(int index, int iscapture); | 63 static const char *DSP_GetDeviceName(int index, int iscapture); |
63 static int DSP_OpenDevice(_THIS, const char *devname, int iscapture); | 64 static int DSP_OpenDevice(_THIS, const char *devname, int iscapture); |
64 static void DSP_WaitDevice(_THIS); | 65 static void DSP_WaitDevice(_THIS); |
65 static void DSP_PlayDevice(_THIS); | 66 static void DSP_PlayDevice(_THIS); |
66 static Uint8 *DSP_GetDeviceBuf(_THIS); | 67 static Uint8 *DSP_GetDeviceBuf(_THIS); |
67 static void DSP_CloseDevice(_THIS); | 68 static void DSP_CloseDevice(_THIS); |
69 static void DSP_Deinitialize(void); | |
68 | 70 |
69 /* Audio driver bootstrap functions */ | 71 /* Audio driver bootstrap functions */ |
72 | |
73 static char **outputDevices = NULL; | |
74 static int outputDeviceCount = 0; | |
75 static char **inputDevices = NULL; | |
76 static int inputDeviceCount = 0; | |
77 | |
78 static inline void | |
79 free_device_list(char ***devs, int *count) | |
80 { | |
81 SDL_FreeUnixAudioDevices(devs, count); | |
82 } | |
83 | |
84 static inline void | |
85 build_device_list(int iscapture, char ***devs, int *count) | |
86 { | |
87 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); | |
88 free_device_list(devs, count); | |
89 SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count); | |
90 } | |
91 | |
92 static inline void | |
93 build_device_lists(void) | |
94 { | |
95 build_device_list(0, &outputDevices, &outputDeviceCount); | |
96 build_device_list(1, &inputDevices, &inputDeviceCount); | |
97 } | |
98 | |
99 | |
100 static inline void | |
101 free_device_lists(void) | |
102 { | |
103 free_device_list(&outputDevices, &outputDeviceCount); | |
104 free_device_list(&inputDevices, &inputDeviceCount); | |
105 } | |
106 | |
70 | 107 |
71 static int | 108 static int |
72 DSP_Available(void) | 109 DSP_Available(void) |
73 { | 110 { |
74 /* | |
75 * !!! FIXME: maybe change this to always available, and move this to | |
76 * !!! FIXME: to device enumeration and opening? | |
77 */ | |
78 int fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); | |
79 int available = 0; | 111 int available = 0; |
80 if (fd >= 0) { | 112 build_device_lists(); |
81 available = 1; | 113 available = ((outputDeviceCount > 0) || (inputDeviceCount > 0)); |
82 close(fd); | 114 free_device_lists(); |
83 } | 115 return available; |
84 return (available); | |
85 } | 116 } |
86 | 117 |
87 | 118 |
88 static int | 119 static int |
89 DSP_Init(SDL_AudioDriverImpl *impl) | 120 DSP_Init(SDL_AudioDriverImpl *impl) |
90 { | 121 { |
91 /* Set the function pointers */ | 122 /* Set the function pointers */ |
92 impl->DetectDevices = DSP_DetectDevices; | 123 impl->DetectDevices = DSP_DetectDevices; |
93 impl->GetDeviceName = DSP_GetDeviceName; | 124 impl->GetDeviceName = DSP_GetDeviceName; |
94 impl->OpenDevice = DSP_OpenDevice; | 125 impl->OpenDevice = DSP_OpenDevice; |
95 impl->WaitDevice = DSP_WaitDevice; | |
96 impl->PlayDevice = DSP_PlayDevice; | 126 impl->PlayDevice = DSP_PlayDevice; |
97 impl->GetDeviceBuf = DSP_GetDeviceBuf; | 127 impl->GetDeviceBuf = DSP_GetDeviceBuf; |
98 impl->CloseDevice = DSP_CloseDevice; | 128 impl->CloseDevice = DSP_CloseDevice; |
99 | 129 impl->Deinitialize = DSP_Deinitialize; |
130 | |
131 build_device_lists(); | |
100 return 1; | 132 return 1; |
101 } | 133 } |
102 | 134 |
103 | 135 |
104 AudioBootStrap DSP_bootstrap = { | 136 AudioBootStrap DSP_bootstrap = { |
105 DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", | 137 DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", |
106 DSP_Available, DSP_Init, 0 | 138 DSP_Available, DSP_Init, 0 |
107 }; | 139 }; |
108 | 140 |
109 | 141 |
142 static void DSP_Deinitialize(void) | |
143 { | |
144 free_device_lists(); | |
145 } | |
146 | |
147 | |
110 static int | 148 static int |
111 DSP_DetectDevices(int iscapture) | 149 DSP_DetectDevices(int iscapture) |
112 { | 150 { |
113 return -1; /* !!! FIXME */ | 151 if (iscapture) { |
114 } | 152 build_device_list(1, &inputDevices, &inputDeviceCount); |
115 | 153 return inputDeviceCount; |
154 } else { | |
155 build_device_list(0, &outputDevices, &outputDeviceCount); | |
156 return outputDeviceCount; | |
157 } | |
158 | |
159 return 0; /* shouldn't ever hit this. */ | |
160 } | |
116 | 161 |
117 static const char * | 162 static const char * |
118 DSP_GetDeviceName(int index, int iscapture) | 163 DSP_GetDeviceName(int index, int iscapture) |
119 { | 164 { |
120 SDL_SetError("No such device"); /* !!! FIXME */ | 165 if ((iscapture) && (index < inputDeviceCount)) { |
166 return inputDevices[index]; | |
167 } else if ((!iscapture) && (index < outputDeviceCount)) { | |
168 return outputDevices[index]; | |
169 } | |
170 | |
171 SDL_SetError("No such device"); | |
121 return NULL; | 172 return NULL; |
122 } | 173 } |
123 | 174 |
124 | 175 |
125 static int | 176 static int |
126 DSP_OpenDevice(_THIS, const char *devname, int iscapture) | 177 DSP_OpenDevice(_THIS, const char *devname, int iscapture) |
127 { | 178 { |
128 char dev[1024]; | 179 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); |
129 int format; | 180 int format; |
130 int value; | 181 int value; |
131 int frag_spec; | 182 int frag_spec; |
132 SDL_AudioFormat test_format; | 183 SDL_AudioFormat test_format; |
184 | |
185 /* We don't care what the devname is...we'll try to open anything. */ | |
186 /* ...but default to first name in the list... */ | |
187 if (devname == NULL) { | |
188 if ( ((iscapture) && (inputDeviceCount == 0)) || | |
189 ((!iscapture) && (outputDeviceCount == 0)) ) { | |
190 SDL_SetError("No such audio device"); | |
191 return 0; | |
192 } | |
193 devname = ((iscapture) ? inputDevices[0] : outputDevices[0]); | |
194 } | |
133 | 195 |
134 /* Initialize all variables that we clean on shutdown */ | 196 /* Initialize all variables that we clean on shutdown */ |
135 this->hidden = (struct SDL_PrivateAudioData *) | 197 this->hidden = (struct SDL_PrivateAudioData *) |
136 SDL_malloc((sizeof *this->hidden)); | 198 SDL_malloc((sizeof *this->hidden)); |
137 if (this->hidden == NULL) { | 199 if (this->hidden == NULL) { |
139 return 0; | 201 return 0; |
140 } | 202 } |
141 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | 203 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
142 this->hidden->audio_fd = -1; | 204 this->hidden->audio_fd = -1; |
143 | 205 |
144 /* !!! FIXME: handle devname */ | |
145 /* !!! FIXME: handle iscapture */ | |
146 | |
147 /* Open the audio device */ | 206 /* Open the audio device */ |
148 this->hidden->audio_fd = SDL_OpenAudioPath(dev, sizeof(dev), OPEN_FLAGS, 0); | 207 this->hidden->audio_fd = open(devname, flags, 0); |
149 if (this->hidden->audio_fd < 0) { | 208 if (this->hidden->audio_fd < 0) { |
150 SDL_SetError("Couldn't open %s: %s", dev, strerror(errno)); | 209 SDL_SetError("Couldn't open %s: %s", devname, strerror(errno)); |
151 return 0; | 210 return 0; |
152 } | 211 } |
153 this->hidden->mixbuf = NULL; | 212 this->hidden->mixbuf = NULL; |
154 | 213 |
155 /* Make the file descriptor use blocking writes with fcntl() */ | 214 /* Make the file descriptor use blocking writes with fcntl() */ |
304 /* We're ready to rock and roll. :-) */ | 363 /* We're ready to rock and roll. :-) */ |
305 return 1; | 364 return 1; |
306 } | 365 } |
307 | 366 |
308 | 367 |
309 /* This function waits until it is possible to write a full sound buffer */ | |
310 static void | |
311 DSP_WaitDevice(_THIS) | |
312 { | |
313 /* Not needed at all since OSS handles waiting automagically */ | |
314 } | |
315 | |
316 | |
317 static void | 368 static void |
318 DSP_PlayDevice(_THIS) | 369 DSP_PlayDevice(_THIS) |
319 { | 370 { |
320 const Uint8 *mixbuf = this->hidden->mixbuf; | 371 const Uint8 *mixbuf = this->hidden->mixbuf; |
321 const int mixlen = this->hidden->mixlen; | 372 const int mixlen = this->hidden->mixlen; |