1 /*****************************************************************************
2 * aout.m: CoreAudio output plugin
3 *****************************************************************************
4 * Copyright (C) 2002-2003 VideoLAN
5 * $Id: aout.m,v 1.23 2003/02/21 16:31:37 hartman Exp $
7 * Authors: Colin Delacroix <colin@zoy.org>
8 * Jon Lech Johansen <jon-vl@nanocrew.net>
9 * Christophe Massiot <massiot@via.ecp.fr>
10 * Heiko Panther <heiko.panther@web.de>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
36 #include "aout_internal.h"
38 #include <Carbon/Carbon.h>
39 #include <CoreAudio/HostTime.h>
40 #include <CoreAudio/AudioHardware.h>
42 #define A52_FRAME_NB 1536
44 #define STREAM_FORMAT_MSG( pre, sfm ) \
45 pre ": [%ld][%4.4s][%ld][%ld][%ld][%ld][%ld][%ld]", \
46 (UInt32)sfm.mSampleRate, (char *)&sfm.mFormatID, \
47 sfm.mFormatFlags, sfm.mBytesPerPacket, \
48 sfm.mFramesPerPacket, sfm.mBytesPerFrame, \
49 sfm.mChannelsPerFrame, sfm.mBitsPerChannel
51 /*****************************************************************************
53 ****************************************************************************/
56 AudioDeviceClassA52 = 1 << 0,
57 AudioDeviceClassPCM2 = 1 << 1,
58 AudioDeviceClassPCM4 = 1 << 2,
59 AudioDeviceClassPCM6 = 1 << 3
62 static struct aout_class_t
65 UInt32 mChannelsPerFrame;
66 enum AudioDeviceClass class;
67 const char *psz_class;
71 { /* old A/52 format type */
78 { /* new A/52 format type */
86 kAudioFormatLinearPCM,
93 kAudioFormatLinearPCM,
100 kAudioFormatLinearPCM,
102 AudioDeviceClassPCM6,
107 #define N_AOUT_CLASSES (sizeof(aout_classes)/sizeof(aout_classes[0]))
109 /*****************************************************************************
111 ****************************************************************************/
120 /*****************************************************************************
122 ****************************************************************************/
126 char *psz_device_name;
128 AudioStreamBasicDescription ** pp_streams;
131 /*****************************************************************************
132 * aout_sys_t: private audio output method descriptor
133 *****************************************************************************
134 * This structure is part of the audio output thread descriptor.
135 * It describes the CoreAudio specific properties of an output thread.
136 *****************************************************************************/
140 struct aout_dev_t * p_devices;
142 struct aout_option_t * p_options;
145 AudioStreamBasicDescription stream_format;
147 UInt32 i_buffer_size;
151 /*****************************************************************************
153 *****************************************************************************/
154 static int InitHardware ( aout_instance_t *p_aout );
155 static int InitDevice ( UInt32 i_dev, aout_instance_t *p_aout );
156 static void FreeDevice ( UInt32 i_dev, aout_instance_t *p_aout );
157 static void FreeHardware ( aout_instance_t *p_aout );
158 static int GetDevice ( aout_instance_t *p_aout,
159 AudioDeviceID *p_devid );
160 static int GetStreamID ( AudioDeviceID devid, UInt32 i_idx,
161 AudioStreamID * p_sid );
162 static int InitStream ( UInt32 i_dev, aout_instance_t *p_aout,
164 static void FreeStream ( UInt32 i_dev, aout_instance_t *p_aout,
167 static void Play ( aout_instance_t *p_aout );
169 static OSStatus IOCallback ( AudioDeviceID inDevice,
170 const AudioTimeStamp *inNow,
171 const void *inInputData,
172 const AudioTimeStamp *inInputTime,
173 AudioBufferList *outOutputData,
174 const AudioTimeStamp *inOutputTime,
175 void *threadGlobals );
177 /*****************************************************************************
178 * Open: open a CoreAudio HAL device
179 *****************************************************************************/
180 int E_(OpenAudio)( vlc_object_t * p_this )
184 UInt32 i, i_param_size;
185 struct aout_sys_t * p_sys;
186 aout_instance_t * p_aout = (aout_instance_t *)p_this;
188 /* Allocate structure */
189 p_sys = (struct aout_sys_t *)malloc( sizeof( struct aout_sys_t ) );
192 msg_Err( p_aout, "out of memory" );
193 return( VLC_ENOMEM );
196 memset( p_sys, 0, sizeof( struct aout_sys_t ) );
197 p_aout->output.p_sys = p_sys;
199 if( InitHardware( p_aout ) )
201 msg_Err( p_aout, "InitHardware failed" );
202 free( (void *)p_sys );
203 return( VLC_EGENERIC );
206 if( var_Type( p_aout, "audio-device" ) == 0 )
208 UInt32 i_option = config_GetInt( p_aout, "macosx-adev" );
210 var_Create( p_aout, "audio-device", VLC_VAR_STRING |
213 for( i = 0; i < p_sys->i_options; i++ )
215 val.psz_string = p_sys->p_options[i].sz_option;
216 var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
220 var_Set( p_aout, "audio-device", val );
224 var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart,
227 val.b_bool = VLC_TRUE;
228 var_Set( p_aout, "intf-change", val );
231 /* Get requested device */
232 if( GetDevice( p_aout, &p_sys->devid ) )
234 msg_Err( p_aout, "GetDevice failed" );
235 FreeHardware( p_aout );
236 free( (void *)p_sys );
237 return( VLC_EGENERIC );
240 p_aout->output.pf_play = Play;
241 aout_VolumeSoftInit( p_aout );
243 /* Get a description of the stream format */
244 i_param_size = sizeof( AudioStreamBasicDescription );
245 err = AudioDeviceGetProperty( p_sys->devid, 0, false,
246 kAudioDevicePropertyStreamFormat,
247 &i_param_size, &p_sys->stream_format );
250 msg_Err( p_aout, "failed to get stream format: [%4.4s]",
252 FreeHardware( p_aout );
253 free( (void *)p_sys );
254 return( VLC_EGENERIC );
257 /* Set the output sample rate */
258 p_aout->output.output.i_rate =
259 (unsigned int)p_sys->stream_format.mSampleRate;
261 msg_Dbg( p_aout, STREAM_FORMAT_MSG( "using format",
262 p_sys->stream_format ) );
264 /* Get the buffer size */
265 i_param_size = sizeof( p_sys->i_buffer_size );
266 err = AudioDeviceGetProperty( p_sys->devid, 0, false,
267 kAudioDevicePropertyBufferSize,
268 &i_param_size, &p_sys->i_buffer_size );
271 msg_Err( p_aout, "failed to get buffer size: [%4.4s]",
273 FreeHardware( p_aout );
274 free( (void *)p_sys );
275 return( VLC_EGENERIC );
278 msg_Dbg( p_aout, "device buffer size: [%ld]", p_sys->i_buffer_size );
280 /* If we do AC3 over SPDIF, set buffer size to one AC3 frame */
281 if( ( p_sys->stream_format.mFormatID == kAudioFormat60958AC3 ||
282 p_sys->stream_format.mFormatID == 'IAC3' ) &&
283 p_sys->i_buffer_size != AOUT_SPDIF_SIZE )
285 p_sys->i_buffer_size = AOUT_SPDIF_SIZE;
286 i_param_size = sizeof( p_sys->i_buffer_size );
287 err = AudioDeviceSetProperty( p_sys->devid, 0, 0, false,
288 kAudioDevicePropertyBufferSize,
289 i_param_size, &p_sys->i_buffer_size );
292 msg_Err( p_aout, "failed to set buffer size: [%4.4s]",
294 FreeHardware( p_aout );
295 free( (void *)p_sys );
296 return( VLC_EGENERIC );
299 msg_Dbg( p_aout, "device buffer size set to: [%ld]",
300 p_sys->i_buffer_size );
303 switch( p_sys->stream_format.mFormatID )
305 case kAudioFormatLinearPCM:
306 p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2');
308 if( p_sys->stream_format.mChannelsPerFrame == 6 )
310 p_aout->output.output.i_physical_channels =
311 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
312 AOUT_CHAN_CENTER | AOUT_CHAN_REARRIGHT |
313 AOUT_CHAN_REARLEFT | AOUT_CHAN_LFE;
315 else if( p_sys->stream_format.mChannelsPerFrame == 4 )
317 p_aout->output.output.i_physical_channels =
318 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
319 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
323 p_aout->output.output.i_physical_channels =
324 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
327 p_aout->output.i_nb_samples = (int)( p_sys->i_buffer_size /
328 p_sys->stream_format.mBytesPerFrame );
332 case kAudioFormat60958AC3:
333 p_aout->output.output.i_format = VLC_FOURCC('s','p','d','i');
334 p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
335 p_aout->output.output.i_frame_length = A52_FRAME_NB;
336 p_aout->output.i_nb_samples = p_aout->output.output.i_frame_length;
340 msg_Err( p_aout, "unknown hardware format: [%4.4s]",
341 (char *)&p_sys->stream_format.mFormatID );
342 FreeHardware( p_aout );
343 free( (void *)p_sys );
344 return( VLC_EGENERIC );
347 /* Set buffer frame size */
348 i_param_size = sizeof( p_aout->output.i_nb_samples );
349 err = AudioDeviceSetProperty( p_sys->devid, 0, 0, false,
350 kAudioDevicePropertyBufferFrameSize,
352 &p_aout->output.i_nb_samples );
355 msg_Err( p_aout, "failed to set buffer frame size: [%4.4s]",
357 FreeHardware( p_aout );
358 free( (void *)p_sys );
359 return( VLC_EGENERIC );
362 msg_Dbg( p_aout, "device buffer frame size set to: [%d]",
363 p_aout->output.i_nb_samples );
366 err = AudioDeviceAddIOProc( p_sys->devid,
367 (AudioDeviceIOProc)IOCallback,
371 msg_Err( p_aout, "AudioDeviceAddIOProc failed: [%4.4s]",
373 FreeHardware( p_aout );
374 free( (void *)p_sys );
375 return( VLC_EGENERIC );
379 err = AudioDeviceStart( p_sys->devid, (AudioDeviceIOProc)IOCallback );
382 msg_Err( p_aout, "AudioDeviceStart failed: [%4.4s]",
384 FreeHardware( p_aout );
385 free( (void *)p_sys );
386 return( VLC_EGENERIC );
389 /* Let's pray for the following operation to be atomic... */
390 p_sys->clock_diff = - (mtime_t)
391 AudioConvertHostTimeToNanos( AudioGetCurrentHostTime() ) / 1000;
392 p_sys->clock_diff += mdate();
394 return( VLC_SUCCESS );
397 /*****************************************************************************
398 * Close: close the CoreAudio HAL device
399 *****************************************************************************/
400 void E_(CloseAudio)( aout_instance_t * p_aout )
403 struct aout_sys_t * p_sys = p_aout->output.p_sys;
406 err = AudioDeviceStop( p_sys->devid, (AudioDeviceIOProc)IOCallback );
409 msg_Err( p_aout, "AudioDeviceStop failed: [%4.4s]", (char *)&err );
412 /* Remove callback */
413 err = AudioDeviceRemoveIOProc( p_sys->devid,
414 (AudioDeviceIOProc)IOCallback );
417 msg_Err( p_aout, "AudioDeviceRemoveIOProc failed: [%4.4s]",
421 FreeHardware( p_aout );
426 /*****************************************************************************
427 * Play: nothing to do
428 *****************************************************************************/
429 static void Play( aout_instance_t * p_aout )
433 /*****************************************************************************
434 * IOCallback: callback for audio output
435 *****************************************************************************/
436 static OSStatus IOCallback( AudioDeviceID inDevice,
437 const AudioTimeStamp *inNow,
438 const void *inInputData,
439 const AudioTimeStamp *inInputTime,
440 AudioBufferList *outOutputData,
441 const AudioTimeStamp *inOutputTime,
442 void *threadGlobals )
444 aout_buffer_t * p_buffer;
445 AudioTimeStamp host_time;
446 mtime_t current_date;
448 aout_instance_t * p_aout = (aout_instance_t *)threadGlobals;
449 struct aout_sys_t * p_sys = p_aout->output.p_sys;
451 host_time.mFlags = kAudioTimeStampHostTimeValid;
452 AudioDeviceTranslateTime( inDevice, inOutputTime, &host_time );
453 current_date = p_sys->clock_diff +
454 AudioConvertHostTimeToNanos( host_time.mHostTime ) / 1000;
456 #define B_SPDI (p_aout->output.output.i_format == VLC_FOURCC('s','p','d','i'))
457 p_buffer = aout_OutputNextBuffer( p_aout, current_date, B_SPDI );
460 if( p_buffer != NULL )
462 /* move data into output data buffer */
463 BlockMoveData( p_buffer->p_buffer,
464 outOutputData->mBuffers[ 0 ].mData,
465 p_sys->i_buffer_size );
467 aout_BufferFree( p_buffer );
471 if( p_aout->output.output.i_format == VLC_FOURCC('f','l','3','2') )
474 int i_size = p_sys->i_buffer_size / sizeof(float);
476 float * a = (float *)outOutputData->mBuffers[ 0 ].mData;
477 for ( i = 0 ; i < i_size ; i++ )
482 memset( outOutputData->mBuffers[ 0 ].mData,
483 0, p_sys->i_buffer_size );
490 /*****************************************************************************
492 *****************************************************************************/
493 static int InitHardware( aout_instance_t * p_aout )
496 UInt32 i, i_param_size;
497 AudioDeviceID * p_devices;
499 struct aout_sys_t * p_sys = p_aout->output.p_sys;
501 /* Get number of devices */
502 err = AudioHardwareGetPropertyInfo( kAudioHardwarePropertyDevices,
503 &i_param_size, NULL );
506 msg_Err( p_aout, "AudioHardwareGetPropertyInfo failed: [%4.4s]",
508 return( VLC_EGENERIC );
511 p_sys->i_devices = i_param_size / sizeof( AudioDeviceID );
513 if( p_sys->i_devices < 1 )
515 msg_Err( p_aout, "no devices found" );
516 return( VLC_EGENERIC );
519 msg_Dbg( p_aout, "system has [%ld] device(s)", p_sys->i_devices );
521 /* Allocate DeviceID array */
522 p_devices = (AudioDeviceID *)malloc( i_param_size );
523 if( p_devices == NULL )
525 msg_Err( p_aout, "out of memory" );
526 return( VLC_ENOMEM );
529 /* Populate DeviceID array */
530 err = AudioHardwareGetProperty( kAudioHardwarePropertyDevices,
531 &i_param_size, (void *)p_devices );
534 msg_Err( p_aout, "AudioHardwareGetProperty failed: [%4.4s]",
536 free( (void *)p_devices );
537 return( VLC_EGENERIC );
540 p_sys->p_devices = (struct aout_dev_t *)
541 malloc( sizeof( struct aout_dev_t ) * p_sys->i_devices );
542 if( p_sys->p_devices == NULL )
544 msg_Err( p_aout, "out of memory" );
545 free( (void *)p_devices );
546 return( VLC_ENOMEM );
549 for( i = 0; i < p_sys->i_devices; i++ )
551 p_sys->p_devices[i].devid = p_devices[i];
553 if( InitDevice( i, p_aout ) )
557 msg_Err( p_aout, "InitDevice(%ld) failed", i );
559 for( j = 0; j < i; j++ )
561 FreeDevice( j, p_aout );
564 free( (void *)p_sys->p_devices );
565 free( (void *)p_devices );
567 return( VLC_EGENERIC );
571 free( (void *)p_devices );
573 return( VLC_SUCCESS );
576 /*****************************************************************************
578 *****************************************************************************/
579 static int InitDevice( UInt32 i_dev, aout_instance_t * p_aout )
582 UInt32 i, i_param_size;
583 AudioBufferList *p_buffer_list;
585 struct aout_sys_t * p_sys = p_aout->output.p_sys;
586 struct aout_dev_t * p_dev = &p_sys->p_devices[i_dev];
588 /* Get length of device name */
589 err = AudioDeviceGetPropertyInfo( p_dev->devid, 0, FALSE,
590 kAudioDevicePropertyDeviceName,
591 &i_param_size, NULL );
594 msg_Err( p_aout, "AudioDeviceGetPropertyInfo failed: [%4.4s]",
596 return( VLC_EGENERIC );
599 /* Allocate memory for device name */
600 p_dev->psz_device_name = (char *)malloc( i_param_size );
601 if( p_dev->psz_device_name == NULL )
603 msg_Err( p_aout, "out of memory" );
604 return( VLC_ENOMEM );
607 /* Get device name */
608 err = AudioDeviceGetProperty( p_dev->devid, 0, FALSE,
609 kAudioDevicePropertyDeviceName,
610 &i_param_size, p_dev->psz_device_name );
613 msg_Err( p_aout, "AudioDeviceGetProperty failed: [%4.4s]",
615 free( (void *)p_dev->psz_device_name );
616 return( VLC_EGENERIC );
619 msg_Dbg( p_aout, "device [%ld] has name [%s]",
620 i_dev, p_dev->psz_device_name );
622 err = AudioDeviceGetPropertyInfo( p_dev->devid, 0, FALSE,
623 kAudioDevicePropertyStreamConfiguration,
624 &i_param_size, NULL );
627 msg_Err( p_aout, "AudioDeviceGetPropertyInfo failed: [%4.4s]",
629 free( (void *)p_dev->psz_device_name );
630 return( VLC_EGENERIC );
633 p_buffer_list = (AudioBufferList *)malloc( i_param_size );
634 if( p_buffer_list == NULL )
636 msg_Err( p_aout, "out of memory" );
637 free( (void *)p_dev->psz_device_name );
638 return( VLC_ENOMEM );
641 err = AudioDeviceGetProperty( p_dev->devid, 0, FALSE,
642 kAudioDevicePropertyStreamConfiguration,
643 &i_param_size, p_buffer_list );
646 msg_Err( p_aout, "AudioDeviceGetProperty failed: [%4.4s]",
648 free( (void *)p_dev->psz_device_name );
649 free( (void *)p_buffer_list );
650 return( VLC_EGENERIC );
653 p_dev->i_streams = p_buffer_list->mNumberBuffers;
654 free( (void *)p_buffer_list );
656 msg_Dbg( p_aout, "device [%ld] has [%ld] streams",
657 i_dev, p_dev->i_streams );
659 p_dev->pp_streams = (AudioStreamBasicDescription **)
660 malloc( p_dev->i_streams *
661 sizeof( *p_dev->pp_streams ) );
662 if( p_dev->pp_streams == NULL )
664 msg_Err( p_aout, "out of memory" );
665 free( (void *)p_dev->psz_device_name );
666 return( VLC_ENOMEM );
669 for( i = 0; i < p_dev->i_streams; i++ )
671 if( InitStream( i_dev, p_aout, i ) )
675 msg_Err( p_aout, "InitStream(%ld, %ld) failed", i_dev, i );
677 for( j = 0; j < i; j++ )
679 FreeStream( i_dev, p_aout, j );
682 free( (void *)p_dev->psz_device_name );
683 free( (void *)p_dev->pp_streams );
685 return( VLC_EGENERIC );
689 return( VLC_SUCCESS );
692 /*****************************************************************************
694 *****************************************************************************/
695 static void FreeDevice( UInt32 i_dev, aout_instance_t * p_aout )
699 struct aout_sys_t * p_sys = p_aout->output.p_sys;
700 struct aout_dev_t * p_dev = &p_sys->p_devices[i_dev];
702 for( i = 0; i < p_dev->i_streams; i++ )
704 FreeStream( i_dev, p_aout, i );
707 free( (void *)p_dev->pp_streams );
708 free( (void *)p_dev->psz_device_name );
711 /*****************************************************************************
713 *****************************************************************************/
714 static void FreeHardware( aout_instance_t * p_aout )
718 struct aout_sys_t * p_sys = p_aout->output.p_sys;
720 for( i = 0; i < p_sys->i_devices; i++ )
722 FreeDevice( i, p_aout );
725 free( (void *)p_sys->p_options );
726 free( (void *)p_sys->p_devices );
729 /*****************************************************************************
731 *****************************************************************************/
732 static int GetStreamID( AudioDeviceID devid, UInt32 i_idx,
733 AudioStreamID * p_sid )
737 AudioStreamID * p_stream_list;
739 err = AudioDeviceGetPropertyInfo( devid, 0, FALSE,
740 kAudioDevicePropertyStreams,
741 &i_param_size, NULL );
744 return( VLC_EGENERIC );
747 p_stream_list = (AudioStreamID *)malloc( i_param_size );
748 if( p_stream_list == NULL )
750 return( VLC_ENOMEM );
753 err = AudioDeviceGetProperty( devid, 0, FALSE,
754 kAudioDevicePropertyStreams,
755 &i_param_size, p_stream_list );
758 free( (void *)p_stream_list );
759 return( VLC_EGENERIC );
762 *p_sid = p_stream_list[i_idx - 1];
764 free( (void *)p_stream_list );
766 return( VLC_SUCCESS );
769 /*****************************************************************************
771 *****************************************************************************/
772 static int InitStream( UInt32 i_dev, aout_instance_t *p_aout,
778 UInt32 j, i_param_size;
780 struct aout_sys_t * p_sys = p_aout->output.p_sys;
781 struct aout_dev_t * p_dev = &p_sys->p_devices[i_dev];
783 if( GetStreamID( p_dev->devid, i_idx + 1, &i_sid ) )
785 msg_Err( p_aout, "GetStreamID(%ld, %ld) failed", i_dev, i_idx );
786 return( VLC_EGENERIC );
789 err = AudioStreamGetPropertyInfo( i_sid, 0,
790 kAudioStreamPropertyPhysicalFormats,
791 &i_param_size, NULL );
794 msg_Err( p_aout, "AudioStreamGetPropertyInfo failed: [%4.4s]",
796 return( VLC_EGENERIC );
799 i_streams = i_param_size / sizeof( AudioStreamBasicDescription );
801 #define P_STREAMS p_dev->pp_streams[i_idx]
803 P_STREAMS = (AudioStreamBasicDescription *)malloc( i_param_size );
804 if( P_STREAMS == NULL )
806 msg_Err( p_aout, "out of memory" );
807 return( VLC_ENOMEM );
810 err = AudioStreamGetProperty( i_sid, 0,
811 kAudioStreamPropertyPhysicalFormats,
812 &i_param_size, P_STREAMS );
815 msg_Err( p_aout, "AudioStreamGetProperty failed: [%4.4s]",
817 free( (void *)P_STREAMS );
818 return( VLC_EGENERIC );
821 for( j = 0; j < N_AOUT_CLASSES; j++ )
823 vlc_bool_t b_found = 0;
824 UInt32 i_channels = 0xFFFFFFFF;
827 for( i = 0; i < i_streams; i++ )
831 msg_Dbg( p_aout, STREAM_FORMAT_MSG( "supported format",
835 if( ( P_STREAMS[i].mFormatID != aout_classes[j].mFormatID ) ||
836 ( P_STREAMS[i].mChannelsPerFrame <
837 aout_classes[j].mChannelsPerFrame ) )
842 if( P_STREAMS[i].mChannelsPerFrame < i_channels )
844 i_channels = P_STREAMS[i].mChannelsPerFrame;
852 p_sys->p_options = (struct aout_option_t *)
853 realloc( p_sys->p_options,
854 ( p_sys->i_options + 1 ) *
855 sizeof( struct aout_option_t ) );
856 if( p_sys->p_options == NULL )
858 msg_Err( p_aout, "out of memory" );
859 free( (void *)P_STREAMS );
860 return( VLC_ENOMEM );
863 #define AOUT_OPTION p_sys->p_options[p_sys->i_options]
865 snprintf( AOUT_OPTION.sz_option,
866 sizeof( AOUT_OPTION.sz_option ) /
867 sizeof( AOUT_OPTION.sz_option[0] ) - 1,
870 p_dev->psz_device_name,
871 aout_classes[j].psz_class );
873 AOUT_OPTION.i_sid = i_sid;
874 AOUT_OPTION.i_dev = i_dev;
875 AOUT_OPTION.i_idx = i_idx;
876 AOUT_OPTION.i_sdx = i_sdx;
877 AOUT_OPTION.i_cdx = j;
887 return( VLC_SUCCESS );
890 /*****************************************************************************
892 *****************************************************************************/
893 static void FreeStream( UInt32 i_dev, aout_instance_t *p_aout,
896 struct aout_sys_t * p_sys = p_aout->output.p_sys;
897 struct aout_dev_t * p_dev = &p_sys->p_devices[i_dev];
899 free( (void *)p_dev->pp_streams[i_idx] );
902 /*****************************************************************************
904 *****************************************************************************/
905 static int GetDevice( aout_instance_t *p_aout, AudioDeviceID *p_devid )
909 unsigned int i_option;
911 struct aout_dev_t * p_dev;
912 struct aout_option_t * p_option;
913 struct aout_sys_t * p_sys = p_aout->output.p_sys;
915 if( var_Get( p_aout, "audio-device", &val ) < 0 )
917 msg_Err( p_aout, "audio-device var does not exist" );
918 return( VLC_ENOVAR );
921 if( !sscanf( val.psz_string, "%d:", &i_option ) ||
922 p_sys->i_options <= i_option )
927 free( (void *)val.psz_string );
929 p_option = &p_sys->p_options[i_option];
930 p_dev = &p_sys->p_devices[p_option->i_dev];
932 #define P_STREAMS p_dev->pp_streams[p_option->i_idx]
934 err = AudioStreamSetProperty( p_option->i_sid, 0, 0,
935 kAudioStreamPropertyPhysicalFormat,
936 sizeof( P_STREAMS[p_option->i_sdx] ),
937 &P_STREAMS[p_option->i_sdx] );
940 msg_Err( p_aout, "AudioStreamSetProperty failed: [%4.4s]",
942 return( VLC_EGENERIC );
947 msg_Dbg( p_aout, "getting device [%ld]", p_option->i_dev );
949 config_PutInt( p_aout, "macosx-adev", i_option );
951 *p_devid = p_dev->devid;
953 return( VLC_SUCCESS );