Improves device selection via portaudio for MacOSX (hostapi coreaudio):

adds the possibility to get the device transport type (USB, bluetooth,
etc.) and an unique identifier. Corrects problems when: loading the same
device twice (for the moment only for the same hostapi), a new plugged
device is selected during a call or if the selected device is unchanged.
Vincent Lucas committed on Oct 29, 2012
26848f0 from https://github.com/jitsi/libsrc/commits/master/portaudio.zip
This commit is contained in:
Ross Bencina 2016-09-03 22:34:22 +10:00
commit e7a274942b
5 changed files with 367 additions and 3 deletions

243
Makefile Normal file
View file

@ -0,0 +1,243 @@
#
# PortAudio V19 Makefile.in
#
# Dominic Mazzoni
# Modifications by Mikael Magnusson
# Modifications by Stelios Bounanos
#
top_srcdir = .
srcdir = .
top_builddir = .
PREFIX = /usr/local
prefix = $(PREFIX)
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
libdir = ${exec_prefix}/lib
includedir = ${prefix}/include
CC = gcc
CXX = @CXX@
CFLAGS = -I/usr/include -I$(top_srcdir)/include -I$(top_srcdir)/src/common -I$(top_srcdir)/src/os/unix -std=c99 -O2 -Wall -pedantic -pipe -fPIC -DNDEBUG -DPA_LITTLE_ENDIAN -arch i386 -arch x86_64 -mmacosx-version-min=10.4 -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=8 -DHAVE_NANOSLEEP=1 -DPA_USE_COREAUDIO=1
LIBS = -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon
AR = /usr/bin/ar
RANLIB = ranlib
SHELL = /bin/sh
LIBTOOL = $(SHELL) $(top_builddir)/libtool
INSTALL = /usr/bin/install -c
INSTALL_DATA = ${INSTALL} -m 644
SHARED_FLAGS =
LDFLAGS =
DLL_LIBS =
CXXFLAGS =
NASM =
NASMOPT =
LN_S = ln -s
LT_CURRENT=2
LT_REVISION=0
LT_AGE=0
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
INCLUDES = portaudio.h
PALIB = libportaudio.la
PAINC = include/portaudio.h
PA_LDFLAGS = $(LDFLAGS) $(SHARED_FLAGS) -rpath $(libdir) -no-undefined \
-export-symbols-regex "(Pa|PaMacCore|PaJack|PaAlsa|PaAsio|PaOSS)_.*" \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
COMMON_OBJS = \
src/common/pa_allocation.o \
src/common/pa_converters.o \
src/common/pa_cpuload.o \
src/common/pa_dither.o \
src/common/pa_debugprint.o \
src/common/pa_front.o \
src/common/pa_process.o \
src/common/pa_stream.o \
src/common/pa_trace.o \
src/hostapi/skeleton/pa_hostapi_skeleton.o
LOOPBACK_OBJS = \
qa/loopback/src/audio_analyzer.o \
qa/loopback/src/biquad_filter.o \
qa/loopback/src/paqa_tools.o \
qa/loopback/src/test_audio_analyzer.o \
qa/loopback/src/write_wav.o \
qa/loopback/src/paqa.o
TESTS = \
bin/paqa_devs \
bin/paqa_errs \
bin/patest1 \
bin/patest_buffer \
bin/patest_callbackstop \
bin/patest_clip \
bin/patest_dither \
bin/patest_hang \
bin/patest_in_overflow \
bin/patest_latency \
bin/patest_leftright \
bin/patest_longsine \
bin/patest_many \
bin/patest_maxsines \
bin/patest_mono \
bin/patest_multi_sine \
bin/patest_out_underflow \
bin/patest_pink \
bin/patest_prime \
bin/patest_read_record \
bin/patest_read_write_wire \
bin/patest_record \
bin/patest_ringmix \
bin/patest_saw \
bin/patest_sine8 \
bin/patest_sine \
bin/patest_sine_channelmaps \
bin/patest_sine_formats \
bin/patest_sine_time \
bin/patest_sine_srate \
bin/patest_start_stop \
bin/patest_stop \
bin/patest_stop_playout \
bin/patest_toomanysines \
bin/patest_two_rates \
bin/patest_underflow \
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
# Most of these don't compile yet. Put them in TESTS, above, if
# you want to try to compile them...
ALL_TESTS = \
$(TESTS) \
bin/patest_sync \
bin/debug_convert \
bin/debug_dither_calc \
bin/debug_dual \
bin/debug_multi_in \
bin/debug_multi_out \
bin/debug_record \
bin/debug_record_reuse \
bin/debug_sine_amp \
bin/debug_sine \
bin/debug_sine_formats \
bin/debug_srate \
bin/debug_test1
OBJS := $(COMMON_OBJS) $(OTHER_OBJS)
LTOBJS := $(OBJS:.o=.lo)
SRC_DIRS = \
src/common \
src/hostapi/alsa \
src/hostapi/asihpi \
src/hostapi/asio \
src/hostapi/coreaudio \
src/hostapi/dsound \
src/hostapi/jack \
src/hostapi/oss \
src/hostapi/wasapi \
src/hostapi/wdmks \
src/hostapi/wmme \
src/os/unix \
src/os/mac_osx \
src/os/win
SUBDIRS =
#SUBDIRS += bindings/cpp
all: lib/$(PALIB) all-recursive tests
tests: bin-stamp $(TESTS)
loopback: bin-stamp bin/paloopback
# With ASIO enabled we must link libportaudio and all test programs with CXX
lib/$(PALIB): lib-stamp $(LTOBJS) $(MAKEFILE) $(PAINC)
$(LIBTOOL) --mode=link $(CC) $(PA_LDFLAGS) -o lib/$(PALIB) $(LTOBJS) $(DLL_LIBS)
@ # $(LIBTOOL) --mode=link --tag=CXX $(CXX) $(PA_LDFLAGS) -o lib/$(PALIB) $(LTOBJS) $(DLL_LIBS)
$(ALL_TESTS): bin/%: lib/$(PALIB) $(MAKEFILE) $(PAINC) test/%.c
$(LIBTOOL) --mode=link $(CC) -o $@ $(CFLAGS) $(top_srcdir)/test/$*.c lib/$(PALIB) $(LIBS)
@ # $(LIBTOOL) --mode=link --tag=CXX $(CXX) -o $@ $(CXXFLAGS) $(top_srcdir)/test/$*.c lib/$(PALIB) $(LIBS)
bin/paloopback: lib/$(PALIB) $(MAKEFILE) $(PAINC) $(LOOPBACK_OBJS)
$(LIBTOOL) --mode=link $(CC) -o $@ $(CFLAGS) $(LOOPBACK_OBJS) lib/$(PALIB) $(LIBS)
@ # $(LIBTOOL) --mode=link --tag=CXX $(CXX) -o $@ $(CXXFLAGS) $(LOOPBACK_OBJS) lib/$(PALIB) $(LIBS)
install: lib/$(PALIB) portaudio-2.0.pc
$(INSTALL) -d $(DESTDIR)$(libdir)
$(LIBTOOL) --mode=install $(INSTALL) lib/$(PALIB) $(DESTDIR)$(libdir)
$(INSTALL) -d $(DESTDIR)$(includedir)
for include in $(INCLUDES); do \
$(INSTALL_DATA) -m 644 $(top_srcdir)/include/$$include $(DESTDIR)$(includedir)/$$include; \
done
$(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig
$(INSTALL) -m 644 portaudio-2.0.pc $(DESTDIR)$(libdir)/pkgconfig/portaudio-2.0.pc
@echo ""
@echo "------------------------------------------------------------"
@echo "PortAudio was successfully installed."
@echo ""
@echo "On some systems (e.g. Linux) you should run 'ldconfig' now"
@echo "to make the shared object available. You may also need to"
@echo "modify your LD_LIBRARY_PATH environment variable to include"
@echo "the directory $(libdir)"
@echo "------------------------------------------------------------"
@echo ""
$(MAKE) install-recursive
uninstall:
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$(PALIB)
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(includedir)/portaudio.h
$(MAKE) uninstall-recursive
clean:
$(LIBTOOL) --mode=clean rm -f $(LTOBJS) $(LOOPBACK_OBJS) $(ALL_TESTS) lib/$(PALIB)
$(RM) bin-stamp lib-stamp
-$(RM) -r bin lib
distclean: clean
$(RM) config.log config.status Makefile libtool portaudio-2.0.pc
%.o: %.c $(MAKEFILE) $(PAINC)
$(CC) -c $(CFLAGS) $< -o $@
%.lo: %.c $(MAKEFILE) $(PAINC)
$(LIBTOOL) --mode=compile $(CC) -c $(CFLAGS) $< -o $@
%.lo: %.cpp $(MAKEFILE) $(PAINC)
$(LIBTOOL) --mode=compile --tag=CXX $(CXX) -c $(CXXFLAGS) $< -o $@
%.o: %.cpp $(MAKEFILE) $(PAINC)
$(CXX) -c $(CXXFLAGS) $< -o $@
%.o: %.asm
$(NASM) $(NASMOPT) -o $@ $<
bin-stamp:
-mkdir bin
touch $@
lib-stamp:
-mkdir lib
-mkdir -p $(SRC_DIRS)
touch $@
Makefile: Makefile.in config.status
$(SHELL) config.status
all-recursive:
if test -n "$(SUBDIRS)" ; then for dir in "$(SUBDIRS)"; do $(MAKE) -C $$dir all; done ; fi
install-recursive:
if test -n "$(SUBDIRS)" ; then for dir in "$(SUBDIRS)"; do $(MAKE) -C $$dir install; done ; fi
uninstall-recursive:
if test -n "$(SUBDIRS)" ; then for dir in "$(SUBDIRS)"; do $(MAKE) -C $$dir uninstall; done ; fi

View file

@ -46,7 +46,7 @@
#include "portaudio.h"
#include <AudioUnit/AudioUnit.h>
//#include <AudioToolbox/AudioToolbox.h>
#include <AudioToolbox/AudioToolbox.h>
#ifdef __cplusplus
extern "C" {

View file

@ -470,7 +470,7 @@ typedef unsigned long PaSampleFormat;
*/
typedef struct PaDeviceInfo
{
int structVersion; /* this is struct version 2 */
int structVersion; /* this is struct version 3 */
const char *name;
PaHostApiIndex hostApi; /* note this is a host API index, not a type id*/
@ -485,6 +485,11 @@ typedef struct PaDeviceInfo
PaTime defaultHighOutputLatency;
double defaultSampleRate;
/*The transport type used by this device: USB, BuiltIn, Bluetooth, etc.*/
const char *transportType;
/*The unique identifier of this device (persistent across boots).*/
const char *deviceUID;
} PaDeviceInfo;

12
portaudio-2.0.pc Normal file
View file

@ -0,0 +1,12 @@
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: PortAudio
Description: Portable audio I/O
Requires:
Version: 19
Libs: -L${libdir} -lportaudio -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework Carbon
Cflags: -I${includedir}

View file

@ -67,6 +67,8 @@
#include <string.h> /* strlen(), memcmp() etc. */
#include <libkern/OSAtomic.h>
#include <CoreFoundation/CFString.h>
#include "pa_mac_core.h"
#include "pa_mac_core_utilities.h"
#include "pa_mac_core_blocking.h"
@ -521,9 +523,111 @@ static PaError InitializeDeviceInfo( PaMacAUHAL *auhalHostApi,
memset(deviceInfo, 0, sizeof(deviceInfo));
deviceInfo->structVersion = 2;
deviceInfo->structVersion = 3;
deviceInfo->hostApi = hostApiIndex;
// target device UID property
unsigned long deviceUID = 0;
AudioObjectPropertyAddress addr;
addr.mSelector = kAudioDevicePropertyDeviceUID;
addr.mScope = kAudioObjectPropertyScopeGlobal;
addr.mElement = kAudioObjectPropertyElementMaster;
CFStringRef deviceUIDString;
propSize = sizeof(deviceUIDString);
err = ERR(AudioObjectGetPropertyData(
macCoreDeviceId,
&addr,
0,
NULL,
&propSize,
&deviceUIDString));
if (err)
return err;
CFIndex deviceUIDLength = CFStringGetLength(deviceUIDString) + 1;
char *ASCIIDeviceUID
= PaUtil_GroupAllocateMemory(auhalHostApi->allocations,deviceUIDLength);
if ( !ASCIIDeviceUID )
return paInsufficientMemory;
deviceInfo->deviceUID = NULL;
if(CFStringGetCString (
deviceUIDString,
ASCIIDeviceUID,
deviceUIDLength,
kCFStringEncodingASCII))
{
deviceInfo->deviceUID = ASCIIDeviceUID;
}
// target device transport type property
addr.mSelector = kAudioDevicePropertyTransportType;
addr.mScope = kAudioObjectPropertyScopeGlobal;
addr.mElement = kAudioObjectPropertyElementMaster;
unsigned int transportType = 0;
propSize = sizeof(transportType);
err = ERR(AudioObjectGetPropertyData(
macCoreDeviceId,
&addr,
0,
NULL,
&propSize,
&transportType));
if (err)
return err;
switch(transportType)
{
case kAudioDeviceTransportTypeAggregate:
deviceInfo->transportType = "Aggregate";
break;
case kAudioDeviceTransportTypeAirPlay:
deviceInfo->transportType = "AirPlay";
break;
case kAudioDeviceTransportTypeAutoAggregate:
deviceInfo->transportType = "Auto aggregate";
break;
case kAudioDeviceTransportTypeAVB:
deviceInfo->transportType = "AVB";
break;
case kAudioDeviceTransportTypeBluetooth:
deviceInfo->transportType = "Bluetooth";
break;
case kAudioDeviceTransportTypeBuiltIn:
deviceInfo->transportType = "Built-in";
break;
case kAudioDeviceTransportTypeDisplayPort:
deviceInfo->transportType = "DisplayPort";
break;
case kAudioDeviceTransportTypeFireWire:
deviceInfo->transportType = "FireWire";
break;
case kAudioDeviceTransportTypeHDMI:
deviceInfo->transportType = "HDMI";
break;
case kAudioDeviceTransportTypePCI:
deviceInfo->transportType = "PCI";
break;
case kAudioDeviceTransportTypeThunderbolt:
deviceInfo->transportType = "Thunderbolt";
break;
case kAudioDeviceTransportTypeUnknown:
deviceInfo->transportType = "Unknown";
break;
case kAudioDeviceTransportTypeUSB:
deviceInfo->transportType = "USB";
break;
case kAudioDeviceTransportTypeVirtual:
deviceInfo->transportType = "Virtual";
break;
default:
deviceInfo->transportType = NULL;
break;
}
/* Get the device name. Fail if we can't get it. */
err = ERR(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL));
if (err)