Update to MPlayer SVN rev 29473 and FFmpeg SVN rev 19572.
[vaapi:athaifas-mplayer.git] / libao2 / ao_coreaudio.c
1 /*
2  * CoreAudio audio output driver for Mac OS X
3  *
4  * original copyright (C) Timothy J. Wood - Aug 2000
5  * ported to MPlayer libao2 by Dan Christiansen
6  *
7  * The S/PDIF part of the code is based on the auhal audio output
8  * module from VideoLAN:
9  * Copyright (c) 2006 Derk-Jan Hartman <hartman at videolan dot org>
10  *
11  * This file is part of MPlayer.
12  *
13  * MPlayer is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * MPlayer is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License along
24  * along with MPlayer; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26  */
27
28 /*
29  * The MacOS X CoreAudio framework doesn't mesh as simply as some
30  * simpler frameworks do.  This is due to the fact that CoreAudio pulls
31  * audio samples rather than having them pushed at it (which is nice
32  * when you are wanting to do good buffering of audio).
33  *
34  * AC-3 and MPEG audio passthrough is possible, but has never been tested
35  * due to lack of a soundcard that supports it.
36  */
37
38 #include <CoreServices/CoreServices.h>
39 #include <AudioUnit/AudioUnit.h>
40 #include <AudioToolbox/AudioToolbox.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <inttypes.h>
45 #include <sys/types.h>
46 #include <unistd.h>
47
48 #include "config.h"
49 #include "mp_msg.h"
50
51 #include "audio_out.h"
52 #include "audio_out_internal.h"
53 #include "libaf/af_format.h"
54 #include "osdep/timer.h"
55 #include "libavutil/fifo.h"
56
57 static const ao_info_t info =
58   {
59     "Darwin/Mac OS X native audio output",
60     "coreaudio",
61     "Timothy J. Wood & Dan Christiansen & Chris Roccati",
62     ""
63   };
64
65 LIBAO_EXTERN(coreaudio)
66
67 /* Prefix for all mp_msg() calls */
68 #define ao_msg(a, b, c...) mp_msg(a, b, "AO: [coreaudio] " c)
69
70 typedef struct ao_coreaudio_s
71 {
72   AudioDeviceID i_selected_dev;             /* Keeps DeviceID of the selected device. */
73   int b_supports_digital;                   /* Does the currently selected device support digital mode? */
74   int b_digital;                            /* Are we running in digital mode? */
75   int b_muted;                              /* Are we muted in digital mode? */
76
77   /* AudioUnit */
78   AudioUnit theOutputUnit;
79
80   /* CoreAudio SPDIF mode specific */
81   pid_t i_hog_pid;                          /* Keeps the pid of our hog status. */
82   AudioStreamID i_stream_id;                /* The StreamID that has a cac3 streamformat */
83   int i_stream_index;                       /* The index of i_stream_id in an AudioBufferList */
84   AudioStreamBasicDescription stream_format;/* The format we changed the stream to */
85   AudioStreamBasicDescription sfmt_revert;  /* The original format of the stream */
86   int b_revert;                             /* Whether we need to revert the stream format */
87   int b_changed_mixing;                     /* Whether we need to set the mixing mode back */
88   int b_stream_format_changed;              /* Flag for main thread to reset stream's format to digital and reset buffer */
89
90   /* Original common part */
91   int packetSize;
92   int paused;
93
94   /* Ring-buffer */
95   AVFifoBuffer *buffer;
96   unsigned int buffer_len; ///< must always be num_chunks * chunk_size
97   unsigned int num_chunks;
98   unsigned int chunk_size;
99 } ao_coreaudio_t;
100
101 static ao_coreaudio_t *ao = NULL;
102
103 /**
104  * \brief add data to ringbuffer
105  */
106 static int write_buffer(unsigned char* data, int len){
107   int free = ao->buffer_len - av_fifo_size(ao->buffer);
108   if (len > free) len = free;
109   return av_fifo_generic_write(ao->buffer, data, len, NULL);
110 }
111
112 /**
113  * \brief remove data from ringbuffer
114  */
115 static int read_buffer(unsigned char* data,int len){
116   int buffered = av_fifo_size(ao->buffer);
117   if (len > buffered) len = buffered;
118   return av_fifo_generic_read(ao->buffer, data, len, NULL);
119 }
120
121 OSStatus theRenderProc(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData)
122 {
123 int amt=av_fifo_size(ao->buffer);
124 int req=(inNumFrames)*ao->packetSize;
125
126         if(amt>req)
127                 amt=req;
128
129         if(amt)
130                 read_buffer((unsigned char *)ioData->mBuffers[0].mData, amt);
131         else audio_pause();
132         ioData->mBuffers[0].mDataByteSize = amt;
133
134         return noErr;
135 }
136
137 static int control(int cmd,void *arg){
138 ao_control_vol_t *control_vol;
139 OSStatus err;
140 Float32 vol;
141         switch (cmd) {
142         case AOCONTROL_GET_VOLUME:
143                 control_vol = (ao_control_vol_t*)arg;
144                 if (ao->b_digital) {
145                         // Digital output has no volume adjust.
146                         return CONTROL_FALSE;
147                 }
148                 err = AudioUnitGetParameter(ao->theOutputUnit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, &vol);
149
150                 if(err==0) {
151                         // printf("GET VOL=%f\n", vol);
152                         control_vol->left=control_vol->right=vol*100.0/4.0;
153                         return CONTROL_TRUE;
154                 }
155                 else {
156                         ao_msg(MSGT_AO, MSGL_WARN, "could not get HAL output volume: [%4.4s]\n", (char *)&err);
157                         return CONTROL_FALSE;
158                 }
159
160         case AOCONTROL_SET_VOLUME:
161                 control_vol = (ao_control_vol_t*)arg;
162
163                 if (ao->b_digital) {
164                         // Digital output can not set volume. Here we have to return true
165                         // to make mixer forget it. Else mixer will add a soft filter,
166                         // that's not we expected and the filter not support ac3 stream
167                         // will cause mplayer die.
168
169                         // Although not support set volume, but at least we support mute.
170                         // MPlayer set mute by set volume to zero, we handle it.
171                         if (control_vol->left == 0 && control_vol->right == 0)
172                                 ao->b_muted = 1;
173                         else
174                                 ao->b_muted = 0;
175                         return CONTROL_TRUE;
176                 }
177
178                 vol=(control_vol->left+control_vol->right)*4.0/200.0;
179                 err = AudioUnitSetParameter(ao->theOutputUnit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, vol, 0);
180                 if(err==0) {
181                         // printf("SET VOL=%f\n", vol);
182                         return CONTROL_TRUE;
183                 }
184                 else {
185                         ao_msg(MSGT_AO, MSGL_WARN, "could not set HAL output volume: [%4.4s]\n", (char *)&err);
186                         return CONTROL_FALSE;
187                 }
188           /* Everything is currently unimplemented */
189         default:
190           return CONTROL_FALSE;
191         }
192
193 }
194
195
196 static void print_format(int lev, const char* str, const AudioStreamBasicDescription *f){
197     uint32_t flags=(uint32_t) f->mFormatFlags;
198     ao_msg(MSGT_AO,lev, "%s %7.1fHz %lubit [%c%c%c%c][%lu][%lu][%lu][%lu][%lu] %s %s %s%s%s%s\n",
199             str, f->mSampleRate, f->mBitsPerChannel,
200             (int)(f->mFormatID & 0xff000000) >> 24,
201             (int)(f->mFormatID & 0x00ff0000) >> 16,
202             (int)(f->mFormatID & 0x0000ff00) >>  8,
203             (int)(f->mFormatID & 0x000000ff) >>  0,
204             f->mFormatFlags, f->mBytesPerPacket,
205             f->mFramesPerPacket, f->mBytesPerFrame,
206             f->mChannelsPerFrame,
207             (flags&kAudioFormatFlagIsFloat) ? "float" : "int",
208             (flags&kAudioFormatFlagIsBigEndian) ? "BE" : "LE",
209             (flags&kAudioFormatFlagIsSignedInteger) ? "S" : "U",
210             (flags&kAudioFormatFlagIsPacked) ? " packed" : "",
211             (flags&kAudioFormatFlagIsAlignedHigh) ? " aligned" : "",
212             (flags&kAudioFormatFlagIsNonInterleaved) ? " ni" : "" );
213 }
214
215
216 static int AudioDeviceSupportsDigital( AudioDeviceID i_dev_id );
217 static int AudioStreamSupportsDigital( AudioStreamID i_stream_id );
218 static int OpenSPDIF(void);
219 static int AudioStreamChangeFormat( AudioStreamID i_stream_id, AudioStreamBasicDescription change_format );
220 static OSStatus RenderCallbackSPDIF( AudioDeviceID inDevice,
221                                     const AudioTimeStamp * inNow,
222                                     const void * inInputData,
223                                     const AudioTimeStamp * inInputTime,
224                                     AudioBufferList * outOutputData,
225                                     const AudioTimeStamp * inOutputTime,
226                                     void * threadGlobals );
227 static OSStatus StreamListener( AudioStreamID inStream,
228                                 UInt32 inChannel,
229                                 AudioDevicePropertyID inPropertyID,
230                                 void * inClientData );
231 static OSStatus DeviceListener( AudioDeviceID inDevice,
232                                 UInt32 inChannel,
233                                 Boolean isInput,
234                                 AudioDevicePropertyID inPropertyID,
235                                 void* inClientData );
236
237 static int init(int rate,int channels,int format,int flags)
238 {
239 AudioStreamBasicDescription inDesc;
240 ComponentDescription desc;
241 Component comp;
242 AURenderCallbackStruct renderCallback;
243 OSStatus err;
244 UInt32 size, maxFrames, i_param_size;
245 char *psz_name;
246 AudioDeviceID devid_def = 0;
247 int b_alive;
248
249     ao_msg(MSGT_AO,MSGL_V, "init([%dHz][%dch][%s][%d])\n", rate, channels, af_fmt2str_short(format), flags);
250
251     ao = calloc(1, sizeof(ao_coreaudio_t));
252
253     ao->i_selected_dev = 0;
254     ao->b_supports_digital = 0;
255     ao->b_digital = 0;
256     ao->b_muted = 0;
257     ao->b_stream_format_changed = 0;
258     ao->i_hog_pid = -1;
259     ao->i_stream_id = 0;
260     ao->i_stream_index = -1;
261     ao->b_revert = 0;
262     ao->b_changed_mixing = 0;
263
264     /* Probe whether device support S/PDIF stream output if input is AC3 stream. */
265     if ((format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_AC3)
266     {
267         /* Find the ID of the default Device. */
268         i_param_size = sizeof(AudioDeviceID);
269         err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
270                                        &i_param_size, &devid_def);
271         if (err != noErr)
272         {
273             ao_msg(MSGT_AO, MSGL_WARN, "could not get default audio device: [%4.4s]\n", (char *)&err);
274             goto err_out;
275         }
276
277         /* Retrieve the length of the device name. */
278         i_param_size = 0;
279         err = AudioDeviceGetPropertyInfo(devid_def, 0, 0,
280                                          kAudioDevicePropertyDeviceName,
281                                          &i_param_size, NULL);
282         if (err != noErr)
283         {
284             ao_msg(MSGT_AO, MSGL_WARN, "could not get default audio device name length: [%4.4s]\n", (char *)&err);
285             goto err_out;
286         }
287
288         /* Retrieve the name of the device. */
289         psz_name = (char *)malloc(i_param_size);
290         err = AudioDeviceGetProperty(devid_def, 0, 0,
291                                      kAudioDevicePropertyDeviceName,
292                                      &i_param_size, psz_name);
293         if (err != noErr)
294         {
295             ao_msg(MSGT_AO, MSGL_WARN, "could not get default audio device name: [%4.4s]\n", (char *)&err);
296             free( psz_name);
297             goto err_out;
298         }
299
300         ao_msg(MSGT_AO,MSGL_V, "got default audio output device ID: %#lx Name: %s\n", devid_def, psz_name );
301
302         if (AudioDeviceSupportsDigital(devid_def))
303         {
304             ao->b_supports_digital = 1;
305             ao->i_selected_dev = devid_def;
306         }
307         ao_msg(MSGT_AO,MSGL_V, "probe default audio output device whether support digital s/pdif output:%d\n", ao->b_supports_digital );
308
309         free( psz_name);
310     }
311
312         // Build Description for the input format
313         inDesc.mSampleRate=rate;
314         inDesc.mFormatID=ao->b_supports_digital ? kAudioFormat60958AC3 : kAudioFormatLinearPCM;
315         inDesc.mChannelsPerFrame=channels;
316         switch(format&AF_FORMAT_BITS_MASK){
317         case AF_FORMAT_8BIT:
318                 inDesc.mBitsPerChannel=8;
319                 break;
320         case AF_FORMAT_16BIT:
321                 inDesc.mBitsPerChannel=16;
322                 break;
323         case AF_FORMAT_24BIT:
324                 inDesc.mBitsPerChannel=24;
325                 break;
326         case AF_FORMAT_32BIT:
327                 inDesc.mBitsPerChannel=32;
328                 break;
329         default:
330                 ao_msg(MSGT_AO, MSGL_WARN, "Unsupported format (0x%08x)\n", format);
331                 goto err_out;
332         }
333
334     if((format&AF_FORMAT_POINT_MASK)==AF_FORMAT_F) {
335         // float
336                 inDesc.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked;
337     }
338     else if((format&AF_FORMAT_SIGN_MASK)==AF_FORMAT_SI) {
339         // signed int
340                 inDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger|kAudioFormatFlagIsPacked;
341     }
342     else {
343         // unsigned int
344                 inDesc.mFormatFlags = kAudioFormatFlagIsPacked;
345     }
346     if ((format & AF_FORMAT_SPECIAL_MASK) == AF_FORMAT_AC3) {
347         // Currently ac3 input (comes from hwac3) is always in native byte-order.
348 #if HAVE_BIGENDIAN
349         inDesc.mFormatFlags |= kAudioFormatFlagIsBigEndian;
350 #endif
351     }
352     else if ((format & AF_FORMAT_END_MASK) == AF_FORMAT_BE)
353         inDesc.mFormatFlags |= kAudioFormatFlagIsBigEndian;
354
355     inDesc.mFramesPerPacket = 1;
356     ao->packetSize = inDesc.mBytesPerPacket = inDesc.mBytesPerFrame = inDesc.mFramesPerPacket*channels*(inDesc.mBitsPerChannel/8);
357     print_format(MSGL_V, "source:",&inDesc);
358
359     if (ao->b_supports_digital)
360     {
361         b_alive = 1;
362         i_param_size = sizeof(b_alive);
363         err = AudioDeviceGetProperty(ao->i_selected_dev, 0, FALSE,
364                                      kAudioDevicePropertyDeviceIsAlive,
365                                      &i_param_size, &b_alive);
366         if (err != noErr)
367             ao_msg(MSGT_AO, MSGL_WARN, "could not check whether device is alive: [%4.4s]\n", (char *)&err);
368         if (!b_alive)
369             ao_msg(MSGT_AO, MSGL_WARN, "device is not alive\n" );
370         /* S/PDIF output need device in HogMode. */
371         i_param_size = sizeof(ao->i_hog_pid);
372         err = AudioDeviceGetProperty(ao->i_selected_dev, 0, FALSE,
373                                      kAudioDevicePropertyHogMode,
374                                      &i_param_size, &ao->i_hog_pid);
375
376         if (err != noErr)
377         {
378             /* This is not a fatal error. Some drivers simply don't support this property. */
379             ao_msg(MSGT_AO, MSGL_WARN, "could not check whether device is hogged: [%4.4s]\n",
380                      (char *)&err);
381             ao->i_hog_pid = -1;
382         }
383
384         if (ao->i_hog_pid != -1 && ao->i_hog_pid != getpid())
385         {
386             ao_msg(MSGT_AO, MSGL_WARN, "Selected audio device is exclusively in use by another program.\n" );
387             goto err_out;
388         }
389         ao->stream_format = inDesc;
390         return OpenSPDIF();
391     }
392
393         /* original analog output code */
394         desc.componentType = kAudioUnitType_Output;
395         desc.componentSubType = kAudioUnitSubType_DefaultOutput;
396         desc.componentManufacturer = kAudioUnitManufacturer_Apple;
397         desc.componentFlags = 0;
398         desc.componentFlagsMask = 0;
399
400         comp = FindNextComponent(NULL, &desc);  //Finds an component that meets the desc spec's
401         if (comp == NULL) {
402                 ao_msg(MSGT_AO, MSGL_WARN, "Unable to find Output Unit component\n");
403                 goto err_out;
404         }
405
406         err = OpenAComponent(comp, &(ao->theOutputUnit));  //gains access to the services provided by the component
407         if (err) {
408                 ao_msg(MSGT_AO, MSGL_WARN, "Unable to open Output Unit component: [%4.4s]\n", (char *)&err);
409                 goto err_out;
410         }
411
412         // Initialize AudioUnit
413         err = AudioUnitInitialize(ao->theOutputUnit);
414         if (err) {
415                 ao_msg(MSGT_AO, MSGL_WARN, "Unable to initialize Output Unit component: [%4.4s]\n", (char *)&err);
416                 goto err_out1;
417         }
418
419         size =  sizeof(AudioStreamBasicDescription);
420         err = AudioUnitSetProperty(ao->theOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &inDesc, size);
421
422         if (err) {
423                 ao_msg(MSGT_AO, MSGL_WARN, "Unable to set the input format: [%4.4s]\n", (char *)&err);
424                 goto err_out2;
425         }
426
427         size = sizeof(UInt32);
428         err = AudioUnitGetProperty(ao->theOutputUnit, kAudioDevicePropertyBufferSize, kAudioUnitScope_Input, 0, &maxFrames, &size);
429
430         if (err)
431         {
432                 ao_msg(MSGT_AO,MSGL_WARN, "AudioUnitGetProperty returned [%4.4s] when getting kAudioDevicePropertyBufferSize\n", (char *)&err);
433                 goto err_out2;
434         }
435
436         ao->chunk_size = maxFrames;//*inDesc.mBytesPerFrame;
437
438         ao_data.samplerate = inDesc.mSampleRate;
439         ao_data.channels = inDesc.mChannelsPerFrame;
440     ao_data.bps = ao_data.samplerate * inDesc.mBytesPerFrame;
441     ao_data.outburst = ao->chunk_size;
442         ao_data.buffersize = ao_data.bps;
443
444         ao->num_chunks = (ao_data.bps+ao->chunk_size-1)/ao->chunk_size;
445     ao->buffer_len = ao->num_chunks * ao->chunk_size;
446     ao->buffer = av_fifo_alloc(ao->buffer_len);
447
448         ao_msg(MSGT_AO,MSGL_V, "using %5d chunks of %d bytes (buffer len %d bytes)\n", (int)ao->num_chunks, (int)ao->chunk_size, (int)ao->buffer_len);
449
450     renderCallback.inputProc = theRenderProc;
451     renderCallback.inputProcRefCon = 0;
452     err = AudioUnitSetProperty(ao->theOutputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallback, sizeof(AURenderCallbackStruct));
453         if (err) {
454                 ao_msg(MSGT_AO, MSGL_WARN, "Unable to set the render callback: [%4.4s]\n", (char *)&err);
455                 goto err_out2;
456         }
457
458         reset();
459
460     return CONTROL_OK;
461
462 err_out2:
463     AudioUnitUninitialize(ao->theOutputUnit);
464 err_out1:
465     CloseComponent(ao->theOutputUnit);
466 err_out:
467     av_fifo_free(ao->buffer);
468     free(ao);
469     ao = NULL;
470     return CONTROL_FALSE;
471 }
472
473 /*****************************************************************************
474  * Setup a encoded digital stream (SPDIF)
475  *****************************************************************************/
476 static int OpenSPDIF(void)
477 {
478     OSStatus                err = noErr;
479     UInt32                  i_param_size, b_mix = 0;
480     Boolean                 b_writeable = 0;
481     AudioStreamID           *p_streams = NULL;
482     int                     i, i_streams = 0;
483
484     /* Start doing the SPDIF setup process. */
485     ao->b_digital = 1;
486
487     /* Hog the device. */
488     i_param_size = sizeof(ao->i_hog_pid);
489     ao->i_hog_pid = getpid() ;
490
491     err = AudioDeviceSetProperty(ao->i_selected_dev, 0, 0, FALSE,
492                                  kAudioDevicePropertyHogMode, i_param_size, &ao->i_hog_pid);
493
494     if (err != noErr)
495     {
496         ao_msg(MSGT_AO, MSGL_WARN, "failed to set hogmode: [%4.4s]\n", (char *)&err);
497         ao->i_hog_pid = -1;
498         goto err_out;
499     }
500
501     /* Set mixable to false if we are allowed to. */
502     err = AudioDeviceGetPropertyInfo(ao->i_selected_dev, 0, FALSE,
503                                      kAudioDevicePropertySupportsMixing,
504                                      &i_param_size, &b_writeable);
505     err = AudioDeviceGetProperty(ao->i_selected_dev, 0, FALSE,
506                                  kAudioDevicePropertySupportsMixing,
507                                  &i_param_size, &b_mix);
508     if (err != noErr && b_writeable)
509     {
510         b_mix = 0;
511         err = AudioDeviceSetProperty(ao->i_selected_dev, 0, 0, FALSE,
512                                      kAudioDevicePropertySupportsMixing,
513                                      i_param_size, &b_mix);
514         ao->b_changed_mixing = 1;
515     }
516     if (err != noErr)
517     {
518         ao_msg(MSGT_AO, MSGL_WARN, "failed to set mixmode: [%4.4s]\n", (char *)&err);
519         goto err_out;
520     }
521
522     /* Get a list of all the streams on this device. */
523     err = AudioDeviceGetPropertyInfo(ao->i_selected_dev, 0, FALSE,
524                                      kAudioDevicePropertyStreams,
525                                      &i_param_size, NULL);
526     if (err != noErr)
527     {
528         ao_msg(MSGT_AO, MSGL_WARN, "could not get number of streams: [%4.4s]\n", (char *)&err);
529         goto err_out;
530     }
531
532     i_streams = i_param_size / sizeof(AudioStreamID);
533     p_streams = (AudioStreamID *)malloc(i_param_size);
534     if (p_streams == NULL)
535     {
536         ao_msg(MSGT_AO, MSGL_WARN, "out of memory\n" );
537         goto err_out;
538     }
539
540     err = AudioDeviceGetProperty(ao->i_selected_dev, 0, FALSE,
541                                  kAudioDevicePropertyStreams,
542                                  &i_param_size, p_streams);
543     if (err != noErr)
544     {
545         ao_msg(MSGT_AO, MSGL_WARN, "could not get number of streams: [%4.4s]\n", (char *)&err);
546         if (p_streams) free(p_streams);
547         goto err_out;
548     }
549
550     ao_msg(MSGT_AO, MSGL_V, "current device stream number: %d\n", i_streams);
551
552     for (i = 0; i < i_streams && ao->i_stream_index < 0; ++i)
553     {
554         /* Find a stream with a cac3 stream. */
555         AudioStreamBasicDescription *p_format_list = NULL;
556         int i_formats = 0, j = 0, b_digital = 0;
557
558         /* Retrieve all the stream formats supported by each output stream. */
559         err = AudioStreamGetPropertyInfo(p_streams[i], 0,
560                                          kAudioStreamPropertyPhysicalFormats,
561                                          &i_param_size, NULL);
562         if (err != noErr)
563         {
564             ao_msg(MSGT_AO, MSGL_WARN, "could not get number of streamformats: [%4.4s]\n", (char *)&err);
565             continue;
566         }
567
568         i_formats = i_param_size / sizeof(AudioStreamBasicDescription);
569         p_format_list = (AudioStreamBasicDescription *)malloc(i_param_size);
570         if (p_format_list == NULL)
571         {
572             ao_msg(MSGT_AO, MSGL_WARN, "could not malloc the memory\n" );
573             continue;
574         }
575
576         err = AudioStreamGetProperty(p_streams[i], 0,
577                                      kAudioStreamPropertyPhysicalFormats,
578                                      &i_param_size, p_format_list);
579         if (err != noErr)
580         {
581             ao_msg(MSGT_AO, MSGL_WARN, "could not get the list of streamformats: [%4.4s]\n", (char *)&err);
582             if (p_format_list) free(p_format_list);
583             continue;
584         }
585
586         /* Check if one of the supported formats is a digital format. */
587         for (j = 0; j < i_formats; ++j)
588         {
589             if (p_format_list[j].mFormatID == 'IAC3' ||
590                   p_format_list[j].mFormatID == kAudioFormat60958AC3)
591             {
592                 b_digital = 1;
593                 break;
594             }
595         }
596
597         if (b_digital)
598         {
599             /* If this stream supports a digital (cac3) format, then set it. */
600             int i_requested_rate_format = -1;
601             int i_current_rate_format = -1;
602             int i_backup_rate_format = -1;
603
604             ao->i_stream_id = p_streams[i];
605             ao->i_stream_index = i;
606
607             if (ao->b_revert == 0)
608             {
609                 /* Retrieve the original format of this stream first if not done so already. */
610                 i_param_size = sizeof(ao->sfmt_revert);
611                 err = AudioStreamGetProperty(ao->i_stream_id, 0,
612                                              kAudioStreamPropertyPhysicalFormat,
613                                              &i_param_size,
614                                              &ao->sfmt_revert);
615                 if (err != noErr)
616                 {
617                     ao_msg(MSGT_AO, MSGL_WARN, "could not retrieve the original streamformat: [%4.4s]\n", (char *)&err);
618                     if (p_format_list) free(p_format_list);
619                     continue;
620                 }
621                 ao->b_revert = 1;
622             }
623
624             for (j = 0; j < i_formats; ++j)
625                 if (p_format_list[j].mFormatID == 'IAC3' ||
626                       p_format_list[j].mFormatID == kAudioFormat60958AC3)
627                 {
628                     if (p_format_list[j].mSampleRate == ao->stream_format.mSampleRate)
629                     {
630                         i_requested_rate_format = j;
631                         break;
632                     }
633                     if (p_format_list[j].mSampleRate == ao->sfmt_revert.mSampleRate)
634                         i_current_rate_format = j;
635                     else if (i_backup_rate_format < 0 || p_format_list[j].mSampleRate > p_format_list[i_backup_rate_format].mSampleRate)
636                         i_backup_rate_format = j;
637                 }
638
639             if (i_requested_rate_format >= 0) /* We prefer to output at the samplerate of the original audio. */
640                 ao->stream_format = p_format_list[i_requested_rate_format];
641             else if (i_current_rate_format >= 0) /* If not possible, we will try to use the current samplerate of the device. */
642                 ao->stream_format = p_format_list[i_current_rate_format];
643             else ao->stream_format = p_format_list[i_backup_rate_format]; /* And if we have to, any digital format will be just fine (highest rate possible). */
644         }
645         if (p_format_list) free(p_format_list);
646     }
647     if (p_streams) free(p_streams);
648
649     if (ao->i_stream_index < 0)
650     {
651         ao_msg(MSGT_AO, MSGL_WARN, "can not find any digital output stream format when OpenSPDIF().\n");
652         goto err_out;
653     }
654
655     print_format(MSGL_V, "original stream format:", &ao->sfmt_revert);
656
657     if (!AudioStreamChangeFormat(ao->i_stream_id, ao->stream_format))
658         goto err_out;
659
660     err = AudioDeviceAddPropertyListener(ao->i_selected_dev,
661                                          kAudioPropertyWildcardChannel,
662                                          0,
663                                          kAudioDevicePropertyDeviceHasChanged,
664                                          DeviceListener,
665                                          NULL);
666     if (err != noErr)
667         ao_msg(MSGT_AO, MSGL_WARN, "AudioDeviceAddPropertyListener for kAudioDevicePropertyDeviceHasChanged failed: [%4.4s]\n", (char *)&err);
668
669
670     /* FIXME: If output stream is not native byte-order, we need change endian somewhere. */
671     /*        Although there's no such case reported.                                     */
672 #if HAVE_BIGENDIAN
673     if (!(ao->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian))
674 #else
675     if (ao->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian)
676 #endif
677         ao_msg(MSGT_AO, MSGL_WARN, "output stream has a no-native byte-order, digital output may failed.\n");
678
679     /* For ac3/dts, just use packet size 6144 bytes as chunk size. */
680     ao->chunk_size = ao->stream_format.mBytesPerPacket;
681
682     ao_data.samplerate = ao->stream_format.mSampleRate;
683     ao_data.channels = ao->stream_format.mChannelsPerFrame;
684     ao_data.bps = ao_data.samplerate * (ao->stream_format.mBytesPerPacket/ao->stream_format.mFramesPerPacket);
685     ao_data.outburst = ao->chunk_size;
686     ao_data.buffersize = ao_data.bps;
687
688     ao->num_chunks = (ao_data.bps+ao->chunk_size-1)/ao->chunk_size;
689     ao->buffer_len = ao->num_chunks * ao->chunk_size;
690     ao->buffer = av_fifo_alloc(ao->buffer_len);
691
692     ao_msg(MSGT_AO,MSGL_V, "using %5d chunks of %d bytes (buffer len %d bytes)\n", (int)ao->num_chunks, (int)ao->chunk_size, (int)ao->buffer_len);
693
694
695     /* Add IOProc callback. */
696     err = AudioDeviceAddIOProc(ao->i_selected_dev,
697                                (AudioDeviceIOProc)RenderCallbackSPDIF,
698                                (void *)ao);
699     if (err != noErr)
700     {
701         ao_msg(MSGT_AO, MSGL_WARN, "AudioDeviceAddIOProc failed: [%4.4s]\n", (char *)&err);
702         goto err_out1;
703     }
704
705     reset();
706
707     return CONTROL_TRUE;
708
709 err_out1:
710     if (ao->b_revert)
711         AudioStreamChangeFormat(ao->i_stream_id, ao->sfmt_revert);
712 err_out:
713     if (ao->b_changed_mixing && ao->sfmt_revert.mFormatID != kAudioFormat60958AC3)
714     {
715         int b_mix = 1;
716         err = AudioDeviceSetProperty(ao->i_selected_dev, 0, 0, FALSE,
717                                      kAudioDevicePropertySupportsMixing,
718                                      i_param_size, &b_mix);
719         if (err != noErr)
720             ao_msg(MSGT_AO, MSGL_WARN, "failed to set mixmode: [%4.4s]\n",
721                    (char *)&err);
722     }
723     if (ao->i_hog_pid == getpid())
724     {
725         ao->i_hog_pid = -1;
726         i_param_size = sizeof(ao->i_hog_pid);
727         err = AudioDeviceSetProperty(ao->i_selected_dev, 0, 0, FALSE,
728                                      kAudioDevicePropertyHogMode,
729                                      i_param_size, &ao->i_hog_pid);
730         if (err != noErr)
731             ao_msg(MSGT_AO, MSGL_WARN, "Could not release hogmode: [%4.4s]\n",
732                    (char *)&err);
733     }
734     av_fifo_free(ao->buffer);
735     free(ao);
736     ao = NULL;
737     return CONTROL_FALSE;
738 }
739
740 /*****************************************************************************
741  * AudioDeviceSupportsDigital: Check i_dev_id for digital stream support.
742  *****************************************************************************/
743 static int AudioDeviceSupportsDigital( AudioDeviceID i_dev_id )
744 {
745     OSStatus                    err = noErr;
746     UInt32                      i_param_size = 0;
747     AudioStreamID               *p_streams = NULL;
748     int                         i = 0, i_streams = 0;
749     int                         b_return = CONTROL_FALSE;
750
751     /* Retrieve all the output streams. */
752     err = AudioDeviceGetPropertyInfo(i_dev_id, 0, FALSE,
753                                      kAudioDevicePropertyStreams,
754                                      &i_param_size, NULL);
755     if (err != noErr)
756     {
757         ao_msg(MSGT_AO,MSGL_V, "could not get number of streams: [%4.4s]\n", (char *)&err);
758         return CONTROL_FALSE;
759     }
760
761     i_streams = i_param_size / sizeof(AudioStreamID);
762     p_streams = (AudioStreamID *)malloc(i_param_size);
763     if (p_streams == NULL)
764     {
765         ao_msg(MSGT_AO,MSGL_V, "out of memory\n");
766         return CONTROL_FALSE;
767     }
768
769     err = AudioDeviceGetProperty(i_dev_id, 0, FALSE,
770                                  kAudioDevicePropertyStreams,
771                                  &i_param_size, p_streams);
772
773     if (err != noErr)
774     {
775         ao_msg(MSGT_AO,MSGL_V, "could not get number of streams: [%4.4s]\n", (char *)&err);
776         free(p_streams);
777         return CONTROL_FALSE;
778     }
779
780     for (i = 0; i < i_streams; ++i)
781     {
782         if (AudioStreamSupportsDigital(p_streams[i]))
783             b_return = CONTROL_OK;
784     }
785
786     free(p_streams);
787     return b_return;
788 }
789
790 /*****************************************************************************
791  * AudioStreamSupportsDigital: Check i_stream_id for digital stream support.
792  *****************************************************************************/
793 static int AudioStreamSupportsDigital( AudioStreamID i_stream_id )
794 {
795     OSStatus err = noErr;
796     UInt32 i_param_size;
797     AudioStreamBasicDescription *p_format_list = NULL;
798     int i, i_formats, b_return = CONTROL_FALSE;
799
800     /* Retrieve all the stream formats supported by each output stream. */
801     err = AudioStreamGetPropertyInfo(i_stream_id, 0,
802                                      kAudioStreamPropertyPhysicalFormats,
803                                      &i_param_size, NULL);
804     if (err != noErr)
805     {
806         ao_msg(MSGT_AO,MSGL_V, "could not get number of streamformats: [%4.4s]\n", (char *)&err);
807         return CONTROL_FALSE;
808     }
809
810     i_formats = i_param_size / sizeof(AudioStreamBasicDescription);
811     p_format_list = (AudioStreamBasicDescription *)malloc(i_param_size);
812     if (p_format_list == NULL)
813     {
814         ao_msg(MSGT_AO,MSGL_V, "could not malloc the memory\n" );
815         return CONTROL_FALSE;
816     }
817
818     err = AudioStreamGetProperty(i_stream_id, 0,
819                                  kAudioStreamPropertyPhysicalFormats,
820                                  &i_param_size, p_format_list);
821     if (err != noErr)
822     {
823         ao_msg(MSGT_AO,MSGL_V, "could not get the list of streamformats: [%4.4s]\n", (char *)&err);
824         free(p_format_list);
825         return CONTROL_FALSE;
826     }
827
828     for (i = 0; i < i_formats; ++i)
829     {
830         print_format(MSGL_V, "supported format:", &p_format_list[i]);
831
832         if (p_format_list[i].mFormatID == 'IAC3' ||
833                   p_format_list[i].mFormatID == kAudioFormat60958AC3)
834             b_return = CONTROL_OK;
835     }
836
837     free(p_format_list);
838     return b_return;
839 }
840
841 /*****************************************************************************
842  * AudioStreamChangeFormat: Change i_stream_id to change_format
843  *****************************************************************************/
844 static int AudioStreamChangeFormat( AudioStreamID i_stream_id, AudioStreamBasicDescription change_format )
845 {
846     OSStatus err = noErr;
847     UInt32 i_param_size = 0;
848     int i;
849
850     static volatile int stream_format_changed;
851     stream_format_changed = 0;
852
853     print_format(MSGL_V, "setting stream format:", &change_format);
854
855     /* Install the callback. */
856     err = AudioStreamAddPropertyListener(i_stream_id, 0,
857                                          kAudioStreamPropertyPhysicalFormat,
858                                          StreamListener,
859                                          (void *)&stream_format_changed);
860     if (err != noErr)
861     {
862         ao_msg(MSGT_AO, MSGL_WARN, "AudioStreamAddPropertyListener failed: [%4.4s]\n", (char *)&err);
863         return CONTROL_FALSE;
864     }
865
866     /* Change the format. */
867     err = AudioStreamSetProperty(i_stream_id, 0, 0,
868                                  kAudioStreamPropertyPhysicalFormat,
869                                  sizeof(AudioStreamBasicDescription),
870                                  &change_format);
871     if (err != noErr)
872     {
873         ao_msg(MSGT_AO, MSGL_WARN, "could not set the stream format: [%4.4s]\n", (char *)&err);
874         return CONTROL_FALSE;
875     }
876
877     /* The AudioStreamSetProperty is not only asynchronious,
878      * it is also not Atomic, in its behaviour.
879      * Therefore we check 5 times before we really give up.
880      * FIXME: failing isn't actually implemented yet. */
881     for (i = 0; i < 5; ++i)
882     {
883         AudioStreamBasicDescription actual_format;
884         int j;
885         for (j = 0; !stream_format_changed && j < 50; ++j)
886             usec_sleep(10000);
887         if (stream_format_changed)
888             stream_format_changed = 0;
889         else
890             ao_msg(MSGT_AO, MSGL_V, "reached timeout\n" );
891
892         i_param_size = sizeof(AudioStreamBasicDescription);
893         err = AudioStreamGetProperty(i_stream_id, 0,
894                                      kAudioStreamPropertyPhysicalFormat,
895                                      &i_param_size,
896                                      &actual_format);
897
898         print_format(MSGL_V, "actual format in use:", &actual_format);
899         if (actual_format.mSampleRate == change_format.mSampleRate &&
900             actual_format.mFormatID == change_format.mFormatID &&
901             actual_format.mFramesPerPacket == change_format.mFramesPerPacket)
902         {
903             /* The right format is now active. */
904             break;
905         }
906         /* We need to check again. */
907     }
908
909     /* Removing the property listener. */
910     err = AudioStreamRemovePropertyListener(i_stream_id, 0,
911                                             kAudioStreamPropertyPhysicalFormat,
912                                             StreamListener);
913     if (err != noErr)
914     {
915         ao_msg(MSGT_AO, MSGL_WARN, "AudioStreamRemovePropertyListener failed: [%4.4s]\n", (char *)&err);
916         return CONTROL_FALSE;
917     }
918
919     return CONTROL_TRUE;
920 }
921
922 /*****************************************************************************
923  * RenderCallbackSPDIF: callback for SPDIF audio output
924  *****************************************************************************/
925 static OSStatus RenderCallbackSPDIF( AudioDeviceID inDevice,
926                                     const AudioTimeStamp * inNow,
927                                     const void * inInputData,
928                                     const AudioTimeStamp * inInputTime,
929                                     AudioBufferList * outOutputData,
930                                     const AudioTimeStamp * inOutputTime,
931                                     void * threadGlobals )
932 {
933     int amt = av_fifo_size(ao->buffer);
934     int req = outOutputData->mBuffers[ao->i_stream_index].mDataByteSize;
935
936     if (amt > req)
937         amt = req;
938     if (amt)
939         read_buffer(ao->b_muted ? NULL : (unsigned char *)outOutputData->mBuffers[ao->i_stream_index].mData, amt);
940
941     return noErr;
942 }
943
944
945 static int play(void* output_samples,int num_bytes,int flags)
946 {
947     int wrote, b_digital;
948
949     // Check whether we need to reset the digital output stream.
950     if (ao->b_digital && ao->b_stream_format_changed)
951     {
952         ao->b_stream_format_changed = 0;
953         b_digital = AudioStreamSupportsDigital(ao->i_stream_id);
954         if (b_digital)
955         {
956             /* Current stream support digital format output, let's set it. */
957             ao_msg(MSGT_AO, MSGL_V, "detected current stream support digital, try to restore digital output...\n");
958
959             if (!AudioStreamChangeFormat(ao->i_stream_id, ao->stream_format))
960             {
961                 ao_msg(MSGT_AO, MSGL_WARN, "restore digital output failed.\n");
962             }
963             else
964             {
965                 ao_msg(MSGT_AO, MSGL_WARN, "restore digital output succeed.\n");
966                 reset();
967             }
968         }
969         else
970             ao_msg(MSGT_AO, MSGL_V, "detected current stream do not support digital.\n");
971     }
972
973     wrote=write_buffer(output_samples, num_bytes);
974     audio_resume();
975     return wrote;
976 }
977
978 /* set variables and buffer to initial state */
979 static void reset(void)
980 {
981   audio_pause();
982   av_fifo_reset(ao->buffer);
983 }
984
985
986 /* return available space */
987 static int get_space(void)
988 {
989   return ao->buffer_len - av_fifo_size(ao->buffer);
990 }
991
992
993 /* return delay until audio is played */
994 static float get_delay(void)
995 {
996   // inaccurate, should also contain the data buffered e.g. by the OS
997   return (float)av_fifo_size(ao->buffer)/(float)ao_data.bps;
998 }
999
1000
1001 /* unload plugin and deregister from coreaudio */
1002 static void uninit(int immed)
1003 {
1004   OSStatus            err = noErr;
1005   UInt32              i_param_size = 0;
1006
1007   if (!immed) {
1008     long long timeleft=(1000000LL*av_fifo_size(ao->buffer))/ao_data.bps;
1009     ao_msg(MSGT_AO,MSGL_DBG2, "%d bytes left @%d bps (%d usec)\n", av_fifo_size(ao->buffer), ao_data.bps, (int)timeleft);
1010     usec_sleep((int)timeleft);
1011   }
1012
1013   if (!ao->b_digital) {
1014       AudioOutputUnitStop(ao->theOutputUnit);
1015       AudioUnitUninitialize(ao->theOutputUnit);
1016       CloseComponent(ao->theOutputUnit);
1017   }
1018   else {
1019       /* Stop device. */
1020       err = AudioDeviceStop(ao->i_selected_dev,
1021                             (AudioDeviceIOProc)RenderCallbackSPDIF);
1022       if (err != noErr)
1023           ao_msg(MSGT_AO, MSGL_WARN, "AudioDeviceStop failed: [%4.4s]\n", (char *)&err);
1024
1025       /* Remove IOProc callback. */
1026       err = AudioDeviceRemoveIOProc(ao->i_selected_dev,
1027                                     (AudioDeviceIOProc)RenderCallbackSPDIF);
1028       if (err != noErr)
1029           ao_msg(MSGT_AO, MSGL_WARN, "AudioDeviceRemoveIOProc failed: [%4.4s]\n", (char *)&err);
1030
1031       if (ao->b_revert)
1032           AudioStreamChangeFormat(ao->i_stream_id, ao->sfmt_revert);
1033
1034       if (ao->b_changed_mixing && ao->sfmt_revert.mFormatID != kAudioFormat60958AC3)
1035       {
1036           int b_mix;
1037           Boolean b_writeable;
1038           /* Revert mixable to true if we are allowed to. */
1039           err = AudioDeviceGetPropertyInfo(ao->i_selected_dev, 0, FALSE, kAudioDevicePropertySupportsMixing,
1040                                            &i_param_size, &b_writeable);
1041           err = AudioDeviceGetProperty(ao->i_selected_dev, 0, FALSE, kAudioDevicePropertySupportsMixing,
1042                                        &i_param_size, &b_mix);
1043           if (err != noErr && b_writeable)
1044           {
1045               b_mix = 1;
1046               err = AudioDeviceSetProperty(ao->i_selected_dev, 0, 0, FALSE,
1047                                            kAudioDevicePropertySupportsMixing, i_param_size, &b_mix);
1048           }
1049           if (err != noErr)
1050               ao_msg(MSGT_AO, MSGL_WARN, "failed to set mixmode: [%4.4s]\n", (char *)&err);
1051       }
1052       if (ao->i_hog_pid == getpid())
1053       {
1054           ao->i_hog_pid = -1;
1055           i_param_size = sizeof(ao->i_hog_pid);
1056           err = AudioDeviceSetProperty(ao->i_selected_dev, 0, 0, FALSE,
1057                                        kAudioDevicePropertyHogMode, i_param_size, &ao->i_hog_pid);
1058           if (err != noErr) ao_msg(MSGT_AO, MSGL_WARN, "Could not release hogmode: [%4.4s]\n", (char *)&err);
1059       }
1060   }
1061
1062   av_fifo_free(ao->buffer);
1063   free(ao);
1064   ao = NULL;
1065 }
1066
1067
1068 /* stop playing, keep buffers (for pause) */
1069 static void audio_pause(void)
1070 {
1071     OSErr err=noErr;
1072
1073     /* Stop callback. */
1074     if (!ao->b_digital)
1075     {
1076         err=AudioOutputUnitStop(ao->theOutputUnit);
1077         if (err != noErr)
1078             ao_msg(MSGT_AO,MSGL_WARN, "AudioOutputUnitStop returned [%4.4s]\n", (char *)&err);
1079     }
1080     else
1081     {
1082         err = AudioDeviceStop(ao->i_selected_dev, (AudioDeviceIOProc)RenderCallbackSPDIF);
1083         if (err != noErr)
1084             ao_msg(MSGT_AO, MSGL_WARN, "AudioDeviceStop failed: [%4.4s]\n", (char *)&err);
1085     }
1086     ao->paused = 1;
1087 }
1088
1089
1090 /* resume playing, after audio_pause() */
1091 static void audio_resume(void)
1092 {
1093     OSErr err=noErr;
1094
1095     if (!ao->paused)
1096         return;
1097
1098     /* Start callback. */
1099     if (!ao->b_digital)
1100     {
1101         err = AudioOutputUnitStart(ao->theOutputUnit);
1102         if (err != noErr)
1103             ao_msg(MSGT_AO,MSGL_WARN, "AudioOutputUnitStart returned [%4.4s]\n", (char *)&err);
1104     }
1105     else
1106     {
1107         err = AudioDeviceStart(ao->i_selected_dev, (AudioDeviceIOProc)RenderCallbackSPDIF);
1108         if (err != noErr)
1109             ao_msg(MSGT_AO, MSGL_WARN, "AudioDeviceStart failed: [%4.4s]\n", (char *)&err);
1110     }
1111     ao->paused = 0;
1112 }
1113
1114 /*****************************************************************************
1115  * StreamListener
1116  *****************************************************************************/
1117 static OSStatus StreamListener( AudioStreamID inStream,
1118                                 UInt32 inChannel,
1119                                 AudioDevicePropertyID inPropertyID,
1120                                 void * inClientData )
1121 {
1122     switch (inPropertyID)
1123     {
1124         case kAudioStreamPropertyPhysicalFormat:
1125             ao_msg(MSGT_AO, MSGL_V, "got notify kAudioStreamPropertyPhysicalFormat changed.\n");
1126             if (inClientData)
1127                 *(volatile int *)inClientData = 1;
1128         default:
1129             break;
1130     }
1131     return noErr;
1132 }
1133
1134 static OSStatus DeviceListener( AudioDeviceID inDevice,
1135                                 UInt32 inChannel,
1136                                 Boolean isInput,
1137                                 AudioDevicePropertyID inPropertyID,
1138                                 void* inClientData )
1139 {
1140     switch (inPropertyID)
1141     {
1142         case kAudioDevicePropertyDeviceHasChanged:
1143             ao_msg(MSGT_AO, MSGL_WARN, "got notify kAudioDevicePropertyDeviceHasChanged.\n");
1144             ao->b_stream_format_changed = 1;
1145         default:
1146             break;
1147     }
1148     return noErr;
1149 }