Compare commits

...
Sign in to create a new pull request.
27 changed files with 2117 additions and 1435 deletions

34
aclocal.m4 vendored
View file

@ -680,7 +680,7 @@ _LT_CONFIG_SAVE_COMMANDS([
# commands through without removal of \ escapes. # commands through without removal of \ escapes.
if test -n "${ZSH_VERSION+set}" ; then if test -n "${ZSH_VERSION+set}" ; then
setopt NO_GLOB_SUBST setopt NO_GLOB_SUBST
fi fi
cfgfile="${ofile}T" cfgfile="${ofile}T"
trap "$RM \"$cfgfile\"; exit 1" 1 2 15 trap "$RM \"$cfgfile\"; exit 1" 1 2 15
@ -1101,8 +1101,8 @@ fi
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
if test -z "$lt_ECHO"; then if test -z "$lt_ECHO"; then
if test "X${echo_test_string+set}" != Xset; then if test "X${echo_test_string+set}" != Xset; then
# find a string as large as possible, as long as the shell can cope with it # find a string as large as possible, as long as the shell can cope with it
for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
# expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
if { echo_test_string=`eval $cmd`; } 2>/dev/null && if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
@ -1111,13 +1111,13 @@ if test -z "$lt_ECHO"; then
break break
fi fi
done done
fi fi
if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
test "X$echo_testing_string" = "X$echo_test_string"; then test "X$echo_testing_string" = "X$echo_test_string"; then
: :
else else
# The Solaris, AIX, and Digital Unix default echo programs unquote # The Solaris, AIX, and Digital Unix default echo programs unquote
# backslashes. This makes it impossible to quote backslashes using # backslashes. This makes it impossible to quote backslashes using
# echo "$something" | sed 's/\\/\\\\/g' # echo "$something" | sed 's/\\/\\\\/g'
@ -1197,7 +1197,7 @@ if test -z "$lt_ECHO"; then
fi fi
fi fi
fi fi
fi fi
fi fi
# Copy echo and quote the copy suitably for passing to libtool from # Copy echo and quote the copy suitably for passing to libtool from
@ -2023,7 +2023,7 @@ else
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
;; ;;
*) *)
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
@ -2218,7 +2218,7 @@ cygwin* | mingw* | pw32* | cegcc*)
library_names_spec='$libname.dll.a' library_names_spec='$libname.dll.a'
# DLL is installed to $(libdir)/../bin by postinstall_cmds # DLL is installed to $(libdir)/../bin by postinstall_cmds
postinstall_cmds='base_file=`basename \${file}`~ postinstall_cmds='base_file=`basename \${file}`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~ dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~ test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname~ $install_prog $dir/$dlname \$dldir/$dlname~
@ -2702,10 +2702,10 @@ fi
if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
fi fi
if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
fi fi
_LT_DECL([], [variables_saved_for_relink], [1], _LT_DECL([], [variables_saved_for_relink], [1],
[Variables whose values should be saved in libtool wrapper scripts and [Variables whose values should be saved in libtool wrapper scripts and
@ -3230,7 +3230,7 @@ else
: ${lt_cv_path_NM=no} : ${lt_cv_path_NM=no}
fi]) fi])
if test "$lt_cv_path_NM" != "no"; then if test "$lt_cv_path_NM" != "no"; then
NM="$lt_cv_path_NM" NM="$lt_cv_path_NM"
else else
# Didn't find any BSD compatible name lister, look for dumpbin. # Didn't find any BSD compatible name lister, look for dumpbin.
AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
@ -4209,7 +4209,7 @@ m4_if([$1], [CXX], [
;; ;;
esac esac
_LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
], [ ],[
runpath_var= runpath_var=
_LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(always_export_symbols, $1)=no
@ -5727,7 +5727,7 @@ if test "$_lt_caught_CXX_error" != yes; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
# #
# There doesn't appear to be a way to prevent this compiler from # There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them # explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library # from the output so that they don't get included in the library
@ -5792,7 +5792,7 @@ if test "$_lt_caught_CXX_error" != yes; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
# #
# There doesn't appear to be a way to prevent this compiler from # There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them # explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library # from the output so that they don't get included in the library
@ -5877,7 +5877,7 @@ if test "$_lt_caught_CXX_error" != yes; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
# #
# There doesn't appear to be a way to prevent this compiler from # There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them # explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library # from the output so that they don't get included in the library
@ -5960,7 +5960,7 @@ if test "$_lt_caught_CXX_error" != yes; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
# #
# There doesn't appear to be a way to prevent this compiler from # There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them # explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library # from the output so that they don't get included in the library
@ -8053,7 +8053,7 @@ m4_define([_PKG_CONFIG],
PKG_CHECK_EXISTS([$3], PKG_CHECK_EXISTS([$3],
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
[pkg_failed=yes]) [pkg_failed=yes])
else else
pkg_failed=untried pkg_failed=untried
fi[]dnl fi[]dnl
])# _PKG_CONFIG ])# _PKG_CONFIG

View file

@ -48,7 +48,7 @@ may remove or edit it.
you want to change it or regenerate `configure' using a newer version you want to change it or regenerate `configure' using a newer version
of `autoconf'. of `autoconf'.
The simplest way to compile this package is: The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type 1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. `./configure' to configure the package for your system.
@ -111,7 +111,7 @@ is an example:
Compiling For Multiple Architectures Compiling For Multiple Architectures
==================================== ====================================
You can compile the package for more than one kind of computer at the You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run directory where you want the object files and executables to go and run
@ -141,7 +141,7 @@ using the `lipo' tool if you have problems.
Installation Names Installation Names
================== ==================
By default, `make install' installs the package's commands under By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You `/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an `configure' the option `--prefix=PREFIX', where PREFIX must be an
@ -196,7 +196,7 @@ Optional Features
with an extra prefix or suffix on their names by giving `configure' the with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package. `configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The is something like `gnu-as' or `x' (for the X Window System). The
@ -292,7 +292,7 @@ A warning: not all `configure' scripts look for a site script.
Defining Variables Defining Variables
================== ==================
Variables not defined in a site shell script can be set in the Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set variables may be lost. In order to avoid this problem, you should set

View file

@ -262,7 +262,7 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
@for dep in $?; do \ @for dep in $?; do \
case '$(am__configure_deps)' in \ case '$(am__configure_deps)' in \
*$$dep*) \ *$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
&& exit 0; \ && exit 0; \
exit 1;; \ exit 1;; \

View file

@ -688,7 +688,7 @@ _LT_CONFIG_SAVE_COMMANDS([
# commands through without removal of \ escapes. # commands through without removal of \ escapes.
if test -n "${ZSH_VERSION+set}" ; then if test -n "${ZSH_VERSION+set}" ; then
setopt NO_GLOB_SUBST setopt NO_GLOB_SUBST
fi fi
cfgfile="${ofile}T" cfgfile="${ofile}T"
trap "$RM \"$cfgfile\"; exit 1" 1 2 15 trap "$RM \"$cfgfile\"; exit 1" 1 2 15
@ -1109,8 +1109,8 @@ fi
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
if test -z "$lt_ECHO"; then if test -z "$lt_ECHO"; then
if test "X${echo_test_string+set}" != Xset; then if test "X${echo_test_string+set}" != Xset; then
# find a string as large as possible, as long as the shell can cope with it # find a string as large as possible, as long as the shell can cope with it
for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
# expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
if { echo_test_string=`eval $cmd`; } 2>/dev/null && if { echo_test_string=`eval $cmd`; } 2>/dev/null &&
@ -1119,13 +1119,13 @@ if test -z "$lt_ECHO"; then
break break
fi fi
done done
fi fi
if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' &&
echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` &&
test "X$echo_testing_string" = "X$echo_test_string"; then test "X$echo_testing_string" = "X$echo_test_string"; then
: :
else else
# The Solaris, AIX, and Digital Unix default echo programs unquote # The Solaris, AIX, and Digital Unix default echo programs unquote
# backslashes. This makes it impossible to quote backslashes using # backslashes. This makes it impossible to quote backslashes using
# echo "$something" | sed 's/\\/\\\\/g' # echo "$something" | sed 's/\\/\\\\/g'
@ -1205,7 +1205,7 @@ if test -z "$lt_ECHO"; then
fi fi
fi fi
fi fi
fi fi
fi fi
# Copy echo and quote the copy suitably for passing to libtool from # Copy echo and quote the copy suitably for passing to libtool from
@ -2031,7 +2031,7 @@ else
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
else else
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
fi fi
;; ;;
*) *)
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
@ -2226,7 +2226,7 @@ cygwin* | mingw* | pw32* | cegcc*)
library_names_spec='$libname.dll.a' library_names_spec='$libname.dll.a'
# DLL is installed to $(libdir)/../bin by postinstall_cmds # DLL is installed to $(libdir)/../bin by postinstall_cmds
postinstall_cmds='base_file=`basename \${file}`~ postinstall_cmds='base_file=`basename \${file}`~
dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
dldir=$destdir/`dirname \$dlpath`~ dldir=$destdir/`dirname \$dlpath`~
test -d \$dldir || mkdir -p \$dldir~ test -d \$dldir || mkdir -p \$dldir~
$install_prog $dir/$dlname \$dldir/$dlname~ $install_prog $dir/$dlname \$dldir/$dlname~
@ -2710,10 +2710,10 @@ fi
if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
fi fi
if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
fi fi
_LT_DECL([], [variables_saved_for_relink], [1], _LT_DECL([], [variables_saved_for_relink], [1],
[Variables whose values should be saved in libtool wrapper scripts and [Variables whose values should be saved in libtool wrapper scripts and
@ -3238,7 +3238,7 @@ else
: ${lt_cv_path_NM=no} : ${lt_cv_path_NM=no}
fi]) fi])
if test "$lt_cv_path_NM" != "no"; then if test "$lt_cv_path_NM" != "no"; then
NM="$lt_cv_path_NM" NM="$lt_cv_path_NM"
else else
# Didn't find any BSD compatible name lister, look for dumpbin. # Didn't find any BSD compatible name lister, look for dumpbin.
AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :)
@ -4217,7 +4217,7 @@ m4_if([$1], [CXX], [
;; ;;
esac esac
_LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
], [ ],[
runpath_var= runpath_var=
_LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(allow_undefined_flag, $1)=
_LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(always_export_symbols, $1)=no
@ -5735,7 +5735,7 @@ if test "$_lt_caught_CXX_error" != yes; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
# #
# There doesn't appear to be a way to prevent this compiler from # There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them # explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library # from the output so that they don't get included in the library
@ -5800,7 +5800,7 @@ if test "$_lt_caught_CXX_error" != yes; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
# #
# There doesn't appear to be a way to prevent this compiler from # There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them # explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library # from the output so that they don't get included in the library
@ -5885,7 +5885,7 @@ if test "$_lt_caught_CXX_error" != yes; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
# #
# There doesn't appear to be a way to prevent this compiler from # There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them # explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library # from the output so that they don't get included in the library
@ -5968,7 +5968,7 @@ if test "$_lt_caught_CXX_error" != yes; then
# Commands to make compiler produce verbose output that lists # Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when # what "hidden" libraries, object files and flags are used when
# linking a shared library. # linking a shared library.
# #
# There doesn't appear to be a way to prevent this compiler from # There doesn't appear to be a way to prevent this compiler from
# explicitly linking system object files so we need to strip them # explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library # from the output so that they don't get included in the library
@ -8354,7 +8354,7 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
# echo "creating $dirpart/$file" # echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file" echo '# dummy' > "$dirpart/$file"
done done
done done
} }
])# _AM_OUTPUT_DEPENDENCY_COMMANDS ])# _AM_OUTPUT_DEPENDENCY_COMMANDS
@ -8408,10 +8408,10 @@ if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I." # is not polluted with repeated "-I."
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
# test to see if srcdir already configured # test to see if srcdir already configured
if test -f $srcdir/config.status; then if test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi fi
fi fi
# test whether we have cygpath # test whether we have cygpath
@ -8638,7 +8638,7 @@ if test "$am__include" = "#"; then
_am_result=BSD _am_result=BSD
;; ;;
esac esac
fi fi
AC_SUBST([am__include]) AC_SUBST([am__include])
AC_SUBST([am__quote]) AC_SUBST([am__quote])
AC_MSG_RESULT([$_am_result]) AC_MSG_RESULT([$_am_result])

BIN
bindings/cpp/configure vendored

Binary file not shown.

View file

@ -35,6 +35,8 @@ Pa_GetStreamReadAvailable @31
Pa_GetStreamWriteAvailable @32 Pa_GetStreamWriteAvailable @32
Pa_GetSampleSize @33 Pa_GetSampleSize @33
Pa_Sleep @34 Pa_Sleep @34
Pa_UpdateAvailableDeviceList @35
Pa_SetDevicesChangedCallback @36
PaAsio_GetAvailableLatencyValues @50 PaAsio_GetAvailableLatencyValues @50
PaAsio_ShowControlPanel @51 PaAsio_ShowControlPanel @51
PaUtil_InitializeX86PlainConverters @52 PaUtil_InitializeX86PlainConverters @52

BIN
configure vendored

Binary file not shown.

View file

@ -1,7 +1,7 @@
#ifndef PORTAUDIO_H #ifndef PORTAUDIO_H
#define PORTAUDIO_H #define PORTAUDIO_H
/* /*
* $Id$ * $Id: portaudio.h 1670 2011-05-04 16:37:52Z rob_bielik $
* PortAudio Portable Real-Time Audio Library * PortAudio Portable Real-Time Audio Library
* PortAudio API Header File * PortAudio API Header File
* Latest version available at: http://www.portaudio.com/ * Latest version available at: http://www.portaudio.com/
@ -121,9 +121,17 @@ const char *Pa_GetErrorText( PaError errorCode );
Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not
required to be fully nested. required to be fully nested.
Note that if Pa_Initialize() returns an error code, Pa_Terminate() should If Pa_Initialize() returns an error code, Pa_Terminate() should
NOT be called. NOT be called.
@note The device list returned by Pa_GetDeviceCount() et al. is frozen
at the time Pa_Initialize() is called, and not updated dynamically, even if
hardware devices (e.g. USB or firewire devices) are connected or disconnected
during the course of the program's lifetime. If it is required to re-scan the
list of devices, one must call Pa_UpdateAvailableDeviceList() or, completely
uninitialize PortAudio using Pa_Terminate(), and then reinitialize it by calling
Pa_Initialize().
@return paNoError if successful, otherwise an error code indicating the cause @return paNoError if successful, otherwise an error code indicating the cause
of failure. of failure.
@ -397,6 +405,20 @@ PaDeviceIndex Pa_GetDefaultInputDevice( void );
*/ */
PaDeviceIndex Pa_GetDefaultOutputDevice( void ); PaDeviceIndex Pa_GetDefaultOutputDevice( void );
/** Update the list of available devices to match currently available hardware devices.
PortAudio's list of available devices is usually frozen at the time Pa_Initialize() is
called. Pa_UpdateAvailableDeviceList() may be called to refresh PortAudio's list
of available devices at any time while PortAudio is initialized.
@note Open streams will not be affected by calls to this function, but
any previously returned PaDeviceInfo pointers are invalidated once this
function is called.
@return an error code indicating whether the device refresh was successful.
*/
PaError Pa_UpdateAvailableDeviceList( void );
/** The type used to represent monotonic time in seconds. PaTime is /** The type used to represent monotonic time in seconds. PaTime is
used for the fields of the PaStreamCallbackTimeInfo argument to the used for the fields of the PaStreamCallbackTimeInfo argument to the
@ -439,7 +461,7 @@ typedef unsigned long PaSampleFormat;
#define paInt16 ((PaSampleFormat) 0x00000008) /**< @see PaSampleFormat */ #define paInt16 ((PaSampleFormat) 0x00000008) /**< @see PaSampleFormat */
#define paInt8 ((PaSampleFormat) 0x00000010) /**< @see PaSampleFormat */ #define paInt8 ((PaSampleFormat) 0x00000010) /**< @see PaSampleFormat */
#define paUInt8 ((PaSampleFormat) 0x00000020) /**< @see PaSampleFormat */ #define paUInt8 ((PaSampleFormat) 0x00000020) /**< @see PaSampleFormat */
#define paCustomFormat ((PaSampleFormat) 0x00010000) /**< @see PaSampleFormat */ #define paCustomFormat ((PaSampleFormat) 0x00010000)/**< @see PaSampleFormat */
#define paNonInterleaved ((PaSampleFormat) 0x80000000) /**< @see PaSampleFormat */ #define paNonInterleaved ((PaSampleFormat) 0x80000000) /**< @see PaSampleFormat */
@ -1143,6 +1165,13 @@ void Pa_Sleep( long msec );
typedef void PaDevicesChangedCallback( void *userData );
PaError Pa_SetDevicesChangedCallback( void *userData, PaStreamFinishedCallback* devicesChangedCallback );
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

Binary file not shown.

View file

@ -162,9 +162,9 @@ func_dirname_and_basename ()
func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"`
if test "X$func_dirname_result" = "X${1}"; then if test "X$func_dirname_result" = "X${1}"; then
func_dirname_result="${3}" func_dirname_result="${3}"
else else
func_dirname_result="$func_dirname_result${2}" func_dirname_result="$func_dirname_result${2}"
fi fi
func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"`
} }
@ -343,7 +343,7 @@ func_mkdir_p ()
# Bail out if we (or some other process) failed to create a directory. # Bail out if we (or some other process) failed to create a directory.
test -d "$my_directory_path" || \ test -d "$my_directory_path" || \
func_fatal_error "Failed to create \`$1'" func_fatal_error "Failed to create \`$1'"
fi fi
} }
@ -566,10 +566,10 @@ elif test "X$1" = X--fallback-echo; then
elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then
# Yippee, $ECHO works! # Yippee, $ECHO works!
: :
else else
# Restart under the correct shell, and then maybe $ECHO will work. # Restart under the correct shell, and then maybe $ECHO will work.
exec $SHELL "$progpath" --no-reexec ${1+"$@"} exec $SHELL "$progpath" --no-reexec ${1+"$@"}
fi fi
if test "X$1" = X--fallback-echo; then if test "X$1" = X--fallback-echo; then
# used as fallback echo # used as fallback echo
@ -578,7 +578,7 @@ if test "X$1" = X--fallback-echo; then
$* $*
EOF EOF
exit $EXIT_SUCCESS exit $EXIT_SUCCESS
fi fi
magic="%%%MAGIC variable%%%" magic="%%%MAGIC variable%%%"
magic_exe="%%%MAGIC EXE variable%%%" magic_exe="%%%MAGIC EXE variable%%%"
@ -1175,7 +1175,7 @@ func_mode_compile ()
continue continue
;; ;;
*) * )
# Accept the current argument as the source file. # Accept the current argument as the source file.
# The previous "srcfile" becomes the current argument. # The previous "srcfile" becomes the current argument.
# #
@ -5553,7 +5553,7 @@ func_mode_link ()
link_static=no # Whether the deplib will be linked statically link_static=no # Whether the deplib will be linked statically
use_static_libs=$prefer_static_libs use_static_libs=$prefer_static_libs
if test "$use_static_libs" = built && test "$installed" = yes; then if test "$use_static_libs" = built && test "$installed" = yes ; then
use_static_libs=no use_static_libs=no
fi fi
if test -n "$library_names" && if test -n "$library_names" &&
@ -7690,7 +7690,7 @@ EOF
# Disable wrappers for cegcc, we are cross compiling anyway. # Disable wrappers for cegcc, we are cross compiling anyway.
wrappers_required=no wrappers_required=no
;; ;;
*) * )
if test "$need_relink" = no || test "$build_libtool_libs" != yes; then if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
wrappers_required=no wrappers_required=no
fi fi
@ -7862,7 +7862,7 @@ EOF
else else
func_emit_wrapper no > $func_ltwrapper_scriptname_result func_emit_wrapper no > $func_ltwrapper_scriptname_result
fi fi
} }
;; ;;
* ) * )
$RM $output $RM $output
@ -8187,7 +8187,7 @@ relink_command=\"$relink_command\""
;; ;;
esac esac
exit $EXIT_SUCCESS exit $EXIT_SUCCESS
} }
{ test "$mode" = link || test "$mode" = relink; } && { test "$mode" = link || test "$mode" = relink; } &&
func_mode_link ${1+"$@"} func_mode_link ${1+"$@"}

View file

@ -1,5 +1,5 @@
/* /*
* $Id$ * $Id: pa_converters.c 1661 2011-04-28 18:54:46Z rob_bielik $
* Portable Audio I/O Library sample conversion mechanism * Portable Audio I/O Library sample conversion mechanism
* *
* Based on the Open Source API proposed by Ross Bencina * Based on the Open Source API proposed by Ross Bencina
@ -1167,8 +1167,8 @@ static void Int24_To_Int16_Dither(
void *sourceBuffer, signed int sourceStride, void *sourceBuffer, signed int sourceStride,
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator ) unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
{ {
unsigned char *src = (unsigned char*)sourceBuffer; unsigned char *src = (unsigned char *)sourceBuffer;
PaInt16 *dest = (PaInt16*)destinationBuffer; PaInt16 *dest = (PaInt16 *)destinationBuffer;
PaInt32 temp, dither; PaInt32 temp, dither;
@ -1255,7 +1255,7 @@ static void Int24_To_Int8_Dither(
src += sourceStride * 3; src += sourceStride * 3;
dest += destinationStride; dest += destinationStride;
} }
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */

View file

@ -1,5 +1,5 @@
/* /*
* $Id$ * $Id: pa_front.c 1673 2011-05-06 04:40:22Z rob_bielik $
* Portable Audio I/O Library Multi-Host API front end * Portable Audio I/O Library Multi-Host API front end
* Validate function parameters and manage multiple host APIs. * Validate function parameters and manage multiple host APIs.
* *
@ -80,7 +80,8 @@
#define PA_VERSION_ 1899 #define PA_VERSION_ 1899
#define PA_VERSION_TEXT_ "PortAudio V19-devel (built " __DATE__ " " __TIME__ ")" #define PA_VERSION_TEXT_ "PortAudio V19-devel (built " __DATE__ " " __TIME__ ")"
extern void PaUtil_InitializeHotPlug();
extern void PaUtil_TerminateHotPlug();
int Pa_GetVersion( void ) int Pa_GetVersion( void )
@ -113,16 +114,26 @@ void PaUtil_SetLastHostErrorInfo( PaHostApiTypeId hostApiType, long errorCode,
} }
typedef struct _PaInternalInfo
{
PaUtilHostApiRepresentation **hostApis_;
int hostApisCount_;
int initializationCount_;
int deviceCount_;
static PaUtilHostApiRepresentation **hostApis_ = 0; PaUtilStreamRepresentation *firstOpenStream_;
static int hostApisCount_ = 0;
static int initializationCount_ = 0;
static int deviceCount_ = 0;
PaUtilStreamRepresentation *firstOpenStream_ = NULL; PaDevicesChangedCallback* devicesChangedCallback_;
void* devicesChangedCallbackUserData_;
} PaInternalInfo;
static PaInternalInfo paInternalInfo_ = {0};
#define PA_IS_INITIALISED_ (initializationCount_ != 0)
#define PA_IS_INITIALISED_ (paInternalInfo_.initializationCount_ != 0)
static int CountHostApiInitializers( void ) static int CountHostApiInitializers( void )
@ -140,17 +151,17 @@ static void TerminateHostApis( void )
/* terminate in reverse order from initialization */ /* terminate in reverse order from initialization */
PA_DEBUG(("TerminateHostApis in \n")); PA_DEBUG(("TerminateHostApis in \n"));
while( hostApisCount_ > 0 ) while( paInternalInfo_.hostApisCount_ > 0 )
{ {
--hostApisCount_; --paInternalInfo_.hostApisCount_;
hostApis_[hostApisCount_]->Terminate( hostApis_[hostApisCount_] ); paInternalInfo_.hostApis_[paInternalInfo_.hostApisCount_]->Terminate( paInternalInfo_.hostApis_[paInternalInfo_.hostApisCount_] );
} }
hostApisCount_ = 0; paInternalInfo_.hostApisCount_ = 0;
deviceCount_ = 0; paInternalInfo_.deviceCount_ = 0;
if( hostApis_ != 0 ) if( paInternalInfo_.hostApis_ != 0 )
PaUtil_FreeMemory( hostApis_ ); PaUtil_FreeMemory( paInternalInfo_.hostApis_ );
hostApis_ = 0; paInternalInfo_.hostApis_ = 0;
PA_DEBUG(("TerminateHostApis out\n")); PA_DEBUG(("TerminateHostApis out\n"));
} }
@ -163,33 +174,33 @@ static PaError InitializeHostApis( void )
initializerCount = CountHostApiInitializers(); initializerCount = CountHostApiInitializers();
hostApis_ = (PaUtilHostApiRepresentation**)PaUtil_AllocateMemory( paInternalInfo_.hostApis_ = (PaUtilHostApiRepresentation**)PaUtil_AllocateMemory(
sizeof(PaUtilHostApiRepresentation*) * initializerCount ); sizeof(PaUtilHostApiRepresentation*) * initializerCount );
if( !hostApis_ ) if( !paInternalInfo_.hostApis_ )
{ {
result = paInsufficientMemory; result = paInsufficientMemory;
goto error; goto error;
} }
hostApisCount_ = 0; paInternalInfo_.hostApisCount_ = 0;
deviceCount_ = 0; paInternalInfo_.deviceCount_ = 0;
baseDeviceIndex = 0; baseDeviceIndex = 0;
for( i=0; i< initializerCount; ++i ) for( i=0; i< initializerCount; ++i )
{ {
hostApis_[hostApisCount_] = NULL; paInternalInfo_.hostApis_[paInternalInfo_.hostApisCount_] = NULL;
PA_DEBUG(( "before paHostApiInitializers[%d].\n",i)); PA_DEBUG(( "before paHostApiInitializers[%d].\n",i));
result = paHostApiInitializers[i]( &hostApis_[hostApisCount_], hostApisCount_ ); result = paHostApiInitializers[i]( &paInternalInfo_.hostApis_[paInternalInfo_.hostApisCount_], paInternalInfo_.hostApisCount_ );
if( result != paNoError ) if( result != paNoError )
goto error; goto error;
PA_DEBUG(( "after paHostApiInitializers[%d].\n",i)); PA_DEBUG(( "after paHostApiInitializers[%d].\n",i));
if( hostApis_[hostApisCount_] ) if( paInternalInfo_.hostApis_[paInternalInfo_.hostApisCount_] )
{ {
PaUtilHostApiRepresentation* hostApi = hostApis_[hostApisCount_]; PaUtilHostApiRepresentation* hostApi = paInternalInfo_.hostApis_[paInternalInfo_.hostApisCount_];
assert( hostApi->info.defaultInputDevice < hostApi->info.deviceCount ); assert( hostApi->info.defaultInputDevice < hostApi->info.deviceCount );
assert( hostApi->info.defaultOutputDevice < hostApi->info.deviceCount ); assert( hostApi->info.defaultOutputDevice < hostApi->info.deviceCount );
@ -202,9 +213,9 @@ static PaError InitializeHostApis( void )
hostApi->info.defaultOutputDevice += baseDeviceIndex; hostApi->info.defaultOutputDevice += baseDeviceIndex;
baseDeviceIndex += hostApi->info.deviceCount; baseDeviceIndex += hostApi->info.deviceCount;
deviceCount_ += hostApi->info.deviceCount; paInternalInfo_.deviceCount_ += hostApi->info.deviceCount;
++hostApisCount_; ++paInternalInfo_.hostApisCount_;
} }
} }
@ -233,15 +244,15 @@ static int FindHostApi( PaDeviceIndex device, int *hostSpecificDeviceIndex )
if( device < 0 ) if( device < 0 )
return -1; return -1;
while( i < hostApisCount_ while( i < paInternalInfo_.hostApisCount_
&& device >= hostApis_[i]->info.deviceCount ) && device >= paInternalInfo_.hostApis_[i]->info.deviceCount )
{ {
device -= hostApis_[i]->info.deviceCount; device -= paInternalInfo_.hostApis_[i]->info.deviceCount;
++i; ++i;
} }
if( i >= hostApisCount_ ) if( i >= paInternalInfo_.hostApisCount_ )
return -1; return -1;
if( hostSpecificDeviceIndex ) if( hostSpecificDeviceIndex )
@ -253,15 +264,15 @@ static int FindHostApi( PaDeviceIndex device, int *hostSpecificDeviceIndex )
static void AddOpenStream( PaStream* stream ) static void AddOpenStream( PaStream* stream )
{ {
((PaUtilStreamRepresentation*)stream)->nextOpenStream = firstOpenStream_; ((PaUtilStreamRepresentation*)stream)->nextOpenStream = paInternalInfo_.firstOpenStream_;
firstOpenStream_ = (PaUtilStreamRepresentation*)stream; paInternalInfo_.firstOpenStream_ = (PaUtilStreamRepresentation*)stream;
} }
static void RemoveOpenStream( PaStream* stream ) static void RemoveOpenStream( PaStream* stream )
{ {
PaUtilStreamRepresentation *previous = NULL; PaUtilStreamRepresentation *previous = NULL;
PaUtilStreamRepresentation *current = firstOpenStream_; PaUtilStreamRepresentation *current = paInternalInfo_.firstOpenStream_;
while( current != NULL ) while( current != NULL )
{ {
@ -269,7 +280,7 @@ static void RemoveOpenStream( PaStream* stream )
{ {
if( previous == NULL ) if( previous == NULL )
{ {
firstOpenStream_ = current->nextOpenStream; paInternalInfo_.firstOpenStream_ = current->nextOpenStream;
} }
else else
{ {
@ -291,8 +302,8 @@ static void CloseOpenStreams( void )
/* we call Pa_CloseStream() here to ensure that the same destruction /* we call Pa_CloseStream() here to ensure that the same destruction
logic is used for automatically closed streams */ logic is used for automatically closed streams */
while( firstOpenStream_ != NULL ) while( paInternalInfo_.firstOpenStream_ != NULL )
Pa_CloseStream( firstOpenStream_ ); Pa_CloseStream( paInternalInfo_.firstOpenStream_ );
} }
@ -304,7 +315,7 @@ PaError Pa_Initialize( void )
if( PA_IS_INITIALISED_ ) if( PA_IS_INITIALISED_ )
{ {
++initializationCount_; ++paInternalInfo_.initializationCount_;
result = paNoError; result = paNoError;
} }
else else
@ -315,9 +326,12 @@ PaError Pa_Initialize( void )
PaUtil_InitializeClock(); PaUtil_InitializeClock();
PaUtil_ResetTraceMessages(); PaUtil_ResetTraceMessages();
/* Initialize hot plug here, so all its internal info is setup */
PaUtil_InitializeHotPlug();
result = InitializeHostApis(); result = InitializeHostApis();
if( result == paNoError ) if( result == paNoError )
++initializationCount_; ++paInternalInfo_.initializationCount_;
} }
PA_LOGAPI_EXIT_PAERROR( "Pa_Initialize", result ); PA_LOGAPI_EXIT_PAERROR( "Pa_Initialize", result );
@ -334,12 +348,14 @@ PaError Pa_Terminate( void )
if( PA_IS_INITIALISED_ ) if( PA_IS_INITIALISED_ )
{ {
if( --initializationCount_ == 0 ) if( --paInternalInfo_.initializationCount_ == 0 )
{ {
CloseOpenStreams(); CloseOpenStreams();
TerminateHostApis(); TerminateHostApis();
PaUtil_TerminateHotPlug();
PaUtil_DumpTraceMessages(); PaUtil_DumpTraceMessages();
} }
result = paNoError; result = paNoError;
@ -425,9 +441,9 @@ PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type )
{ {
result = paHostApiNotFound; result = paHostApiNotFound;
for( i=0; i < hostApisCount_; ++i ) for( i=0; i < paInternalInfo_.hostApisCount_; ++i )
{ {
if( hostApis_[i]->info.type == type ) if( paInternalInfo_.hostApis_[i]->info.type == type )
{ {
result = i; result = i;
break; break;
@ -455,11 +471,11 @@ PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **ho
{ {
result = paHostApiNotFound; result = paHostApiNotFound;
for( i=0; i < hostApisCount_; ++i ) for( i=0; i < paInternalInfo_.hostApisCount_; ++i )
{ {
if( hostApis_[i]->info.type == type ) if( paInternalInfo_.hostApis_[i]->info.type == type )
{ {
*hostApi = hostApis_[i]; *hostApi = paInternalInfo_.hostApis_[i];
result = paNoError; result = paNoError;
break; break;
} }
@ -504,7 +520,7 @@ PaHostApiIndex Pa_GetHostApiCount( void )
} }
else else
{ {
result = hostApisCount_; result = paInternalInfo_.hostApisCount_;
} }
PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetHostApiCount", "PaHostApiIndex: %d", result ); PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetHostApiCount", "PaHostApiIndex: %d", result );
@ -530,7 +546,7 @@ PaHostApiIndex Pa_GetDefaultHostApi( void )
/* internal consistency check: make sure that the default host api /* internal consistency check: make sure that the default host api
index is within range */ index is within range */
if( result < 0 || result >= hostApisCount_ ) if( result < 0 || result >= paInternalInfo_.hostApisCount_ )
{ {
result = paInternalError; result = paInternalError;
} }
@ -557,7 +573,7 @@ const PaHostApiInfo* Pa_GetHostApiInfo( PaHostApiIndex hostApi )
PA_LOGAPI(("\tPaHostApiInfo*: NULL [ PortAudio not initialized ]\n" )); PA_LOGAPI(("\tPaHostApiInfo*: NULL [ PortAudio not initialized ]\n" ));
} }
else if( hostApi < 0 || hostApi >= hostApisCount_ ) else if( hostApi < 0 || hostApi >= paInternalInfo_.hostApisCount_ )
{ {
info = NULL; info = NULL;
@ -567,7 +583,7 @@ const PaHostApiInfo* Pa_GetHostApiInfo( PaHostApiIndex hostApi )
} }
else else
{ {
info = &hostApis_[hostApi]->info; info = &paInternalInfo_.hostApis_[hostApi]->info;
PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" )); PA_LOGAPI(("Pa_GetHostApiInfo returned:\n" ));
PA_LOGAPI(("\tPaHostApiInfo*: 0x%p\n", info )); PA_LOGAPI(("\tPaHostApiInfo*: 0x%p\n", info ));
@ -597,20 +613,20 @@ PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, int ho
} }
else else
{ {
if( hostApi < 0 || hostApi >= hostApisCount_ ) if( hostApi < 0 || hostApi >= paInternalInfo_.hostApisCount_ )
{ {
result = paInvalidHostApi; result = paInvalidHostApi;
} }
else else
{ {
if( hostApiDeviceIndex < 0 || if( hostApiDeviceIndex < 0 ||
hostApiDeviceIndex >= hostApis_[hostApi]->info.deviceCount ) hostApiDeviceIndex >= paInternalInfo_.hostApis_[hostApi]->info.deviceCount )
{ {
result = paInvalidDevice; result = paInvalidDevice;
} }
else else
{ {
result = hostApis_[hostApi]->privatePaFrontInfo.baseDeviceIndex + hostApiDeviceIndex; result = paInternalInfo_.hostApis_[hostApi]->privatePaFrontInfo.baseDeviceIndex + hostApiDeviceIndex;
} }
} }
} }
@ -633,7 +649,7 @@ PaDeviceIndex Pa_GetDeviceCount( void )
} }
else else
{ {
result = deviceCount_; result = paInternalInfo_.deviceCount_;
} }
PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetDeviceCount", "PaDeviceIndex: %d", result ); PA_LOGAPI_EXIT_PAERROR_OR_T_RESULT( "Pa_GetDeviceCount", "PaDeviceIndex: %d", result );
@ -656,7 +672,7 @@ PaDeviceIndex Pa_GetDefaultInputDevice( void )
} }
else else
{ {
result = hostApis_[hostApi]->info.defaultInputDevice; result = paInternalInfo_.hostApis_[hostApi]->info.defaultInputDevice;
} }
PA_LOGAPI_EXIT_T( "Pa_GetDefaultInputDevice", "PaDeviceIndex: %d", result ); PA_LOGAPI_EXIT_T( "Pa_GetDefaultInputDevice", "PaDeviceIndex: %d", result );
@ -679,7 +695,7 @@ PaDeviceIndex Pa_GetDefaultOutputDevice( void )
} }
else else
{ {
result = hostApis_[hostApi]->info.defaultOutputDevice; result = paInternalInfo_.hostApis_[hostApi]->info.defaultOutputDevice;
} }
PA_LOGAPI_EXIT_T( "Pa_GetDefaultOutputDevice", "PaDeviceIndex: %d", result ); PA_LOGAPI_EXIT_T( "Pa_GetDefaultOutputDevice", "PaDeviceIndex: %d", result );
@ -688,6 +704,117 @@ PaDeviceIndex Pa_GetDefaultOutputDevice( void )
} }
PaError Pa_UpdateAvailableDeviceList( void )
{
PaError result = paNoError;
void **scanResults = NULL;
int *deviceCounts = NULL;
int i = 0;
PA_LOGAPI_ENTER( "Pa_UpdateAvailableDeviceList" );
if( !PA_IS_INITIALISED_ )
{
result = paNotInitialized;
goto done;
}
/* Allocate data structures used in 2-stage commit */
scanResults = (void **) PaUtil_AllocateMemory( sizeof(void*) * paInternalInfo_.hostApisCount_ );
if( !scanResults )
{
result = paInsufficientMemory;
goto done;
}
deviceCounts = ( int * ) PaUtil_AllocateMemory( sizeof( int ) * paInternalInfo_.hostApisCount_ );
if( !deviceCounts )
{
result = paInsufficientMemory;
goto done;
}
/* Phase 1: Perform a scan of new devices */
for( i = 0 ; i < paInternalInfo_.hostApisCount_ ; ++i )
{
PaUtilHostApiRepresentation *hostApi = paInternalInfo_.hostApis_[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 */
if( i < paInternalInfo_.hostApisCount_ )
{
/* If failure, rollback the scan changes back to original state */
int j = 0;
for( j = 0 ; j < i ; ++j )
{
PaUtilHostApiRepresentation *hostApi = paInternalInfo_.hostApis_[j];
if( hostApi->DisposeDeviceInfos == NULL )
continue;
PA_DEBUG(( "Performing rollback for device list scan for host api %d.\n",i));
hostApi->DisposeDeviceInfos( hostApi, scanResults[ j ], deviceCounts[ j ] );
}
}
else
{
int baseDeviceIndex = 0;
paInternalInfo_.deviceCount_ = 0;
/* Otherwise, commit the scan changes to each back-end */
for( i = 0 ; i < paInternalInfo_.hostApisCount_ ; ++i )
{
PaUtilHostApiRepresentation *hostApi = paInternalInfo_.hostApis_[i];
if( hostApi->CommitDeviceInfos == NULL )
{
/* Not yet implemented for this backend. Just
assume that the baseDeviceIndex and the paInternalInfo_.deviceCount_ are
incremented according to the values in the info */
baseDeviceIndex += hostApi->info.deviceCount;
paInternalInfo_.deviceCount_ += hostApi->info.deviceCount;
continue;
}
PA_DEBUG(( "Committing device list scan for host api %d.\n",i));
if( hostApi->CommitDeviceInfos( hostApi, i, scanResults[ i ], deviceCounts[ i ] ) != paNoError )
{
PA_DEBUG(( "Committing failed (shouldn't happen) %d.\n",i));
result = paInternalError;
goto done;
}
assert( hostApi->info.defaultInputDevice < hostApi->info.deviceCount );
assert( hostApi->info.defaultOutputDevice < hostApi->info.deviceCount );
hostApi->privatePaFrontInfo.baseDeviceIndex = baseDeviceIndex;
if( hostApi->info.defaultInputDevice != paNoDevice )
hostApi->info.defaultInputDevice += baseDeviceIndex;
if( hostApi->info.defaultOutputDevice != paNoDevice )
hostApi->info.defaultOutputDevice += baseDeviceIndex;
baseDeviceIndex += hostApi->info.deviceCount;
paInternalInfo_.deviceCount_ += hostApi->info.deviceCount;
}
}
done:
if( scanResults )
PaUtil_FreeMemory( scanResults );
if( deviceCounts )
PaUtil_FreeMemory( deviceCounts );
return result;
}
const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device ) const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )
{ {
int hostSpecificDeviceIndex; int hostSpecificDeviceIndex;
@ -708,7 +835,7 @@ const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )
} }
else else
{ {
result = hostApis_[hostApiIndex]->deviceInfos[ hostSpecificDeviceIndex ]; result = paInternalInfo_.hostApis_[hostApiIndex]->deviceInfos[ hostSpecificDeviceIndex ];
PA_LOGAPI(("Pa_GetDeviceInfo returned:\n" )); PA_LOGAPI(("Pa_GetDeviceInfo returned:\n" ));
PA_LOGAPI(("\tPaDeviceInfo*: 0x%p:\n", result )); PA_LOGAPI(("\tPaDeviceInfo*: 0x%p:\n", result ));
@ -850,7 +977,7 @@ static PaError ValidateOpenStreamParameters(
if( inputHostApiIndex != -1 ) if( inputHostApiIndex != -1 )
{ {
*hostApiInputDevice = paUseHostApiSpecificDeviceSpecification; *hostApiInputDevice = paUseHostApiSpecificDeviceSpecification;
*hostApi = hostApis_[inputHostApiIndex]; *hostApi = paInternalInfo_.hostApis_[inputHostApiIndex];
} }
else else
{ {
@ -864,14 +991,14 @@ static PaError ValidateOpenStreamParameters(
} }
else else
{ {
if( inputParameters->device < 0 || inputParameters->device >= deviceCount_ ) if( inputParameters->device < 0 || inputParameters->device >= paInternalInfo_.deviceCount_ )
return paInvalidDevice; return paInvalidDevice;
inputHostApiIndex = FindHostApi( inputParameters->device, hostApiInputDevice ); inputHostApiIndex = FindHostApi( inputParameters->device, hostApiInputDevice );
if( inputHostApiIndex < 0 ) if( inputHostApiIndex < 0 )
return paInternalError; return paInternalError;
*hostApi = hostApis_[inputHostApiIndex]; *hostApi = paInternalInfo_.hostApis_[inputHostApiIndex];
if( inputParameters->channelCount <= 0 ) if( inputParameters->channelCount <= 0 )
return paInvalidChannelCount; return paInvalidChannelCount;
@ -901,7 +1028,7 @@ static PaError ValidateOpenStreamParameters(
if( outputHostApiIndex != -1 ) if( outputHostApiIndex != -1 )
{ {
*hostApiOutputDevice = paUseHostApiSpecificDeviceSpecification; *hostApiOutputDevice = paUseHostApiSpecificDeviceSpecification;
*hostApi = hostApis_[outputHostApiIndex]; *hostApi = paInternalInfo_.hostApis_[outputHostApiIndex];
} }
else else
{ {
@ -915,14 +1042,14 @@ static PaError ValidateOpenStreamParameters(
} }
else else
{ {
if( outputParameters->device < 0 || outputParameters->device >= deviceCount_ ) if( outputParameters->device < 0 || outputParameters->device >= paInternalInfo_.deviceCount_ )
return paInvalidDevice; return paInvalidDevice;
outputHostApiIndex = FindHostApi( outputParameters->device, hostApiOutputDevice ); outputHostApiIndex = FindHostApi( outputParameters->device, hostApiOutputDevice );
if( outputHostApiIndex < 0 ) if( outputHostApiIndex < 0 )
return paInternalError; return paInternalError;
*hostApi = hostApis_[outputHostApiIndex]; *hostApi = paInternalInfo_.hostApis_[outputHostApiIndex];
if( outputParameters->channelCount <= 0 ) if( outputParameters->channelCount <= 0 )
return paInvalidChannelCount; return paInvalidChannelCount;
@ -1751,3 +1878,29 @@ PaError Pa_GetSampleSize( PaSampleFormat format )
return (PaError) result; return (PaError) result;
} }
extern void PaUtil_LockHotPlug();
extern void PaUtil_UnlockHotPlug();
PaError Pa_SetDevicesChangedCallback( void *userData, PaStreamFinishedCallback* devicesChangedCallback )
{
PaUtil_LockHotPlug();
paInternalInfo_.devicesChangedCallback_ = devicesChangedCallback;
paInternalInfo_.devicesChangedCallbackUserData_ = userData;
PaUtil_UnlockHotPlug();
return paNoError;
}
/* Called whenever a OS audio device change has been detected */
void PaUtil_DevicesChanged(unsigned state, void* pData)
{
(void)state;
(void)pData;
PaUtil_LockHotPlug();
if (paInternalInfo_.devicesChangedCallback_)
{
(paInternalInfo_.devicesChangedCallback_)(paInternalInfo_.devicesChangedCallbackUserData_);
}
PaUtil_UnlockHotPlug();
}

View file

@ -1,7 +1,7 @@
#ifndef PA_HOSTAPI_H #ifndef PA_HOSTAPI_H
#define PA_HOSTAPI_H #define PA_HOSTAPI_H
/* /*
* $Id$ * $Id: pa_hostapi.h 1664 2011-05-01 16:10:58Z rossb $
* Portable Audio I/O Library * Portable Audio I/O Library
* host api representation * host api representation
* *
@ -275,6 +275,37 @@ typedef struct PaUtilHostApiRepresentation {
const PaStreamParameters *inputParameters, const PaStreamParameters *inputParameters,
const PaStreamParameters *outputParameters, const PaStreamParameters *outputParameters,
double sampleRate ); double sampleRate );
/**
Collect current native device information and compute a new device count.
This method should not result in the host API making any changes to its
internal data structures, instead it is the first step in a two-stage commit
process which will be completed only if all host API scans return with no errors.
Some time later the caller will either (1) pass scanResults and newDeviceCount
to CommitDeviceInfos() to complete the transaction, or (2) pass scanResults
and newDeviceCount to DisposeDeviceInfos() to abort the transaction.
*/
PaError (*ScanDeviceInfos)( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void **scanResults, int *newDeviceCount );
/**
Replace the previous device information with the device information
passed in as an argument via scanResults. This is the second/final stage of
the two-stage transaction required for updating the available device information.
This function should free any resources associated with the previous device
information.
@FIXME: this function should probably not return an error code as it should not be
permitted to fail.
*/
PaError (*CommitDeviceInfos)( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void *scanResults, int deviceCount );
/**
Free device information previously returned by ScanDeviceInfos(). This function
will be called in cases where the update available device info transaction
failed for some reason.
*/
PaError (*DisposeDeviceInfos)( struct PaUtilHostApiRepresentation *hostApi, void *scanResults, int deviceCount );
} PaUtilHostApiRepresentation; } PaUtilHostApiRepresentation;

View file

@ -1,5 +1,5 @@
/* /*
* $Id$ * $Id: pa_process.c 1661 2011-04-28 18:54:46Z rob_bielik $
* Portable Audio I/O Library * Portable Audio I/O Library
* streamCallback <-> host buffer processing adapter * streamCallback <-> host buffer processing adapter
* *
@ -847,7 +847,7 @@ static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp,
{ {
if( bp->userOutputSampleFormatIsEqualToHost && !bp->hostOutputIsInterleaved ) if( bp->userOutputSampleFormatIsEqualToHost && !bp->hostOutputIsInterleaved )
{ {
for( i=0; i<bp->outputChannelCount; ++i ) for( i = 0; i < bp->outputChannelCount; ++i )
{ {
bp->tempOutputBufferPtrs[i] = hostOutputChannels[i].data; bp->tempOutputBufferPtrs[i] = hostOutputChannels[i].data;
} }

View file

@ -1,5 +1,5 @@
/* /*
* $Id$ * $Id: pa_linux_alsa.c 1661 2011-04-28 18:54:46Z rob_bielik $
* PortAudio Portable Real-Time Audio Library * PortAudio Portable Real-Time Audio Library
* Latest Version at: http://www.portaudio.com * Latest Version at: http://www.portaudio.com
* ALSA implementation by Joshua Haberman and Arve Knudsen * ALSA implementation by Joshua Haberman and Arve Knudsen
@ -3137,7 +3137,7 @@ error:
ENSURE_( alsa_snd_pcm_hw_params_get_rate_min( hwParams, &_min, &_dir ), paUnanticipatedHostError ); ENSURE_( alsa_snd_pcm_hw_params_get_rate_min( hwParams, &_min, &_dir ), paUnanticipatedHostError );
ENSURE_( alsa_snd_pcm_hw_params_get_rate_max( hwParams, &_max, &_dir ), paUnanticipatedHostError ); ENSURE_( alsa_snd_pcm_hw_params_get_rate_max( hwParams, &_max, &_dir ), paUnanticipatedHostError );
PA_DEBUG(( "%s: SR min = %d, max = %d, req = %lu\n", __FUNCTION__, _min, _max, approx )); PA_DEBUG(( "%s: SR min = %d, max = %d, req = %lu\n", __FUNCTION__, _min, _max, approx ));
} }
goto end; goto end;
} }

View file

@ -1756,7 +1756,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
AudioDeviceAddPropertyListener( stream->inputDevice, 0, /* isInput = */ TRUE, kAudioDevicePropertyLatency, AudioDeviceAddPropertyListener( stream->inputDevice, 0, /* isInput = */ TRUE, kAudioDevicePropertyLatency,
AudioDevicePropertyInputLatencySamplesListenerProc, stream ); AudioDevicePropertyInputLatencySamplesListenerProc, stream );
}else{ } else {
stream->deviceInputLatencySamples = 0; stream->deviceInputLatencySamples = 0;
stream->deviceInputLatencySamples_ioProcCopy = 0; stream->deviceInputLatencySamples_ioProcCopy = 0;
} }

View file

@ -1,5 +1,5 @@
/* /*
* $Id$ * $Id: pa_win_ds.c 1672 2011-05-04 20:11:30Z rossb $
* Portable Audio I/O Library DirectSound implementation * Portable Audio I/O Library DirectSound implementation
* *
* Authors: Phil Burk, Robert Marsanyi & Ross Bencina * Authors: Phil Burk, Robert Marsanyi & Ross Bencina
@ -75,10 +75,6 @@
#include "pa_win_waveformat.h" #include "pa_win_waveformat.h"
#include "pa_win_wdmks_utils.h" #include "pa_win_wdmks_utils.h"
#ifndef PA_USE_WMME
#error "Portaudio internal error: PA_USE_WMME=0/1 not defined. pa_hostapi.h should ensure that it is."
#endif
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */ #if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */
#pragma comment( lib, "dsound.lib" ) #pragma comment( lib, "dsound.lib" )
#pragma comment( lib, "winmm.lib" ) #pragma comment( lib, "winmm.lib" )
@ -141,6 +137,9 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
const PaStreamParameters *inputParameters, const PaStreamParameters *inputParameters,
const PaStreamParameters *outputParameters, const PaStreamParameters *outputParameters,
double sampleRate ); 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 );
static PaError CloseStream( PaStream* stream ); static PaError CloseStream( PaStream* stream );
static PaError StartStream( PaStream *stream ); static PaError StartStream( PaStream *stream );
static PaError StopStream( PaStream *stream ); static PaError StopStream( PaStream *stream );
@ -249,6 +248,12 @@ typedef struct PaWinDsStream
volatile int abortProcessing; /* stop thread immediately */ volatile int abortProcessing; /* stop thread immediately */
} PaWinDsStream; } PaWinDsStream;
typedef struct PaWinDsScanDeviceInfosResults{ /* used for tranferring device infos during scanning / rescanning */
PaDeviceInfo **deviceInfos;
PaDeviceIndex defaultInputDevice;
PaDeviceIndex defaultOutputDevice;
} PaWinDsScanDeviceInfosResults;
/************************************************************************************ /************************************************************************************
** Duplicate the input string using the allocations allocator. ** Duplicate the input string using the allocations allocator.
@ -293,7 +298,7 @@ typedef struct DSDeviceNameAndGUIDVector{
int count; int count;
int free; int free;
DSDeviceNameAndGUID *items; // Allocated using LocalAlloc() DSDeviceNameAndGUID *items; /* Allocated using LocalAlloc() */
} DSDeviceNameAndGUIDVector; } DSDeviceNameAndGUIDVector;
typedef struct DSDeviceNamesAndGUIDs{ typedef struct DSDeviceNamesAndGUIDs{
@ -590,28 +595,15 @@ static double defaultSampleRateSearchOrder_[] =
** The device will not be added to the device list if any errors are encountered. ** The device will not be added to the device list if any errors are encountered.
*/ */
static PaError AddOutputDeviceInfoFromDirectSound( static PaError AddOutputDeviceInfoFromDirectSound(
PaWinDsHostApiRepresentation *winDsHostApi, char *name, LPGUID lpGUID, char *pnpInterface ) PaWinDsDeviceInfo *winDsDeviceInfo, char *name, LPGUID lpGUID, char *pnpInterface )
{ {
PaUtilHostApiRepresentation *hostApi = &winDsHostApi->inheritedHostApiRep;
PaWinDsDeviceInfo *winDsDeviceInfo = (PaWinDsDeviceInfo*) hostApi->deviceInfos[hostApi->info.deviceCount];
PaDeviceInfo *deviceInfo = &winDsDeviceInfo->inheritedDeviceInfo; PaDeviceInfo *deviceInfo = &winDsDeviceInfo->inheritedDeviceInfo;
HRESULT hr; HRESULT hr;
LPDIRECTSOUND lpDirectSound; LPDIRECTSOUND lpDirectSound = NULL;
DSCAPS caps; DSCAPS caps;
int deviceOK = TRUE;
PaError result = paNoError; PaError result = paNoError;
int i; int i;
/* Copy GUID to the device info structure. Set pointer. */
if( lpGUID == NULL )
{
winDsDeviceInfo->lpGUID = NULL;
}
else
{
memcpy( &winDsDeviceInfo->guid, lpGUID, sizeof(GUID) );
winDsDeviceInfo->lpGUID = &winDsDeviceInfo->guid;
}
if( lpGUID ) if( lpGUID )
{ {
@ -619,7 +611,7 @@ static PaError AddOutputDeviceInfoFromDirectSound(
IsEqualGUID (&IID_IRolandVSCEmulated2,lpGUID) ) IsEqualGUID (&IID_IRolandVSCEmulated2,lpGUID) )
{ {
PA_DEBUG(("BLACKLISTED: %s \n",name)); PA_DEBUG(("BLACKLISTED: %s \n",name));
return paNoError; return paInvalidDevice;
} }
} }
@ -627,23 +619,6 @@ static PaError AddOutputDeviceInfoFromDirectSound(
Note that using CoCreateInstance doesn't work on windows CE. Note that using CoCreateInstance doesn't work on windows CE.
*/ */
hr = paWinDsDSoundEntryPoints.DirectSoundCreate( lpGUID, &lpDirectSound, NULL ); hr = paWinDsDSoundEntryPoints.DirectSoundCreate( lpGUID, &lpDirectSound, NULL );
/** try using CoCreateInstance because DirectSoundCreate was hanging under
some circumstances - note this was probably related to the
#define BOOL short bug which has now been fixed
@todo delete this comment and the following code once we've ensured
there is no bug.
*/
/*
hr = CoCreateInstance( &CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSound, (void**)&lpDirectSound );
if( hr == S_OK )
{
hr = IDirectSound_Initialize( lpDirectSound, lpGUID );
}
*/
if( hr != DS_OK ) if( hr != DS_OK )
{ {
if (hr == DSERR_ALLOCATED) if (hr == DSERR_ALLOCATED)
@ -664,7 +639,8 @@ static PaError AddOutputDeviceInfoFromDirectSound(
lpGUID->Data4[6], lpGUID->Data4[6],
lpGUID->Data4[7])); lpGUID->Data4[7]));
deviceOK = FALSE; result = paUnanticipatedHostError;
goto error;
} }
else else
{ {
@ -675,7 +651,9 @@ static PaError AddOutputDeviceInfoFromDirectSound(
if( hr != DS_OK ) if( hr != DS_OK )
{ {
DBUG(("Cannot GetCaps() for DirectSound device %s. Result = 0x%x\n", name, hr )); DBUG(("Cannot GetCaps() for DirectSound device %s. Result = 0x%x\n", name, hr ));
deviceOK = FALSE;
result = paUnanticipatedHostError;
goto error;
} }
else else
{ {
@ -684,12 +662,11 @@ static PaError AddOutputDeviceInfoFromDirectSound(
if( caps.dwFlags & DSCAPS_EMULDRIVER ) if( caps.dwFlags & DSCAPS_EMULDRIVER )
{ {
/* If WMME supported, then reject Emulated drivers because they are lousy. */ /* If WMME supported, then reject Emulated drivers because they are lousy. */
deviceOK = FALSE; result = paInvalidDevice;
goto error;
} }
#endif #endif
if( deviceOK )
{
deviceInfo->maxInputChannels = 0; deviceInfo->maxInputChannels = 0;
winDsDeviceInfo->deviceInputChannelCountIsKnown = 1; winDsDeviceInfo->deviceInputChannelCountIsKnown = 1;
@ -817,20 +794,28 @@ static PaError AddOutputDeviceInfoFromDirectSound(
//printf( "min %d max %d\n", caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate ); //printf( "min %d max %d\n", caps.dwMinSecondarySampleRate, caps.dwMaxSecondarySampleRate );
// dwFlags | DSCAPS_CONTINUOUSRATE // dwFlags | DSCAPS_CONTINUOUSRATE
} }
}
IDirectSound_Release( lpDirectSound ); IDirectSound_Release( lpDirectSound );
} }
if( deviceOK ) /* Copy GUID to the device info structure. Set pointer. */
if( lpGUID == NULL )
{ {
winDsDeviceInfo->lpGUID = NULL;
}
else
{
memcpy( &winDsDeviceInfo->guid, lpGUID, sizeof(GUID) );
winDsDeviceInfo->lpGUID = &winDsDeviceInfo->guid;
}
deviceInfo->name = name; deviceInfo->name = name;
if( lpGUID == NULL ) return result;
hostApi->info.defaultOutputDevice = hostApi->info.deviceCount;
hostApi->info.deviceCount++; error:
} if( lpDirectSound )
IDirectSound_Release( lpDirectSound );
return result; return result;
} }
@ -844,44 +829,20 @@ static PaError AddOutputDeviceInfoFromDirectSound(
** The device will not be added to the device list if any errors are encountered. ** The device will not be added to the device list if any errors are encountered.
*/ */
static PaError AddInputDeviceInfoFromDirectSoundCapture( static PaError AddInputDeviceInfoFromDirectSoundCapture(
PaWinDsHostApiRepresentation *winDsHostApi, char *name, LPGUID lpGUID, char *pnpInterface ) PaWinDsDeviceInfo *winDsDeviceInfo, char *name, LPGUID lpGUID, char *pnpInterface )
{ {
PaUtilHostApiRepresentation *hostApi = &winDsHostApi->inheritedHostApiRep;
PaWinDsDeviceInfo *winDsDeviceInfo = (PaWinDsDeviceInfo*) hostApi->deviceInfos[hostApi->info.deviceCount];
PaDeviceInfo *deviceInfo = &winDsDeviceInfo->inheritedDeviceInfo; PaDeviceInfo *deviceInfo = &winDsDeviceInfo->inheritedDeviceInfo;
HRESULT hr; HRESULT hr;
LPDIRECTSOUNDCAPTURE lpDirectSoundCapture; LPDIRECTSOUNDCAPTURE lpDirectSoundCapture = NULL;
DSCCAPS caps; DSCCAPS caps;
int deviceOK = TRUE;
PaError result = paNoError; PaError result = paNoError;
/* Copy GUID to the device info structure. Set pointer. */
if( lpGUID == NULL )
{
winDsDeviceInfo->lpGUID = NULL;
}
else
{
winDsDeviceInfo->lpGUID = &winDsDeviceInfo->guid;
memcpy( &winDsDeviceInfo->guid, lpGUID, sizeof(GUID) );
}
hr = paWinDsDSoundEntryPoints.DirectSoundCaptureCreate( lpGUID, &lpDirectSoundCapture, NULL ); hr = paWinDsDSoundEntryPoints.DirectSoundCaptureCreate( lpGUID, &lpDirectSoundCapture, NULL );
/** try using CoCreateInstance because DirectSoundCreate was hanging under
some circumstances - note this was probably related to the
#define BOOL short bug which has now been fixed
@todo delete this comment and the following code once we've ensured
there is no bug.
*/
/*
hr = CoCreateInstance( &CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectSoundCapture, (void**)&lpDirectSoundCapture );
*/
if( hr != DS_OK ) if( hr != DS_OK )
{ {
DBUG(("Cannot create Capture for %s. Result = 0x%x\n", name, hr )); DBUG(("Cannot create Capture for %s. Result = 0x%x\n", name, hr ));
deviceOK = FALSE; result = paUnanticipatedHostError;
goto error;
} }
else else
{ {
@ -892,7 +853,8 @@ static PaError AddInputDeviceInfoFromDirectSoundCapture(
if( hr != DS_OK ) if( hr != DS_OK )
{ {
DBUG(("Cannot GetCaps() for Capture device %s. Result = 0x%x\n", name, hr )); DBUG(("Cannot GetCaps() for Capture device %s. Result = 0x%x\n", name, hr ));
deviceOK = FALSE; result = paUnanticipatedHostError;
goto error;
} }
else else
{ {
@ -900,12 +862,11 @@ static PaError AddInputDeviceInfoFromDirectSoundCapture(
if( caps.dwFlags & DSCAPS_EMULDRIVER ) if( caps.dwFlags & DSCAPS_EMULDRIVER )
{ {
/* If WMME supported, then reject Emulated drivers because they are lousy. */ /* If WMME supported, then reject Emulated drivers because they are lousy. */
deviceOK = FALSE; result = paInvalidDevice;
goto error;
} }
#endif #endif
if( deviceOK )
{
deviceInfo->maxInputChannels = caps.dwChannels; deviceInfo->maxInputChannels = caps.dwChannels;
winDsDeviceInfo->deviceInputChannelCountIsKnown = 1; winDsDeviceInfo->deviceInputChannelCountIsKnown = 1;
@ -930,20 +891,20 @@ static PaError AddInputDeviceInfoFromDirectSoundCapture(
deviceInfo->defaultHighOutputLatency = 0.; /** @todo IMPLEMENT ME */ deviceInfo->defaultHighOutputLatency = 0.; /** @todo IMPLEMENT ME */
/* constants from a WINE patch by Francois Gouget, see: /* constants from a WINE patch by Francois Gouget, see:
http://www.winehq.com/hypermail/wine-patches/2003/01/0290.html http://www.winehq.com/hypermail/wine-patches/2003/01/0290.html
--- ---
Date: Fri, 14 May 2004 10:38:12 +0200 (CEST) Date: Fri, 14 May 2004 10:38:12 +0200 (CEST)
From: Francois Gouget <fgouget@ ... .fr> From: Francois Gouget <fgouget@ ... .fr>
To: Ross Bencina <rbencina@ ... .au> To: Ross Bencina <rbencina@ ... .au>
Subject: Re: Permission to use wine 48/96 wave patch in BSD licensed library Subject: Re: Permission to use wine 48/96 wave patch in BSD licensed library
[snip] [snip]
I give you permission to use the patch below under the BSD license. I give you permission to use the patch below under the BSD license.
http://www.winehq.com/hypermail/wine-patches/2003/01/0290.html http://www.winehq.com/hypermail/wine-patches/2003/01/0290.html
[snip] [snip]
*/ */
#ifndef WAVE_FORMAT_48M08 #ifndef WAVE_FORMAT_48M08
#define WAVE_FORMAT_48M08 0x00001000 /* 48 kHz, Mono, 8-bit */ #define WAVE_FORMAT_48M08 0x00001000 /* 48 kHz, Mono, 8-bit */
@ -989,20 +950,29 @@ static PaError AddInputDeviceInfoFromDirectSoundCapture(
} }
else deviceInfo->defaultSampleRate = 0.; else deviceInfo->defaultSampleRate = 0.;
} }
}
IDirectSoundCapture_Release( lpDirectSoundCapture ); IDirectSoundCapture_Release( lpDirectSoundCapture );
} }
if( deviceOK )
/* Copy GUID to the device info structure. Set pointer. */
if( lpGUID == NULL )
{ {
winDsDeviceInfo->lpGUID = NULL;
}
else
{
winDsDeviceInfo->lpGUID = &winDsDeviceInfo->guid;
memcpy( &winDsDeviceInfo->guid, lpGUID, sizeof(GUID) );
}
deviceInfo->name = name; deviceInfo->name = name;
if( lpGUID == NULL ) return result;
hostApi->info.defaultInputDevice = hostApi->info.deviceCount;
hostApi->info.deviceCount++; error:
} if( lpDirectSoundCapture )
IDirectSoundCapture_Release( lpDirectSoundCapture );
return result; return result;
} }
@ -1012,12 +982,10 @@ static PaError AddInputDeviceInfoFromDirectSoundCapture(
PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex ) PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
{ {
PaError result = paNoError; PaError result = paNoError;
int i, deviceCount; int deviceCount;
PaWinDsHostApiRepresentation *winDsHostApi; PaWinDsHostApiRepresentation *winDsHostApi;
DSDeviceNamesAndGUIDs deviceNamesAndGUIDs;
PaWinDsDeviceInfo *deviceInfoArray;
char comWasInitialized = 0; char comWasInitialized = 0;
void *scanResults = 0;
/* /*
If COM is already initialized CoInitialize will either return If COM is already initialized CoInitialize will either return
@ -1034,11 +1002,6 @@ PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInde
if( hr != RPC_E_CHANGED_MODE ) if( hr != RPC_E_CHANGED_MODE )
comWasInitialized = 1; comWasInitialized = 1;
/* initialise guid vectors so they can be safely deleted on error */
deviceNamesAndGUIDs.winDsHostApi = NULL;
deviceNamesAndGUIDs.inputNamesAndGUIDs.items = NULL;
deviceNamesAndGUIDs.outputNamesAndGUIDs.items = NULL;
PaWinDs_InitializeDSoundEntryPoints(); PaWinDs_InitializeDSoundEntryPoints();
winDsHostApi = (PaWinDsHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinDsHostApiRepresentation) ); winDsHostApi = (PaWinDsHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinDsHostApiRepresentation) );
@ -1062,109 +1025,25 @@ PaError PaWinDs_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInde
(*hostApi)->info.type = paDirectSound; (*hostApi)->info.type = paDirectSound;
(*hostApi)->info.name = "Windows DirectSound"; (*hostApi)->info.name = "Windows DirectSound";
/* these are all updated by CommitDeviceInfos() */
(*hostApi)->info.deviceCount = 0; (*hostApi)->info.deviceCount = 0;
(*hostApi)->info.defaultInputDevice = paNoDevice; (*hostApi)->info.defaultInputDevice = paNoDevice;
(*hostApi)->info.defaultOutputDevice = paNoDevice; (*hostApi)->info.defaultOutputDevice = paNoDevice;
(*hostApi)->deviceInfos = 0;
result = ScanDeviceInfos( &winDsHostApi->inheritedHostApiRep, hostApiIndex, &scanResults, &deviceCount );
/* DSound - enumerate devices to count them and to gather their GUIDs */
result = InitializeDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.inputNamesAndGUIDs, winDsHostApi->allocations );
if( result != paNoError )
goto error;
result = InitializeDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.outputNamesAndGUIDs, winDsHostApi->allocations );
if( result != paNoError )
goto error;
paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&deviceNamesAndGUIDs.inputNamesAndGUIDs );
paWinDsDSoundEntryPoints.DirectSoundEnumerateA( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&deviceNamesAndGUIDs.outputNamesAndGUIDs );
if( deviceNamesAndGUIDs.inputNamesAndGUIDs.enumerationError != paNoError )
{
result = deviceNamesAndGUIDs.inputNamesAndGUIDs.enumerationError;
goto error;
}
if( deviceNamesAndGUIDs.outputNamesAndGUIDs.enumerationError != paNoError )
{
result = deviceNamesAndGUIDs.outputNamesAndGUIDs.enumerationError;
goto error;
}
deviceCount = deviceNamesAndGUIDs.inputNamesAndGUIDs.count + deviceNamesAndGUIDs.outputNamesAndGUIDs.count;
#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
if( deviceCount > 0 )
{
deviceNamesAndGUIDs.winDsHostApi = winDsHostApi;
FindDevicePnpInterfaces( &deviceNamesAndGUIDs );
}
#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
if( deviceCount > 0 )
{
/* allocate array for pointers to PaDeviceInfo structs */
(*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
winDsHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount );
if( !(*hostApi)->deviceInfos )
{
result = paInsufficientMemory;
goto error;
}
/* allocate all PaDeviceInfo structs in a contiguous block */
deviceInfoArray = (PaWinDsDeviceInfo*)PaUtil_GroupAllocateMemory(
winDsHostApi->allocations, sizeof(PaWinDsDeviceInfo) * deviceCount );
if( !deviceInfoArray )
{
result = paInsufficientMemory;
goto error;
}
for( i=0; i < deviceCount; ++i )
{
PaDeviceInfo *deviceInfo = &deviceInfoArray[i].inheritedDeviceInfo;
deviceInfo->structVersion = 2;
deviceInfo->hostApi = hostApiIndex;
deviceInfo->name = 0;
(*hostApi)->deviceInfos[i] = deviceInfo;
}
for( i=0; i < deviceNamesAndGUIDs.inputNamesAndGUIDs.count; ++i )
{
result = AddInputDeviceInfoFromDirectSoundCapture( winDsHostApi,
deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].name,
deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].lpGUID,
deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].pnpInterface );
if( result != paNoError )
goto error;
}
for( i=0; i < deviceNamesAndGUIDs.outputNamesAndGUIDs.count; ++i )
{
result = AddOutputDeviceInfoFromDirectSound( winDsHostApi,
deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].name,
deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].lpGUID,
deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].pnpInterface );
if( result != paNoError )
goto error;
}
}
result = TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.inputNamesAndGUIDs );
if( result != paNoError )
goto error;
result = TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.outputNamesAndGUIDs );
if( result != paNoError ) if( result != paNoError )
goto error; goto error;
/* FIXME for now we ignore the result of CommitDeviceInfos(), it should probably be an atomic non-failing operation */
CommitDeviceInfos( &winDsHostApi->inheritedHostApiRep, hostApiIndex, scanResults, deviceCount );
(*hostApi)->Terminate = Terminate; (*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream; (*hostApi)->OpenStream = OpenStream;
(*hostApi)->IsFormatSupported = IsFormatSupported; (*hostApi)->IsFormatSupported = IsFormatSupported;
(*hostApi)->ScanDeviceInfos = ScanDeviceInfos;
(*hostApi)->CommitDeviceInfos = CommitDeviceInfos;
(*hostApi)->DisposeDeviceInfos = DisposeDeviceInfos;
PaUtil_InitializeStreamInterface( &winDsHostApi->callbackStreamInterface, CloseStream, StartStream, PaUtil_InitializeStreamInterface( &winDsHostApi->callbackStreamInterface, CloseStream, StartStream,
StopStream, AbortStream, IsStreamStopped, IsStreamActive, StopStream, AbortStream, IsStreamStopped, IsStreamActive,
@ -1191,9 +1070,6 @@ error:
PaUtil_FreeMemory( winDsHostApi ); PaUtil_FreeMemory( winDsHostApi );
} }
TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.inputNamesAndGUIDs );
TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.outputNamesAndGUIDs );
if( comWasInitialized ) if( comWasInitialized )
CoUninitialize(); CoUninitialize();
@ -1369,6 +1245,231 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
return paFormatIsSupported; return paFormatIsSupported;
} }
/***********************************************************************************/
static PaError ScanDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex hostApiIndex, void **scanResults, int *newDeviceCount )
{
PaWinDsHostApiRepresentation *winDsHostApi = (PaWinDsHostApiRepresentation*)hostApi;
PaWinDsDeviceInfo *deviceInfoArray;
char comWasInitialized = winDsHostApi->comWasInitialized;
PaError result = paNoError;
PaWinDsScanDeviceInfosResults *outArgument = 0;
DSDeviceNamesAndGUIDs deviceNamesAndGUIDs;
int i = 0;
int maximumNewDeviceCount = 0;
/* Check preconditions */
if( !comWasInitialized || scanResults == NULL || newDeviceCount == NULL )
return paInternalError;
/* initialize the out params */
*scanResults = NULL;
*newDeviceCount = 0;
/* initialise guid vectors so they can be safely deleted on error */
deviceNamesAndGUIDs.winDsHostApi = NULL;
deviceNamesAndGUIDs.inputNamesAndGUIDs.items = NULL;
deviceNamesAndGUIDs.outputNamesAndGUIDs.items = NULL;
result = InitializeDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.inputNamesAndGUIDs, winDsHostApi->allocations );
if( result != paNoError )
goto error;
result = InitializeDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.outputNamesAndGUIDs, winDsHostApi->allocations );
if( result != paNoError )
goto error;
deviceNamesAndGUIDs.winDsHostApi = winDsHostApi;
/* DSound - enumerate devices to count them and to gather their GUIDs and device names */
paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&deviceNamesAndGUIDs.inputNamesAndGUIDs );
if( deviceNamesAndGUIDs.inputNamesAndGUIDs.enumerationError != paNoError )
{
result = deviceNamesAndGUIDs.inputNamesAndGUIDs.enumerationError;
goto error;
}
paWinDsDSoundEntryPoints.DirectSoundEnumerateA( (LPDSENUMCALLBACK)CollectGUIDsProc, (void *)&deviceNamesAndGUIDs.outputNamesAndGUIDs );
if( deviceNamesAndGUIDs.outputNamesAndGUIDs.enumerationError != paNoError )
{
result = deviceNamesAndGUIDs.outputNamesAndGUIDs.enumerationError;
goto error;
}
maximumNewDeviceCount = deviceNamesAndGUIDs.inputNamesAndGUIDs.count +
deviceNamesAndGUIDs.outputNamesAndGUIDs.count;
#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
if( maximumNewDeviceCount > 0 )
{
FindDevicePnpInterfaces( &deviceNamesAndGUIDs );
}
#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
if( maximumNewDeviceCount > 0 )
{
/* Allocate the out param for all the info we need */
outArgument = (PaWinDsScanDeviceInfosResults *) PaUtil_GroupAllocateMemory(
winDsHostApi->allocations, sizeof(PaWinDsScanDeviceInfosResults) );
if( !outArgument )
{
result = paInsufficientMemory;
goto error;
}
/* allocate array for pointers to PaDeviceInfo structs */
outArgument->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
winDsHostApi->allocations, sizeof(PaDeviceInfo*) * maximumNewDeviceCount );
if( !outArgument->deviceInfos )
{
result = paInsufficientMemory;
goto error;
}
/* allocate all PaDeviceInfo structs in a contiguous block */
deviceInfoArray = (PaWinDsDeviceInfo*)PaUtil_GroupAllocateMemory(
winDsHostApi->allocations, sizeof(PaWinDsDeviceInfo) * maximumNewDeviceCount );
if( !deviceInfoArray )
{
result = paInsufficientMemory;
goto error;
}
for( i = 0 ; i < maximumNewDeviceCount; ++i )
{
PaDeviceInfo *deviceInfo = &deviceInfoArray[i].inheritedDeviceInfo;
deviceInfo->structVersion = 2;
deviceInfo->hostApi = hostApiIndex;
deviceInfo->name = 0;
outArgument->deviceInfos[ i ] = deviceInfo;
}
for( i = 0 ; i < deviceNamesAndGUIDs.inputNamesAndGUIDs.count ; ++i )
{
PaWinDsDeviceInfo *winDsDeviceInfo = (PaWinDsDeviceInfo*)outArgument->deviceInfos[*newDeviceCount];
result = AddInputDeviceInfoFromDirectSoundCapture( winDsDeviceInfo,
deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].name,
deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].lpGUID,
deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].pnpInterface );
if( result == paNoError )
{
if( deviceNamesAndGUIDs.inputNamesAndGUIDs.items[i].lpGUID == NULL )
outArgument->defaultInputDevice = *newDeviceCount;
(*newDeviceCount)++;
}
/* ignore error results here and just skip the device */
}
for( i = 0 ; i < deviceNamesAndGUIDs.outputNamesAndGUIDs.count ; ++i )
{
PaWinDsDeviceInfo *winDsDeviceInfo = (PaWinDsDeviceInfo*)outArgument->deviceInfos[*newDeviceCount];
result = AddOutputDeviceInfoFromDirectSound( winDsDeviceInfo,
deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].name,
deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].lpGUID,
deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].pnpInterface );
if( result == paNoError )
{
if( deviceNamesAndGUIDs.outputNamesAndGUIDs.items[i].lpGUID == NULL )
outArgument->defaultOutputDevice = *newDeviceCount;
(*newDeviceCount)++;
}
/* ignore error results here and just skip the device */
}
}
result = TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.inputNamesAndGUIDs );
if( result != paNoError )
goto error;
result = TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.outputNamesAndGUIDs );
if( result != paNoError )
goto error;
*scanResults = outArgument;
return result;
error:
TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.inputNamesAndGUIDs );
TerminateDSDeviceNameAndGUIDVector( &deviceNamesAndGUIDs.outputNamesAndGUIDs );
if( outArgument )
{
if( outArgument->deviceInfos )
{
if( outArgument->deviceInfos[0] )
{
PaUtil_GroupFreeMemory( winDsHostApi->allocations, outArgument->deviceInfos[0] );
}
PaUtil_GroupFreeMemory( winDsHostApi->allocations, outArgument->deviceInfos );
}
}
return result;
}
static PaError CommitDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, PaHostApiIndex index, void *scanResults, int deviceCount )
{
PaWinDsHostApiRepresentation *winDsHostApi = (PaWinDsHostApiRepresentation*)hostApi;
PaError result = paNoError;
int i = 0;
hostApi->info.deviceCount = 0;
hostApi->info.defaultInputDevice = paNoDevice;
hostApi->info.defaultOutputDevice = paNoDevice;
/* Free any old memory which might be in the device info */
if( hostApi->deviceInfos )
{
PaUtil_GroupFreeMemory( winDsHostApi->allocations, hostApi->deviceInfos[0] );
PaUtil_GroupFreeMemory( winDsHostApi->allocations, hostApi->deviceInfos );
hostApi->deviceInfos = NULL;
}
if( scanResults != NULL )
{
PaWinDsScanDeviceInfosResults *scanDeviceInfosResults = ( PaWinDsScanDeviceInfosResults * ) 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( winDsHostApi->allocations, scanDeviceInfosResults );
}
return result;
}
static PaError DisposeDeviceInfos( struct PaUtilHostApiRepresentation *hostApi, void *scanResults, int deviceCount )
{
PaWinDsHostApiRepresentation *winDsHostApi = (PaWinDsHostApiRepresentation*)hostApi;
if( scanResults != NULL )
{
PaWinDsScanDeviceInfosResults *scanDeviceInfosResults = ( PaWinDsScanDeviceInfosResults * ) scanResults;
if( scanDeviceInfosResults->deviceInfos )
{
PaUtil_GroupFreeMemory( winDsHostApi->allocations, scanDeviceInfosResults->deviceInfos[0] ); /* all device info structs are allocated in a block so we can destroy them here */
PaUtil_GroupFreeMemory( winDsHostApi->allocations, scanDeviceInfosResults->deviceInfos );
}
PaUtil_GroupFreeMemory( winDsHostApi->allocations, scanDeviceInfosResults );
}
return paNoError;
}
/************************************************************************* /*************************************************************************
** Determine minimum number of buffers required for this host based ** Determine minimum number of buffers required for this host based

View file

@ -1572,20 +1572,20 @@ static void LogWAVEFORMATEXTENSIBLE(const WAVEFORMATEXTENSIBLE *in)
{ {
case WAVE_FORMAT_EXTENSIBLE: { case WAVE_FORMAT_EXTENSIBLE: {
PRINT(("wFormatTag =WAVE_FORMAT_EXTENSIBLE\n")); PRINT(("wFormatTag=WAVE_FORMAT_EXTENSIBLE\n"));
if (IsEqualGUID(&in->SubFormat, &pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) if (IsEqualGUID(&in->SubFormat, &pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
{ {
PRINT(("SubFormat =KSDATAFORMAT_SUBTYPE_IEEE_FLOAT\n")); PRINT(("SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT\n"));
} }
else else
if (IsEqualGUID(&in->SubFormat, &pa_KSDATAFORMAT_SUBTYPE_PCM)) if (IsEqualGUID(&in->SubFormat, &pa_KSDATAFORMAT_SUBTYPE_PCM))
{ {
PRINT(("SubFormat =KSDATAFORMAT_SUBTYPE_PCM\n")); PRINT(("SubFormat=KSDATAFORMAT_SUBTYPE_PCM\n"));
} }
else else
{ {
PRINT(("SubFormat =CUSTOM GUID{%d:%d:%d:%d%d%d%d%d%d%d%d}\n", PRINT(("SubFormat=CUSTOM GUID{%d:%d:%d:%d%d%d%d%d%d%d%d}\n",
in->SubFormat.Data1, in->SubFormat.Data1,
in->SubFormat.Data2, in->SubFormat.Data2,
in->SubFormat.Data3, in->SubFormat.Data3,
@ -1598,13 +1598,13 @@ static void LogWAVEFORMATEXTENSIBLE(const WAVEFORMATEXTENSIBLE *in)
(int)in->SubFormat.Data4[6], (int)in->SubFormat.Data4[6],
(int)in->SubFormat.Data4[7])); (int)in->SubFormat.Data4[7]));
} }
PRINT(("Samples.wValidBitsPerSample =%d\n", in->Samples.wValidBitsPerSample)); PRINT(("Samples.wValidBitsPerSample=%d\n", in->Samples.wValidBitsPerSample));
PRINT(("dwChannelMask =0x%X\n",in->dwChannelMask)); PRINT(("dwChannelMask =0x%X\n",in->dwChannelMask));
break; } break; }
case WAVE_FORMAT_PCM: PRINT(("wFormatTag =WAVE_FORMAT_PCM\n")); break; case WAVE_FORMAT_PCM: PRINT(("wFormatTag=WAVE_FORMAT_PCM\n")); break;
case WAVE_FORMAT_IEEE_FLOAT: PRINT(("wFormatTag =WAVE_FORMAT_IEEE_FLOAT\n")); break; case WAVE_FORMAT_IEEE_FLOAT: PRINT(("wFormatTag=WAVE_FORMAT_IEEE_FLOAT\n")); break;
default: default:
PRINT(("wFormatTag =UNKNOWN(%d)\n",old->wFormatTag)); break; PRINT(("wFormatTag =UNKNOWN(%d)\n",old->wFormatTag)); break;
} }
@ -1689,13 +1689,13 @@ static PaError MakeWaveFormatFromParams(WAVEFORMATEXTENSIBLE *wavex, const PaStr
old->nBlockAlign = (old->nChannels * (old->wBitsPerSample/8)); old->nBlockAlign = (old->nChannels * (old->wBitsPerSample/8));
old->nAvgBytesPerSec = (old->nSamplesPerSec * old->nBlockAlign); old->nAvgBytesPerSec = (old->nSamplesPerSec * old->nBlockAlign);
// WAVEFORMATEX //WAVEFORMATEX
if ((params->channelCount <= 2) && ((bitsPerSample == 16) || (bitsPerSample == 8))) if ((params->channelCount <= 2) && ((bitsPerSample == 16) || (bitsPerSample == 8)))
{ {
old->cbSize = 0; old->cbSize = 0;
old->wFormatTag = WAVE_FORMAT_PCM; old->wFormatTag = WAVE_FORMAT_PCM;
} }
// WAVEFORMATEXTENSIBLE //WAVEFORMATEXTENSIBLE
else else
{ {
old->wFormatTag = WAVE_FORMAT_EXTENSIBLE; old->wFormatTag = WAVE_FORMAT_EXTENSIBLE;

View file

@ -1,5 +1,5 @@
/* /*
* $Id$ * $Id: pa_win_wmme.c 1663 2011-05-01 13:21:43Z rossb $
* pa_win_wmme.c * pa_win_wmme.c
* Implementation of PortAudio for Windows MultiMedia Extensions (WMME) * Implementation of PortAudio for Windows MultiMedia Extensions (WMME)
* *
@ -1087,6 +1087,9 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
(*hostApi)->Terminate = Terminate; (*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream; (*hostApi)->OpenStream = OpenStream;
(*hostApi)->IsFormatSupported = IsFormatSupported; (*hostApi)->IsFormatSupported = IsFormatSupported;
(*hostApi)->ScanDeviceInfos = 0;
(*hostApi)->CommitDeviceInfos = 0;
(*hostApi)->DisposeDeviceInfos = 0;
PaUtil_InitializeStreamInterface( &winMmeHostApi->callbackStreamInterface, CloseStream, StartStream, PaUtil_InitializeStreamInterface( &winMmeHostApi->callbackStreamInterface, CloseStream, StartStream,
StopStream, AbortStream, IsStreamStopped, IsStreamActive, StopStream, AbortStream, IsStreamStopped, IsStreamActive,

315
src/os/win/pa_win_hotplug.c Normal file
View file

@ -0,0 +1,315 @@
#include "pa_util.h"
#include "pa_debugprint.h"
#include "pa_allocation.h"
#include "pa_win_wdmks_utils.h"
#include <windows.h>
#include <dbt.h>
#include <process.h>
#include <assert.h>
#include <ks.h>
#include <ksmedia.h>
#include <setupapi.h>
#include <stdio.h>
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */
#pragma comment( lib, "setupapi.lib" )
#endif
/* 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*);
/* use CreateThread for CYGWIN/Windows Mobile, _beginthreadex for all others */
#if !defined(__CYGWIN__) && !defined(_WIN32_WCE)
#define CREATE_THREAD_FUNCTION (HANDLE)_beginthreadex
#define PA_THREAD_FUNC static unsigned WINAPI
#else
#define CREATE_THREAD_FUNCTION CreateThread
#define PA_THREAD_FUNC static DWORD WINAPI
#endif
typedef struct PaHotPlugDeviceInfo
{
wchar_t name[MAX_PATH];
struct PaHotPlugDeviceInfo* next;
} PaHotPlugDeviceInfo;
typedef struct PaHotPlugDeviceEventHandlerInfo
{
HANDLE hWnd;
HANDLE hMsgThread;
HANDLE hNotify;
CRITICAL_SECTION lock;
PaUtilAllocationGroup* cacheAllocGroup;
PaHotPlugDeviceInfo* cache;
} PaHotPlugDeviceEventHandlerInfo;
static BOOL RemoveDeviceFromCache(PaHotPlugDeviceEventHandlerInfo* pInfo, const wchar_t* name)
{
if (pInfo->cache != NULL)
{
PaHotPlugDeviceInfo* lastEntry = 0;
PaHotPlugDeviceInfo* entry = pInfo->cache;
while (entry != NULL)
{
if (_wcsicmp(entry->name, name) == 0)
{
if (lastEntry)
{
lastEntry->next = entry->next;
}
else
{
pInfo->cache = NULL;
}
PaUtil_GroupFreeMemory(pInfo->cacheAllocGroup, entry);
return TRUE;
}
lastEntry = entry;
entry = entry->next;
}
}
return FALSE;
}
static void InsertDeviceIntoCache(PaHotPlugDeviceEventHandlerInfo* pInfo, const wchar_t* name)
{
PaHotPlugDeviceInfo** ppEntry = NULL;
/* Remove it first (if possible) so we don't accidentally get duplicates */
RemoveDeviceFromCache(pInfo, name);
if (pInfo->cache == NULL)
{
ppEntry = &pInfo->cache;
}
else
{
PaHotPlugDeviceInfo* entry = pInfo->cache;
while (entry->next != NULL)
{
entry = entry->next;
}
ppEntry = &entry->next;
}
*ppEntry = (PaHotPlugDeviceInfo*)PaUtil_GroupAllocateMemory(pInfo->cacheAllocGroup, sizeof(PaHotPlugDeviceInfo));
wcsncpy((*ppEntry)->name, name, MAX_PATH-1);
(*ppEntry)->next = NULL;
}
static BOOL IsDeviceAudio(const wchar_t* deviceName)
{
int channelCnt = 0;
channelCnt += PaWin_WDMKS_QueryFilterMaximumChannelCount((void*)deviceName, 1);
channelCnt += PaWin_WDMKS_QueryFilterMaximumChannelCount((void*)deviceName, 0);
return (channelCnt > 0);
}
static void PopulateCacheWithAvailableAudioDevices(PaHotPlugDeviceEventHandlerInfo* pInfo)
{
HDEVINFO handle = NULL;
const int sizeInterface = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + (MAX_PATH * sizeof(WCHAR));
SP_DEVICE_INTERFACE_DETAIL_DATA_W* devInterfaceDetails = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)PaUtil_AllocateMemory(sizeInterface);
if (devInterfaceDetails)
{
devInterfaceDetails->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
/* Open a handle to search for devices (filters) */
handle = SetupDiGetClassDevsW(&KSCATEGORY_AUDIO,NULL,NULL,DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if( handle != NULL )
{
int device;
/* Iterate through the devices */
for( device = 0;;device++ )
{
SP_DEVICE_INTERFACE_DATA interfaceData;
SP_DEVINFO_DATA devInfoData;
int noError;
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
interfaceData.Reserved = 0;
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
devInfoData.Reserved = 0;
noError = SetupDiEnumDeviceInterfaces(handle,NULL,&KSCATEGORY_AUDIO,device,&interfaceData);
if( !noError )
break; /* No more devices */
noError = SetupDiGetDeviceInterfaceDetailW(handle,&interfaceData,devInterfaceDetails,sizeInterface,NULL,&devInfoData);
if( noError )
{
if (IsDeviceAudio(devInterfaceDetails->DevicePath))
{
PA_DEBUG(("Hotplug cache populated with: '%S'\n", devInterfaceDetails->DevicePath));
InsertDeviceIntoCache(pInfo, devInterfaceDetails->DevicePath);
}
}
}
SetupDiDestroyDeviceInfoList(handle);
}
PaUtil_FreeMemory(devInterfaceDetails);
}
}
static LRESULT CALLBACK PaMsgWinProcW(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
PaHotPlugDeviceEventHandlerInfo* pInfo = (PaHotPlugDeviceEventHandlerInfo*)( GetWindowLongPtr(hWnd, GWLP_USERDATA) );
switch(msg)
{
case WM_DEVICECHANGE:
switch(wParam)
{
case DBT_DEVICEARRIVAL:
{
PDEV_BROADCAST_DEVICEINTERFACE_W ptr = (PDEV_BROADCAST_DEVICEINTERFACE_W)lParam;
if (ptr->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
break;
if (!IsEqualGUID(&ptr->dbcc_classguid, &KSCATEGORY_AUDIO))
break;
if (IsDeviceAudio(ptr->dbcc_name))
{
PA_DEBUG(("Device inserted : %S\n", ptr->dbcc_name));
InsertDeviceIntoCache(pInfo, ptr->dbcc_name);
PaUtil_DevicesChanged(1, ptr->dbcc_name);
}
}
break;
case DBT_DEVICEREMOVECOMPLETE:
{
PDEV_BROADCAST_DEVICEINTERFACE_W ptr = (PDEV_BROADCAST_DEVICEINTERFACE_W)lParam;
if (ptr->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
break;
if (!IsEqualGUID(&ptr->dbcc_classguid, &KSCATEGORY_AUDIO))
break;
if (RemoveDeviceFromCache(pInfo, ptr->dbcc_name))
{
PA_DEBUG(("Device removed : %S\n", ptr->dbcc_name));
PaUtil_DevicesChanged(2, ptr->dbcc_name);
}
}
break;
default:
break;
}
break;
}
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
PA_THREAD_FUNC PaRunMessageLoop(void* ptr)
{
PaHotPlugDeviceEventHandlerInfo* pInfo = (PaHotPlugDeviceEventHandlerInfo*)ptr;
WNDCLASSW wnd = { 0 };
HMODULE hInstance = GetModuleHandleW(NULL);
wnd.lpfnWndProc = PaMsgWinProcW;
wnd.hInstance = hInstance;
wnd.lpszClassName = L"{1E0D4F5A-B31F-4dcc-AE3C-4F30A47BD521}"; /* Using a GUID as class name */
pInfo->hWnd = CreateWindowW((LPCWSTR)MAKEINTATOM(RegisterClassW(&wnd)), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL);
if (pInfo->hWnd)
{
DEV_BROADCAST_DEVICEINTERFACE_W NotificationFilter = { sizeof(DEV_BROADCAST_DEVICEINTERFACE_W) };
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
#ifndef DEVICE_NOTIFY_ALL_INTERFACE_CLASSES
#define DEVICE_NOTIFY_ALL_INTERFACE_CLASSES 0x00000004
#endif
pInfo->hNotify = RegisterDeviceNotificationW(
pInfo->hWnd,
&NotificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE|DEVICE_NOTIFY_ALL_INTERFACE_CLASSES
);
assert(pInfo->hNotify);
SetWindowLongPtr(pInfo->hWnd, GWLP_USERDATA, (LONG_PTR)pInfo);
if (pInfo->hNotify)
{
MSG msg;
BOOL result;
while((result = GetMessageW(&msg, pInfo->hWnd, 0, 0)) != 0)
{
if (result == -1)
{
break;
}
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
UnregisterDeviceNotification(pInfo->hNotify);
pInfo->hNotify = 0;
}
DestroyWindow(pInfo->hWnd);
pInfo->hWnd = 0;
}
return 0;
}
static PaHotPlugDeviceEventHandlerInfo* s_handler = 0;
void PaUtil_InitializeHotPlug()
{
if (s_handler == 0)
{
s_handler = (PaHotPlugDeviceEventHandlerInfo*)PaUtil_AllocateMemory(sizeof(PaHotPlugDeviceEventHandlerInfo));
if (s_handler)
{
s_handler->cacheAllocGroup = PaUtil_CreateAllocationGroup();
InitializeCriticalSection(&s_handler->lock);
PopulateCacheWithAvailableAudioDevices(s_handler);
/* Start message thread */
s_handler->hMsgThread = CREATE_THREAD_FUNCTION(NULL, 0, PaRunMessageLoop, s_handler, 0, NULL);
assert(s_handler->hMsgThread != 0);
}
}
}
void PaUtil_TerminateHotPlug()
{
if (s_handler != 0)
{
if (s_handler->hWnd)
{
PostMessage(s_handler->hWnd, WM_QUIT, 0, 0);
if (WaitForSingleObject(s_handler->hMsgThread, 1000) == WAIT_TIMEOUT)
{
TerminateThread(s_handler->hMsgThread, -1);
}
}
DeleteCriticalSection(&s_handler->lock);
PaUtil_FreeAllAllocations( s_handler->cacheAllocGroup );
PaUtil_DestroyAllocationGroup( s_handler->cacheAllocGroup );
PaUtil_FreeMemory( s_handler );
s_handler = 0;
}
}
void PaUtil_LockHotPlug()
{
EnterCriticalSection(&s_handler->lock);
}
void PaUtil_UnlockHotPlug()
{
LeaveCriticalSection(&s_handler->lock);
}

View file

@ -56,24 +56,24 @@
#include "pa_win_wdmks_utils.h" #include "pa_win_wdmks_utils.h"
#if !defined(PA_WDMKS_NO_KSGUID_LIB) && !defined(PAWIN_WDMKS_NO_KSGUID_LIB) #if !defined(PA_WDMKS_NO_KSGUID_LIB) && !defined(PAWIN_WDMKS_NO_KSGUID_LIB)
#if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */ #if (defined(WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1200))) /* MSC version 6 and above */
#pragma comment( lib, "ksguid.lib" ) #pragma comment( lib, "ksguid.lib" )
#endif #endif
#define pa_KSDATAFORMAT_TYPE_AUDIO KSDATAFORMAT_TYPE_AUDIO #define pa_KSDATAFORMAT_TYPE_AUDIO KSDATAFORMAT_TYPE_AUDIO
#define pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT KSDATAFORMAT_SUBTYPE_IEEE_FLOAT #define pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
#define pa_KSDATAFORMAT_SUBTYPE_PCM KSDATAFORMAT_SUBTYPE_PCM #define pa_KSDATAFORMAT_SUBTYPE_PCM KSDATAFORMAT_SUBTYPE_PCM
#define pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX KSDATAFORMAT_SUBTYPE_WAVEFORMATEX #define pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX KSDATAFORMAT_SUBTYPE_WAVEFORMATEX
#define pa_KSMEDIUMSETID_Standard KSMEDIUMSETID_Standard #define pa_KSMEDIUMSETID_Standard KSMEDIUMSETID_Standard
#define pa_KSINTERFACESETID_Standard KSINTERFACESETID_Standard #define pa_KSINTERFACESETID_Standard KSINTERFACESETID_Standard
#define pa_KSPROPSETID_Pin KSPROPSETID_Pin #define pa_KSPROPSETID_Pin KSPROPSETID_Pin
#else #else
static const GUID pa_KSDATAFORMAT_TYPE_AUDIO = { STATIC_KSDATAFORMAT_TYPE_AUDIO }; static const GUID pa_KSDATAFORMAT_TYPE_AUDIO = { STATIC_KSDATAFORMAT_TYPE_AUDIO };
static const GUID pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT }; static const GUID pa_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { STATIC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT };
static const GUID pa_KSDATAFORMAT_SUBTYPE_PCM = { STATIC_KSDATAFORMAT_SUBTYPE_PCM }; static const GUID pa_KSDATAFORMAT_SUBTYPE_PCM = { STATIC_KSDATAFORMAT_SUBTYPE_PCM };
static const GUID pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX = { STATIC_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX }; static const GUID pa_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX = { STATIC_KSDATAFORMAT_SUBTYPE_WAVEFORMATEX };
static const GUID pa_KSMEDIUMSETID_Standard = { STATIC_KSMEDIUMSETID_Standard }; static const GUID pa_KSMEDIUMSETID_Standard = { STATIC_KSMEDIUMSETID_Standard };
static const GUID pa_KSINTERFACESETID_Standard = { STATIC_KSINTERFACESETID_Standard }; static const GUID pa_KSINTERFACESETID_Standard = { STATIC_KSINTERFACESETID_Standard };
static const GUID pa_KSPROPSETID_Pin = { STATIC_KSPROPSETID_Pin }; static const GUID pa_KSPROPSETID_Pin = { STATIC_KSPROPSETID_Pin };
#endif #endif

View file

@ -9,7 +9,7 @@
@author Phil Burk <philburk@softsynth.com> @author Phil Burk <philburk@softsynth.com>
*/ */
/* /*
* $Id$ * $Id: patest_leftright.c 1661 2011-04-28 18:54:46Z rob_bielik $
* *
* This program uses the PortAudio Portable Audio Library. * This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com * For more information see: http://www.portaudio.com

View file

@ -6,7 +6,7 @@
@author Phil Burk <philburk@softsynth.com> @author Phil Burk <philburk@softsynth.com>
*/ */
/* /*
* $Id$ * $Id: patest_out_underflow.c 1661 2011-04-28 18:54:46Z rob_bielik $
* *
* This program uses the PortAudio Portable Audio Library. * This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com * For more information see: http://www.portaudio.com

View file

@ -89,7 +89,7 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer,
timeInfo->currentTime, timeInfo->currentTime,
timeInfo->outputBufferDacTime ); timeInfo->outputBufferDacTime );
printf( "getStreamTime() returns: %g\n", Pa_GetStreamTime(data->stream) - data->start ); printf( "getStreamTime() returns: %g\n", Pa_GetStreamTime(data->stream)-data->start );
for( i=0; i<framesPerBuffer; i++ ) for( i=0; i<framesPerBuffer; i++ )
{ {

View file

@ -4,7 +4,7 @@
@author Phil Burk <philburk@softsynth.com> @author Phil Burk <philburk@softsynth.com>
*/ */
/* /*
* $Id$ * $Id: patest_two_rates.c 1661 2011-04-28 18:54:46Z rob_bielik $
* *
* Author: Phil Burk http://www.softsynth.com * Author: Phil Burk http://www.softsynth.com
* *
@ -64,9 +64,9 @@ typedef struct
} paTestData; } paTestData;
/* This routine will be called by the PortAudio engine when audio is needed. /* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything ** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free(). ** that could mess up the system like calling malloc() or free().
*/ */
static int patestCallback( const void *inputBuffer, void *outputBuffer, static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo, const PaStreamCallbackTimeInfo* timeInfo,

View file

@ -0,0 +1,48 @@
#include <stdio.h>
#include <assert.h>
#include "portaudio.h"
void printDevices()
{
int deviceCount = Pa_GetDeviceCount();
int i;
for( i=0; i < deviceCount; ++i ){
const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i);
const PaHostApiInfo *hostApiInfo = Pa_GetHostApiInfo( deviceInfo->hostApi );
assert( deviceInfo != 0 );
printf( "%d %s (%s)\n", i, deviceInfo->name, hostApiInfo->name );
}
}
static void devicesChangedCallback(void* p)
{
(void)p;
printf( "Portaudio device list have changed!\n" );
}
int main(int argc, char* argv[])
{
Pa_Initialize();
Pa_SetDevicesChangedCallback(NULL, devicesChangedCallback);
for(;;){
printDevices();
printf( "press [enter] to update the device list. or q + [enter] to quit.\n" );
if( getchar() == 'q' )
break;
Pa_UpdateAvailableDeviceList();
}
Pa_Terminate();
return 0;
}