[jitsi-dev] Fwd: [jitsi~svn:9348] Ongoing work on cross protocol conference calls. Adds missing portaudio h


#1

Hi Lyubomir,

I have just commited my ongoing work on cross protocol conference calls.
If I have broken something related to video conference or other things,
do not hesitate to tell me.

···

--
Seb

-------- Message original --------
Sujet: [jitsi~svn:9348] Ongoing work on cross protocol conference calls. Adds missing portaudio h
Date : Wed, 8 Feb 2012 15:37:25 +0000
De : s_vincent@java.net
Répondre à : commits@jitsi.java.net
Pour : commits@jitsi.java.net

Project: jitsi
Repository: svn
Revision: 9348
Author: s_vincent
Date: 2012-02-08 15:37:21 UTC
Link:

Log Message:
------------
Ongoing work on cross protocol conference calls. Adds missing portaudio hotplug patch.

Revisions:
----------
9348

Modified Paths:
---------------
trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
trunk/src/net/java/sip/communicator/impl/neomedia/device/VideoTranslatorMediaDevice.java
trunk/src/net/java/sip/communicator/service/protocol/AbstractCall.java
trunk/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceFocusPanel.java
trunk/src/net/java/sip/communicator/impl/protocol/gibberish/CallGibberishImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerGTalkImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallGTalkImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/mock/MockOperationSetBasicTelephony.java
trunk/src/net/java/sip/communicator/service/protocol/Call.java
trunk/src/net/java/sip/communicator/impl/protocol/sip/OperationSetTelephonyConferencingSipImpl.java
trunk/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferencePeerPanel.java
trunk/src/net/java/sip/communicator/service/protocol/media/MediaAwareCall.java
trunk/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
trunk/src/net/java/sip/communicator/impl/protocol/sip/CallPeerSipImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/mock/MockCallPeer.java
trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallJabberImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/sip/CallSipImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetTelephonyConferencingJabberImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/mock/MockCall.java
trunk/src/net/java/sip/communicator/impl/gui/main/call/conference/ConferenceCallPanel.java
trunk/src/net/java/sip/communicator/service/protocol/OperationSetBasicTelephony.java
trunk/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java
trunk/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/gibberish/OperationSetBasicTelephonyGibberishImpl.java
trunk/src/net/java/sip/communicator/service/protocol/CallPeer.java
trunk/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
trunk/src/net/java/sip/communicator/impl/protocol/sip/OperationSetBasicTelephonySipImpl.java
trunk/src/net/java/sip/communicator/impl/globalshortcut/CallShortcut.java
trunk/src/net/java/sip/communicator/impl/protocol/gibberish/CallPeerGibberishImpl.java

Added Paths:
------------
trunk/src/net/java/sip/communicator/service/protocol/event/CallGroupEvent.java
trunk/src/net/java/sip/communicator/service/protocol/event/CallGroupListener.java
trunk/src/native/portaudio/portaudio-hotplug-os.patch
trunk/src/net/java/sip/communicator/service/protocol/CallGroup.java

Diffs:
------
Index: trunk/src/native/portaudio/portaudio-hotplug-os.patch

--- trunk/src/native/portaudio/portaudio-hotplug-os.patch (revision 0)
+++ trunk/src/native/portaudio/portaudio-hotplug-os.patch (revision 9348)
@@ -0,0 +1,1311 @@
+Index: test/patest_update_available_device_list.c
+===================================================================
+--- test/patest_update_available_device_list.c (revision 1799)
++++ test/patest_update_available_device_list.c (working copy)
+@@ -1,5 +1,6 @@
+ #include<stdio.h>
+ #include<assert.h>
++#include<unistd.h>
+
+ #include "portaudio.h"
+
+@@ -33,9 +34,10 @@
+
+ for(;;){
+ printDevices();
+-
++
+ printf( "press [enter] to update the device list. or q + [enter] to quit.\n" );
+- if( getchar() == 'q' )
++ char ch = getchar();
++ if( ch == 'q' )
+ break;
+
+ Pa_UpdateAvailableDeviceList();
+Index: configure
+===================================================================
+--- configure (revision 1799)
++++ configure (working copy)
+@@ -11341,7 +11341,7 @@
+ fi
+ SHARED_FLAGS="$LIBS -dynamiclib $mac_arches $mac_sysroot $mac_version_min"
+ CFLAGS="-std=c99 $CFLAGS $mac_arches $mac_sysroot $mac_version_min"
+- OTHER_OBJS="src/os/unix/pa_unix_hostapis.o src/os/unix/pa_unix_util.o src/hostapi/coreaudio/pa_mac_core.o src/hostapi/coreaudio/pa_mac_core_utilities.o src/hostapi/coreaudio/pa_mac_core_blocking.o src/common/pa_ringbuffer.o"
++ OTHER_OBJS="src/os/unix/pa_unix_hostapis.o src/os/unix/pa_unix_util.o src/hostapi/coreaudio/pa_mac_core.o src/hostapi/coreaudio/pa_mac_core_utilities.o src/hostapi/coreaudio/pa_mac_core_blocking.o src/common/pa_ringbuffer.o src/os/mac_osx/pa_osx_hotplug.o"
+ PADLL="libportaudio.dylib"
+ ;;
+
+@@ -11373,7 +11373,7 @@
+
+ if [ "x$with_wdmks" = "xyes" ]; then
+ DXDIR="$with_dxdir"
+- add_objects src/hostapi/wdmks/pa_win_wdmks.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o
++ add_objects src/hostapi/wdmks/pa_win_wdmks.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o src/os/win/pa_win_wdmks_utils.o
+ LIBS="-lwinmm -lm -luuid -lsetupapi -lole32"
+ DLL_LIBS="${DLL_LIBS} -lwinmm -lm -L$DXDIR/lib -luuid -lsetupapi -lole32"
+ #VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\""
+@@ -11610,7 +11610,7 @@
+ if [ "$have_alsa" = "yes" ]&& [ "$with_alsa" != "no" ] ; then
+ DLL_LIBS="$DLL_LIBS -lasound"
+ LIBS="$LIBS -lasound"
+- OTHER_OBJS="$OTHER_OBJS src/hostapi/alsa/pa_linux_alsa.o"
++ OTHER_OBJS="$OTHER_OBJS src/hostapi/alsa/pa_linux_alsa.o src/os/unix/pa_linux_hotplug.o"
+ INCLUDES="$INCLUDES pa_linux_alsa.h"
+ $as_echo "#define PA_USE_ALSA 1">>confdefs.h
+
+Index: Makefile.in
+===================================================================
+--- Makefile.in (revision 1799)
++++ Makefile.in (working copy)
+@@ -107,6 +107,7 @@
+ bin/patest_wire \
+ bin/patest_write_sine \
+ bin/patest_write_sine_nonint \
++ bin/patest_update_available_device_list \
+ bin/pa_devs \
+ bin/pa_fuzz \
+ bin/pa_minlat
+@@ -146,6 +147,7 @@
+ src/hostapi/wdmks \
+ src/hostapi/wmme \
+ src/os/unix \
++ src/os/mac_osx \
+ src/os/win
+
+ SUBDIRS =
+Index: configure.in
+===================================================================
+--- configure.in (revision 1799)
++++ configure.in (working copy)
+@@ -216,7 +216,7 @@
+ fi
+ SHARED_FLAGS="$LIBS -dynamiclib $mac_arches $mac_sysroot $mac_version_min"
+ CFLAGS="-std=c99 $CFLAGS $mac_arches $mac_sysroot $mac_version_min"
+- OTHER_OBJS="src/os/unix/pa_unix_hostapis.o src/os/unix/pa_unix_util.o src/hostapi/coreaudio/pa_mac_core.o src/hostapi/coreaudio/pa_mac_core_utilities.o src/hostapi/coreaudio/pa_mac_core_blocking.o src/common/pa_ringbuffer.o"
++ OTHER_OBJS="src/os/unix/pa_unix_hostapis.o src/os/unix/pa_unix_util.o src/hostapi/coreaudio/pa_mac_core.o src/hostapi/coreaudio/pa_mac_core_utilities.o src/hostapi/coreaudio/pa_mac_core_blocking.o src/common/pa_ringbuffer.o src/os/mac_osx/pa_osx_hotplug.o"
+ PADLL="libportaudio.dylib"
+ ;;
+
+@@ -230,7 +230,7 @@
+
+ if [[ "x$with_directx" = "xyes" ]]; then
+ DXDIR="$with_dxdir"
+- add_objects src/hostapi/dsound/pa_win_ds.o src/hostapi/dsound/pa_win_ds_dynlink.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o src/os/win/pa_win_waveformat.o
++ add_objects src/hostapi/dsound/pa_win_ds.o src/hostapi/dsound/pa_win_ds_dynlink.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o src/os/win/pa_win_waveformat.o src/os/win/pa_win_hotplug.o
+ LIBS="-lwinmm -lm -ldsound -lole32"
+ DLL_LIBS="${DLL_LIBS} -lwinmm -lm -L$DXDIR/lib -ldsound -lole32"
+ #VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\""
+@@ -249,7 +249,7 @@
+
+ if [[ "x$with_wdmks" = "xyes" ]]; then
+ DXDIR="$with_dxdir"
+- add_objects src/hostapi/wdmks/pa_win_wdmks.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o
++ add_objects src/hostapi/wdmks/pa_win_wdmks.o src/os/win/pa_win_hostapis.o src/os/win/pa_win_util.o src/os/win/pa_win_wdmks_utils.o
+ LIBS="-lwinmm -lm -luuid -lsetupapi -lole32"
+ DLL_LIBS="${DLL_LIBS} -lwinmm -lm -L$DXDIR/lib -luuid -lsetupapi -lole32"
+ #VC98="\"/c/Program Files/Microsoft Visual Studio/VC98/Include\""
+@@ -319,7 +319,7 @@
+ if [[ "$have_alsa" = "yes" ]&& [ "$with_alsa" != "no" ]] ; then
+ DLL_LIBS="$DLL_LIBS -lasound"
+ LIBS="$LIBS -lasound"
+- OTHER_OBJS="$OTHER_OBJS src/hostapi/alsa/pa_linux_alsa.o"
++ OTHER_OBJS="$OTHER_OBJS src/hostapi/alsa/pa_linux_alsa.o src/os/unix/pa_linux_hotplug.o"
+ INCLUDES="$INCLUDES pa_linux_alsa.h"
+ AC_DEFINE(PA_USE_ALSA)
+ fi
+Index: src/os/unix/pa_linux_hotplug.c
+===================================================================
+--- src/os/unix/pa_linux_hotplug.c (revision 0)
++++ src/os/unix/pa_linux_hotplug.c (revision 0)
+@@ -0,0 +1,147 @@
++
++#include "pa_util.h"
++#include "pa_debugprint.h"
++#include "pa_allocation.h"
++#include "pa_linux_alsa.h"
++#include "pa_hostapi.h"
++
++#include<alsa/asoundlib.h>
++
++#include<stdio.h>
++#include<signal.h>
++#include<pthread.h>
++
++/* Implemented in pa_front.c
++ @param first 0 = unknown, 1 = insertion, 2 = removal
++ @param second Host specific device change info (in windows it is the (unicode) device path)
++*/
++extern void PaUtil_DevicesChanged(unsigned, void*);
++
++static pthread_t g_thread_id;
++static pthread_mutex_t g_mutex;
++static volatile sig_atomic_t g_run = 0;
++
++static int device_list_size(void)
++{
++ snd_ctl_t *handle;
++ int card, err, dev, idx;
++ int nb = 0;
++ snd_ctl_card_info_t *info;
++ snd_pcm_info_t *pcminfo;
++ snd_ctl_card_info_alloca(&info);
++ snd_pcm_info_alloca(&pcminfo);
++
++ card = -1;
++ if (snd_card_next(&card)< 0 || card< 0)
++ {
++ return nb;
++ }
++
++ while (card>= 0)
++ {
++ char name[32];
++
++ sprintf(name, "hw:%d", card);
++ if ((err = snd_ctl_open(&handle, name, 0))< 0)
++ {
++ goto next_card;
++ }
++ if ((err = snd_ctl_card_info(handle, info))< 0)
++ {
++ snd_ctl_close(handle);
++ goto next_card;
++ }
++ dev = -1;
++ while (1)
++ {
++ unsigned int count;
++ int hasPlayback = 0;
++ int hasCapture = 0;
++
++ snd_ctl_pcm_next_device(handle,&dev);
++
++ if (dev< 0)
++ break;
++ snd_pcm_info_set_device(pcminfo, dev);
++ snd_pcm_info_set_subdevice(pcminfo, 0);
++ snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
++ if ((err = snd_ctl_pcm_info(handle, pcminfo))>= 0)
++ {
++ hasCapture = 1;
++ }
++
++ snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
++ if ((err = snd_ctl_pcm_info(handle, pcminfo))>= 0)
++ {
++ hasPlayback = 1;
++
++ count = snd_pcm_info_get_subdevices_count(pcminfo);
++ }
++
++ if(hasPlayback == 0&& hasCapture == 0)
++ continue;
++
++ nb++;
++ }
++ snd_ctl_close(handle);
++next_card:
++ if (snd_card_next(&card)< 0)
++ {
++ break;
++ }
++ }
++ return nb;
++}
++
++static void* thread_fcn(void* data)
++{
++ int currentDevices = 0;
++
++ currentDevices = device_list_size();
++
++ while(g_run)
++ {
++ int count = 0;
++
++ sleep(1);
++ count = device_list_size();
++ if(count != currentDevices)
++ {
++ /* 1 = add device, 2 = remove device */
++ int add = (count> currentDevices) ? 1 : 2;
++
++ currentDevices = count;
++
++ PaUtil_DevicesChanged(add, NULL);
++ }
++ }
++
++ return NULL;
++}
++
++void PaUtil_InitializeHotPlug()
++{
++ pthread_mutex_init(&g_mutex, NULL);
++ g_run = 1;
++ pthread_create(&g_thread_id, NULL, thread_fcn, NULL);
++}
++
++void PaUtil_TerminateHotPlug()
++{
++ void* ret = NULL;
++
++ g_run = 0;
++ pthread_join(g_thread_id,&ret);
++ pthread_mutex_destroy(&g_mutex);
++}
++
++void PaUtil_LockHotPlug()
++{
++ pthread_mutex_lock(&g_mutex);
++}
++
++void PaUtil_UnlockHotPlug()
++{
++ pthread_mutex_unlock(&g_mutex);
++}
++
+Index: src/os/mac_osx/pa_osx_hotplug.c
+===================================================================
+--- src/os/mac_osx/pa_osx_hotplug.c (revision 0)
++++ src/os/mac_osx/pa_osx_hotplug.c (revision 0)
+@@ -0,0 +1,76 @@
++
++#include "pa_util.h"
++#include "pa_debugprint.h"
++#include "pa_allocation.h"
++
++#include<stdio.h>
++
++#include<AudioUnit/AudioUnit.h>
++#include<AudioToolbox/AudioToolbox.h>
++
++/* Implemented in pa_front.c
++ @param first 0 = unknown, 1 = insertion, 2 = removal
++ @param second Host specific device change info (in windows it is the (unicode) device path)
++*/
++extern void PaUtil_DevicesChanged(unsigned, void*);
++
++/* Callback for audio hardware property changes. */
++static OSStatus audioPropertyCallback(AudioHardwarePropertyID inPropertyID,
++ void *refCon)
++{
++ (void)refCon;
++ switch (inPropertyID)
++ {
++ /*
++ * These are the other types of notifications we might receive, however, they are beyond
++ * the scope of this sample and we ignore them.
++ */
++ case kAudioHardwarePropertyDefaultInputDevice:
++ PA_DEBUG(("audioPropertyCallback: default input device changed\n"));
++ break;
++ case kAudioHardwarePropertyDefaultOutputDevice:
++ PA_DEBUG(("audioPropertyCallback: default output device changed\n"));
++ break;
++ case kAudioHardwarePropertyDefaultSystemOutputDevice:
++ PA_DEBUG(("audioPropertyCallback: default system output device changed\n"));
++ break;
++ case kAudioHardwarePropertyDevices:
++ PA_DEBUG(("audioPropertyCallback: device list changed\n"));
++ PaUtil_DevicesChanged(1, NULL);
++ break;
++ default:
++ PA_DEBUG(("audioPropertyCallback: unknown message id=%08lx\n", inPropertyID));
++ break;
++ }
++
++ return noErr;
++}
++
++void PaUtil_InitializeHotPlug()
++{
++ AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices,
++ audioPropertyCallback, NULL);
++ AudioHardwareAddPropertyListener(kAudioHardwarePropertyDefaultInputDevice,
++ audioPropertyCallback, NULL);
++ AudioHardwareAddPropertyListener(kAudioHardwarePropertyDefaultOutputDevice,
++ audioPropertyCallback, NULL);
++}
++
++void PaUtil_TerminateHotPlug()
++{
++ AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices,
++ audioPropertyCallback);
++ AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDefaultInputDevice,
++ audioPropertyCallback);
++ AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDefaultOutputDevice,
++ audioPropertyCallback);
++}
++
++void PaUtil_LockHotPlug()
++{
++}
++
++void PaUtil_UnlockHotPlug()
++{
++}
++
+Index: src/os/win/pa_win_hotplug.c
+===================================================================
+--- src/os/win/pa_win_hotplug.c (revision 1799)
++++ src/os/win/pa_win_hotplug.c (working copy)
+@@ -186,6 +186,8 @@
+ {
+ PA_DEBUG(("Device inserted : %S\n", ptr->dbcc_name));
+ InsertDeviceIntoCache(pInfo, ptr->dbcc_name);
++ /* yield some seconds because added device may not be completely configured */
++ Sleep(2000);
+ PaUtil_DevicesChanged(1, ptr->dbcc_name);
+ }
+ }
+@@ -202,6 +204,7 @@
+ if (RemoveDeviceFromCache(pInfo, ptr->dbcc_name))
+ {
+ PA_DEBUG(("Device removed : %S\n", ptr->dbcc_name));
++ Sleep(2000);
+ PaUtil_DevicesChanged(2, ptr->dbcc_name);
+ }
+ }
+Index: src/os/win/pa_win_hostapis.c
+===================================================================
+--- src/os/win/pa_win_hostapis.c (revision 1799)
++++ src/os/win/pa_win_hostapis.c (working copy)
+@@ -81,7 +81,7 @@
+ #endif
+
+ #if PA_USE_WDMKS
+- PaWinWdm_Initialize,
++ //PaWinWdm_Initialize,
+ #endif
+
+ #if PA_USE_SKELETON
+Index: src/hostapi/alsa/pa_linux_alsa.c
+===================================================================
+--- src/hostapi/alsa/pa_linux_alsa.c (revision 1799)
++++ src/hostapi/alsa/pa_linux_alsa.c (working copy)
+@@ -668,6 +668,15 @@
+ }
+ PaAlsaDeviceInfo;
+
++/* used for tranferring device infos during scanning / rescanning */
++typedef struct PaLinuxScanDeviceInfosResults
++{
++ PaDeviceInfo **deviceInfos;
++ PaDeviceIndex defaultInputDevice;
++ PaDeviceIndex defaultOutputDevice;
++ int deviceCount;
++} PaLinuxScanDeviceInfosResults;
++
+ /* prototypes for functions declared in this file */
+
+ static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
+@@ -692,10 +701,17 @@
+ static PaError IsStreamActive( PaStream *stream );
+ static PaTime GetStreamTime( PaStream *stream );
+ static double GetStreamCpuLoad( PaStream* stream );
+-static PaError BuildDeviceList( PaAlsaHostApiRepresentation *hostApi );
++static PaError BuildDeviceList( PaAlsaHostApiRepresentation *hostApi, void** scanResults, int* deviceCount );
+ static int SetApproximateSampleRate( snd_pcm_t *pcm, snd_pcm_hw_params_t *hwParams, double sampleRate );
+ static int GetExactSampleRate( snd_pcm_hw_params_t *hwParams, double *sampleRate );
+
++static PaError ScanDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
++ void **newDeviceInfos, int *newDeviceCount );
++static PaError CommitDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
++ void *deviceInfos, int deviceCount);
++static PaError DisposeDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, void *deviceInfos,
++ int deviceCount );
++
+ /* Callback prototypes */
+ static void *CallbackThreadFunc( void *userData );
+
+@@ -722,6 +738,8 @@
+ {
+ PaError result = paNoError;
+ PaAlsaHostApiRepresentation *alsaHostApi = NULL;
++ void* scanResults = NULL;
++ int deviceCount = 0;
+
+ /* Try loading Alsa library. */
+ if (!PaAlsa_LoadLibrary())
+@@ -733,20 +751,29 @@
+ alsaHostApi->hostApiIndex = hostApiIndex;
+
+ *hostApi = (PaUtilHostApiRepresentation*)alsaHostApi;
++ (*hostApi)->deviceInfos = NULL;
+ (*hostApi)->info.structVersion = 1;
+ (*hostApi)->info.type = paALSA;
+ (*hostApi)->info.name = "ALSA";
+
++ (*hostApi)->ScanDeviceInfos = NULL;
++ (*hostApi)->CommitDeviceInfos = NULL;
++ (*hostApi)->DisposeDeviceInfos = NULL;
+ (*hostApi)->Terminate = Terminate;
+ (*hostApi)->OpenStream = OpenStream;
+ (*hostApi)->IsFormatSupported = IsFormatSupported;
++ (*hostApi)->ScanDeviceInfos = ScanDeviceInfos;
++ (*hostApi)->CommitDeviceInfos = CommitDeviceInfos;
++ (*hostApi)->DisposeDeviceInfos = DisposeDeviceInfos;
+
+ /** If AlsaErrorHandler is to be used, do not forget to unregister callback pointer in
+ Terminate function.
+ */
+ /*ENSURE_( snd_lib_error_set_handler(AlsaErrorHandler), paUnanticipatedHostError );*/
+
+- PA_ENSURE( BuildDeviceList( alsaHostApi ) );
++ ScanDeviceInfos(&alsaHostApi->baseHostApiRep, hostApiIndex,&scanResults,
++&deviceCount);
++ CommitDeviceInfos(&alsaHostApi->baseHostApiRep, hostApiIndex, scanResults, deviceCount);
+
+ PaUtil_InitializeStreamInterface(&alsaHostApi->callbackStreamInterface,
+ CloseStream, StartStream,
+@@ -802,7 +829,10 @@
+ }
+
+ PaUtil_FreeMemory( alsaHostApi );
+- alsa_snd_config_update_free_global();
++// damencho, removed fo compability with pulseaudio versions before 0.9.16
++// segfault application:
++// bugtrack alsa: 0002124: snd_config_update_free_global kills applications using user space alsa plugins
++// snd_config_update_free_global();
+
+ /* Close Alsa library. */
+ PaAlsa_CloseLibrary();
+@@ -1075,7 +1105,7 @@
+ }
+
+ static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* deviceName, int blocking,
+- PaAlsaDeviceInfo* devInfo, int* devIdx )
++ PaAlsaDeviceInfo* devInfo, int* devIdx, PaLinuxScanDeviceInfosResults* out )
+ {
+ PaError result = 0;
+ PaDeviceInfo *baseDeviceInfo =&devInfo->baseDeviceInfo;
+@@ -1128,20 +1158,20 @@
+ if( baseDeviceInfo->maxInputChannels> 0 || baseDeviceInfo->maxOutputChannels> 0 )
+ {
+ /* Make device default if there isn't already one or it is the ALSA "default" device */
+- if( (baseApi->info.defaultInputDevice == paNoDevice || !strcmp(deviceName->alsaName,
++ if( (out->defaultInputDevice == paNoDevice || !strcmp(deviceName->alsaName,
+ "default" ))&& baseDeviceInfo->maxInputChannels> 0 )
+ {
+- baseApi->info.defaultInputDevice = *devIdx;
++ out->defaultInputDevice = *devIdx;
+ PA_DEBUG(("Default input device: %s\n", deviceName->name));
+ }
+- if( (baseApi->info.defaultOutputDevice == paNoDevice || !strcmp(deviceName->alsaName,
++ if( (out->defaultOutputDevice == paNoDevice || !strcmp(deviceName->alsaName,
+ "default" ))&& baseDeviceInfo->maxOutputChannels> 0 )
+ {
+- baseApi->info.defaultOutputDevice = *devIdx;
++ out->defaultOutputDevice = *devIdx;
+ PA_DEBUG(("Default output device: %s\n", deviceName->name));
+ }
+ PA_DEBUG(("%s: Adding device %s: %d\n", __FUNCTION__, deviceName->name, *devIdx));
+- baseApi->deviceInfos[*devIdx] = (PaDeviceInfo *) devInfo;
++ out->deviceInfos[*devIdx] = (PaDeviceInfo *) devInfo;
+ (*devIdx) += 1;
+ }
+ else
+@@ -1154,9 +1184,10 @@
+ }
+
+ /* Build PaDeviceInfo list, ignore devices for which we cannot determine capabilities (possibly busy, sigh) */
+-static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi )
++static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi, void** scanResults, int* count)
+ {
+ PaUtilHostApiRepresentation *baseApi =&alsaApi->baseHostApiRep;
++ PaLinuxScanDeviceInfosResults *outArgument = NULL;
+ PaAlsaDeviceInfo *deviceInfoArray;
+ int cardIdx = -1, devIdx = 0;
+ snd_ctl_card_info_t *cardInfo;
+@@ -1171,13 +1202,11 @@
+ #ifdef PA_ENABLE_DEBUG_OUTPUT
+ PaTime startTime = PaUtil_GetTime();
+ #endif
++ PaLinuxScanDeviceInfosResults* out = NULL;
+
+ if( getenv( "PA_ALSA_INITIALIZE_BLOCK" )&& atoi( getenv( "PA_ALSA_INITIALIZE_BLOCK" ) ) )
+ blocking = 0;
+
+- /* These two will be set to the first working input and output device, respectively */
+- baseApi->info.defaultInputDevice = paNoDevice;
+- baseApi->info.defaultOutputDevice = paNoDevice;
+
+ /* Gather info about hw devices
+
+@@ -1341,8 +1370,14 @@
+ else
+ PA_DEBUG(( "%s: Iterating over ALSA plugins failed: %s\n", __FUNCTION__, alsa_snd_strerror( res ) ));
+
++ out = (PaLinuxScanDeviceInfosResults *) PaUtil_GroupAllocateMemory(
++ alsaApi->allocations, sizeof(PaLinuxScanDeviceInfosResults) );
++
++ out->defaultInputDevice = paNoDevice;
++ out->defaultOutputDevice = paNoDevice;
++
+ /* allocate deviceInfo memory based on the number of devices */
+- PA_UNLESS( baseApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
++ PA_UNLESS( out->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
+ alsaApi->allocations, sizeof(PaDeviceInfo*) * (numDeviceNames) ), paInsufficientMemory );
+
+ /* allocate all device info structs in a contiguous block */
+@@ -1367,7 +1402,7 @@
+ continue;
+ }
+
+- PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo,&devIdx ) );
++ PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo,&devIdx, out ) );
+ }
+ assert( devIdx< numDeviceNames );
+ /* Now inspect 'dmix' and 'default' plugins */
+@@ -1381,11 +1416,13 @@
+ }
+
+ PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo,
+-&devIdx ) );
++&devIdx, out ) );
+ }
+ free( hwDevInfos );
+
+- baseApi->info.deviceCount = devIdx; /* Number of successfully queried devices */
++ out->deviceCount = devIdx; /* Number of successfully queried devices */
++ *scanResults = out;
++ *count = out->deviceCount;
+
+ #ifdef PA_ENABLE_DEBUG_OUTPUT
+ PA_DEBUG(( "%s: Building device list took %f seconds\n", __FUNCTION__, PaUtil_GetTime() - startTime ));
+@@ -2036,8 +2073,9 @@
+ }
+
+ ENSURE_( alsa_snd_pcm_sw_params_set_avail_min( self->pcm, swParams, self->framesPerBuffer ), paUnanticipatedHostError );
+- ENSURE_( alsa_snd_pcm_sw_params_set_xfer_align( self->pcm, swParams, 1 ), paUnanticipatedHostError );
++// ENSURE_( alsa_snd_pcm_sw_params_set_xfeir_align( self->pcm, swParams, 1 ), paUnanticipatedHostError );
+ ENSURE_( alsa_snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_ENABLE ), paUnanticipatedHostError );
++ ENSURE_( alsa_snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams, SND_PCM_TSTAMP_ENABLE ), paUnanticipatedHostError );
+
+ /* Set the parameters! */
+ ENSURE_( alsa_snd_pcm_sw_params( self->pcm, swParams ), paUnanticipatedHostError );
+@@ -3544,9 +3582,20 @@
+ snd_pcm_sframes_t framesAvail = alsa_snd_pcm_avail_update( self->pcm );
+ *xrunOccurred = 0;
+
+- if( -EPIPE == framesAvail )
+- {
++ /* Get pcm_state and check for xrun condition. On playback I often see
++ * xrun but avail_update does not return -EPIPE but framesAvail larger
++ * than bufferSize. In case of xrun status set xrun flag, leave framesize
++ * as reported by avail_update, will be fixed below. In case avail_update
++ * returns -EPIPE process as usual. wd-xxx
++ */
++ snd_pcm_state_t state = snd_pcm_state( self->pcm ); /* wd-xxx */
++ if (state == SND_PCM_STATE_XRUN) {
++ // printf("xrun, fav %d\n", framesAvail); fflush(stdout); // DEBUG-WD
+ *xrunOccurred = 1;
++ }
++ if( -EPIPE == framesAvail) {
++ // printf("xrun-1, fav %d\n", framesAvail); fflush(stdout); // DEBUG-WD
++ *xrunOccurred = 1;
+ framesAvail = 0;
+ }
+ else
+@@ -3554,6 +3603,11 @@
+ ENSURE_( framesAvail, paUnanticipatedHostError );
+ }
+
++ /* Fix frames avail, should not be bigger than bufferSize wd-xxx */
++ if (framesAvail> self->bufferSize) {
++ // printf("xrun-2, fav %d\n", framesAvail); fflush(stdout); // DEBUG-WD
++ framesAvail = self->bufferSize;
++ }
+ *numFrames = framesAvail;
+
+ error:
+@@ -3603,6 +3657,13 @@
+
+ *shouldPoll = 0;
+ }
++ else
++ {
++ // not actually used
++ unsigned long framesAvail = 0;
++ // now check for xrun
++ PaAlsaStreamComponent_GetAvailableFrames(self,&framesAvail, xrun );
++ }
+
+ error:
+ return result;
+@@ -3693,6 +3754,10 @@
+ framesAvail,&xrun ) );
+ if( xrun )
+ {
++ if(*frameAvail == 0)
++ {
++ result = paInternalError;
++ }
+ goto end;
+ }
+
+@@ -3740,6 +3805,7 @@
+ Pa_Sleep( 1 ); /* avoid hot loop */
+ continue;
+ }
++ result = paInternalError;
+
+ /* TODO: Add macro for checking system calls */
+ PA_ENSURE( paInternalError );
+@@ -3769,6 +3835,7 @@
+ xrun = 1; /* try recovering device */
+
+ PA_DEBUG(( "%s: poll timed out\n", __FUNCTION__, timeouts ));
++ result = paTimedOut;
+ goto end;/*PA_ENSURE( paTimedOut );*/
+ }
+ }
+@@ -4326,9 +4393,24 @@
+ while( frames> 0 )
+ {
+ int xrun = 0;
+- PA_ENSURE( PaAlsaStream_WaitForFrames( stream,&framesAvail,&xrun ) );
++ PA_ENSURE( PaAlsaStream_WaitForFrames( stream,&framesAvail,&xrun ) );
++ /*
++ * In case of overrun WaitForFrames leaves the capture stream in STATE_PREPARED
++ * most of the time. handleXrun() restarts the ALSA stream only in case
++ * snd_pcm_recover() fails, which usually does not happen.
++ * Here we start the pcm stream again and go for another try. Another
++ * option is: set result to paOverrun and return to caller. Then
++ * the caller needs to call ReadStream again. This takes more time and
++ * we lose even more frames.
++ */
++ if (xrun) { /* wd-xxx */
++ if( snd_pcm_state( stream->capture.pcm ) == SND_PCM_STATE_PREPARED ) {
++ ENSURE_( snd_pcm_start( stream->capture.pcm ), paUnanticipatedHostError );
++ }
++ continue;
++ }
++
+ framesGot = PA_MIN( framesAvail, frames );
+-
+ PA_ENSURE( PaAlsaStream_SetUpBuffers( stream,&framesGot,&xrun ) );
+ if( framesGot> 0 )
+ {
+@@ -4546,3 +4628,75 @@
+ busyRetries_ = retries;
+ return paNoError;
+ }
++
++static PaError ScanDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex hostApiIndex,
++ void **scanResults, int *newDeviceCount)
++{
++ PaAlsaHostApiRepresentation* alsaHostApi = (PaAlsaHostApiRepresentation*)hostApi;
++ PaError result = paNoError;
++ PA_ENSURE(BuildDeviceList( alsaHostApi, scanResults, newDeviceCount ));
++
++ return paNoError;
++
++error:
++ return result;
++}
++
++static PaError CommitDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
++ void *scanResults, int deviceCount)
++{
++ PaAlsaHostApiRepresentation* alsaHostApi = (PaAlsaHostApiRepresentation*)hostApi;
++ PaError result = paNoError;
++
++ /* These two will be set to the first working input and output device, respectively */
++ hostApi->info.defaultInputDevice = paNoDevice;
++ hostApi->info.defaultOutputDevice = paNoDevice;
++
++ /* Free any old memory which might be in the device info */
++ if( hostApi->deviceInfos )
++ {
++ /* all device info structs are allocated in a block so we can destroy them here */
++ PaUtil_GroupFreeMemory( alsaHostApi->allocations, hostApi->deviceInfos[0] );
++ PaUtil_GroupFreeMemory( alsaHostApi->allocations, hostApi->deviceInfos );
++ hostApi->deviceInfos = NULL;
++ }
++
++ if( scanResults != NULL )
++ {
++ PaLinuxScanDeviceInfosResults *scanDeviceInfosResults = ( PaLinuxScanDeviceInfosResults * ) scanResults;
++
++ if( deviceCount> 0 )
++ {
++ /* use the array allocated in ScanDeviceInfos() as our deviceInfos */
++ hostApi->deviceInfos = scanDeviceInfosResults->deviceInfos;
++ hostApi->info.defaultInputDevice = scanDeviceInfosResults->defaultInputDevice;
++ hostApi->info.defaultOutputDevice = scanDeviceInfosResults->defaultOutputDevice;
++ hostApi->info.deviceCount = deviceCount;
++ }
++
++ PaUtil_GroupFreeMemory( alsaHostApi->allocations, scanDeviceInfosResults );
++ }
++
++ return result;
++}
++
++static PaError DisposeDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, void *scanResults, int deviceCount)
++{
++ PaAlsaHostApiRepresentation *alsaHostApi = (PaAlsaHostApiRepresentation*)hostApi;
++
++ if( scanResults != NULL )
++ {
++ PaLinuxScanDeviceInfosResults *scanDeviceInfosResults = ( PaLinuxScanDeviceInfosResults * ) scanResults;
++ if( scanDeviceInfosResults->deviceInfos )
++ {
++ /* all device info structs are allocated in a block so we can destroy them here */
++ PaUtil_GroupFreeMemory( alsaHostApi->allocations, scanDeviceInfosResults->deviceInfos[0] );
++ PaUtil_GroupFreeMemory( alsaHostApi->allocations, scanDeviceInfosResults->deviceInfos );
++ }
++
++ PaUtil_GroupFreeMemory(alsaHostApi->allocations, scanDeviceInfosResults );
++ }
++
++ return paNoError;
++}
++
+Index: src/hostapi/oss/pa_unix_oss.c
+===================================================================
+--- src/hostapi/oss/pa_unix_oss.c (revision 1799)
++++ src/hostapi/oss/pa_unix_oss.c (working copy)
+@@ -256,6 +256,9 @@
+ (*hostApi)->Terminate = Terminate;
+ (*hostApi)->OpenStream = OpenStream;
+ (*hostApi)->IsFormatSupported = IsFormatSupported;
++ (*hostApi)->ScanDeviceInfos = NULL;
++ (*hostApi)->CommitDeviceInfos = NULL;
++ (*hostApi)->DisposeDeviceInfos = NULL;
+
+ PA_ENSURE( BuildDeviceList( ossHostApi ) );
+
+Index: src/hostapi/skeleton/pa_hostapi_skeleton.c
+===================================================================
+--- src/hostapi/skeleton/pa_hostapi_skeleton.c (revision 1799)
++++ src/hostapi/skeleton/pa_hostapi_skeleton.c (working copy)
+@@ -206,9 +206,15 @@
+ }
+ }
+
++ (*hostApi)->ScanDeviceInfos = NULL;
++ (*hostApi)->CommitDeviceInfos = NULL;
++ (*hostApi)->DisposeDeviceInfos = NULL;
+ (*hostApi)->Terminate = Terminate;
+ (*hostApi)->OpenStream = OpenStream;
+ (*hostApi)->IsFormatSupported = IsFormatSupported;
++ (*hostApi)->ScanDeviceInfos = NULL;
++ (*hostApi)->CommitDeviceInfos = NULL;
++ (*hostApi)->DisposeDeviceInfos = NULL;
+
+ PaUtil_InitializeStreamInterface(&skeletonHostApi->callbackStreamInterface, CloseStream, StartStream,
+ StopStream, AbortStream, IsStreamStopped, IsStreamActive,
+Index: src/hostapi/wasapi/pa_win_wasapi.c
+===================================================================
+--- src/hostapi/wasapi/pa_win_wasapi.c (revision 1799)
++++ src/hostapi/wasapi/pa_win_wasapi.c (working copy)
+@@ -1386,6 +1386,9 @@
+ }
+ }
+
++ (*hostApi)->ScanDeviceInfos = NULL;
++ (*hostApi)->CommitDeviceInfos = NULL;
++ (*hostApi)->DisposeDeviceInfos = NULL;
+ (*hostApi)->Terminate = Terminate;
+ (*hostApi)->OpenStream = OpenStream;
+ (*hostApi)->IsFormatSupported = IsFormatSupported;
+Index: src/hostapi/wdmks/pa_win_wdmks.c
+===================================================================
+--- src/hostapi/wdmks/pa_win_wdmks.c (revision 1799)
++++ src/hostapi/wdmks/pa_win_wdmks.c (working copy)
+@@ -1885,6 +1885,9 @@
+
+ (*hostApi)->info.deviceCount = deviceCount;
+
++ (*hostApi)->ScanDeviceInfos = NULL;
++ (*hostApi)->CommitDeviceInfos = NULL;
++ (*hostApi)->DisposeDeviceInfos = NULL;
+ (*hostApi)->Terminate = Terminate;
+ (*hostApi)->OpenStream = OpenStream;
+ (*hostApi)->IsFormatSupported = IsFormatSupported;
+@@ -3305,4 +3308,4 @@
+ /* IMPLEMENT ME, see portaudio.h for required behavior*/
+ PA_LOGL_;
+ return 0;
+-}
+\ No newline at end of file
++}
+Index: src/hostapi/jack/pa_jack.c
+===================================================================
+--- src/hostapi/jack/pa_jack.c (revision 1799)
++++ src/hostapi/jack/pa_jack.c (working copy)
+@@ -749,6 +749,9 @@
+
+ /* Register functions */
+
++ (*hostApi)->ScanDeviceInfos = NULL;
++ (*hostApi)->CommitDeviceInfos = NULL;
++ (*hostApi)->DisposeDeviceInfos = NULL;
+ (*hostApi)->Terminate = Terminate;
+ (*hostApi)->OpenStream = OpenStream;
+ (*hostApi)->IsFormatSupported = IsFormatSupported;
+Index: src/hostapi/coreaudio/pa_mac_core.c
+===================================================================
+--- src/hostapi/coreaudio/pa_mac_core.c (revision 1799)
++++ src/hostapi/coreaudio/pa_mac_core.c (working copy)
+@@ -80,7 +80,28 @@
+ /* prototypes for functions declared in this file */
+
+ PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
++static PaError ScanDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
++ void **newDeviceInfos, int *newDeviceCount );
++static PaError CommitDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
++ void *deviceInfos, int deviceCount);
++static PaError DisposeDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, void *deviceInfos,
++ int deviceCount );
+
++/* structures */
++
++/* used for tranferring device infos during scanning / rescanning */
++typedef struct PaMacScanDeviceInfosResults
++{
++ PaDeviceInfo **deviceInfos;
++ PaDeviceIndex defaultInputDevice;
++ PaDeviceIndex defaultOutputDevice;
++
++ AudioDeviceID* devIds;
++ int devCount;
++ AudioDeviceID devInputDevice;
++ AudioDeviceID devOutputDevice;
++} PaMacScanDeviceInfosResults;
++
+ /*
+ * Function declared in pa_mac_core.h. Sets up a PaMacCoreStreamInfoStruct
+ * with the requested flags and initializes channel map.
+@@ -132,7 +153,6 @@
+ return NULL;
+ PaMacAUHAL *macCoreHostApi = (PaMacAUHAL*)hostApi;
+ AudioDeviceID hostApiDevice = macCoreHostApi->devIds[device];
+-
+ UInt32 size = 0;
+
+ error = AudioDeviceGetPropertyInfo( hostApiDevice,
+@@ -311,46 +331,57 @@
+ }
+
+-/*currently, this is only used in initialization, but it might be modified
+- to be used when the list of devices changes.*/
+-static PaError gatherDeviceInfo(PaMacAUHAL *auhalHostApi)
++//static PaError gatherDeviceInfo(PaMacAUHAL *auhalHostApi)
++static PaError gatherDeviceInfo(PaMacAUHAL* auhalHostApi, void** scanResults, int* count)
+ {
+- UInt32 size;
+- UInt32 propsize;
++ UInt32 propsize = 0;
++ UInt32 size = sizeof(AudioDeviceID);
++ PaMacScanDeviceInfosResults *outArgument = NULL;
++ PaError result = paNoError;
++
+ VVDBUG(("gatherDeviceInfo()\n"));
+- /* -- free any previous allocations -- */
+- if( auhalHostApi->devIds )
+- PaUtil_GroupFreeMemory(auhalHostApi->allocations, auhalHostApi->devIds);
+- auhalHostApi->devIds = NULL;
+-
+ /* -- figure out how many devices there are -- */
+ AudioHardwareGetPropertyInfo( kAudioHardwarePropertyDevices,
+&propsize,
+ NULL );
+- auhalHostApi->devCount = propsize / sizeof( AudioDeviceID );
++ *count = (propsize / sizeof(AudioDeviceID));
+
+- VDBUG( ( "Found %ld device(s).\n", auhalHostApi->devCount ) );
++ VDBUG( ( "Found %ld device(s).\n", *count ) );
+
++ if(*count == 0)
++ return paNoError;
++
++ /* Allocate the out param for all the info we need */
++ outArgument = (PaMacScanDeviceInfosResults *) PaUtil_GroupAllocateMemory(
++ auhalHostApi->allocations, sizeof(PaMacScanDeviceInfosResults) );
++
++ if( !outArgument )
++ {
++ result = paInsufficientMemory;
++ return result;
++ }
++
++ outArgument->devCount = *count;
++
+ /* -- copy the device IDs -- */
+- auhalHostApi->devIds = (AudioDeviceID *)PaUtil_GroupAllocateMemory(
++ outArgument->devIds = (AudioDeviceID *)PaUtil_GroupAllocateMemory(
+ auhalHostApi->allocations,
+ propsize );
+- if( !auhalHostApi->devIds )
++ if( !outArgument->devIds )
+ return paInsufficientMemory;
+ AudioHardwareGetProperty( kAudioHardwarePropertyDevices,
+&propsize,
+- auhalHostApi->devIds );
++ outArgument->devIds );
+ #ifdef MAC_CORE_VERBOSE_DEBUG
+ {
+ int i;
+- for( i=0; i<auhalHostApi->devCount; ++i )
+- printf( "Device %d\t: %ld\n", i, auhalHostApi->devIds[i] );
++ for( i=0; i<outArgument->devCount; ++i )
++ printf( "Device %d\t: %ld\n", i, outArgument->devIds[i] );
+ }
+ #endif
+
+- size = sizeof(AudioDeviceID);
+- auhalHostApi->defaultIn = kAudioDeviceUnknown;
+- auhalHostApi->defaultOut = kAudioDeviceUnknown;
++ outArgument->devInputDevice = kAudioDeviceUnknown;
++ outArgument->devOutputDevice = kAudioDeviceUnknown;
+
+ /* determine the default device. */
+ /* I am not sure how these calls to AudioHardwareGetProperty()
+@@ -358,42 +389,44 @@
+ device as the default. */
+ if( 0 != AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
+&size,
+-&auhalHostApi->defaultIn) ) {
++&outArgument->devInputDevice) ) {
+ int i;
+- auhalHostApi->defaultIn = kAudioDeviceUnknown;
++ outArgument->devInputDevice = kAudioDeviceUnknown;
+ VDBUG(("Failed to get default input device from OS."));
+ VDBUG((" I will substitute the first available input Device."));
+- for( i=0; i<auhalHostApi->devCount; ++i ) {
++
++ for( i=0; i< outArgument->devCount; ++i ) {
+ PaDeviceInfo devInfo;
+ if( 0 != GetChannelInfo( auhalHostApi,&devInfo,
+- auhalHostApi->devIds[i], TRUE ) )
++ outArgument->devIds[i], TRUE ) )
+ if( devInfo.maxInputChannels ) {
+- auhalHostApi->defaultIn = auhalHostApi->devIds[i];
++ outArgument->devInputDevice = outArgument->devIds[i];
+ break;
+ }
+ }
+ }
+ if( 0 != AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
+&size,
+-&auhalHostApi->defaultOut) ) {
++&outArgument->devOutputDevice) ) {
+ int i;
+- auhalHostApi->defaultIn = kAudioDeviceUnknown;
++ outArgument->devOutputDevice = kAudioDeviceUnknown;
+ VDBUG(("Failed to get default output device from OS."));
+ VDBUG((" I will substitute the first available output Device."));
+- for( i=0; i<auhalHostApi->devCount; ++i ) {
++ for( i=0; i<outArgument->devCount; ++i ) {
+ PaDeviceInfo devInfo;
+ if( 0 != GetChannelInfo( auhalHostApi,&devInfo,
+- auhalHostApi->devIds[i], FALSE ) )
++ outArgument->devIds[i], FALSE ) )
+ if( devInfo.maxOutputChannels ) {
+- auhalHostApi->defaultOut = auhalHostApi->devIds[i];
++ outArgument->devOutputDevice = outArgument->devIds[i];
+ break;
+ }
+ }
+ }
+
+- VDBUG( ( "Default in : %ld\n", auhalHostApi->defaultIn ) );
+- VDBUG( ( "Default out: %ld\n", auhalHostApi->defaultOut ) );
++ VDBUG( ( "Default in : %ld\n", outArgument->devInputDevice ) );
++ VDBUG( ( "Default out: %ld\n", outArgument->devOutputDevice ) );
+
++ *scanResults = outArgument;
+ return paNoError;
+ }
+
+@@ -402,9 +435,9 @@
+ AudioDeviceID macCoreDeviceId,
+ int isInput)
+ {
+- UInt32 propSize;
++ UInt32 propSize = 0;
+ PaError err = paNoError;
+- UInt32 i;
++ UInt32 i = 0;
+ int numChannels = 0;
+ AudioBufferList *buflist = NULL;
+ UInt32 frameLatency;
+@@ -528,10 +561,10 @@
+ PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
+ {
+ PaError result = paNoError;
+- int i;
+ PaMacAUHAL *auhalHostApi = NULL;
+- PaDeviceInfo *deviceInfoArray;
+ int unixErr;
++ void* scanResults = NULL;
++ int deviceCount = 0;
+
+ VVDBUG(("PaMacCore_Initialize(): hostApiIndex=%d\n", hostApiIndex));
+
+@@ -572,65 +605,29 @@
+ auhalHostApi->devIds = NULL;
+ auhalHostApi->devCount = 0;
+
+- /* get the info we need about the devices */
+- result = gatherDeviceInfo( auhalHostApi );
+- if( result != paNoError )
+- goto error;
+-
+ *hostApi =&auhalHostApi->inheritedHostApiRep;
+ (*hostApi)->info.structVersion = 1;
+ (*hostApi)->info.type = paCoreAudio;
+ (*hostApi)->info.name = "Core Audio";
+-
++
++ (*hostApi)->deviceInfos = NULL;
++
+ (*hostApi)->info.defaultInputDevice = paNoDevice;
+ (*hostApi)->info.defaultOutputDevice = paNoDevice;
+-
+ (*hostApi)->info.deviceCount = 0;
+
+- if( auhalHostApi->devCount> 0 )
+- {
+- (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
+- auhalHostApi->allocations, sizeof(PaDeviceInfo*) * auhalHostApi->devCount);
+- if( !(*hostApi)->deviceInfos )
+- {
+- result = paInsufficientMemory;
+- goto error;
+- }
++ (*hostApi)->ScanDeviceInfos = ScanDeviceInfos;
++ (*hostApi)->CommitDeviceInfos = CommitDeviceInfos;
++ (*hostApi)->DisposeDeviceInfos = DisposeDeviceInfos;
+
+- /* allocate all device info structs in a contiguous block */
+- deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
+- auhalHostApi->allocations, sizeof(PaDeviceInfo) * auhalHostApi->devCount );
+- if( !deviceInfoArray )
+- {
+- result = paInsufficientMemory;
+- goto error;
+- }
++ result = ScanDeviceInfos(&auhalHostApi->inheritedHostApiRep, hostApiIndex,&scanResults,
++&deviceCount);
+
+- for( i=0; i< auhalHostApi->devCount; ++i )
+- {
+- int err;
+- err = InitializeDeviceInfo( auhalHostApi,&deviceInfoArray[i],
+- auhalHostApi->devIds[i],
+- hostApiIndex );
+- if (err == paNoError)
+- { /* copy some info and set the defaults */
+- (*hostApi)->deviceInfos[(*hostApi)->info.deviceCount] =&deviceInfoArray[i];
+- if (auhalHostApi->devIds[i] == auhalHostApi->defaultIn)
+- (*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
+- if (auhalHostApi->devIds[i] == auhalHostApi->defaultOut)
+- (*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
+- (*hostApi)->info.deviceCount++;
+- }
+- else
+- { /* there was an error. we need to shift the devices down, so we ignore this one */
+- int j;
+- auhalHostApi->devCount--;
+- for( j=i; j<auhalHostApi->devCount; ++j )
+- auhalHostApi->devIds[j] = auhalHostApi->devIds[j+1];
+- i--;
+- }
+- }
+- }
++ if(result != paNoError)
++ goto error;
++
++ /* FIXME for now we ignore the result of CommitDeviceInfos(), it should probably be an atomic non-failing operation */
++ CommitDeviceInfos(&auhalHostApi->inheritedHostApiRep, hostApiIndex, scanResults, deviceCount );
+
+ (*hostApi)->Terminate = Terminate;
+ (*hostApi)->OpenStream = OpenStream;
+@@ -2468,3 +2465,148 @@
+
+ return PaUtil_GetCpuLoad(&stream->cpuLoadMeasurer );
+ }
++
++static PaError ScanDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex hostApiIndex,
++ void **scanResults, int *newDeviceCount)
++{
++ PaMacAUHAL* auhalHostApi = (PaMacAUHAL*)hostApi;
++ PaDeviceInfo *deviceInfoArray = NULL;
++ PaError result = paNoError;
++ int i = 0;
++ PaMacScanDeviceInfosResults* out = NULL;
++
++ /* get the info we need about the devices */
++ result = gatherDeviceInfo( auhalHostApi, scanResults, newDeviceCount );
++
++ if( result != paNoError )
++ return result;
++
++ out = (PaMacScanDeviceInfosResults*)*scanResults;
++
++ if( out->devCount> 0 )
++ {
++ int count = 0;
++
++ /* allocate array for pointers to PaDeviceInfo structs */
++ out->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
++ auhalHostApi->allocations, sizeof(PaDeviceInfo*) * out->devCount);
++ if( !out->deviceInfos )
++ {
++ result = paInsufficientMemory;
++ return result;
++ }
++
++ /* allocate all device info structs in a contiguous block */
++ deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
++ auhalHostApi->allocations, sizeof(PaDeviceInfo) * out->devCount );
++ if( !deviceInfoArray )
++ {
++ result = paInsufficientMemory;
++ return result;
++ }
++
++ for( i=0; i< out->devCount; ++i )
++ {
++ int err;
++ err = InitializeDeviceInfo( auhalHostApi,&deviceInfoArray[i],
++ out->devIds[i],
++ hostApiIndex );
++ if (err == paNoError)
++ {
++ /* copy some info and set the defaults */
++ out->deviceInfos[count] =&deviceInfoArray[i];
++
++ if (out->devIds[i] == out->devInputDevice)
++ {
++ out->defaultInputDevice = count;
++ }
++ if (out->devIds[i] == out->devOutputDevice)
++ {
++ out->defaultOutputDevice = count;
++ }
++ count++;
++ }
++ else
++ {
++ /* there was an error. we need to shift the devices down, so we ignore this one */
++ int j;
++ out->devCount--;
++ for( j=i; j<out->devCount; ++j )
++ out->devIds[j] = out->devIds[j+1];
++ i--;
++ }
++ }
++ }
++ *newDeviceCount = out->devCount;
++
++ return paNoError;
++}
++
++static PaError CommitDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index,
++ void *scanResults, int deviceCount)
++{
++ PaMacAUHAL* auhalHostApi = (PaMacAUHAL*)hostApi;
++ PaError result = paNoError;
++
++ hostApi->info.deviceCount = 0;
++ hostApi->info.defaultInputDevice = paNoDevice;
++ hostApi->info.defaultOutputDevice = paNoDevice;
++
++ /* -- free any previous allocations -- */
++ if( auhalHostApi->devIds )
++ {
++ PaUtil_GroupFreeMemory(auhalHostApi->allocations, auhalHostApi->devIds);
++ }
++ auhalHostApi->devIds = NULL;
++
++ /* Free any old memory which might be in the device info */
++ if( hostApi->deviceInfos )
++ {
++ PaUtil_GroupFreeMemory( auhalHostApi->allocations, hostApi->deviceInfos[0] );
++ PaUtil_GroupFreeMemory( auhalHostApi->allocations, hostApi->deviceInfos );
++ hostApi->deviceInfos = NULL;
++ }
++
++ if( scanResults != NULL )
++ {
++ PaMacScanDeviceInfosResults *scanDeviceInfosResults = ( PaMacScanDeviceInfosResults * ) scanResults;
++
++ if( deviceCount> 0 )
++ {
++ /* use the array allocated in ScanDeviceInfos() as our deviceInfos */
++ hostApi->deviceInfos = scanDeviceInfosResults->deviceInfos;
++ hostApi->info.defaultInputDevice = scanDeviceInfosResults->defaultInputDevice;
++ hostApi->info.defaultOutputDevice = scanDeviceInfosResults->defaultOutputDevice;
++ hostApi->info.deviceCount = deviceCount;
++ auhalHostApi->devIds = scanDeviceInfosResults->devIds;
++ auhalHostApi->devCount = scanDeviceInfosResults->devCount;
++ auhalHostApi->defaultIn = scanDeviceInfosResults->devInputDevice;
++ auhalHostApi->defaultOut = scanDeviceInfosResults->devOutputDevice;
++ }
++
++ PaUtil_GroupFreeMemory( auhalHostApi->allocations, scanDeviceInfosResults );
++ }
++
++ return result;
++}
++
++static PaError DisposeDeviceInfos(struct PaUtilHostApiRepresentation *hostApi, void *scanResults, int deviceCount)
++{
++ PaMacAUHAL *auhalHostApi = (PaMacAUHAL*)hostApi;
++
++ if( scanResults != NULL )
++ {
++ PaMacScanDeviceInfosResults *scanDeviceInfosResults = ( PaMacScanDeviceInfosResults * ) scanResults;
++ if( scanDeviceInfosResults->deviceInfos )
++ {
++ /* all device info structs are allocated in a block so we can destroy them here */
++ PaUtil_GroupFreeMemory( auhalHostApi->allocations, scanDeviceInfosResults->deviceInfos[0] );
++ PaUtil_GroupFreeMemory( auhalHostApi->allocations, scanDeviceInfosResults->deviceInfos );
++ }
++
++ PaUtil_GroupFreeMemory(auhalHostApi->allocations, scanDeviceInfosResults );
++ }
++
++ return paNoError;
++}
++
+Index: src/hostapi/asio/pa_asio.cpp
+===================================================================
+--- src/hostapi/asio/pa_asio.cpp (revision 1799)
++++ src/hostapi/asio/pa_asio.cpp (working copy)
+@@ -1315,6 +1315,9 @@
+ }
+
++ (*hostApi)->ScanDeviceInfos = NULL;
++ (*hostApi)->CommitDeviceInfos = NULL;
++ (*hostApi)->DisposeDeviceInfos = NULL;
+ (*hostApi)->Terminate = Terminate;
+ (*hostApi)->OpenStream = OpenStream;
+ (*hostApi)->IsFormatSupported = IsFormatSupported;
+Index: src/common/pa_front.c
+===================================================================
+--- src/common/pa_front.c (revision 1799)
++++ src/common/pa_front.c (working copy)
+@@ -737,13 +737,12 @@
+ for( i = 0 ; i< paInternalInfo_.hostApisCount_ ; ++i )
+ {
+ PaUtilHostApiRepresentation *hostApi = paInternalInfo_.hostApis_[i];
++ PA_DEBUG(( "Scanning new device list for host api %d.\n",i));
+ if( hostApi->ScanDeviceInfos == NULL )
+ continue;
+
+- PA_DEBUG(( "Scanning new device list for host api %d.\n",i));
+ if( hostApi->ScanDeviceInfos( hostApi, i,&scanResults[ i ],&deviceCounts[ i ] ) != paNoError )
+ break;
+-
+ }
+
+ /* Check the result of the scan operation */
Index: trunk/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java

--- trunk/src/net/java/sip/communicator/service/protocol/media/AbstractOperationSetTelephonyConferencing.java
[truncated due to length]