comparison libao2/ao_macosx.c @ 10152:b252d1b6829e

cleanup/cosmetic patch by the author :)
author alex
date Thu, 22 May 2003 16:12:54 +0000
parents f2725d6717bd
children 99798c3cdb93
comparison
equal deleted inserted replaced
10151:f096d8578c3d 10152:b252d1b6829e
18 * GNU General Public License for more details. 18 * GNU General Public License for more details.
19 * 19 *
20 * You should have received a copy of the GNU General Public License 20 * You should have received a copy of the GNU General Public License
21 * along with GNU Make; see the file COPYING. If not, write to 21 * along with GNU Make; see the file COPYING. If not, write to
22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * $Id$
25 */ 23 */
26 24
27 /* 25 /*
28 * The MacOS X CoreAudio framework doesn't mesh as simply as some 26 * The MacOS X CoreAudio framework doesn't mesh as simply as some
29 * simpler frameworks do. This is due to the fact that CoreAudio pulls 27 * simpler frameworks do. This is due to the fact that CoreAudio pulls
35 * 33 *
36 * 14/5-2003: Ported to MPlayer libao2 by Dan Christiansen 34 * 14/5-2003: Ported to MPlayer libao2 by Dan Christiansen
37 * 35 *
38 * AC-3 and MPEG audio passthrough is possible, but I don't have 36 * AC-3 and MPEG audio passthrough is possible, but I don't have
39 * access to a sound card that supports it. 37 * access to a sound card that supports it.
40 */
41
42
43 */ 38 */
44 39
45 #include <CoreAudio/AudioHardware.h> 40 #include <CoreAudio/AudioHardware.h>
46 #include <stdio.h> 41 #include <stdio.h>
47 #include <string.h> 42 #include <string.h>
62 "" 57 ""
63 }; 58 };
64 59
65 LIBAO_EXTERN(macosx) 60 LIBAO_EXTERN(macosx)
66 61
62 /* Prefix for all mp_msg() calls */
63 #define ao_msg(a, b, c...) mp_msg(a, b, "AO: [macosx] " c)
64
67 /* This is large, but best (maybe it should be even larger). 65 /* This is large, but best (maybe it should be even larger).
68 * CoreAudio supposedly has an internal latency in the order of 2ms */ 66 * CoreAudio supposedly has an internal latency in the order of 2ms */
69 #define NUM_BUFS 128 67 #define NUM_BUFS 128
70 68
71 typedef struct ao_macosx_s 69 typedef struct ao_macosx_s
95 int len2=0; 93 int len2=0;
96 int x; 94 int x;
97 95
98 while(len>0){ 96 while(len>0){
99 if(ao->full_buffers==NUM_BUFS) { 97 if(ao->full_buffers==NUM_BUFS) {
100 mp_msg(MSGT_AO,MSGL_V, "ao_macosx: Buffer overrun\n"); 98 ao_msg(MSGT_AO,MSGL_V, "Buffer overrun\n");
101 break; 99 break;
102 } 100 }
103 101
104 x=ao->buffer_len-ao->buf_write_pos; 102 x=ao->buffer_len-ao->buf_write_pos;
105 if(x>len) x=len; 103 if(x>len) x=len;
125 int len2=0; 123 int len2=0;
126 int x; 124 int x;
127 125
128 while(len>0){ 126 while(len>0){
129 if(ao->full_buffers==0) { 127 if(ao->full_buffers==0) {
130 mp_msg(MSGT_AO,MSGL_V, "ao_macosx: Buffer underrun\n"); 128 ao_msg(MSGT_AO,MSGL_V, "Buffer underrun\n");
131 break; 129 break;
132 } 130 }
133 131
134 x=ao->buffer_len-ao->buf_read_pos; 132 x=ao->buffer_len-ao->buf_read_pos;
135 if(x>len) x=len; 133 if(x>len) x=len;
169 case AOCONTROL_SET_DEVICE: 167 case AOCONTROL_SET_DEVICE:
170 case AOCONTROL_GET_DEVICE: 168 case AOCONTROL_GET_DEVICE:
171 case AOCONTROL_GET_VOLUME: 169 case AOCONTROL_GET_VOLUME:
172 case AOCONTROL_SET_VOLUME: 170 case AOCONTROL_SET_VOLUME:
173 /* unimplemented/meaningless */ 171 /* unimplemented/meaningless */
174 return CONTROL_NA; 172 return CONTROL_FALSE;
175 case AOCONTROL_QUERY_FORMAT: 173 case AOCONTROL_QUERY_FORMAT:
176 /* stick with what CoreAudio requests */ 174 /* stick with what CoreAudio requests */
177 return CONTROL_NA; 175 return CONTROL_FALSE;
178 default: 176 default:
179 return CONTROL_UNKNOWN; 177 return CONTROL_FALSE;
180 } 178 }
181 179
182 } 180 }
183 181
184 182
197 195
198 /* get default output device */ 196 /* get default output device */
199 propertySize = sizeof(ao->outputDeviceID); 197 propertySize = sizeof(ao->outputDeviceID);
200 status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &propertySize, &(ao->outputDeviceID)); 198 status = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &propertySize, &(ao->outputDeviceID));
201 if (status) { 199 if (status) {
202 mp_msg(MSGT_AO,MSGL_WARN, 200 ao_msg(MSGT_AO,MSGL_WARN,
203 "ao_coreaudio: AudioHardwareGetProperty returned %d\n", 201 "AudioHardwareGetProperty returned %d\n",
204 (int)status); 202 (int)status);
205 return CONTROL_ERROR; 203 return CONTROL_FALSE;
206 } 204 }
207 205
208 if (ao->outputDeviceID == kAudioDeviceUnknown) { 206 if (ao->outputDeviceID == kAudioDeviceUnknown) {
209 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: AudioHardwareGetProperty: ao->outputDeviceID is kAudioDeviceUnknown\n"); 207 ao_msg(MSGT_AO,MSGL_WARN, "AudioHardwareGetProperty: ao->outputDeviceID is kAudioDeviceUnknown\n");
210 return CONTROL_ERROR; 208 return CONTROL_FALSE;
211 } 209 }
212 210
213 /* get default output format 211 /* get default output format
214 * TODO: get all support formats and iterate through them 212 * TODO: get all support formats and iterate through them
215 */ 213 */
216 propertySize = sizeof(ao->outputStreamBasicDescription); 214 propertySize = sizeof(ao->outputStreamBasicDescription);
217 status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &propertySize, &ao->outputStreamBasicDescription); 215 status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &propertySize, &ao->outputStreamBasicDescription);
218 if (status) { 216 if (status) {
219 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: AudioDeviceGetProperty returned %d when getting kAudioDevicePropertyStreamFormat\n", (int)status); 217 ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceGetProperty returned %d when getting kAudioDevicePropertyStreamFormat\n", (int)status);
220 return CONTROL_ERROR; 218 return CONTROL_FALSE;
221 } 219 }
222 220
223 mp_msg(MSGT_AO,MSGL_V, "hardware format...\n"); 221 ao_msg(MSGT_AO,MSGL_V, "hardware format...\n");
224 mp_msg(MSGT_AO,MSGL_V, "%f mSampleRate\n", ao->outputStreamBasicDescription.mSampleRate); 222 ao_msg(MSGT_AO,MSGL_V, "%f mSampleRate\n", ao->outputStreamBasicDescription.mSampleRate);
225 mp_msg(MSGT_AO,MSGL_V, " %c%c%c%c mFormatID\n", 223 ao_msg(MSGT_AO,MSGL_V, " %c%c%c%c mFormatID\n",
226 (int)(ao->outputStreamBasicDescription.mFormatID & 0xff000000) >> 24, 224 (int)(ao->outputStreamBasicDescription.mFormatID & 0xff000000) >> 24,
227 (int)(ao->outputStreamBasicDescription.mFormatID & 0x00ff0000) >> 16, 225 (int)(ao->outputStreamBasicDescription.mFormatID & 0x00ff0000) >> 16,
228 (int)(ao->outputStreamBasicDescription.mFormatID & 0x0000ff00) >> 8, 226 (int)(ao->outputStreamBasicDescription.mFormatID & 0x0000ff00) >> 8,
229 (int)(ao->outputStreamBasicDescription.mFormatID & 0x000000ff) >> 0); 227 (int)(ao->outputStreamBasicDescription.mFormatID & 0x000000ff) >> 0);
230 mp_msg(MSGT_AO,MSGL_V, "%5d mBytesPerPacket\n", 228 ao_msg(MSGT_AO,MSGL_V, "%5d mBytesPerPacket\n",
231 (int)ao->outputStreamBasicDescription.mBytesPerPacket); 229 (int)ao->outputStreamBasicDescription.mBytesPerPacket);
232 mp_msg(MSGT_AO,MSGL_V, "%5d mFramesPerPacket\n", 230 ao_msg(MSGT_AO,MSGL_V, "%5d mFramesPerPacket\n",
233 (int)ao->outputStreamBasicDescription.mFramesPerPacket); 231 (int)ao->outputStreamBasicDescription.mFramesPerPacket);
234 mp_msg(MSGT_AO,MSGL_V, "%5d mBytesPerFrame\n", 232 ao_msg(MSGT_AO,MSGL_V, "%5d mBytesPerFrame\n",
235 (int)ao->outputStreamBasicDescription.mBytesPerFrame); 233 (int)ao->outputStreamBasicDescription.mBytesPerFrame);
236 mp_msg(MSGT_AO,MSGL_V, "%5d mChannelsPerFrame\n", 234 ao_msg(MSGT_AO,MSGL_V, "%5d mChannelsPerFrame\n",
237 (int)ao->outputStreamBasicDescription.mChannelsPerFrame); 235 (int)ao->outputStreamBasicDescription.mChannelsPerFrame);
238 236
239 /* get requested buffer length */ 237 /* get requested buffer length */
240 propertySize = sizeof(ao->buffer_len); 238 propertySize = sizeof(ao->buffer_len);
241 status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyBufferSize, &propertySize, &ao->buffer_len); 239 status = AudioDeviceGetProperty(ao->outputDeviceID, 0, false, kAudioDevicePropertyBufferSize, &propertySize, &ao->buffer_len);
242 if (status) { 240 if (status) {
243 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: AudioDeviceGetProperty returned %d when getting kAudioDevicePropertyBufferSize\n", (int)status); 241 ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceGetProperty returned %d when getting kAudioDevicePropertyBufferSize\n", (int)status);
244 return CONTROL_ERROR; 242 return CONTROL_FALSE;
245 } 243 }
246 mp_msg(MSGT_AO,MSGL_V, "%5d ao->buffer_len\n", (int)ao->buffer_len); 244 ao_msg(MSGT_AO,MSGL_V, "%5d ao->buffer_len\n", (int)ao->buffer_len);
247 245
248 ao_data.samplerate = (int)ao->outputStreamBasicDescription.mSampleRate; 246 /* FIXME:
247 *
248 * Resampling of 32-bit float audio is broken in MPlayer. Refuse to
249 * handle anything other than the native format until this is fixed
250 * or this module is rewritten, whichever comes first.
251 */
252 if (ao_data.samplerate == ao->outputStreamBasicDescription.mSampleRate) {
253 ao_data.samplerate = (int)ao->outputStreamBasicDescription.mSampleRate;
254 } else {
255 ao_msg(MSGT_AO,MSGL_WARN, "Resampling not supported yet.\n");
256 return 0;
257 }
258
249 ao_data.channels = ao->outputStreamBasicDescription.mChannelsPerFrame; 259 ao_data.channels = ao->outputStreamBasicDescription.mChannelsPerFrame;
250 ao_data.outburst = ao_data.buffersize = ao->buffer_len; 260 ao_data.outburst = ao_data.buffersize = ao->buffer_len;
251 ao_data.bps = 261 ao_data.bps =
252 ao_data.samplerate * ao->outputStreamBasicDescription.mBytesPerFrame; 262 ao_data.samplerate * ao->outputStreamBasicDescription.mBytesPerFrame;
253 263
254 if (ao->outputStreamBasicDescription.mFormatID == kAudioFormatLinearPCM) { 264 if (ao->outputStreamBasicDescription.mFormatID == kAudioFormatLinearPCM) {
255 uint32_t flags = ao->outputStreamBasicDescription.mFormatFlags; 265 uint32_t flags = ao->outputStreamBasicDescription.mFormatFlags;
256 if (flags & kAudioFormatFlagIsFloat) { 266 if (flags & kAudioFormatFlagIsFloat) {
257 ao_data.format = AFMT_FLOAT; 267 ao_data.format = AFMT_FLOAT;
258 } else { 268 } else {
259 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: Unsupported audio output " 269 ao_msg(MSGT_AO,MSGL_WARN, "Unsupported audio output "
260 "format. Please report this to the developers\n", 270 "format %d. Please report this to the developer\n",
261 (int)status); 271 (int)status);
262 } 272 return CONTROL_FALSE;
263 273 }
274
264 } else { 275 } else {
265 /* TODO: handle AFMT_AC3, AFMT_MPEG & friends */ 276 /* TODO: handle AFMT_AC3, AFMT_MPEG & friends */
266 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: Default Audio Device doesn't " 277 ao_msg(MSGT_AO,MSGL_WARN, "Default Audio Device doesn't "
267 "support Linear PCM!\n"); 278 "support Linear PCM!\n");
268 return CONTROL_ERROR; 279 return CONTROL_FALSE;
269 } 280 }
270 281
271 /* Allocate ring-buffer memory */ 282 /* Allocate ring-buffer memory */
272 for(i=0;i<NUM_BUFS;i++) 283 for(i=0;i<NUM_BUFS;i++)
273 ao->buffer[i]=(unsigned char *) malloc(ao->buffer_len); 284 ao->buffer[i]=(unsigned char *) malloc(ao->buffer_len);
278 reset(); 289 reset();
279 290
280 /* Set the IO proc that CoreAudio will call when it needs data */ 291 /* Set the IO proc that CoreAudio will call when it needs data */
281 status = AudioDeviceAddIOProc(ao->outputDeviceID, audioDeviceIOProc, NULL); 292 status = AudioDeviceAddIOProc(ao->outputDeviceID, audioDeviceIOProc, NULL);
282 if (status) { 293 if (status) {
283 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: AudioDeviceAddIOProc returned %d\n", (int)status); 294 ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceAddIOProc returned %d\n", (int)status);
284 return CONTROL_ERROR; 295 return CONTROL_FALSE;
285 } 296 }
286 297
287 /* Start callback */ 298 /* Start callback */
288 status = AudioDeviceStart(ao->outputDeviceID, audioDeviceIOProc); 299 status = AudioDeviceStart(ao->outputDeviceID, audioDeviceIOProc);
289 if (status) { 300 if (status) {
290 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: AudioDeviceStart returned %d\n", 301 ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceStart returned %d\n",
291 (int)status); 302 (int)status);
292 return CONTROL_ERROR; 303 return CONTROL_FALSE;
293 } 304 }
294 305
295 return CONTROL_OK; 306 return CONTROL_OK;
296 } 307 }
297 308
315 ao->buf_write_pos=0; 326 ao->buf_write_pos=0;
316 327
317 ao->full_buffers=0; 328 ao->full_buffers=0;
318 ao->buffered_bytes=0; 329 ao->buffered_bytes=0;
319 330
331 /* zero output buffer */
320 for (i = 0; i < NUM_BUFS; i++) 332 for (i = 0; i < NUM_BUFS; i++)
321 bzero(ao->buffer[i], ao->buffer_len); 333 bzero(ao->buffer[i], ao->buffer_len);
322 334
323 pthread_mutex_unlock(&ao->buffer_mutex); 335 pthread_mutex_unlock(&ao->buffer_mutex);
324 336
325 return; 337 return;
326 } 338 }
327 339
331 { 343 {
332 return (NUM_BUFS-ao->full_buffers)*ao_data.buffersize - ao->buf_write_pos; 344 return (NUM_BUFS-ao->full_buffers)*ao_data.buffersize - ao->buf_write_pos;
333 } 345 }
334 346
335 347
336 /* return delay until audio is played 348 /* return delay until audio is played */
337 * FIXME */
338 static float get_delay() 349 static float get_delay()
339 { 350 {
340 return (float)(ao->buffered_bytes)/(float)ao_data.bps; 351 return (float)(ao->buffered_bytes)/(float)ao_data.bps;
341 } 352 }
342 353
349 360
350 reset(); 361 reset();
351 362
352 status = AudioDeviceRemoveIOProc(ao->outputDeviceID, audioDeviceIOProc); 363 status = AudioDeviceRemoveIOProc(ao->outputDeviceID, audioDeviceIOProc);
353 if (status) 364 if (status)
354 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: AudioDeviceRemoveIOProc " 365 ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceRemoveIOProc "
355 "returned %d\n", (int)status); 366 "returned %d\n", (int)status);
356 367
357 for(i=0;i<NUM_BUFS;i++) free(ao->buffer[i]); 368 for(i=0;i<NUM_BUFS;i++) free(ao->buffer[i]);
358 free(ao); 369 free(ao);
359 } 370 }
365 OSErr status; 376 OSErr status;
366 377
367 /* stop callback */ 378 /* stop callback */
368 status = AudioDeviceStop(ao->outputDeviceID, audioDeviceIOProc); 379 status = AudioDeviceStop(ao->outputDeviceID, audioDeviceIOProc);
369 if (status) 380 if (status)
370 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: AudioDeviceStop returned %d\n", 381 ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceStop returned %d\n",
371 (int)status); 382 (int)status);
372 } 383 }
373 384
374 385
375 /* resume playing, after audio_pause() */ 386 /* resume playing, after audio_pause() */
376 static void audio_resume() 387 static void audio_resume()
377 { 388 {
378 OSErr status = AudioDeviceStart(ao->outputDeviceID, audioDeviceIOProc); 389 OSErr status = AudioDeviceStart(ao->outputDeviceID, audioDeviceIOProc);
379 if (status) 390 if (status)
380 mp_msg(MSGT_AO,MSGL_WARN, "ao_coreaudio: AudioDeviceStart returned %d\n", 391 ao_msg(MSGT_AO,MSGL_WARN, "AudioDeviceStart returned %d\n",
381 (int)status); 392 (int)status);
382 } 393 }
383
384