winepulse: Add initial stub for pulseaudio support.
Includes API compatibility patch by Juergen Tretthahn <orson@orson.at>. Synchronous static data initialization by Andrew Eikum <aeikum@codeweavers.com>. Signed-off-by: Andrew Eikum <aeikum@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
e4bc220802
commit
3fe0c08992
|
@ -654,6 +654,8 @@ OSS4_CFLAGS
|
||||||
ALSA_LIBS
|
ALSA_LIBS
|
||||||
GSTREAMER_LIBS
|
GSTREAMER_LIBS
|
||||||
GSTREAMER_CFLAGS
|
GSTREAMER_CFLAGS
|
||||||
|
PULSE_CFLAGS
|
||||||
|
PULSE_LIBS
|
||||||
GETTEXTPO_LIBS
|
GETTEXTPO_LIBS
|
||||||
Z_LIBS
|
Z_LIBS
|
||||||
FREETYPE_LIBS
|
FREETYPE_LIBS
|
||||||
|
@ -830,6 +832,7 @@ with_oss
|
||||||
with_pcap
|
with_pcap
|
||||||
with_png
|
with_png
|
||||||
with_pthread
|
with_pthread
|
||||||
|
with_pulse
|
||||||
with_sane
|
with_sane
|
||||||
with_tiff
|
with_tiff
|
||||||
with_v4l
|
with_v4l
|
||||||
|
@ -1341,6 +1344,7 @@ enable_winemapi
|
||||||
enable_winemp3_acm
|
enable_winemp3_acm
|
||||||
enable_wineoss_drv
|
enable_wineoss_drv
|
||||||
enable_wineps_drv
|
enable_wineps_drv
|
||||||
|
enable_winepulse_drv
|
||||||
enable_wineqtdecoder
|
enable_wineqtdecoder
|
||||||
enable_winex11_drv
|
enable_winex11_drv
|
||||||
enable_wing32
|
enable_wing32
|
||||||
|
@ -1523,6 +1527,8 @@ LCMS2_CFLAGS
|
||||||
LCMS2_LIBS
|
LCMS2_LIBS
|
||||||
FREETYPE_CFLAGS
|
FREETYPE_CFLAGS
|
||||||
FREETYPE_LIBS
|
FREETYPE_LIBS
|
||||||
|
PULSE_CFLAGS
|
||||||
|
PULSE_LIBS
|
||||||
GSTREAMER_CFLAGS
|
GSTREAMER_CFLAGS
|
||||||
GSTREAMER_LIBS
|
GSTREAMER_LIBS
|
||||||
CAPI20_CFLAGS
|
CAPI20_CFLAGS
|
||||||
|
@ -2205,6 +2211,7 @@ Optional Packages:
|
||||||
--without-pcap do not use the Packet Capture library
|
--without-pcap do not use the Packet Capture library
|
||||||
--without-png do not use PNG
|
--without-png do not use PNG
|
||||||
--without-pthread do not use the pthread library
|
--without-pthread do not use the pthread library
|
||||||
|
--without-pulse do not use PulseAudio sound support
|
||||||
--without-sane do not use SANE (scanner support)
|
--without-sane do not use SANE (scanner support)
|
||||||
--without-tiff do not use TIFF
|
--without-tiff do not use TIFF
|
||||||
--without-v4l do not use v4l1 (v4l support)
|
--without-v4l do not use v4l1 (v4l support)
|
||||||
|
@ -2265,6 +2272,9 @@ Some influential environment variables:
|
||||||
C compiler flags for freetype2, overriding pkg-config
|
C compiler flags for freetype2, overriding pkg-config
|
||||||
FREETYPE_LIBS
|
FREETYPE_LIBS
|
||||||
Linker flags for freetype2, overriding pkg-config
|
Linker flags for freetype2, overriding pkg-config
|
||||||
|
PULSE_CFLAGS
|
||||||
|
C compiler flags for libpulse, overriding pkg-config
|
||||||
|
PULSE_LIBS Linker flags for libpulse, overriding pkg-config
|
||||||
GSTREAMER_CFLAGS
|
GSTREAMER_CFLAGS
|
||||||
C compiler flags for gstreamer-app-0.10, overriding pkg-config
|
C compiler flags for gstreamer-app-0.10, overriding pkg-config
|
||||||
GSTREAMER_LIBS
|
GSTREAMER_LIBS
|
||||||
|
@ -3452,6 +3462,12 @@ if test "${with_pthread+set}" = set; then :
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Check whether --with-pulse was given.
|
||||||
|
if test "${with_pulse+set}" = set; then :
|
||||||
|
withval=$with_pulse;
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Check whether --with-sane was given.
|
# Check whether --with-sane was given.
|
||||||
if test "${with_sane+set}" = set; then :
|
if test "${with_sane+set}" = set; then :
|
||||||
withval=$with_sane;
|
withval=$with_sane;
|
||||||
|
@ -12576,6 +12592,94 @@ esac
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
PULSE_LIBS=""
|
||||||
|
|
||||||
|
PULSE_CFLAGS=""
|
||||||
|
|
||||||
|
if test "x$with_pulse" != "xno";
|
||||||
|
then
|
||||||
|
if ${PULSE_CFLAGS:+false} :; then :
|
||||||
|
if ${PKG_CONFIG+:} false; then :
|
||||||
|
PULSE_CFLAGS=`$PKG_CONFIG --cflags libpulse 2>/dev/null`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ${PULSE_LIBS:+false} :; then :
|
||||||
|
if ${PKG_CONFIG+:} false; then :
|
||||||
|
PULSE_LIBS=`$PKG_CONFIG --libs libpulse 2>/dev/null`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
$as_echo "$as_me:${as_lineno-$LINENO}: libpulse cflags: $PULSE_CFLAGS" >&5
|
||||||
|
$as_echo "$as_me:${as_lineno-$LINENO}: libpulse libs: $PULSE_LIBS" >&5
|
||||||
|
ac_save_CPPFLAGS=$CPPFLAGS
|
||||||
|
CPPFLAGS="$CPPFLAGS $PULSE_CFLAGS"
|
||||||
|
for ac_header in pulse/pulseaudio.h
|
||||||
|
do :
|
||||||
|
ac_fn_c_check_header_mongrel "$LINENO" "pulse/pulseaudio.h" "ac_cv_header_pulse_pulseaudio_h" "$ac_includes_default"
|
||||||
|
if test "x$ac_cv_header_pulse_pulseaudio_h" = xyes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define HAVE_PULSE_PULSEAUDIO_H 1
|
||||||
|
_ACEOF
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pa_stream_is_corked in -lpulse" >&5
|
||||||
|
$as_echo_n "checking for pa_stream_is_corked in -lpulse... " >&6; }
|
||||||
|
if ${ac_cv_lib_pulse_pa_stream_is_corked+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
ac_check_lib_save_LIBS=$LIBS
|
||||||
|
LIBS="-lpulse $PULSE_LIBS $LIBS"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
/* Override any GCC internal prototype to avoid an error.
|
||||||
|
Use char because int might match the return type of a GCC
|
||||||
|
builtin and then its argument prototype would still apply. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
char pa_stream_is_corked ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return pa_stream_is_corked ();
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
ac_cv_lib_pulse_pa_stream_is_corked=yes
|
||||||
|
else
|
||||||
|
ac_cv_lib_pulse_pa_stream_is_corked=no
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
LIBS=$ac_check_lib_save_LIBS
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pulse_pa_stream_is_corked" >&5
|
||||||
|
$as_echo "$ac_cv_lib_pulse_pa_stream_is_corked" >&6; }
|
||||||
|
if test "x$ac_cv_lib_pulse_pa_stream_is_corked" = xyes; then :
|
||||||
|
:
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
CPPFLAGS=$ac_save_CPPFLAGS
|
||||||
|
test -z "$PULSE_CFLAGS" || PULSE_CFLAGS=`echo " $PULSE_CFLAGS" | sed 's/ -I\([^/]\)/ -I\$(top_builddir)\/\1/g'`
|
||||||
|
test -z "$PULSE_LIBS" || PULSE_LIBS=`echo " $PULSE_LIBS" | sed 's/ -L\([^/]\)/ -L\$(top_builddir)\/\1/g'`
|
||||||
|
|
||||||
|
fi
|
||||||
|
if test "$ac_cv_lib_pulse_pa_stream_is_corked" != "yes"; then :
|
||||||
|
case "x$with_pulse" in
|
||||||
|
x) as_fn_append wine_notices "|libpulse ${notice_platform}development files not found or too old, Pulse won't be supported." ;;
|
||||||
|
xno) ;;
|
||||||
|
*) as_fn_error $? "libpulse ${notice_platform}development files not found or too old, Pulse won't be supported.
|
||||||
|
This is an error since --with-pulse was requested." "$LINENO" 5 ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
if test "x$with_gstreamer" != "xno"
|
if test "x$with_gstreamer" != "xno"
|
||||||
then
|
then
|
||||||
if ${GSTREAMER_CFLAGS:+false} :; then :
|
if ${GSTREAMER_CFLAGS:+false} :; then :
|
||||||
|
@ -13922,12 +14026,13 @@ fi
|
||||||
|
|
||||||
test -n "$ALSA_LIBS" || enable_winealsa_drv=${enable_winealsa_drv:-no}
|
test -n "$ALSA_LIBS" || enable_winealsa_drv=${enable_winealsa_drv:-no}
|
||||||
test -n "$COREAUDIO_LIBS" || enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no}
|
test -n "$COREAUDIO_LIBS" || enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no}
|
||||||
|
test -n "$PULSE_LIBS" || enable_winepulse_drv=${enable_winepulse_drv:-no}
|
||||||
test "x$ac_cv_member_oss_sysinfo_numaudioengines" = xyes || enable_wineoss_drv=${enable_wineoss_drv:-no}
|
test "x$ac_cv_member_oss_sysinfo_numaudioengines" = xyes || enable_wineoss_drv=${enable_wineoss_drv:-no}
|
||||||
test "$ac_cv_header_linux_joystick_h" = "yes" -o "$ac_cv_header_IOKit_hid_IOHIDLib_h" = "yes" || enable_winejoystick_drv=${enable_winejoystick_drv:-no}
|
test "$ac_cv_header_linux_joystick_h" = "yes" -o "$ac_cv_header_IOKit_hid_IOHIDLib_h" = "yes" || enable_winejoystick_drv=${enable_winejoystick_drv:-no}
|
||||||
|
|
||||||
if test "x$ALSA_LIBS$COREAUDIO_LIBS" = "x" -a \
|
if test "x$ALSA_LIBS$COREAUDIO_LIBS$PULSE_LIBS" = "x" -a \
|
||||||
"x$ac_cv_member_oss_sysinfo_numaudioengines" != xyes -a \
|
"x$ac_cv_member_oss_sysinfo_numaudioengines" != xyes -a \
|
||||||
"x$with_alsa$with_coreaudio$with_oss" != xnonono
|
"x$with_alsa$with_coreaudio$with_oss$with_pulse" != xnononono
|
||||||
then
|
then
|
||||||
as_fn_append wine_warnings "|No sound system was found. Windows applications will be silent."
|
as_fn_append wine_warnings "|No sound system was found. Windows applications will be silent."
|
||||||
fi
|
fi
|
||||||
|
@ -17177,6 +17282,8 @@ FREETYPE_CFLAGS = $FREETYPE_CFLAGS
|
||||||
FREETYPE_LIBS = $FREETYPE_LIBS
|
FREETYPE_LIBS = $FREETYPE_LIBS
|
||||||
Z_LIBS = $Z_LIBS
|
Z_LIBS = $Z_LIBS
|
||||||
GETTEXTPO_LIBS = $GETTEXTPO_LIBS
|
GETTEXTPO_LIBS = $GETTEXTPO_LIBS
|
||||||
|
PULSE_LIBS = $PULSE_LIBS
|
||||||
|
PULSE_CFLAGS = $PULSE_CFLAGS
|
||||||
GSTREAMER_CFLAGS = $GSTREAMER_CFLAGS
|
GSTREAMER_CFLAGS = $GSTREAMER_CFLAGS
|
||||||
GSTREAMER_LIBS = $GSTREAMER_LIBS
|
GSTREAMER_LIBS = $GSTREAMER_LIBS
|
||||||
ALSA_LIBS = $ALSA_LIBS
|
ALSA_LIBS = $ALSA_LIBS
|
||||||
|
@ -17954,6 +18061,7 @@ wine_fn_config_dll winemp3.acm enable_winemp3_acm
|
||||||
wine_fn_config_dll wineoss.drv enable_wineoss_drv
|
wine_fn_config_dll wineoss.drv enable_wineoss_drv
|
||||||
wine_fn_config_dll wineps.drv enable_wineps_drv clean,po
|
wine_fn_config_dll wineps.drv enable_wineps_drv clean,po
|
||||||
wine_fn_config_dll wineps16.drv16 enable_win16
|
wine_fn_config_dll wineps16.drv16 enable_win16
|
||||||
|
wine_fn_config_dll winepulse.drv enable_winepulse_drv
|
||||||
wine_fn_config_dll wineqtdecoder enable_wineqtdecoder
|
wine_fn_config_dll wineqtdecoder enable_wineqtdecoder
|
||||||
wine_fn_config_dll winex11.drv enable_winex11_drv
|
wine_fn_config_dll winex11.drv enable_winex11_drv
|
||||||
wine_fn_config_dll wing.dll16 enable_win16
|
wine_fn_config_dll wing.dll16 enable_win16
|
||||||
|
|
19
configure.ac
19
configure.ac
|
@ -72,6 +72,7 @@ AC_ARG_WITH(pcap, AS_HELP_STRING([--without-pcap],[do not use the Packet Ca
|
||||||
AC_ARG_WITH(png, AS_HELP_STRING([--without-png],[do not use PNG]))
|
AC_ARG_WITH(png, AS_HELP_STRING([--without-png],[do not use PNG]))
|
||||||
AC_ARG_WITH(pthread, AS_HELP_STRING([--without-pthread],[do not use the pthread library]),
|
AC_ARG_WITH(pthread, AS_HELP_STRING([--without-pthread],[do not use the pthread library]),
|
||||||
[if test "x$withval" = "xno"; then ac_cv_header_pthread_h=no; fi])
|
[if test "x$withval" = "xno"; then ac_cv_header_pthread_h=no; fi])
|
||||||
|
AC_ARG_WITH(pulse, AC_HELP_STRING([--without-pulse],[do not use PulseAudio sound support]))
|
||||||
AC_ARG_WITH(sane, AS_HELP_STRING([--without-sane],[do not use SANE (scanner support)]))
|
AC_ARG_WITH(sane, AS_HELP_STRING([--without-sane],[do not use SANE (scanner support)]))
|
||||||
AC_ARG_WITH(tiff, AS_HELP_STRING([--without-tiff],[do not use TIFF]))
|
AC_ARG_WITH(tiff, AS_HELP_STRING([--without-tiff],[do not use TIFF]))
|
||||||
AC_ARG_WITH(v4l, AS_HELP_STRING([--without-v4l],[do not use v4l1 (v4l support)]))
|
AC_ARG_WITH(v4l, AS_HELP_STRING([--without-v4l],[do not use v4l1 (v4l support)]))
|
||||||
|
@ -1547,6 +1548,18 @@ then
|
||||||
[GetText ${notice_platform}development files not found (or too old), po files can't be rebuilt.])
|
[GetText ${notice_platform}development files not found (or too old), po files can't be rebuilt.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dnl **** Check for PulseAudio ****
|
||||||
|
AC_SUBST(PULSE_LIBS,"")
|
||||||
|
AC_SUBST(PULSE_CFLAGS,"")
|
||||||
|
if test "x$with_pulse" != "xno";
|
||||||
|
then
|
||||||
|
WINE_PACKAGE_FLAGS(PULSE,[libpulse],,,,
|
||||||
|
[AC_CHECK_HEADERS(pulse/pulseaudio.h,
|
||||||
|
[AC_CHECK_LIB(pulse, pa_stream_is_corked,[:],,[$PULSE_LIBS])])])
|
||||||
|
fi
|
||||||
|
WINE_NOTICE_WITH(pulse, [test "$ac_cv_lib_pulse_pa_stream_is_corked" != "yes"],
|
||||||
|
[libpulse ${notice_platform}development files not found or too old, Pulse won't be supported.])
|
||||||
|
|
||||||
dnl **** Check for gstreamer ****
|
dnl **** Check for gstreamer ****
|
||||||
if test "x$with_gstreamer" != "xno"
|
if test "x$with_gstreamer" != "xno"
|
||||||
then
|
then
|
||||||
|
@ -1779,13 +1792,14 @@ fi
|
||||||
dnl **** Disable unsupported winmm drivers ****
|
dnl **** Disable unsupported winmm drivers ****
|
||||||
test -n "$ALSA_LIBS" || enable_winealsa_drv=${enable_winealsa_drv:-no}
|
test -n "$ALSA_LIBS" || enable_winealsa_drv=${enable_winealsa_drv:-no}
|
||||||
test -n "$COREAUDIO_LIBS" || enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no}
|
test -n "$COREAUDIO_LIBS" || enable_winecoreaudio_drv=${enable_winecoreaudio_drv:-no}
|
||||||
|
test -n "$PULSE_LIBS" || enable_winepulse_drv=${enable_winepulse_drv:-no}
|
||||||
test "x$ac_cv_member_oss_sysinfo_numaudioengines" = xyes || enable_wineoss_drv=${enable_wineoss_drv:-no}
|
test "x$ac_cv_member_oss_sysinfo_numaudioengines" = xyes || enable_wineoss_drv=${enable_wineoss_drv:-no}
|
||||||
test "$ac_cv_header_linux_joystick_h" = "yes" -o "$ac_cv_header_IOKit_hid_IOHIDLib_h" = "yes" || enable_winejoystick_drv=${enable_winejoystick_drv:-no}
|
test "$ac_cv_header_linux_joystick_h" = "yes" -o "$ac_cv_header_IOKit_hid_IOHIDLib_h" = "yes" || enable_winejoystick_drv=${enable_winejoystick_drv:-no}
|
||||||
|
|
||||||
dnl **** Check for any sound system ****
|
dnl **** Check for any sound system ****
|
||||||
if test "x$ALSA_LIBS$COREAUDIO_LIBS" = "x" -a \
|
if test "x$ALSA_LIBS$COREAUDIO_LIBS$PULSE_LIBS" = "x" -a \
|
||||||
"x$ac_cv_member_oss_sysinfo_numaudioengines" != xyes -a \
|
"x$ac_cv_member_oss_sysinfo_numaudioengines" != xyes -a \
|
||||||
"x$with_alsa$with_coreaudio$with_oss" != xnonono
|
"x$with_alsa$with_coreaudio$with_oss$with_pulse" != xnononono
|
||||||
then
|
then
|
||||||
WINE_WARNING([No sound system was found. Windows applications will be silent.])
|
WINE_WARNING([No sound system was found. Windows applications will be silent.])
|
||||||
fi
|
fi
|
||||||
|
@ -3402,6 +3416,7 @@ WINE_CONFIG_DLL(winemp3.acm)
|
||||||
WINE_CONFIG_DLL(wineoss.drv)
|
WINE_CONFIG_DLL(wineoss.drv)
|
||||||
WINE_CONFIG_DLL(wineps.drv,,[clean,po])
|
WINE_CONFIG_DLL(wineps.drv,,[clean,po])
|
||||||
WINE_CONFIG_DLL(wineps16.drv16,enable_win16)
|
WINE_CONFIG_DLL(wineps16.drv16,enable_win16)
|
||||||
|
WINE_CONFIG_DLL(winepulse.drv)
|
||||||
WINE_CONFIG_DLL(wineqtdecoder)
|
WINE_CONFIG_DLL(wineqtdecoder)
|
||||||
WINE_CONFIG_DLL(winex11.drv)
|
WINE_CONFIG_DLL(winex11.drv)
|
||||||
WINE_CONFIG_DLL(wing.dll16,enable_win16)
|
WINE_CONFIG_DLL(wing.dll16,enable_win16)
|
||||||
|
|
|
@ -113,7 +113,7 @@ static BOOL init_driver(void)
|
||||||
{
|
{
|
||||||
static const WCHAR drv_value[] = {'A','u','d','i','o',0};
|
static const WCHAR drv_value[] = {'A','u','d','i','o',0};
|
||||||
|
|
||||||
static WCHAR default_list[] = {'a','l','s','a',',','o','s','s',',',
|
static WCHAR default_list[] = {'p','u','l','s','e',',','a','l','s','a',',','o','s','s',',',
|
||||||
'c','o','r','e','a','u','d','i','o',0};
|
'c','o','r','e','a','u','d','i','o',0};
|
||||||
|
|
||||||
DriverFuncs driver;
|
DriverFuncs driver;
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
MODULE = winepulse.drv
|
||||||
|
IMPORTS = dxguid uuid winmm user32 advapi32 ole32
|
||||||
|
EXTRALIBS = $(PULSE_LIBS) $(PTHREAD_LIBS)
|
||||||
|
EXTRAINCL = $(PULSE_CFLAGS)
|
||||||
|
|
||||||
|
C_SRCS = \
|
||||||
|
mmdevdrv.c
|
|
@ -0,0 +1,282 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2011-2012 Maarten Lankhorst
|
||||||
|
* Copyright 2010-2011 Maarten Lankhorst for CodeWeavers
|
||||||
|
* Copyright 2011 Andrew Eikum for CodeWeavers
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NONAMELESSUNION
|
||||||
|
#define COBJMACROS
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <poll.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <pulse/pulseaudio.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "wine/debug.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
#include "wine/list.h"
|
||||||
|
|
||||||
|
#include "ole2.h"
|
||||||
|
#include "dshow.h"
|
||||||
|
#include "dsound.h"
|
||||||
|
#include "propsys.h"
|
||||||
|
|
||||||
|
#include "initguid.h"
|
||||||
|
#include "ks.h"
|
||||||
|
#include "ksmedia.h"
|
||||||
|
#include "mmdeviceapi.h"
|
||||||
|
#include "audioclient.h"
|
||||||
|
#include "endpointvolume.h"
|
||||||
|
#include "audiopolicy.h"
|
||||||
|
|
||||||
|
WINE_DEFAULT_DEBUG_CHANNEL(pulse);
|
||||||
|
|
||||||
|
#define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
|
||||||
|
|
||||||
|
/* From <dlls/mmdevapi/mmdevapi.h> */
|
||||||
|
enum DriverPriority {
|
||||||
|
Priority_Unavailable = 0,
|
||||||
|
Priority_Low,
|
||||||
|
Priority_Neutral,
|
||||||
|
Priority_Preferred
|
||||||
|
};
|
||||||
|
|
||||||
|
static const REFERENCE_TIME MinimumPeriod = 30000;
|
||||||
|
static const REFERENCE_TIME DefaultPeriod = 100000;
|
||||||
|
|
||||||
|
static pa_context *pulse_ctx;
|
||||||
|
static pa_mainloop *pulse_ml;
|
||||||
|
|
||||||
|
static pthread_mutex_t pulse_lock;
|
||||||
|
|
||||||
|
static GUID pulse_render_guid =
|
||||||
|
{ 0xfd47d9cc, 0x4218, 0x4135, { 0x9c, 0xe2, 0x0c, 0x19, 0x5c, 0x87, 0x40, 0x5b } };
|
||||||
|
static GUID pulse_capture_guid =
|
||||||
|
{ 0x25da76d0, 0x033c, 0x4235, { 0x90, 0x02, 0x19, 0xf4, 0x88, 0x94, 0xac, 0x6f } };
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
|
||||||
|
{
|
||||||
|
if (reason == DLL_PROCESS_ATTACH) {
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
|
||||||
|
DisableThreadLibraryCalls(dll);
|
||||||
|
|
||||||
|
pthread_mutexattr_init(&attr);
|
||||||
|
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
|
||||||
|
|
||||||
|
if (pthread_mutex_init(&pulse_lock, &attr) != 0)
|
||||||
|
pthread_mutex_init(&pulse_lock, NULL);
|
||||||
|
} else if (reason == DLL_PROCESS_DETACH) {
|
||||||
|
if (pulse_ctx) {
|
||||||
|
pa_context_disconnect(pulse_ctx);
|
||||||
|
pa_context_unref(pulse_ctx);
|
||||||
|
}
|
||||||
|
if (pulse_ml)
|
||||||
|
pa_mainloop_quit(pulse_ml, 0);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const WCHAR defaultW[] = {'P','u','l','s','e','a','u','d','i','o',0};
|
||||||
|
|
||||||
|
/* Following pulseaudio design here, mainloop has the lock taken whenever
|
||||||
|
* it is handling something for pulse, and the lock is required whenever
|
||||||
|
* doing any pa_* call that can affect the state in any way
|
||||||
|
*
|
||||||
|
* pa_cond_wait is used when waiting on results, because the mainloop needs
|
||||||
|
* the same lock taken to affect the state
|
||||||
|
*
|
||||||
|
* This is basically the same as the pa_threaded_mainloop implementation,
|
||||||
|
* but that cannot be used because it uses pthread_create directly
|
||||||
|
*
|
||||||
|
* pa_threaded_mainloop_(un)lock -> pthread_mutex_(un)lock
|
||||||
|
* pa_threaded_mainloop_signal -> pthread_cond_signal
|
||||||
|
* pa_threaded_mainloop_wait -> pthread_cond_wait
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int pulse_poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, void *userdata) {
|
||||||
|
int r;
|
||||||
|
pthread_mutex_unlock(&pulse_lock);
|
||||||
|
r = poll(ufds, nfds, timeout);
|
||||||
|
pthread_mutex_lock(&pulse_lock);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pulse_contextcallback(pa_context *c, void *userdata)
|
||||||
|
{
|
||||||
|
switch (pa_context_get_state(c)) {
|
||||||
|
default:
|
||||||
|
FIXME("Unhandled state: %i\n", pa_context_get_state(c));
|
||||||
|
case PA_CONTEXT_CONNECTING:
|
||||||
|
case PA_CONTEXT_UNCONNECTED:
|
||||||
|
case PA_CONTEXT_AUTHORIZING:
|
||||||
|
case PA_CONTEXT_SETTING_NAME:
|
||||||
|
case PA_CONTEXT_TERMINATED:
|
||||||
|
TRACE("State change to %i\n", pa_context_get_state(c));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case PA_CONTEXT_READY:
|
||||||
|
TRACE("Ready\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PA_CONTEXT_FAILED:
|
||||||
|
ERR("Context failed: %s\n", pa_strerror(pa_context_errno(c)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* some poorly-behaved applications call audio functions during DllMain, so we
|
||||||
|
* have to do as much as possible without creating a new thread. this function
|
||||||
|
* sets up a synchronous connection to verify the server is running and query
|
||||||
|
* static data. */
|
||||||
|
static HRESULT pulse_test_connect(void)
|
||||||
|
{
|
||||||
|
int len, ret;
|
||||||
|
WCHAR path[PATH_MAX], *name;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
pulse_ml = pa_mainloop_new();
|
||||||
|
|
||||||
|
pa_mainloop_set_poll_func(pulse_ml, pulse_poll_func, NULL);
|
||||||
|
|
||||||
|
GetModuleFileNameW(NULL, path, sizeof(path)/sizeof(*path));
|
||||||
|
name = strrchrW(path, '\\');
|
||||||
|
if (!name)
|
||||||
|
name = path;
|
||||||
|
else
|
||||||
|
name++;
|
||||||
|
len = WideCharToMultiByte(CP_UNIXCP, 0, name, -1, NULL, 0, NULL, NULL);
|
||||||
|
str = pa_xmalloc(len);
|
||||||
|
WideCharToMultiByte(CP_UNIXCP, 0, name, -1, str, len, NULL, NULL);
|
||||||
|
TRACE("Name: %s\n", str);
|
||||||
|
pulse_ctx = pa_context_new(pa_mainloop_get_api(pulse_ml), str);
|
||||||
|
pa_xfree(str);
|
||||||
|
if (!pulse_ctx) {
|
||||||
|
ERR("Failed to create context\n");
|
||||||
|
pa_mainloop_free(pulse_ml);
|
||||||
|
pulse_ml = NULL;
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pa_context_set_state_callback(pulse_ctx, pulse_contextcallback, NULL);
|
||||||
|
|
||||||
|
TRACE("libpulse protocol version: %u. API Version %u\n", pa_context_get_protocol_version(pulse_ctx), PA_API_VERSION);
|
||||||
|
if (pa_context_connect(pulse_ctx, NULL, 0, NULL) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* Wait for connection */
|
||||||
|
while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0) {
|
||||||
|
pa_context_state_t state = pa_context_get_state(pulse_ctx);
|
||||||
|
|
||||||
|
if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (state == PA_CONTEXT_READY)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("Test-connected to server %s with protocol version: %i.\n",
|
||||||
|
pa_context_get_server(pulse_ctx),
|
||||||
|
pa_context_get_server_protocol_version(pulse_ctx));
|
||||||
|
|
||||||
|
pa_context_unref(pulse_ctx);
|
||||||
|
pulse_ctx = NULL;
|
||||||
|
pa_mainloop_free(pulse_ml);
|
||||||
|
pulse_ml = NULL;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pa_context_unref(pulse_ctx);
|
||||||
|
pulse_ctx = NULL;
|
||||||
|
pa_mainloop_free(pulse_ml);
|
||||||
|
pulse_ml = NULL;
|
||||||
|
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, const WCHAR ***ids, GUID **keys,
|
||||||
|
UINT *num, UINT *def_index)
|
||||||
|
{
|
||||||
|
WCHAR *id;
|
||||||
|
|
||||||
|
TRACE("%d %p %p %p\n", flow, ids, num, def_index);
|
||||||
|
|
||||||
|
*num = 1;
|
||||||
|
*def_index = 0;
|
||||||
|
|
||||||
|
*ids = HeapAlloc(GetProcessHeap(), 0, sizeof(**ids));
|
||||||
|
*keys = NULL;
|
||||||
|
if (!*ids)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
(*ids)[0] = id = HeapAlloc(GetProcessHeap(), 0, sizeof(defaultW));
|
||||||
|
*keys = HeapAlloc(GetProcessHeap(), 0, sizeof(**keys));
|
||||||
|
if (!*keys || !id) {
|
||||||
|
HeapFree(GetProcessHeap(), 0, id);
|
||||||
|
HeapFree(GetProcessHeap(), 0, *keys);
|
||||||
|
HeapFree(GetProcessHeap(), 0, *ids);
|
||||||
|
*ids = NULL;
|
||||||
|
*keys = NULL;
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
memcpy(id, defaultW, sizeof(defaultW));
|
||||||
|
|
||||||
|
if (flow == eRender)
|
||||||
|
(*keys)[0] = pulse_render_guid;
|
||||||
|
else
|
||||||
|
(*keys)[0] = pulse_capture_guid;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WINAPI AUDDRV_GetPriority(void)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
pthread_mutex_lock(&pulse_lock);
|
||||||
|
hr = pulse_test_connect();
|
||||||
|
pthread_mutex_unlock(&pulse_lock);
|
||||||
|
return SUCCEEDED(hr) ? Priority_Low : Priority_Unavailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient **out)
|
||||||
|
{
|
||||||
|
TRACE("%s %p %p\n", debugstr_guid(guid), dev, out);
|
||||||
|
*out = NULL;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
|
||||||
|
IAudioSessionManager2 **out)
|
||||||
|
{
|
||||||
|
*out = NULL;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
# MMDevAPI driver functions
|
||||||
|
@ stdcall -private GetPriority() AUDDRV_GetPriority
|
||||||
|
@ stdcall -private GetEndpointIDs(long ptr ptr ptr ptr) AUDDRV_GetEndpointIDs
|
||||||
|
@ stdcall -private GetAudioEndpoint(ptr ptr ptr) AUDDRV_GetAudioEndpoint
|
||||||
|
@ stdcall -private GetAudioSessionManager(ptr ptr) AUDDRV_GetAudioSessionManager
|
|
@ -696,6 +696,9 @@
|
||||||
/* Define to 1 if you have the <pthread_np.h> header file. */
|
/* Define to 1 if you have the <pthread_np.h> header file. */
|
||||||
#undef HAVE_PTHREAD_NP_H
|
#undef HAVE_PTHREAD_NP_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <pulse/pulseaudio.h> header file. */
|
||||||
|
#undef HAVE_PULSE_PULSEAUDIO_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <pwd.h> header file. */
|
/* Define to 1 if you have the <pwd.h> header file. */
|
||||||
#undef HAVE_PWD_H
|
#undef HAVE_PWD_H
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue