diff --git a/lib/native/mac/libjnmaccoreaudio.jnilib b/lib/native/mac/libjnmaccoreaudio.jnilib index 5be4b22878f8b79b21dab272c8c80b913127a3f2..45ab370812c8b7c3337591fa32f8d6e2ccca656d 100755 Binary files a/lib/native/mac/libjnmaccoreaudio.jnilib and b/lib/native/mac/libjnmaccoreaudio.jnilib differ diff --git a/src/native/macosx/coreaudio/jni/org_jitsi_impl_neomedia_MacCoreAudioDevice.c b/src/native/macosx/coreaudio/jni/org_jitsi_impl_neomedia_MacCoreAudioDevice.c index 5ec04cd9267143d09efb6d49aed9cedf271626e3..31aac0d4018a5cf0d32dd068e378bafbb3a9f026 100644 --- a/src/native/macosx/coreaudio/jni/org_jitsi_impl_neomedia_MacCoreAudioDevice.c +++ b/src/native/macosx/coreaudio/jni/org_jitsi_impl_neomedia_MacCoreAudioDevice.c @@ -189,13 +189,14 @@ Java_org_jitsi_impl_neomedia_MacCoreAudioDevice_startStream jint bitsPerChannel, jboolean isFloat, jboolean isBigEndian, - jboolean isNonInterleaved) + jboolean isNonInterleaved, + jboolean isInput) { const char * deviceUIDPtr = (*env)->GetStringUTFChars(env, deviceUID, 0); jobject callbackObject = (*env)->NewGlobalRef(env, callback); maccoreaudio_stream* stream = NULL; - if(maccoreaudio_isInputDevice(deviceUIDPtr)) // input + if(isInput && maccoreaudio_isInputDevice(deviceUIDPtr)) // input { jmethodID callbackMethod = maccoreaudio_getCallbackMethodID( env, @@ -213,7 +214,7 @@ Java_org_jitsi_impl_neomedia_MacCoreAudioDevice_startStream isBigEndian, isNonInterleaved); } - else if(maccoreaudio_isOutputDevice(deviceUIDPtr)) // output + else if(!isInput && maccoreaudio_isOutputDevice(deviceUIDPtr)) // output { jmethodID callbackMethod = maccoreaudio_getCallbackMethodID( env, diff --git a/src/native/macosx/coreaudio/jni/org_jitsi_impl_neomedia_MacCoreAudioDevice.h b/src/native/macosx/coreaudio/jni/org_jitsi_impl_neomedia_MacCoreAudioDevice.h index 729cbe1dc32745fc6b70aa71b32f3de124d98944..225dbcca090839ad4afb019e951e734520fb4f2c 100644 --- a/src/native/macosx/coreaudio/jni/org_jitsi_impl_neomedia_MacCoreAudioDevice.h +++ b/src/native/macosx/coreaudio/jni/org_jitsi_impl_neomedia_MacCoreAudioDevice.h @@ -93,7 +93,8 @@ JNIEXPORT jlong JNICALL Java_org_jitsi_impl_neomedia_MacCoreAudioDevice_startStr jint bitsPerChannel, jboolean isFloat, jboolean isBigEndian, - jboolean isNonInterleaved); + jboolean isNonInterleaved, + jboolean isInput); /* * Class: org_jitsi_impl_neomedia_MacCoreAudioDevice diff --git a/src/native/macosx/coreaudio/lib/device.c b/src/native/macosx/coreaudio/lib/device.c index d517c2f3ee54169d6b4f401323debd2f366685fc..3c9e89f2a35452d270affc43c88c610c9bafc3f4 100644 --- a/src/native/macosx/coreaudio/lib/device.c +++ b/src/native/macosx/coreaudio/lib/device.c @@ -8,6 +8,7 @@ #include <CoreAudio/CoreAudio.h> #include <CoreFoundation/CFString.h> +#include <pthread.h> #include <stdio.h> /** @@ -135,6 +136,22 @@ OSStatus maccoreaudio_getStreamVirtualFormat( AudioStreamID stream, AudioStreamBasicDescription * format); +OSStatus +maccoreaudio_getDeviceFormat( + const char * deviceUID, + unsigned char isOutput, + AudioStreamBasicDescription * deviceFormat); + +OSStatus +maccoreaudio_getDeviceFormatDeprecated( + const char * deviceUID, + unsigned char isOutput, + AudioStreamBasicDescription * deviceFormat); + +void +maccoreaudio_getDefaultFormat( + AudioStreamBasicDescription * deviceFormat); + /** * Do nothing: there is no need to initializes anything to get device * information on MacOsX. @@ -233,8 +250,10 @@ AudioDeviceID maccoreaudio_getDeviceForSpecificScope( kCFStringEncodingASCII)) == NULL) { fprintf(stderr, - "getDevice (coreaudio/device.c): \ - \n\tCFStringCreateWithCString\n"); + "maccoreaudio_getDevice (coreaudio/device.c): \ + \n\tCFStringCreateWithCString for device %s\n", + deviceUID); + fflush(stderr); return kAudioObjectUnknown; } @@ -258,9 +277,15 @@ AudioDeviceID maccoreaudio_getDeviceForSpecificScope( &translation)) != noErr) { fprintf(stderr, - "getDevice (coreaudio/device.c): \ - \n\tAudioObjectGetPropertyData, err: %d\n", - ((int) err)); + "maccoreaudio_getDevice (coreaudio/device.c): \ + \n\tAudioObjectGetPropertyData, err: %d for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); + + // Frees the allocated device UID ref. + CFRelease(deviceUIDRef); + return kAudioObjectUnknown; } @@ -331,6 +356,7 @@ char* maccoreaudio_getDefaultDeviceUID( "maccoreaudio_getDefaultDeviceUID (coreaudio/device.c): \ \n\tAudioObjectGetPropertyData, err: %d\n", ((int) err)); + fflush(stderr); return NULL; } @@ -342,6 +368,7 @@ char* maccoreaudio_getDefaultDeviceUID( fprintf(stderr, "maccoreaudio_getDefaultDeviceUID (coreaudio/device.c): \ \n\tgetAudioDeviceProperty\n"); + fflush(stderr); return NULL; } @@ -399,8 +426,10 @@ char* maccoreaudio_getDeviceProperty( if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) { fprintf(stderr, - "getDeviceProperty (coreaudio/device.c): \ - \n\tgetDevice\n"); + "maccoreaudio_getDeviceProperty (coreaudio/device.c): \ + \n\tgetDevice: %s\n", + deviceUID); + fflush(stderr); return NULL; } @@ -441,9 +470,10 @@ char* maccoreaudio_getAudioDeviceProperty( &deviceProperty)) != noErr) { fprintf(stderr, - "getDeviceProperty (coreaudio/device.c): \ + "maccoreaudio_getDeviceProperty (coreaudio/device.c): \ \n\tAudioObjectGetPropertyData, err: %d\n", ((int) err)); + fflush(stderr); return NULL; } @@ -455,7 +485,7 @@ char* maccoreaudio_getAudioDeviceProperty( = (char *) malloc(devicePropertyLength * sizeof(char))) == NULL) { - perror("getDeviceProperty (coreaudio/device.c): \ + perror("maccoreaudio_getDeviceProperty (coreaudio/device.c): \ \n\tmalloc\n"); return NULL; } @@ -539,8 +569,10 @@ OSStatus maccoreaudio_setDeviceVolume( if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) { fprintf(stderr, - "setDeviceVolume (coreaudio/device.c): \ - \n\tgetDevice (unknown device for UID: %s)\n", deviceUID); + "maccoreaudio_setDeviceVolume (coreaudio/device.c): \ + \n\tmaccoreaudio_getDevice (unknown device for UID: %s)\n", + deviceUID); + fflush(stderr); return -1; } @@ -548,9 +580,12 @@ OSStatus maccoreaudio_setDeviceVolume( if((maccoreaudio_getChannelsForStereo(deviceUID, channels)) != noErr) { fprintf(stderr, - "setDeviceVolume (coreaudio/device.c): \ - \n\tgetChannelsForStereo, err: %d\n", - ((int) err)); + "maccoreaudio_setDeviceVolume (coreaudio/device.c): \ + \n\tmaccoreaudio_getChannelsForStereo, err: %d \ + for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); return err; } @@ -586,9 +621,12 @@ OSStatus maccoreaudio_setDeviceVolume( &volume)) != noErr) { fprintf(stderr, - "setDeviceVolume (coreaudio/device.c): \ - \n\tAudioObjectSetPropertyData, err: %d\n", - ((int) err)); + "maccoreaudio_setDeviceVolume (coreaudio/device.c): \ + \n\tAudioObjectSetPropertyData, err: %d \ + for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); return err; } } @@ -656,8 +694,10 @@ Float32 maccoreaudio_getDeviceVolume( if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) { fprintf(stderr, - "getDeviceVolume (coreaudio/device.c): \ - \n\tgetDevice\n"); + "maccoreaudio_getDeviceVolume (coreaudio/device.c): \ + \n\tmaccoreaudio_getDevice: %s\n", + deviceUID); + fflush(stderr); return -1.0; } @@ -665,9 +705,12 @@ Float32 maccoreaudio_getDeviceVolume( if((maccoreaudio_getChannelsForStereo(deviceUID, channels)) != noErr) { fprintf(stderr, - "getDeviceVolume (coreaudio/device.c): \ - \n\tgetChannelsForStereo, err: %d\n", - ((int) err)); + "maccoreaudio_getDeviceVolume (coreaudio/device.c): \ + \n\tmaccoreaudio_getChannelsForStereo, err: %d \ + for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); return -1.0; } @@ -703,9 +746,12 @@ Float32 maccoreaudio_getDeviceVolume( &volume)) != noErr) { fprintf(stderr, - "getDeviceVolume (coreaudio/device.c): \ - \n\tAudioObjectSetPropertyData, err: %d\n", - ((int) err)); + "maccoreaudio_getDeviceVolume (coreaudio/device.c): \ + \n\tAudioObjectSetPropertyData, err: %d \ + for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); return -1.0; } } @@ -737,8 +783,10 @@ OSStatus maccoreaudio_getChannelsForStereo( if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) { fprintf(stderr, - "getChannelsForStereo (coreaudio/device.c): \ - \n\tgetDevice\n"); + "maccoreaudio_getChannelsForStereo (coreaudio/device.c): \ + \n\tmaccoreaudio_getDevice: %s\n", + deviceUID); + fflush(stderr); return -1; } @@ -756,9 +804,11 @@ OSStatus maccoreaudio_getChannelsForStereo( channels)) != noErr) { fprintf(stderr, - "getChannelsForStereo (coreaudio/device.c): \ - \n\tAudioObjectGetPropertyData, err: %d\n", - ((int) err)); + "maccoreaudio_getChannelsForStereo (coreaudio/device.c): \ + \n\tAudioObjectGetPropertyData, err: %d for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); return err; } @@ -823,8 +873,10 @@ int maccoreaudio_countChannels( if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) { fprintf(stderr, - "getChannelsForStereo (coreaudio/device.c): \ - \n\tgetDevice\n"); + "maccoreaudio_countChannels (coreaudio/device.c): \ + \n\tmaccoreaudio_getDevice: %s\n", + deviceUID); + fflush(stderr); return -1; } @@ -837,8 +889,11 @@ int maccoreaudio_countChannels( { fprintf(stderr, "maccoreaudio_countChannels (coreaudio/device.c): \ - \n\tAudioObjectGetPropertyDataSize, err: %d\n", - ((int) err)); + \n\tAudioObjectGetPropertyDataSize, err: %d \ + for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); return -1; } @@ -860,8 +915,10 @@ int maccoreaudio_countChannels( { fprintf(stderr, "maccoreaudio_countChannels (coreaudio/device.c): \ - \n\tAudioObjectGetPropertyData, err: %d\n", - ((int) err)); + \n\tAudioObjectGetPropertyData, err: %d for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); return -1; } for(i = 0; i < audioBufferList->mNumberBuffers; ++i) @@ -894,8 +951,10 @@ Float64 maccoreaudio_getNominalSampleRate( if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) { fprintf(stderr, - "getNominalSampleRate (coreaudio/device.c): \ - \n\tgetDevice\n"); + "maccoreaudio_getNominalSampleRate (coreaudio/device.c): \ + \n\tmaccoreaudio_getDevice: %s\n", + deviceUID); + fflush(stderr); return -1.0; } @@ -915,9 +974,11 @@ Float64 maccoreaudio_getNominalSampleRate( != noErr) { fprintf(stderr, - "getNominalSampleRate (coreaudio/device.c): \ - \n\tAudioObjactGetPropertyData, err: %d\n", - (int) err); + "maccoreaudio_getNominalSampleRate (coreaudio/device.c): \ + \n\tAudioObjactGetPropertyData, err: %d for device %s\n", + (int) err, + deviceUID); + fflush(stderr); return -1.0; } @@ -950,8 +1011,11 @@ OSStatus maccoreaudio_getAvailableNominalSampleRates( if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) { fprintf(stderr, - "getAvailableNominalSampleRates (coreaudio/device.c): \ - \n\tgetDevice\n"); + "maccoreaudio_getAvailableNominalSampleRates \ + (coreaudio/device.c): \ + \n\tmaccoreaudio_getDevice: %s\n", + deviceUID); + fflush(stderr); return -1.0; } @@ -971,9 +1035,12 @@ OSStatus maccoreaudio_getAvailableNominalSampleRates( != noErr) { fprintf(stderr, - "getAvailableNominalSampleRates (coreaudio/device.c): \ - \n\tAudioObjactGetPropertyData, err: %d\n", - (int) err); + "maccoreaudio_getAvailableNominalSampleRates \ + (coreaudio/device.c): \ + \n\tAudioObjactGetPropertyData, err: %d for device %s\n", + (int) err, + deviceUID); + fflush(stderr); return -1.0; } @@ -1015,9 +1082,10 @@ int maccoreaudio_getDeviceUIDList( != noErr) { fprintf(stderr, - "getDeviceUIDList (coreaudio/device.c): \ + "maccoreaudio_getDeviceUIDList (coreaudio/device.c): \ \n\tAudioObjectGetPropertyDataSize, err: %d\n", ((int) err)); + fflush(stderr); return -1; } @@ -1026,7 +1094,7 @@ int maccoreaudio_getDeviceUIDList( if((devices = (AudioDeviceID*) malloc(nbDevices * sizeof(AudioDeviceID))) == NULL) { - perror("getDeviceUIDList (coreaudio/device.c): \ + perror("maccoreaudio_getDeviceUIDList (coreaudio/device.c): \ \n\tmalloc\n"); return -1; } @@ -1042,9 +1110,10 @@ int maccoreaudio_getDeviceUIDList( { free(devices); fprintf(stderr, - "getDeviceUIDList (coreaudio/device.c): \ + "maccoreaudio_getDeviceUIDList (coreaudio/device.c): \ \n\tAudioObjectGetPropertyData, err: %d\n", ((int) err)); + fflush(stderr); return -1; } @@ -1052,7 +1121,7 @@ int maccoreaudio_getDeviceUIDList( == NULL) { free(devices); - perror("getDeviceUIDList (coreaudio/device.c): \ + perror("maccoreaudio_getDeviceUIDList (coreaudio/device.c): \ \n\tmalloc\n"); return -1; } @@ -1073,8 +1142,9 @@ int maccoreaudio_getDeviceUIDList( free(*deviceUIDList); free(devices); fprintf(stderr, - "getDeviceUIDList (coreaudio/device.c): \ - \n\tgetAudioDeviceProperty\n"); + "maccoreaudio_getDeviceUIDList (coreaudio/device.c): \ + \n\tmaccoreaudio_getAudioDeviceProperty\n"); + fflush(stderr); return -1; } } @@ -1097,11 +1167,18 @@ void maccoreaudio_initializeHotplug( kAudioObjectPropertyElementMaster }; - AudioObjectAddPropertyListener( - kAudioObjectSystemObject, - &address, - maccoreaudio_devicesChangedCallback, - callbackFunction); + if(AudioObjectAddPropertyListener( + kAudioObjectSystemObject, + &address, + maccoreaudio_devicesChangedCallback, + callbackFunction) + != noErr) + { + fprintf(stderr, + "maccoreaudio_initializeHotplug (coreaudio/device.c): \ + \n\tAudioObjectAddPropertyListener\n"); + fflush(stderr); + } } /** @@ -1116,11 +1193,18 @@ void maccoreaudio_uninitializeHotplug() kAudioObjectPropertyElementMaster }; - AudioObjectRemovePropertyListener( - kAudioObjectSystemObject, - &address, - maccoreaudio_devicesChangedCallback, - NULL); + if(AudioObjectRemovePropertyListener( + kAudioObjectSystemObject, + &address, + maccoreaudio_devicesChangedCallback, + NULL) + != noErr) + { + fprintf(stderr, + "maccoreaudio_uninitializeHotplug (coreaudio/device.c): \ + \n\tAudioObjectRemovePropertyListener\n"); + fflush(stderr); + } } /** @@ -1165,7 +1249,9 @@ const char* maccoreaudio_getTransportType( { fprintf(stderr, "maccoreaudio_getTransportType (coreaudio/device.c): \ - \n\tgetDevice\n"); + \n\tgetDevice: %s\n", + deviceUID); + fflush(stderr); return NULL; } // target device transport type property @@ -1188,8 +1274,10 @@ const char* maccoreaudio_getTransportType( { fprintf(stderr, "maccoreaudio_getTransportType (coreaudio/device.c): \ - \n\tAudioObjectGetPropertyData: err: %d\n", - (int) err); + \n\tAudioObjectGetPropertyData: err: 0x%x for device %s\n", + (int) err, + deviceUID); + fflush(stderr); return NULL; } @@ -1238,6 +1326,11 @@ const char* maccoreaudio_getTransportType( return transportTypeVirtual; break; default: + fprintf(stderr, + "maccoreaudio_getTransportType (coreaudio/device.c): \ + \n\tNo transport type found for device %s\n", + deviceUID); + fflush(stderr); return NULL; break; } @@ -1320,13 +1413,16 @@ maccoreaudio_stream * maccoreaudio_startStream( unsigned char isNonInterleaved) { AudioDeviceID device; + OSStatus err = noErr; // Gets the correspoding device if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) { fprintf(stderr, "maccoreaudio_startStream (coreaudio/device.c): \ - \n\tgetDevice\n"); + \n\tmaccoreaudio_getDevice: %s\n", + deviceUID); + fflush(stderr); return NULL; } @@ -1344,6 +1440,14 @@ maccoreaudio_stream * maccoreaudio_startStream( stream->callbackObject = callbackObject; stream->callbackMethod = callbackMethod; + if(pthread_mutex_init(&stream->mutex, NULL) != 0) + { + perror("maccoreaudio_startStream (coreaudio/device.c): \ + \n\tpthread_mutex_init\n"); + free(stream); + return NULL; + } + AudioStreamBasicDescription javaFormat; FillOutASBDForLPCM( &javaFormat, @@ -1354,65 +1458,137 @@ maccoreaudio_stream * maccoreaudio_startStream( isFloat, isBigEndian, isNonInterleaved); - if(maccoreaudio_initConverter( + if((err = maccoreaudio_initConverter( deviceUID, &javaFormat, isJavaFormatSource, &stream->converter, - &stream->conversionRatio) + &stream->conversionRatio)) != noErr) { - free(stream); fprintf(stderr, "maccoreaudio_startStream (coreaudio/device.c): \ - \n\tmaccoreaudio_initConverter\n"); + \n\tmaccoreaudio_initConverter: 0x%x for device %s\n", + (int) err, + deviceUID); + fflush(stderr); + pthread_mutex_destroy(&stream->mutex); + free(stream); return NULL; } // register the IOProc - if(AudioDeviceCreateIOProcID( + if((err = AudioDeviceCreateIOProcID( device, readWriteFunction, stream, - &stream->ioProcId) != noErr) + &stream->ioProcId)) != noErr) { - free(stream); fprintf(stderr, "maccoreaudio_startStream (coreaudio/device.c): \ - \n\tAudioDeviceIOProcID\n"); + \n\tAudioDeviceIOProcID: 0x%x for device %s\n", + (int) err, + deviceUID); + fflush(stderr); + AudioConverterDispose(stream->converter); + pthread_mutex_destroy(&stream->mutex); + free(stream); return NULL; } // start IO - AudioDeviceStart(device, stream->ioProcId); + if((err = AudioDeviceStart(device, stream->ioProcId)) != noErr) + { + fprintf(stderr, + "maccoreaudio_startStream (coreaudio/device.c): \ + \n\tAudioDeviceStart: 0x%x for device %s\n", + (int) err, + deviceUID); + fflush(stderr); + AudioDeviceDestroyIOProcID(device, stream->ioProcId); + AudioConverterDispose(stream->converter); + pthread_mutex_destroy(&stream->mutex); + free(stream); + return NULL; + } return stream; } +/** + * Stops the stream for the given device. + * + * @param deviceUID The device identifier. + * @param stream The stream to stop. + */ void maccoreaudio_stopStream( const char * deviceUID, maccoreaudio_stream * stream) { AudioDeviceID device; + OSStatus err = noErr; + + if(pthread_mutex_lock(&stream->mutex) != 0) + { + perror("maccoreaudio_stopStream (coreaudio/device.c): \ + \n\tpthread_mutex_lock\n"); + } // Gets the correspoding device if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) { fprintf(stderr, "maccoreaudio_stopStream (coreaudio/device.c): \ - \n\tgetDevice: %s\n", + \n\tmaccoreaudio_getDevice: %s\n", deviceUID); fflush(stderr); - return; + } + else + { + // stop IO + if((err = AudioDeviceStop(device, stream->ioProcId)) != noErr) + { + fprintf(stderr, + "maccoreaudio_stopStream (coreaudio/device.c): \ + \n\tAudioDeviceStop: 0x%x for device %s\n", + (int) err, + deviceUID); + fflush(stderr); + } + // unregister the IOProc + if((err = AudioDeviceDestroyIOProcID(device, stream->ioProcId)) + != noErr) + { + fprintf(stderr, + "maccoreaudio_stopStream (coreaudio/device.c): \ + \n\tAudioDeviceDestroyIOProcID: 0x%x for device %s\n", + (int) err, + deviceUID); + fflush(stderr); + } } - // stop IO - AudioDeviceStop(device, stream->ioProcId); - - // unregister the IOProc - AudioDeviceDestroyIOProcID(device, stream->ioProcId); + if((err = AudioConverterDispose(stream->converter)) != noErr) + { + fprintf(stderr, + "maccoreaudio_stopStream (coreaudio/device.c): \ + \n\tAudioConverterDispose: 0x%x for device %s\n", + (int) err, + deviceUID); + fflush(stderr); + } - AudioConverterDispose(stream->converter); + stream->ioProcId = 0; + if(pthread_mutex_unlock(&stream->mutex) != 0) + { + perror("maccoreaudio_stopStream (coreaudio/device.c): \ + \n\tpthread_mutex_unlock\n"); + } + if(pthread_mutex_destroy(&stream->mutex) != 0) + { + perror("maccoreaudio_stopStream (coreaudio/device.c): \ + \n\tpthread_mutex_destroy\n"); + } free(stream); } @@ -1434,34 +1610,52 @@ OSStatus maccoreaudio_readInputStream( = inInputData->mBuffers[0].mDataByteSize * stream->conversionRatio; char tmpBuffer[tmpLength]; int i; - for(i = 0; i < inInputData->mNumberBuffers; ++i) + + if(pthread_mutex_lock(&stream->mutex) == 0) { - if(inInputData->mBuffers[i].mData != NULL - && inInputData->mBuffers[i].mDataByteSize > 0) + if(stream->ioProcId != 0) { - if((err = AudioConverterConvertBuffer( - stream->converter, - inInputData->mBuffers[i].mDataByteSize, - inInputData->mBuffers[i].mData, - &tmpLength, - tmpBuffer)) - != noErr) + for(i = 0; i < inInputData->mNumberBuffers; ++i) { - fprintf(stderr, + if(inInputData->mBuffers[i].mData != NULL + && inInputData->mBuffers[i].mDataByteSize > 0) + { + if((err = AudioConverterConvertBuffer( + stream->converter, + inInputData->mBuffers[i].mDataByteSize, + inInputData->mBuffers[i].mData, + &tmpLength, + tmpBuffer)) + != noErr) + { + fprintf(stderr, "maccoreaudio_readInputStream (coreaudio/device.c): \ - \n\tAudioConverterConvertBuffer: %x\n", - (int) err); - fflush(stderr); - return err; + \n\tAudioConverterConvertBuffer: 0x%x\n", + (int) err); + fflush(stderr); + pthread_mutex_unlock(&stream->mutex); + return err; + } + + callbackFunction( + tmpBuffer, + tmpLength, + stream->callbackObject, + stream->callbackMethod); + } } - - callbackFunction( - tmpBuffer, - tmpLength, - stream->callbackObject, - stream->callbackMethod); + } + if(pthread_mutex_unlock(&stream->mutex) != 0) + { + perror("maccoreaudio_readInputStream (coreaudio/device.c): \ + \n\tpthread_mutex_unlock\n"); } } + else + { + perror("maccoreaudio_readInputStream (coreaudio/device.c): \ + \n\tpthread_mutex_lock\n"); + } return noErr; } @@ -1490,25 +1684,46 @@ OSStatus maccoreaudio_writeOutputStream( = outOutputData->mBuffers[0].mDataByteSize * stream->conversionRatio; char tmpBuffer[tmpLength]; - callbackFunction( - tmpBuffer, - tmpLength, - stream->callbackObject, - stream->callbackMethod); - - if((err = AudioConverterConvertBuffer( - stream->converter, - tmpLength, + if(pthread_mutex_lock(&stream->mutex) == 0) + { + if(stream->ioProcId != 0) + { + callbackFunction( tmpBuffer, - &outOutputData->mBuffers[0].mDataByteSize, - outOutputData->mBuffers[0].mData)) - != noErr) + tmpLength, + stream->callbackObject, + stream->callbackMethod); + + if((err = AudioConverterConvertBuffer( + stream->converter, + tmpLength, + tmpBuffer, + &outOutputData->mBuffers[0].mDataByteSize, + outOutputData->mBuffers[0].mData)) + != noErr) + { + fprintf(stderr, + "maccoreaudio_writeOutputStream (coreaudio/device.c): \ + \n\tAudioConverterConvertBuffer: 0x%x\n", (int) err); + fflush(stderr); + memset( + outOutputData->mBuffers[0].mData, + 0, + outOutputData->mBuffers[0].mDataByteSize); + pthread_mutex_unlock(&stream->mutex); + return err; + } + } + if(pthread_mutex_unlock(&stream->mutex) != 0) + { + perror("maccoreaudio_writeOutputStream (coreaudio/device.c): \ + \n\tpthread_mutex_unlock\n"); + } + } + else { - fprintf(stderr, - "maccoreaudio_writeOutputStream (coreaudio/device.c): \ - \n\tAudioConverterConvertBuffer\n"); - fflush(stderr); - return err; + perror("maccoreaudio_writeOutputStream (coreaudio/device.c): \ + \n\tpthread_mutex_lock\n"); } // Copies the same data into the other buffers. @@ -1602,56 +1817,38 @@ OSStatus maccoreaudio_initConverter( AudioConverterRef * converter, double * conversionRatio) { - AudioDeviceID device; + AudioStreamBasicDescription deviceFormat; OSStatus err = noErr; - AudioObjectPropertyAddress address; - - // Gets the correspoding device - if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) + if((err = maccoreaudio_getDeviceFormat( + deviceUID, + isJavaFormatSource, + &deviceFormat)) + != noErr) { fprintf(stderr, "maccoreaudio_initConverter (coreaudio/device.c): \ - \n\tgetDevice\n"); + \n\tmaccoreaudio_getDeviceFormat for device: %s\n", + deviceUID); fflush(stderr); - return kAudioObjectUnknown; - } - AudioStreamBasicDescription deviceFormat; - AudioStreamID audioStreamIds[1]; - UInt32 size = sizeof(AudioStreamID *); - address.mSelector = kAudioDevicePropertyStreams; - address.mScope = kAudioObjectPropertyScopeGlobal; - address.mElement = kAudioObjectPropertyElementMaster; - if((err = AudioObjectGetPropertyData( - device, - &address, - 0, - NULL, - &size, - &audioStreamIds)) - != noErr) - { - fprintf(stderr, - "maccoreaudio_countChannels (coreaudio/device.c): \ - \n\tAudioObjectGetPropertyData, err: 0x%x\n", - ((int) err)); - fflush(stderr); - return err; - } + if((err = maccoreaudio_getDeviceFormatDeprecated( + deviceUID, + isJavaFormatSource, + &deviceFormat)) != noErr) + { + fprintf(stderr, + "maccoreaudio_initConverter (coreaudio/device.c): \ + \n\tmaccoreaudio_getDeviceFormatDeprecated \ + for device: %s\n", + deviceUID); + fflush(stderr); - if((err = maccoreaudio_getStreamVirtualFormat( - audioStreamIds[0], - &deviceFormat)) - != noErr) - { - fprintf(stderr, - "maccoreaudio_countChannels (coreaudio/device.c): \ - \n\tmaccoreaudiogetStreamVirtualFormat, err: 0x%x\n", - ((int) err)); - fflush(stderr); - return err; + // Everything has failed to retrieve the device format, then try + // with the default one. + maccoreaudio_getDefaultFormat(&deviceFormat); + } } - + const AudioStreamBasicDescription *inFormat = javaFormat; const AudioStreamBasicDescription *outFormat = &deviceFormat; if(!isJavaFormatSource) @@ -1664,7 +1861,7 @@ OSStatus maccoreaudio_initConverter( != noErr) { fprintf(stderr, - "maccoreaudio_countChannels (coreaudio/device.c): \ + "maccoreaudio_initConverter (coreaudio/device.c): \ \n\tAudioConverterNew, err: 0x%x\n", ((int) err)); fflush(stderr); @@ -1672,9 +1869,8 @@ OSStatus maccoreaudio_initConverter( } *conversionRatio = - ((double) javaFormat->mBytesPerFrame) - / ((double) deviceFormat.mBytesPerFrame) - * javaFormat->mSampleRate / deviceFormat.mSampleRate; + ((double) javaFormat->mBytesPerFrame * javaFormat->mSampleRate) + / ((double) deviceFormat.mBytesPerFrame * deviceFormat.mSampleRate); return err; } @@ -1750,3 +1946,164 @@ inline void FillOutASBDForLPCM( outASBD->mChannelsPerFrame = inChannelsPerFrame; outASBD->mBitsPerChannel = inValidBitsPerChannel; } + +/** + * Returns the device format. + * + * @param deviceUID The device identifier. + * @param isOutput True if the device is an output device. + * @param deviceFormat The structure to fill in with the device format. + * + * @return noErr if everything works fine. Any other value for an error. + */ +OSStatus +maccoreaudio_getDeviceFormat( + const char * deviceUID, + unsigned char isOutput, + AudioStreamBasicDescription * deviceFormat) +{ + AudioDeviceID device; + OSStatus err = noErr; + AudioObjectPropertyAddress address; + + // Gets the correspoding device + if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) + { + fprintf(stderr, + "maccoreaudio_getDeviceFormat (coreaudio/device.c): \ + \n\tgetDevice: %s\n", + deviceUID); + fflush(stderr); + return kAudioObjectUnknown; + } + + AudioStreamID audioStreamIds[1]; + UInt32 size = sizeof(AudioStreamID *); + address.mSelector = kAudioDevicePropertyStreams; + if(isOutput) + { + address.mScope = kAudioDevicePropertyScopeOutput; + } + else + { + address.mScope = kAudioDevicePropertyScopeInput; + } + address.mElement = kAudioObjectPropertyElementMaster; + if((err = AudioObjectGetPropertyData( + device, + &address, + 0, + NULL, + &size, + &audioStreamIds)) + != noErr) + { + fprintf(stderr, + "maccoreaudio_getDeviceFormat (coreaudio/device.c): \ + \n\tAudioObjectGetPropertyData, err: 0x%x for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); + return err; + } + + if((err = maccoreaudio_getStreamVirtualFormat( + audioStreamIds[0], + deviceFormat)) + != noErr) + { + fprintf(stderr, + "maccoreaudio_getDeviceFormat (coreaudio/device.c): \ + \n\tmaccoreaudio_getStreamVirtualFormat, err: 0x%x\ + for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); + return err; + } + + return err; +} + +/** + * Returns the device format using deprecated property. + * + * @param deviceUID The device identifier. + * @param isOutput True if the device is an output device. + * @param deviceFormat The structure to fill in with the device format. + * + * @return noErr if everything works fine. Any other value for an error. + */ +OSStatus +maccoreaudio_getDeviceFormatDeprecated( + const char * deviceUID, + unsigned char isOutput, + AudioStreamBasicDescription * deviceFormat) +{ + AudioDeviceID device; + OSStatus err = noErr; + AudioObjectPropertyAddress address; + + // Gets the correspoding device + if((device = maccoreaudio_getDevice(deviceUID)) == kAudioObjectUnknown) + { + fprintf(stderr, + "maccoreaudio_getDeviceFormatDeprecated (coreaudio/device.c): \ + \n\tgetDevice: %s\n", + deviceUID); + fflush(stderr); + return kAudioObjectUnknown; + } + + UInt32 size = sizeof(AudioStreamBasicDescription); + // This property ought to some day be deprecated. + address.mSelector = kAudioDevicePropertyStreamFormat; + if(isOutput) + { + address.mScope = kAudioDevicePropertyScopeOutput; + } + else + { + address.mScope = kAudioDevicePropertyScopeInput; + } + address.mElement = kAudioObjectPropertyElementMaster; + + if((err = AudioObjectGetPropertyData( + device, + &address, + 0, + NULL, + &size, + deviceFormat)) + != noErr) + { + fprintf(stderr, + "maccoreaudio_getDeviceFormatDeprecated (coreaudio/device.c): \ + \n\tAudioObjectGetPropertyData err: 0x%x for device %s\n", + ((int) err), + deviceUID); + fflush(stderr); + } + + return err; +} + +/** + * Returns the default format. + * + * @param deviceFormat The structure to fill in with the default format. + */ +void +maccoreaudio_getDefaultFormat( + AudioStreamBasicDescription * deviceFormat) +{ + FillOutASBDForLPCM( + deviceFormat, + 44100.0, + 2, + 8 * sizeof(AudioUnitSampleType), // 32 + 8 * sizeof(AudioUnitSampleType), // 32 + true, + false, + false); +} diff --git a/src/native/macosx/coreaudio/lib/device.h b/src/native/macosx/coreaudio/lib/device.h index b13fc50f477d948ce212b975ba615cf8d801060e..829375bfe29b1082fb6b95c9709b95ef76ffd5a0 100644 --- a/src/native/macosx/coreaudio/lib/device.h +++ b/src/native/macosx/coreaudio/lib/device.h @@ -26,6 +26,7 @@ typedef struct void* callbackMethod; AudioConverterRef converter; double conversionRatio; + pthread_mutex_t mutex; } maccoreaudio_stream; int maccoreaudio_initDevices( diff --git a/src/org/jitsi/impl/neomedia/MacCoreAudioDevice.java b/src/org/jitsi/impl/neomedia/MacCoreAudioDevice.java index 530ce28fc4b342c0e0a9f9fa49cdb5750d932153..abae38c8a2d5233ee97096eace9f6a134f235cab 100644 --- a/src/org/jitsi/impl/neomedia/MacCoreAudioDevice.java +++ b/src/org/jitsi/impl/neomedia/MacCoreAudioDevice.java @@ -86,7 +86,8 @@ public static native long startStream( int bitsPerChannel, boolean isFloat, boolean isBigEndian, - boolean isNonInterleaved); + boolean isNonInterleaved, + boolean isInput); public static native void stopStream(String deviceUID, long stream); diff --git a/src/org/jitsi/impl/neomedia/device/Devices.java b/src/org/jitsi/impl/neomedia/device/Devices.java index 49deeb961b6a6535b89bbe07bc2d0cc27ee289aa..9cc4fa944bb90cf5ec561aa499cfabc92c71b5e7 100644 --- a/src/org/jitsi/impl/neomedia/device/Devices.java +++ b/src/org/jitsi/impl/neomedia/device/Devices.java @@ -162,6 +162,8 @@ public CaptureDeviceInfo2 getSelectedDevice( loadDevicePreferences(property); renameOldFashionedIdentifier(activeDevices); + boolean isEmptyList = devicePreferences.isEmpty(); + // Search if an active device is a new one (is not stored in the // preferences yet). If true, then active this device and set it as // default device (only for USB devices since the user has @@ -188,6 +190,17 @@ public CaptureDeviceInfo2 getSelectedDevice( isSelected = false; } + // When initiates the first list (when there is no user + // preferences yet), set the Bluetooh and Airplay to the end + // of the list (this corresponds to move all other type + // of devices on top of the preference list). + if(isEmptyList + && !activeDevice.isSameTransportType("Bluetooth") + && !activeDevice.isSameTransportType("AirPlay")) + { + isSelected = true; + } + // Adds the device in the preference list (to the end of the // list, or on top if selected. saveDevice(property, activeDevice, isSelected); diff --git a/src/org/jitsi/impl/neomedia/device/MacCoreaudioSystem.java b/src/org/jitsi/impl/neomedia/device/MacCoreaudioSystem.java index 20d1e8b373faf6bbb1cd1c9b86c003b623319682..1363804c9967fdecb985ca555fee352b4aeac195 100644 --- a/src/org/jitsi/impl/neomedia/device/MacCoreaudioSystem.java +++ b/src/org/jitsi/impl/neomedia/device/MacCoreaudioSystem.java @@ -779,6 +779,6 @@ private void reinitialize() @Override public String toString() { - return "MacCoreaudio"; + return "Core Audio"; } } diff --git a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/maccoreaudio/MacCoreaudioStream.java b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/maccoreaudio/MacCoreaudioStream.java index 1289c46a2369bc03042e527c43da361301c2dcac..8f14c37f8d5ed51408245125a0b7ee79d17aa100 100644 --- a/src/org/jitsi/impl/neomedia/jmfext/media/protocol/maccoreaudio/MacCoreaudioStream.java +++ b/src/org/jitsi/impl/neomedia/jmfext/media/protocol/maccoreaudio/MacCoreaudioStream.java @@ -121,9 +121,11 @@ public void didUpdateAvailableDeviceList() { synchronized(startStopMutex) { - setDeviceUID(deviceUID); - if(start) + if(stream == 0 && start) + { + setDeviceUID(deviceUID); start(); + } deviceUID = null; start = false; } @@ -134,7 +136,7 @@ public void willUpdateAvailableDeviceList() { synchronized(startStopMutex) { - if (stream == 0) + if(stream == 0) { deviceUID = null; start = false; @@ -369,7 +371,8 @@ public void start() format.getSampleSizeInBits(), false, format.getEndian() == AudioFormat.BIG_ENDIAN, - false); + false, + true); MacCoreaudioSystem.didOpenStream(); } } diff --git a/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/MacCoreaudioRenderer.java b/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/MacCoreaudioRenderer.java index c5a30e1bdf96eed1a6fae15e13e5569cbed1c191..ac80361525699ac0112d1cd0218a2d820a34e1f3 100644 --- a/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/MacCoreaudioRenderer.java +++ b/src/org/jitsi/impl/neomedia/jmfext/media/renderer/audio/MacCoreaudioRenderer.java @@ -448,6 +448,7 @@ public void start() inputFormat.getSampleSizeInBits(), false, inputFormat.getEndian() == AudioFormat.BIG_ENDIAN, + false, false); MacCoreaudioSystem.didOpenStream(); }