+/*****************************************************************************
+ * AudioStreamChangeFormat: Change i_stream_id to change_format
+ *****************************************************************************/
+static int AudioStreamChangeFormat( aout_instance_t *p_aout, AudioStreamID i_stream_id, AudioStreamBasicDescription change_format )
+{
+ OSStatus err = noErr;
+ UInt32 i_param_size = 0;
+ int i;
+
+ struct timeval now;
+ struct timespec timeout;
+ struct { vlc_mutex_t lock; vlc_cond_t cond; } w;
+
+ msg_Dbg( p_aout, STREAM_FORMAT_MSG( "setting stream format: ", change_format ) );
+
+ /* Condition because SetProperty is asynchronious */
+ vlc_cond_init( p_aout, &w.cond );
+ vlc_mutex_init( p_aout, &w.lock );
+ vlc_mutex_lock( &w.lock );
+
+ /* Install the callback */
+ err = AudioStreamAddPropertyListener( i_stream_id, 0,
+ kAudioStreamPropertyPhysicalFormat,
+ StreamListener, (void *)&w );
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "AudioStreamAddPropertyListener failed: [%4.4s]", (char *)&err );
+ return VLC_FALSE;
+ }
+
+ /* change the format */
+ err = AudioStreamSetProperty( i_stream_id, 0, 0,
+ kAudioStreamPropertyPhysicalFormat,
+ sizeof( AudioStreamBasicDescription ),
+ &change_format );
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "could not set the stream format: [%4.4s]", (char *)&err );
+ return VLC_FALSE;
+ }
+
+ /* The AudioStreamSetProperty is not only asynchronious (requiring the locks)
+ * it is also not Atomic, in it's behaviour.
+ * Therefore we check 5 times before we really give up.
+ * FIXME: failing isn't actually implemented yet. */
+ for( i = 0; i < 5; i++ )
+ {
+ AudioStreamBasicDescription actual_format;
+
+ gettimeofday( &now, NULL );
+ timeout.tv_sec = now.tv_sec;
+ timeout.tv_nsec = (now.tv_usec + 500000) * 1000;
+
+ if( pthread_cond_timedwait( &w.cond.cond, &w.lock.mutex, &timeout ) )
+ {
+ msg_Dbg( p_aout, "reached timeout" );
+ }
+
+ i_param_size = sizeof( AudioStreamBasicDescription );
+ err = AudioStreamGetProperty( i_stream_id, 0,
+ kAudioStreamPropertyPhysicalFormat,
+ &i_param_size,
+ &actual_format );
+
+ msg_Dbg( p_aout, STREAM_FORMAT_MSG( "actual format in use: ", actual_format ) );
+ if( actual_format.mSampleRate == change_format.mSampleRate &&
+ actual_format.mFormatID == change_format.mFormatID &&
+ actual_format.mFramesPerPacket == change_format.mFramesPerPacket )
+ {
+ /* The right format is now active */
+ break;
+ }
+ /* We need to check again */
+ }
+
+ /* Removing the property listener */
+ err = AudioStreamRemovePropertyListener( i_stream_id, 0,
+ kAudioStreamPropertyPhysicalFormat,
+ StreamListener );
+ if( err != noErr )
+ {
+ msg_Err( p_aout, "AudioStreamRemovePropertyListener failed: [%4.4s]", (char *)&err );
+ return VLC_FALSE;
+ }
+
+ /* Destroy the lock and condition */
+ vlc_mutex_unlock( &w.lock );
+ vlc_mutex_destroy( &w.lock );
+ vlc_cond_destroy( &w.cond );
+
+ return VLC_TRUE;
+}
+