Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
7a15eb93
Commit
7a15eb93
authored
Aug 03, 2005
by
Peter Åstrand
Committed by
Alexandre Julliard
Aug 03, 2005
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implemented an Esound driver.
parent
4fa411fa
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
2471 additions
and
6 deletions
+2471
-6
configure
configure
+137
-4
configure.ac
configure.ac
+24
-2
Makefile.in
dlls/Makefile.in
+6
-0
.cvsignore
dlls/winmm/wineesd/.cvsignore
+2
-0
Makefile.in
dlls/winmm/wineesd/Makefile.in
+16
-0
audio.c
dlls/winmm/wineesd/audio.c
+2144
-0
esound.c
dlls/winmm/wineesd/esound.c
+92
-0
esound.h
dlls/winmm/wineesd/esound.h
+34
-0
wineesd.drv.spec
dlls/winmm/wineesd/wineesd.drv.spec
+3
-0
config.h.in
include/config.h.in
+3
-0
audio.c
programs/winecfg/audio.c
+9
-0
properties.c
programs/winecfg/properties.c
+1
-0
No files found.
configure
View file @
7a15eb93
...
...
@@ -311,7 +311,7 @@ ac_includes_default="\
# include <unistd.h>
#endif"
ac_subst_vars
=
'SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS DLLDEFS build build_cpu build_vendor build_os host host_cpu host_vendor host_os WIN16_FILES WIN16_INSTALL SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX CPPBIN ac_ct_CPPBIN TOOLSDIR CPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS LEX LEXLIB LEX_OUTPUT_ROOT XLEX BISON AS ac_ct_AS LD ac_ct_LD AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP WINDRES ac_ct_WINDRES LN_S LN EGREP LDCONFIG INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LINT LINTFLAGS FONTFORGE LIBPTHREAD XLIB XFILES OPENGLFILES GLU32FILES OPENGL_LIBS GLUT_LIBS GLUT32FILES NASLIBS XML2LIBS XML2INCL CURSESLIBS sane_devel SANELIBS SANEINCL ICULIBS LCMSLIBS LDAPLIBS ft_devel ft_devel2 FREETYPELIBS FREETYPEINCL FONTSSUBDIRS ARTSCCONFIG ARTSLIBS ARTSINCL ALSALIBS AUDIOIOLIBS EXTRACFLAGS DLLEXT DLLFLAGS DLLIBS LDSHARED LDDLLFLAGS LIBEXT IMPLIBEXT DLLTOOL ac_ct_DLLTOOL DLLWRAP ac_ct_DLLWRAP LDEXECFLAGS LDLIBWINEFLAGS COREFOUNDATIONLIB IOKITLIB CROSSTEST CROSSCC CROSSWINDRES LDPATH CRTLIBS SOCKETLIBS WINE_BINARIES MAIN_BINARY LDD ALLOCA LIBOBJS LTLIBOBJS'
ac_subst_vars
=
'SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS DLLDEFS build build_cpu build_vendor build_os host host_cpu host_vendor host_os WIN16_FILES WIN16_INSTALL SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX CPPBIN ac_ct_CPPBIN TOOLSDIR CPP X_CFLAGS X_PRE_LIBS X_LIBS X_EXTRA_LIBS LEX LEXLIB LEX_OUTPUT_ROOT XLEX BISON AS ac_ct_AS LD ac_ct_LD AR ac_ct_AR RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP WINDRES ac_ct_WINDRES LN_S LN EGREP LDCONFIG INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LINT LINTFLAGS FONTFORGE LIBPTHREAD XLIB XFILES OPENGLFILES GLU32FILES OPENGL_LIBS GLUT_LIBS GLUT32FILES NASLIBS XML2LIBS XML2INCL CURSESLIBS sane_devel SANELIBS SANEINCL ICULIBS LCMSLIBS LDAPLIBS ft_devel ft_devel2 FREETYPELIBS FREETYPEINCL FONTSSUBDIRS ARTSCCONFIG ARTSLIBS ARTSINCL
ESDCONFIG ESDLIBS ESDINCL
ALSALIBS AUDIOIOLIBS EXTRACFLAGS DLLEXT DLLFLAGS DLLIBS LDSHARED LDDLLFLAGS LIBEXT IMPLIBEXT DLLTOOL ac_ct_DLLTOOL DLLWRAP ac_ct_DLLWRAP LDEXECFLAGS LDLIBWINEFLAGS COREFOUNDATIONLIB IOKITLIB CROSSTEST CROSSCC CROSSWINDRES LDPATH CRTLIBS SOCKETLIBS WINE_BINARIES MAIN_BINARY LDD ALLOCA LIBOBJS LTLIBOBJS'
ac_subst_files
=
'MAKE_RULES MAKE_DLL_RULES MAKE_TEST_RULES MAKE_LIB_RULES MAKE_PROG_RULES'
# Initialize some variables set by options.
...
...
@@ -11616,6 +11616,135 @@ fi
CFLAGS
=
"
$save_CFLAGS
"
fi
# Extract the first word of "esd-config", so it can be a program name with args.
set
dummy esd-config
;
ac_word
=
$2
echo
"
$as_me
:
$LINENO
: checking for
$ac_word
"
>
&5
echo
$ECHO_N
"checking for
$ac_word
...
$ECHO_C
"
>
&6
if
test
"
${
ac_cv_path_ESDCONFIG
+set
}
"
=
set
;
then
echo
$ECHO_N
"(cached)
$ECHO_C
"
>
&6
else
case
$ESDCONFIG
in
[
\\
/]
*
|
?:[
\\
/]
*
)
ac_cv_path_ESDCONFIG
=
"
$ESDCONFIG
"
# Let the user override the test with a path.
;;
*
)
as_save_IFS
=
$IFS
;
IFS
=
$PATH_SEPARATOR
for
as_dir
in
$PATH
do
IFS
=
$as_save_IFS
test
-z
"
$as_dir
"
&&
as_dir
=
.
for
ac_exec_ext
in
''
$ac_executable_extensions
;
do
if
$as_executable_p
"
$as_dir
/
$ac_word$ac_exec_ext
"
;
then
ac_cv_path_ESDCONFIG
=
"
$as_dir
/
$ac_word$ac_exec_ext
"
echo
"
$as_me
:
$LINENO
: found
$as_dir
/
$ac_word$ac_exec_ext
"
>
&5
break
2
fi
done
done
;;
esac
fi
ESDCONFIG
=
$ac_cv_path_ESDCONFIG
if
test
-n
"
$ESDCONFIG
"
;
then
echo
"
$as_me
:
$LINENO
: result:
$ESDCONFIG
"
>
&5
echo
"
${
ECHO_T
}
$ESDCONFIG
"
>
&6
else
echo
"
$as_me
:
$LINENO
: result: no"
>
&5
echo
"
${
ECHO_T
}
no"
>
&6
fi
if
test
x
$ESDCONFIG
!=
x
-a
x
$ESDCONFIG
!=
x
'"$ESDCONFIG"'
;
then
ESD_CFLAGS
=
""
for
i
in
`
$ESDCONFIG
--cflags
`
do
case
"
$i
"
in
-I
*
)
ESD_CFLAGS
=
"
$ESD_CFLAGS
$i
"
;;
esac
done
ESD_LIBS
=
`
$ESDCONFIG
--libs
`
save_CFLAGS
=
"
$CFLAGS
"
CFLAGS
=
"
$CFLAGS
$ESD_CFLAGS
"
echo
"
$as_me
:
$LINENO
: checking for esd_open_sound in -lesd"
>
&5
echo
$ECHO_N
"checking for esd_open_sound in -lesd...
$ECHO_C
"
>
&6
if
test
"
${
ac_cv_lib_esd_esd_open_sound
+set
}
"
=
set
;
then
echo
$ECHO_N
"(cached)
$ECHO_C
"
>
&6
else
ac_check_lib_save_LIBS
=
$LIBS
LIBS
=
"-lesd
$LIBS
"
cat
>
conftest.
$ac_ext
<<
_ACEOF
/* confdefs.h. */
_ACEOF
cat
confdefs.h
>>
conftest.
$ac_ext
cat
>>
conftest.
$ac_ext
<<
_ACEOF
/* end confdefs.h. */
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
extern "C"
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char esd_open_sound ();
int
main ()
{
esd_open_sound ();
;
return 0;
}
_ACEOF
rm
-f
conftest.
$ac_objext
conftest
$ac_exeext
if
{
(
eval echo
"
$as_me
:
$LINENO
:
\"
$ac_link
\"
"
)
>
&5
(
eval
$ac_link
)
2>conftest.er1
ac_status
=
$?
grep
-v
'^ *+'
conftest.er1
>
conftest.err
rm
-f
conftest.er1
cat
conftest.err
>
&5
echo
"
$as_me
:
$LINENO
:
\$
? =
$ac_status
"
>
&5
(
exit
$ac_status
)
;
}
&&
{
ac_try
=
'test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{
(
eval echo
"
$as_me
:
$LINENO
:
\"
$ac_try
\"
"
)
>
&5
(
eval
$ac_try
)
2>&5
ac_status
=
$?
echo
"
$as_me
:
$LINENO
:
\$
? =
$ac_status
"
>
&5
(
exit
$ac_status
)
;
}
;
}
&&
{
ac_try
=
'test -s conftest$ac_exeext'
{
(
eval echo
"
$as_me
:
$LINENO
:
\"
$ac_try
\"
"
)
>
&5
(
eval
$ac_try
)
2>&5
ac_status
=
$?
echo
"
$as_me
:
$LINENO
:
\$
? =
$ac_status
"
>
&5
(
exit
$ac_status
)
;
}
;
}
;
then
ac_cv_lib_esd_esd_open_sound
=
yes
else
echo
"
$as_me
: failed program was:"
>
&5
sed
's/^/| /'
conftest.
$ac_ext
>
&5
ac_cv_lib_esd_esd_open_sound
=
no
fi
rm
-f
conftest.err conftest.
$ac_objext
\
conftest
$ac_exeext
conftest.
$ac_ext
LIBS
=
$ac_check_lib_save_LIBS
fi
echo
"
$as_me
:
$LINENO
: result:
$ac_cv_lib_esd_esd_open_sound
"
>
&5
echo
"
${
ECHO_T
}
$ac_cv_lib_esd_esd_open_sound
"
>
&6
if
test
$ac_cv_lib_esd_esd_open_sound
=
yes
;
then
ESDLIBS
=
$ESD_LIBS
ESDINCL
=
$ESD_CFLAGS
cat
>>
confdefs.h
<<
\
_ACEOF
#define HAVE_ESD 1
_ACEOF
fi
CFLAGS
=
"
$save_CFLAGS
"
fi
ALSALIBS
=
""
...
...
@@ -20549,7 +20678,7 @@ MAKE_LIB_RULES=libs/Makelib.rules
MAKE_PROG_RULES
=
programs/Makeprog.rules
ac_config_files
=
"
$ac_config_files
Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/activeds/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/advpack/Makefile dlls/advpack/tests/Makefile dlls/amstream/Makefile dlls/atl/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cards/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/crypt32/tests/Makefile dlls/cryptdll/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3drm/Makefile dlls/d3dx8/Makefile dlls/d3dxof/Makefile dlls/dbghelp/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput/tests/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnet/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/dxdiagn/Makefile dlls/dxerr8/Makefile dlls/dxerr9/Makefile dlls/dxguid/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/hhctrl.ocx/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/ifsmgr.vxd/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/itss/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/lzexpand/tests/Makefile dlls/mapi32/Makefile dlls/mapi32/tests/Makefile dlls/midimap/Makefile dlls/mlang/Makefile dlls/mlang/tests/Makefile dlls/mmdevldr.vxd/Makefile dlls/monodebg.vxd/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msacm/tests/Makefile dlls/mscms/Makefile dlls/mscms/tests/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/mshtml/tests/Makefile dlls/msi/Makefile dlls/msi/tests/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvcrtd/tests/Makefile dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/mswsock/Makefile dlls/msxml3/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/objsel/Makefile dlls/odbc32/Makefile dlls/odbccp32/Makefile dlls/ole32/Makefile dlls/ole32/tests/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/powrprof/Makefile dlls/psapi/Makefile dlls/psapi/tests/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/quartz/tests/Makefile dlls/rasapi32/Makefile dlls/riched20/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/rsabase/Makefile dlls/rsabase/tests/Makefile dlls/rsaenh/Makefile dlls/rsaenh/tests/Makefile dlls/secur32/Makefile dlls/secur32/tests/Makefile dlls/sensapi/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/stdole2.tlb/Makefile dlls/stdole32.tlb/Makefile dlls/sti/Makefile dlls/strmiids/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/usp10/Makefile dlls/uuid/Makefile dlls/uxtheme/Makefile dlls/vdhcp.vxd/Makefile dlls/vdmdbg/Makefile dlls/version/Makefile dlls/version/tests/Makefile dlls/vmm.vxd/Makefile dlls/vnbt.vxd/Makefile dlls/vnetbios.vxd/Makefile dlls/vtdapi.vxd/Makefile dlls/vwin32.vxd/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/wined3d/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio
/Makefile dlls/winmm/winejack/Makefile dlls/winmm/winenas/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wldap32/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/wtsapi32/Makefile dlls/x11drv/Makefile documentation/Makefile fonts/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/hh/Makefile programs/msiexec/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/taskmgr/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile"
ac_config_files
=
"
$ac_config_files
Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/activeds/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/advpack/Makefile dlls/advpack/tests/Makefile dlls/amstream/Makefile dlls/atl/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cards/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/crypt32/tests/Makefile dlls/cryptdll/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3drm/Makefile dlls/d3dx8/Makefile dlls/d3dxof/Makefile dlls/dbghelp/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput/tests/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnet/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/dxdiagn/Makefile dlls/dxerr8/Makefile dlls/dxerr9/Makefile dlls/dxguid/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/hhctrl.ocx/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/ifsmgr.vxd/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/itss/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/lzexpand/tests/Makefile dlls/mapi32/Makefile dlls/mapi32/tests/Makefile dlls/midimap/Makefile dlls/mlang/Makefile dlls/mlang/tests/Makefile dlls/mmdevldr.vxd/Makefile dlls/monodebg.vxd/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msacm/tests/Makefile dlls/mscms/Makefile dlls/mscms/tests/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/mshtml/tests/Makefile dlls/msi/Makefile dlls/msi/tests/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvcrtd/tests/Makefile dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/mswsock/Makefile dlls/msxml3/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/objsel/Makefile dlls/odbc32/Makefile dlls/odbccp32/Makefile dlls/ole32/Makefile dlls/ole32/tests/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/powrprof/Makefile dlls/psapi/Makefile dlls/psapi/tests/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/quartz/tests/Makefile dlls/rasapi32/Makefile dlls/riched20/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/rsabase/Makefile dlls/rsabase/tests/Makefile dlls/rsaenh/Makefile dlls/rsaenh/tests/Makefile dlls/secur32/Makefile dlls/secur32/tests/Makefile dlls/sensapi/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/stdole2.tlb/Makefile dlls/stdole32.tlb/Makefile dlls/sti/Makefile dlls/strmiids/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/usp10/Makefile dlls/uuid/Makefile dlls/uxtheme/Makefile dlls/vdhcp.vxd/Makefile dlls/vdmdbg/Makefile dlls/version/Makefile dlls/version/tests/Makefile dlls/vmm.vxd/Makefile dlls/vnbt.vxd/Makefile dlls/vnetbios.vxd/Makefile dlls/vtdapi.vxd/Makefile dlls/vwin32.vxd/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/wined3d/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/wineesd
/Makefile dlls/winmm/winejack/Makefile dlls/winmm/winenas/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wldap32/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/wtsapi32/Makefile dlls/x11drv/Makefile documentation/Makefile fonts/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/hh/Makefile programs/msiexec/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/taskmgr/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile"
cat
>
confcache
<<
\
_ACEOF
...
...
@@ -21284,6 +21413,7 @@ do
"dlls/winmm/winealsa/Makefile" ) CONFIG_FILES="
$CONFIG_FILES
dlls/winmm/winealsa/Makefile" ;;
"dlls/winmm/winearts/Makefile" ) CONFIG_FILES="
$CONFIG_FILES
dlls/winmm/winearts/Makefile" ;;
"dlls/winmm/wineaudioio/Makefile" ) CONFIG_FILES="
$CONFIG_FILES
dlls/winmm/wineaudioio/Makefile" ;;
"dlls/winmm/wineesd/Makefile" ) CONFIG_FILES="
$CONFIG_FILES
dlls/winmm/wineesd/Makefile" ;;
"dlls/winmm/winejack/Makefile" ) CONFIG_FILES="
$CONFIG_FILES
dlls/winmm/winejack/Makefile" ;;
"dlls/winmm/winenas/Makefile" ) CONFIG_FILES="
$CONFIG_FILES
dlls/winmm/winenas/Makefile" ;;
"dlls/winmm/wineoss/Makefile" ) CONFIG_FILES="
$CONFIG_FILES
dlls/winmm/wineoss/Makefile" ;;
...
...
@@ -21525,6 +21655,9 @@ s,@FONTSSUBDIRS@,$FONTSSUBDIRS,;t t
s,@ARTSCCONFIG@,
$ARTSCCONFIG
,;t t
s,@ARTSLIBS@,
$ARTSLIBS
,;t t
s,@ARTSINCL@,
$ARTSINCL
,;t t
s,@ESDCONFIG@,
$ESDCONFIG
,;t t
s,@ESDLIBS@,
$ESDLIBS
,;t t
s,@ESDINCL@,
$ESDINCL
,;t t
s,@ALSALIBS@,
$ALSALIBS
,;t t
s,@AUDIOIOLIBS@,
$AUDIOIOLIBS
,;t t
s,@EXTRACFLAGS@,
$EXTRACFLAGS
,;t t
...
...
@@ -22216,11 +22349,11 @@ fi
if
test
-z
"
$ALSALIBS
"
-a
-z
"
$ARTSC_LIBS
"
-a
-z
"
$AUDIOIOLIBS
"
-a
\
-z
"
$ac_cv_lib_soname_jack
"
-a
-z
"
$NASLIBS
"
-a
\
"
$ac_cv_c_opensoundsystem
"
=
"no"
"
$ac_cv_c_opensoundsystem
"
=
"no"
-a
-z
"
$ESD_LIBS
"
then
echo
"*** No sound system was found. Windows applications will be silent."
echo
"*** The currently supported sound systems are:"
echo
"*** ALSA, ARTS, AudioIO, Jack, NAS and OSS"
echo
"*** ALSA, ARTS,
EsounD,
AudioIO, Jack, NAS and OSS"
fi
echo
...
...
configure.ac
View file @
7a15eb93
...
...
@@ -725,6 +725,27 @@ then
CFLAGS="$save_CFLAGS"
fi
dnl **** Check for EsounD ****
AC_PATH_PROG(ESDCONFIG, esd-config)
if test x$ESDCONFIG != x -a x$ESDCONFIG != x'"$ESDCONFIG"';
then
ESD_CFLAGS=""
for i in `$ESDCONFIG --cflags`
do
case "$i" in
-I*) ESD_CFLAGS="$ESD_CFLAGS $i";;
esac
done
ESD_LIBS=`$ESDCONFIG --libs`
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $ESD_CFLAGS"
AC_CHECK_LIB(esd,esd_open_sound,
[AC_SUBST(ESDLIBS, $ESD_LIBS)
AC_SUBST(ESDINCL, $ESD_CFLAGS)
AC_DEFINE(HAVE_ESD, 1, [Define if you have EsounD sound server])])
CFLAGS="$save_CFLAGS"
fi
dnl **** Check for ALSA 1.x ****
AC_SUBST(ALSALIBS,"")
AC_CHECK_HEADERS(alsa/asoundlib.h sys/asoundlib.h, break)
...
...
@@ -1753,6 +1774,7 @@ dlls/winmm/wavemap/Makefile
dlls/winmm/winealsa/Makefile
dlls/winmm/winearts/Makefile
dlls/winmm/wineaudioio/Makefile
dlls/winmm/wineesd/Makefile
dlls/winmm/winejack/Makefile
dlls/winmm/winenas/Makefile
dlls/winmm/wineoss/Makefile
...
...
@@ -1848,11 +1870,11 @@ fi
if test -z "$ALSALIBS" -a -z "$ARTSC_LIBS" -a -z "$AUDIOIOLIBS" -a \
-z "$ac_cv_lib_soname_jack" -a -z "$NASLIBS" -a \
"$ac_cv_c_opensoundsystem" = "no"
"$ac_cv_c_opensoundsystem" = "no"
-a -z "$ESD_LIBS"
then
echo "*** No sound system was found. Windows applications will be silent."
echo "*** The currently supported sound systems are:"
echo "*** ALSA, ARTS, AudioIO, Jack, NAS and OSS"
echo "*** ALSA, ARTS,
EsounD,
AudioIO, Jack, NAS and OSS"
fi
echo
...
...
dlls/Makefile.in
View file @
7a15eb93
...
...
@@ -164,6 +164,7 @@ BASEDIRS = \
winmm/winealsa
\
winmm/winearts
\
winmm/wineaudioio
\
winmm/wineesd
\
winmm/winejack
\
winmm/winenas
\
winmm/wineoss
\
...
...
@@ -403,6 +404,7 @@ SYMLINKS_SO = \
winearts.drv.so
\
wineaudioio.drv.so
\
winedos.dll.so
\
wineesd.drv.so
\
winejack.drv.so
\
winemp3.acm.so
\
winenas.drv.so
\
...
...
@@ -956,6 +958,9 @@ winedos.dll.so: winedos/winedos.dll.so
wprocs.dll.so
:
winedos.dll.so
$(RM)
$@
&&
$(LN_S)
winedos.dll.so
$@
wineesd.drv.so
:
winmm/wineesd/wineesd.drv.so
$(RM)
$@
&&
$(LN_S)
winmm/wineesd/wineesd.drv.so
$@
winejack.drv.so
:
winmm/winejack/winejack.drv.so
$(RM)
$@
&&
$(LN_S)
winmm/winejack/winejack.drv.so
$@
...
...
@@ -1758,6 +1763,7 @@ winmm/winearts/winearts.drv.so: winmm/winearts
winmm/wineaudioio/wineaudioio.drv.so
:
winmm/wineaudioio
wined3d/wined3d.dll.so
:
wined3d
winedos/winedos.dll.so
:
winedos
winmm/wineesd/wineesd.drv.so
:
winmm/wineesd
winmm/winejack/winejack.drv.so
:
winmm/winejack
msacm/winemp3/winemp3.acm.so
:
msacm/winemp3
winmm/winenas/winenas.drv.so
:
winmm/winenas
...
...
dlls/winmm/wineesd/.cvsignore
0 → 100644
View file @
7a15eb93
Makefile
wineesd.drv.dbg.c
dlls/winmm/wineesd/Makefile.in
0 → 100644
View file @
7a15eb93
TOPSRCDIR
=
@top_srcdir@
TOPOBJDIR
=
../../..
SRCDIR
=
@srcdir@
VPATH
=
@srcdir@
MODULE
=
wineesd.drv
IMPORTS
=
winmm user32 kernel32
EXTRAINCL
=
@ESDINCL@
EXTRALIBS
=
@ESDLIBS@
-ldxguid
-luuid
C_SRCS
=
\
esound.c
\
audio.c
@MAKE_DLL_RULES@
### Dependencies:
dlls/winmm/wineesd/audio.c
0 → 100644
View file @
7a15eb93
/*
* Wine Driver for EsounD Sound Server
* http://www.tux.org/~ricdude/EsounD.html
*
* Copyright 1994 Martin Ayotte
* 1999 Eric Pouech (async playing in waveOut/waveIn)
* 2000 Eric Pouech (loops in waveOut)
* 2004 Zhangrong Huang (EsounD version of this file)
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* NOTE:
* with esd we cannot stop the audio that is already in
* the servers buffer.
*
* FIXME:
* pause in waveOut does not work correctly in loop mode
*
* does something need to be done in for WaveIn DirectSound?
*
*/
/*#define EMULATE_SB16*/
#include "config.h"
#include <math.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <fcntl.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winerror.h"
#include "wine/winuser16.h"
#include "mmddk.h"
#include "dsound.h"
#include "dsdriver.h"
#include "esound.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
wave
);
#ifdef HAVE_ESD
#include <esd.h>
/* define if you want to use esd_monitor_stream instead of
* esd_record_stream for waveIn stream
*/
/*#define WID_USE_ESDMON*/
#define BUFFER_REFILL_THRESHOLD 4
#define MAX_WAVEOUTDRV (10)
#define MAX_WAVEINDRV (10)
/* state diagram for waveOut writing:
*
* +---------+-------------+---------------+---------------------------------+
* | state | function | event | new state |
* +---------+-------------+---------------+---------------------------------+
* | | open() | | STOPPED |
* | PAUSED | write() | | PAUSED |
* | STOPPED | write() | <thrd create> | PLAYING |
* | PLAYING | write() | HEADER | PLAYING |
* | (other) | write() | <error> | |
* | (any) | pause() | PAUSING | PAUSED |
* | PAUSED | restart() | RESTARTING | PLAYING (if no thrd => STOPPED) |
* | (any) | reset() | RESETTING | STOPPED |
* | (any) | close() | CLOSING | CLOSED |
* +---------+-------------+---------------+---------------------------------+
*/
/* states of the playing device */
#define WINE_WS_PLAYING 0
#define WINE_WS_PAUSED 1
#define WINE_WS_STOPPED 2
#define WINE_WS_CLOSED 3
/* events to be send to device */
enum
win_wm_message
{
WINE_WM_PAUSING
=
WM_USER
+
1
,
WINE_WM_RESTARTING
,
WINE_WM_RESETTING
,
WINE_WM_HEADER
,
WINE_WM_UPDATE
,
WINE_WM_BREAKLOOP
,
WINE_WM_CLOSING
,
WINE_WM_STARTING
,
WINE_WM_STOPPING
};
typedef
struct
{
enum
win_wm_message
msg
;
/* message identifier */
DWORD
param
;
/* parameter for this message */
HANDLE
hEvent
;
/* if message is synchronous, handle of event for synchro */
}
RING_MSG
;
/* implement an in-process message ring for better performance
* (compared to passing thru the server)
* this ring will be used by the input (resp output) record (resp playback) routine
*/
#define ESD_RING_BUFFER_INCREMENT 64
typedef
struct
{
RING_MSG
*
messages
;
int
ring_buffer_size
;
int
msg_tosave
;
int
msg_toget
;
HANDLE
msg_event
;
CRITICAL_SECTION
msg_crst
;
}
ESD_MSG_RING
;
typedef
struct
{
volatile
int
state
;
/* one of the WINE_WS_ manifest constants */
WAVEOPENDESC
waveDesc
;
WORD
wFlags
;
PCMWAVEFORMAT
format
;
WAVEOUTCAPSA
caps
;
char
interface_name
[
32
];
DWORD
dwSleepTime
;
/* Num of milliseconds to sleep between filling the dsp buffers */
/* esd information */
int
esd_fd
;
/* the socket fd we get from esd when opening a stream for playing */
int
bytes_per_frame
;
DWORD
dwBufferSize
;
/* size of whole buffer in bytes */
char
*
sound_buffer
;
long
buffer_size
;
DWORD
volume_left
;
/* volume control information */
DWORD
volume_right
;
LPWAVEHDR
lpQueuePtr
;
/* start of queued WAVEHDRs (waiting to be notified) */
LPWAVEHDR
lpPlayPtr
;
/* start of not yet fully played buffers */
DWORD
dwPartialOffset
;
/* Offset of not yet written bytes in lpPlayPtr */
LPWAVEHDR
lpLoopPtr
;
/* pointer of first buffer in loop, if any */
DWORD
dwLoops
;
/* private copy of loop counter */
DWORD
dwPlayedTotal
;
/* number of bytes actually played since opening */
DWORD
dwWrittenTotal
;
/* number of bytes written to the audio device since opening */
/* synchronization stuff */
HANDLE
hStartUpEvent
;
HANDLE
hThread
;
DWORD
dwThreadID
;
ESD_MSG_RING
msgRing
;
}
WINE_WAVEOUT
;
typedef
struct
{
volatile
int
state
;
/* one of the WINE_WS_ manifest constants */
WAVEOPENDESC
waveDesc
;
WORD
wFlags
;
PCMWAVEFORMAT
format
;
WAVEINCAPSA
caps
;
char
interface_name
[
32
];
/* esd information */
int
esd_fd
;
/* the socket fd we get from esd when opening a stream for recording */
int
bytes_per_frame
;
LPWAVEHDR
lpQueuePtr
;
DWORD
dwRecordedTotal
;
/* synchronization stuff */
HANDLE
hStartUpEvent
;
HANDLE
hThread
;
DWORD
dwThreadID
;
ESD_MSG_RING
msgRing
;
}
WINE_WAVEIN
;
static
char
*
esd_host
;
/* the esd host */
static
WINE_WAVEOUT
WOutDev
[
MAX_WAVEOUTDRV
];
static
WINE_WAVEIN
WInDev
[
MAX_WAVEINDRV
];
static
DWORD
wodDsCreate
(
UINT
wDevID
,
PIDSDRIVER
*
drv
);
static
DWORD
wodDsDesc
(
UINT
wDevID
,
PDSDRIVERDESC
desc
);
/* These strings used only for tracing */
static
const
char
*
wodPlayerCmdString
[]
=
{
"WINE_WM_PAUSING"
,
"WINE_WM_RESTARTING"
,
"WINE_WM_RESETTING"
,
"WINE_WM_HEADER"
,
"WINE_WM_UPDATE"
,
"WINE_WM_BREAKLOOP"
,
"WINE_WM_CLOSING"
,
"WINE_WM_STARTING"
,
"WINE_WM_STOPPING"
,
};
/*======================================================================*
* Low level WAVE implementation *
*======================================================================*/
/* Volume functions derived from Alsaplayer source */
/* length is the number of 16 bit samples */
void
volume_effect16
(
void
*
bufin
,
void
*
bufout
,
int
length
,
int
left
,
int
right
,
int
nChannels
)
{
short
*
d_out
=
(
short
*
)
bufout
;
short
*
d_in
=
(
short
*
)
bufin
;
int
i
,
v
;
/*
TRACE("length == %d, nChannels == %d\n", length, nChannels);
*/
if
(
right
==
-
1
)
right
=
left
;
for
(
i
=
0
;
i
<
length
;
i
+=
(
nChannels
))
{
v
=
(
int
)
((
*
(
d_in
++
)
*
left
)
/
100
);
*
(
d_out
++
)
=
(
v
>
32767
)
?
32767
:
((
v
<-
32768
)
?
-
32768
:
v
);
if
(
nChannels
==
2
)
{
v
=
(
int
)
((
*
(
d_in
++
)
*
right
)
/
100
);
*
(
d_out
++
)
=
(
v
>
32767
)
?
32767
:
((
v
<-
32768
)
?
-
32768
:
v
);
}
}
}
/* length is the number of 8 bit samples */
void
volume_effect8
(
void
*
bufin
,
void
*
bufout
,
int
length
,
int
left
,
int
right
,
int
nChannels
)
{
BYTE
*
d_out
=
(
BYTE
*
)
bufout
;
BYTE
*
d_in
=
(
BYTE
*
)
bufin
;
int
i
,
v
;
/*
TRACE("length == %d, nChannels == %d\n", length, nChannels);
*/
if
(
right
==
-
1
)
right
=
left
;
for
(
i
=
0
;
i
<
length
;
i
+=
(
nChannels
))
{
v
=
(
BYTE
)
((
*
(
d_in
++
)
*
left
)
/
100
);
*
(
d_out
++
)
=
(
v
>
255
)
?
255
:
((
v
<
0
)
?
0
:
v
);
if
(
nChannels
==
2
)
{
v
=
(
BYTE
)
((
*
(
d_in
++
)
*
right
)
/
100
);
*
(
d_out
++
)
=
(
v
>
255
)
?
255
:
((
v
<
0
)
?
0
:
v
);
}
}
}
/******************************************************************
* ESD_CloseWaveOutDevice
*
*/
void
ESD_CloseWaveOutDevice
(
WINE_WAVEOUT
*
wwo
)
{
esd_close
(
wwo
->
esd_fd
);
/* close the esd socket fd */
wwo
->
esd_fd
=
-
1
;
/* free up the buffer we use for volume and reset the size */
if
(
wwo
->
sound_buffer
)
{
HeapFree
(
GetProcessHeap
(),
0
,
wwo
->
sound_buffer
);
wwo
->
sound_buffer
=
NULL
;
}
wwo
->
buffer_size
=
0
;
}
/******************************************************************
* ESD_CloseWaveInDevice
*
*/
void
ESD_CloseWaveInDevice
(
WINE_WAVEIN
*
wwi
)
{
esd_close
(
wwi
->
esd_fd
);
/* close the esd socket fd */
wwi
->
esd_fd
=
-
1
;
}
/******************************************************************
* ESD_WaveClose
*/
LONG
ESD_WaveClose
(
void
)
{
int
iDevice
;
/* close all open devices */
for
(
iDevice
=
0
;
iDevice
<
MAX_WAVEOUTDRV
;
iDevice
++
)
{
if
(
WOutDev
[
iDevice
].
esd_fd
!=
-
1
)
{
ESD_CloseWaveOutDevice
(
&
WOutDev
[
iDevice
]);
}
}
for
(
iDevice
=
0
;
iDevice
<
MAX_WAVEINDRV
;
iDevice
++
)
{
if
(
WInDev
[
iDevice
].
esd_fd
!=
-
1
)
{
ESD_CloseWaveInDevice
(
&
WInDev
[
iDevice
]);
}
}
return
1
;
}
/******************************************************************
* ESD_WaveInit
*
* Initialize internal structures from ESD server info
*/
LONG
ESD_WaveInit
(
void
)
{
int
i
;
int
fd
;
TRACE
(
"called
\n
"
);
/* FIXME: Maybe usefully to set the esd host. */
esd_host
=
NULL
;
/* Testing whether the esd host is alive. */
if
((
fd
=
esd_open_sound
(
esd_host
))
<
0
)
{
WARN
(
"esd_open_sound() failed (%d)
\n
"
,
errno
);
return
-
1
;
}
esd_close
(
fd
);
/* initialize all device handles to -1 */
for
(
i
=
0
;
i
<
MAX_WAVEOUTDRV
;
++
i
)
{
WOutDev
[
i
].
esd_fd
=
-
1
;
memset
(
&
WOutDev
[
i
].
caps
,
0
,
sizeof
(
WOutDev
[
i
].
caps
));
/* zero out
caps values */
/* FIXME: some programs compare this string against the content of the registry
* for MM drivers. The names have to match in order for the program to work
* (e.g. MS win9x mplayer.exe)
*/
#ifdef EMULATE_SB16
WOutDev
[
i
].
caps
.
wMid
=
0x0002
;
WOutDev
[
i
].
caps
.
wPid
=
0x0104
;
strcpy
(
WOutDev
[
i
].
caps
.
szPname
,
"SB16 Wave Out"
);
#else
WOutDev
[
i
].
caps
.
wMid
=
0x00FF
;
/* Manufac ID */
WOutDev
[
i
].
caps
.
wPid
=
0x0001
;
/* Product ID */
/* strcpy(WOutDev[i].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/
strcpy
(
WOutDev
[
i
].
caps
.
szPname
,
"CS4236/37/38"
);
#endif
snprintf
(
WOutDev
[
i
].
interface_name
,
sizeof
(
WOutDev
[
i
].
interface_name
),
"wineesd: %d"
,
i
);
WOutDev
[
i
].
caps
.
vDriverVersion
=
0x0100
;
WOutDev
[
i
].
caps
.
dwFormats
=
0x00000000
;
WOutDev
[
i
].
caps
.
dwSupport
=
WAVECAPS_VOLUME
;
WOutDev
[
i
].
caps
.
wChannels
=
2
;
WOutDev
[
i
].
caps
.
dwSupport
|=
WAVECAPS_LRVOLUME
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_4M08
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_4S08
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_4S16
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_4M16
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_2M08
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_2S08
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_2M16
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_2S16
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_1M08
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_1S08
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_1M16
;
WOutDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_1S16
;
}
for
(
i
=
0
;
i
<
MAX_WAVEINDRV
;
++
i
)
{
WInDev
[
i
].
esd_fd
=
-
1
;
memset
(
&
WInDev
[
i
].
caps
,
0
,
sizeof
(
WInDev
[
i
].
caps
));
/* zero out
caps values */
/* FIXME: some programs compare this string against the content of the registry
* for MM drivers. The names have to match in order for the program to work
* (e.g. MS win9x mplayer.exe)
*/
#ifdef EMULATE_SB16
WInDev
[
i
].
caps
.
wMid
=
0x0002
;
WInDev
[
i
].
caps
.
wPid
=
0x0104
;
strcpy
(
WInDev
[
i
].
caps
.
szPname
,
"SB16 Wave In"
);
#else
WInDev
[
i
].
caps
.
wMid
=
0x00FF
;
WInDev
[
i
].
caps
.
wPid
=
0x0001
;
strcpy
(
WInDev
[
i
].
caps
.
szPname
,
"CS4236/37/38"
);
#endif
snprintf
(
WInDev
[
i
].
interface_name
,
sizeof
(
WInDev
[
i
].
interface_name
),
"wineesd: %d"
,
i
);
WInDev
[
i
].
caps
.
vDriverVersion
=
0x0100
;
WInDev
[
i
].
caps
.
dwFormats
=
0x00000000
;
WInDev
[
i
].
caps
.
wChannels
=
2
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_4M08
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_4S08
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_4S16
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_4M16
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_2M08
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_2S08
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_2M16
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_2S16
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_1M08
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_1S08
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_1M16
;
WInDev
[
i
].
caps
.
dwFormats
|=
WAVE_FORMAT_1S16
;
WInDev
[
i
].
caps
.
wReserved1
=
0
;
}
return
0
;
}
/******************************************************************
* ESD_InitRingMessage
*
* Initialize the ring of messages for passing between driver's caller and playback/record
* thread
*/
static
int
ESD_InitRingMessage
(
ESD_MSG_RING
*
mr
)
{
mr
->
msg_toget
=
0
;
mr
->
msg_tosave
=
0
;
mr
->
msg_event
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
mr
->
ring_buffer_size
=
ESD_RING_BUFFER_INCREMENT
;
mr
->
messages
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
mr
->
ring_buffer_size
*
sizeof
(
RING_MSG
));
InitializeCriticalSection
(
&
mr
->
msg_crst
);
return
0
;
}
/******************************************************************
* ESD_DestroyRingMessage
*
*/
static
int
ESD_DestroyRingMessage
(
ESD_MSG_RING
*
mr
)
{
CloseHandle
(
mr
->
msg_event
);
HeapFree
(
GetProcessHeap
(),
0
,
mr
->
messages
);
mr
->
messages
=
NULL
;
DeleteCriticalSection
(
&
mr
->
msg_crst
);
return
0
;
}
/******************************************************************
* ESD_AddRingMessage
*
* Inserts a new message into the ring (should be called from DriverProc derivated routines)
*/
static
int
ESD_AddRingMessage
(
ESD_MSG_RING
*
mr
,
enum
win_wm_message
msg
,
DWORD
param
,
BOOL
wait
)
{
HANDLE
hEvent
=
INVALID_HANDLE_VALUE
;
EnterCriticalSection
(
&
mr
->
msg_crst
);
if
((
mr
->
msg_toget
==
((
mr
->
msg_tosave
+
1
)
%
mr
->
ring_buffer_size
)))
{
int
old_ring_buffer_size
=
mr
->
ring_buffer_size
;
mr
->
ring_buffer_size
+=
ESD_RING_BUFFER_INCREMENT
;
TRACE
(
"mr->ring_buffer_size=%d
\n
"
,
mr
->
ring_buffer_size
);
mr
->
messages
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
mr
->
messages
,
mr
->
ring_buffer_size
*
sizeof
(
RING_MSG
));
/* Now we need to rearrange the ring buffer so that the new
buffers just allocated are in between mr->msg_tosave and
mr->msg_toget.
*/
if
(
mr
->
msg_tosave
<
mr
->
msg_toget
)
{
memmove
(
&
(
mr
->
messages
[
mr
->
msg_toget
+
ESD_RING_BUFFER_INCREMENT
]),
&
(
mr
->
messages
[
mr
->
msg_toget
]),
sizeof
(
RING_MSG
)
*
(
old_ring_buffer_size
-
mr
->
msg_toget
)
);
mr
->
msg_toget
+=
ESD_RING_BUFFER_INCREMENT
;
}
}
if
(
wait
)
{
hEvent
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
if
(
hEvent
==
INVALID_HANDLE_VALUE
)
{
ERR
(
"can't create event !?
\n
"
);
LeaveCriticalSection
(
&
mr
->
msg_crst
);
return
0
;
}
if
(
mr
->
msg_toget
!=
mr
->
msg_tosave
&&
mr
->
messages
[
mr
->
msg_toget
].
msg
!=
WINE_WM_HEADER
)
FIXME
(
"two fast messages in the queue!!!!
\n
"
);
/* fast messages have to be added at the start of the queue */
mr
->
msg_toget
=
(
mr
->
msg_toget
+
mr
->
ring_buffer_size
-
1
)
%
mr
->
ring_buffer_size
;
mr
->
messages
[
mr
->
msg_toget
].
msg
=
msg
;
mr
->
messages
[
mr
->
msg_toget
].
param
=
param
;
mr
->
messages
[
mr
->
msg_toget
].
hEvent
=
hEvent
;
}
else
{
mr
->
messages
[
mr
->
msg_tosave
].
msg
=
msg
;
mr
->
messages
[
mr
->
msg_tosave
].
param
=
param
;
mr
->
messages
[
mr
->
msg_tosave
].
hEvent
=
INVALID_HANDLE_VALUE
;
mr
->
msg_tosave
=
(
mr
->
msg_tosave
+
1
)
%
mr
->
ring_buffer_size
;
}
LeaveCriticalSection
(
&
mr
->
msg_crst
);
SetEvent
(
mr
->
msg_event
);
/* signal a new message */
if
(
wait
)
{
/* wait for playback/record thread to have processed the message */
WaitForSingleObject
(
hEvent
,
INFINITE
);
CloseHandle
(
hEvent
);
}
return
1
;
}
/******************************************************************
* ESD_RetrieveRingMessage
*
* Get a message from the ring. Should be called by the playback/record thread.
*/
static
int
ESD_RetrieveRingMessage
(
ESD_MSG_RING
*
mr
,
enum
win_wm_message
*
msg
,
DWORD
*
param
,
HANDLE
*
hEvent
)
{
EnterCriticalSection
(
&
mr
->
msg_crst
);
if
(
mr
->
msg_toget
==
mr
->
msg_tosave
)
/* buffer empty ? */
{
LeaveCriticalSection
(
&
mr
->
msg_crst
);
return
0
;
}
*
msg
=
mr
->
messages
[
mr
->
msg_toget
].
msg
;
mr
->
messages
[
mr
->
msg_toget
].
msg
=
0
;
*
param
=
mr
->
messages
[
mr
->
msg_toget
].
param
;
*
hEvent
=
mr
->
messages
[
mr
->
msg_toget
].
hEvent
;
mr
->
msg_toget
=
(
mr
->
msg_toget
+
1
)
%
mr
->
ring_buffer_size
;
LeaveCriticalSection
(
&
mr
->
msg_crst
);
return
1
;
}
/*======================================================================*
* Low level WAVE OUT implementation *
*======================================================================*/
/**************************************************************************
* wodNotifyClient [internal]
*/
static
DWORD
wodNotifyClient
(
WINE_WAVEOUT
*
wwo
,
WORD
wMsg
,
DWORD
dwParam1
,
DWORD
dwParam2
)
{
TRACE
(
"wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX
\n
"
,
wMsg
,
dwParam1
,
dwParam2
);
switch
(
wMsg
)
{
case
WOM_OPEN
:
case
WOM_CLOSE
:
case
WOM_DONE
:
if
(
wwo
->
wFlags
!=
DCB_NULL
&&
!
DriverCallback
(
wwo
->
waveDesc
.
dwCallback
,
wwo
->
wFlags
,
(
HDRVR
)
wwo
->
waveDesc
.
hWave
,
wMsg
,
wwo
->
waveDesc
.
dwInstance
,
dwParam1
,
dwParam2
))
{
WARN
(
"can't notify client !
\n
"
);
return
MMSYSERR_ERROR
;
}
break
;
default:
FIXME
(
"Unknown callback message %u
\n
"
,
wMsg
);
return
MMSYSERR_INVALPARAM
;
}
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodUpdatePlayedTotal [internal]
*
*/
static
BOOL
wodUpdatePlayedTotal
(
WINE_WAVEOUT
*
wwo
)
{
/* total played is the bytes written less the bytes to write ;-) */
wwo
->
dwPlayedTotal
=
wwo
->
dwWrittenTotal
;
return
TRUE
;
}
/**************************************************************************
* wodPlayer_BeginWaveHdr [internal]
*
* Makes the specified lpWaveHdr the currently playing wave header.
* If the specified wave header is a begin loop and we're not already in
* a loop, setup the loop.
*/
static
void
wodPlayer_BeginWaveHdr
(
WINE_WAVEOUT
*
wwo
,
LPWAVEHDR
lpWaveHdr
)
{
wwo
->
lpPlayPtr
=
lpWaveHdr
;
if
(
!
lpWaveHdr
)
return
;
if
(
lpWaveHdr
->
dwFlags
&
WHDR_BEGINLOOP
)
{
if
(
wwo
->
lpLoopPtr
)
{
WARN
(
"Already in a loop. Discarding loop on this header (%p)
\n
"
,
lpWaveHdr
);
TRACE
(
"Already in a loop. Discarding loop on this header (%p)
\n
"
,
lpWaveHdr
);
}
else
{
TRACE
(
"Starting loop (%ldx) with %p
\n
"
,
lpWaveHdr
->
dwLoops
,
lpWaveHdr
);
wwo
->
lpLoopPtr
=
lpWaveHdr
;
/* Windows does not touch WAVEHDR.dwLoops,
* so we need to make an internal copy */
wwo
->
dwLoops
=
lpWaveHdr
->
dwLoops
;
}
}
wwo
->
dwPartialOffset
=
0
;
}
/**************************************************************************
* wodPlayer_PlayPtrNext [internal]
*
* Advance the play pointer to the next waveheader, looping if required.
*/
static
LPWAVEHDR
wodPlayer_PlayPtrNext
(
WINE_WAVEOUT
*
wwo
)
{
LPWAVEHDR
lpWaveHdr
=
wwo
->
lpPlayPtr
;
wwo
->
dwPartialOffset
=
0
;
if
((
lpWaveHdr
->
dwFlags
&
WHDR_ENDLOOP
)
&&
wwo
->
lpLoopPtr
)
{
/* We're at the end of a loop, loop if required */
if
(
--
wwo
->
dwLoops
>
0
)
{
wwo
->
lpPlayPtr
=
wwo
->
lpLoopPtr
;
}
else
{
/* Handle overlapping loops correctly */
if
(
wwo
->
lpLoopPtr
!=
lpWaveHdr
&&
(
lpWaveHdr
->
dwFlags
&
WHDR_BEGINLOOP
))
{
FIXME
(
"Correctly handled case ? (ending loop buffer also starts a new loop)
\n
"
);
/* shall we consider the END flag for the closing loop or for
* the opening one or for both ???
* code assumes for closing loop only
*/
}
else
{
lpWaveHdr
=
lpWaveHdr
->
lpNext
;
}
wwo
->
lpLoopPtr
=
NULL
;
wodPlayer_BeginWaveHdr
(
wwo
,
lpWaveHdr
);
}
}
else
{
/* We're not in a loop. Advance to the next wave header */
wodPlayer_BeginWaveHdr
(
wwo
,
lpWaveHdr
=
lpWaveHdr
->
lpNext
);
}
return
lpWaveHdr
;
}
/**************************************************************************
* wodPlayer_NotifyWait [internal]
* Returns the number of milliseconds to wait before attempting to notify
* completion of the specified wavehdr.
* This is based on the number of bytes remaining to be written in the
* wave.
*/
static
DWORD
wodPlayer_NotifyWait
(
const
WINE_WAVEOUT
*
wwo
,
LPWAVEHDR
lpWaveHdr
)
{
DWORD
dwMillis
;
if
(
lpWaveHdr
->
reserved
<
wwo
->
dwPlayedTotal
)
{
dwMillis
=
1
;
}
else
{
dwMillis
=
(
lpWaveHdr
->
reserved
-
wwo
->
dwPlayedTotal
)
*
1000
/
wwo
->
format
.
wf
.
nAvgBytesPerSec
;
if
(
!
dwMillis
)
dwMillis
=
1
;
}
TRACE
(
"dwMillis = %ld
\n
"
,
dwMillis
);
return
dwMillis
;
}
/**************************************************************************
* wodPlayer_WriteMaxFrags [internal]
* Writes the maximum number of bytes possible to the DSP and returns
* the number of bytes written.
*/
static
int
wodPlayer_WriteMaxFrags
(
WINE_WAVEOUT
*
wwo
,
DWORD
*
bytes
)
{
/* Only attempt to write to free bytes */
DWORD
dwLength
=
wwo
->
lpPlayPtr
->
dwBufferLength
-
wwo
->
dwPartialOffset
;
int
toWrite
=
min
(
dwLength
,
*
bytes
);
int
written
;
TRACE
(
"Writing wavehdr %p.%lu[%lu]
\n
"
,
wwo
->
lpPlayPtr
,
wwo
->
dwPartialOffset
,
wwo
->
lpPlayPtr
->
dwBufferLength
);
/* see if our buffer isn't large enough for the data we are writing */
if
(
wwo
->
buffer_size
<
toWrite
)
{
if
(
wwo
->
sound_buffer
)
{
wwo
->
sound_buffer
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
wwo
->
sound_buffer
,
toWrite
);
wwo
->
buffer_size
=
toWrite
;
}
}
/* if we don't have a buffer then get one */
if
(
!
wwo
->
sound_buffer
)
{
/* allocate some memory for the buffer */
wwo
->
sound_buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
toWrite
);
wwo
->
buffer_size
=
toWrite
;
}
/* if we don't have a buffer then error out */
if
(
!
wwo
->
sound_buffer
)
{
ERR
(
"error allocating sound_buffer memory
\n
"
);
return
0
;
}
TRACE
(
"toWrite == %d
\n
"
,
toWrite
);
/* apply volume to the bits */
/* for single channel audio streams we only use the LEFT volume */
if
(
wwo
->
format
.
wBitsPerSample
==
16
)
{
/* apply volume to the buffer we are about to send */
/* divide toWrite(bytes) by 2 as volume processes by 16 bits */
volume_effect16
(
wwo
->
lpPlayPtr
->
lpData
+
wwo
->
dwPartialOffset
,
wwo
->
sound_buffer
,
toWrite
>>
1
,
wwo
->
volume_left
,
wwo
->
volume_right
,
wwo
->
format
.
wf
.
nChannels
);
}
else
if
(
wwo
->
format
.
wBitsPerSample
==
8
)
{
/* apply volume to the buffer we are about to send */
volume_effect8
(
wwo
->
lpPlayPtr
->
lpData
+
wwo
->
dwPartialOffset
,
wwo
->
sound_buffer
,
toWrite
,
wwo
->
volume_left
,
wwo
->
volume_right
,
wwo
->
format
.
wf
.
nChannels
);
}
else
{
FIXME
(
"unsupported wwo->format.wBitsPerSample of %d
\n
"
,
wwo
->
format
.
wBitsPerSample
);
}
/* send the audio data to esd for playing */
written
=
write
(
wwo
->
esd_fd
,
wwo
->
sound_buffer
,
toWrite
);
TRACE
(
"written = %d
\n
"
,
written
);
if
(
written
<=
0
)
{
*
bytes
=
0
;
/* apparently esd is actually full */
return
written
;
/* if we wrote nothing just return */
}
if
(
written
>=
dwLength
)
wodPlayer_PlayPtrNext
(
wwo
);
/* If we wrote all current wavehdr, skip to the next one */
else
wwo
->
dwPartialOffset
+=
written
;
/* Remove the amount written */
if
(
written
<
toWrite
)
*
bytes
=
0
;
else
*
bytes
-=
written
;
wwo
->
dwWrittenTotal
+=
written
;
/* update stats on this wave device */
return
written
;
/* return the number of bytes written */
}
/**************************************************************************
* wodPlayer_NotifyCompletions [internal]
*
* Notifies and remove from queue all wavehdrs which have been played to
* the speaker (ie. they have cleared the audio device). If force is true,
* we notify all wavehdrs and remove them all from the queue even if they
* are unplayed or part of a loop.
*/
static
DWORD
wodPlayer_NotifyCompletions
(
WINE_WAVEOUT
*
wwo
,
BOOL
force
)
{
LPWAVEHDR
lpWaveHdr
;
if
(
wwo
->
lpQueuePtr
)
{
TRACE
(
"lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p), reserved=(%ld), dwWrittenTotal=(%ld), force=(%d)
\n
"
,
wwo
->
lpQueuePtr
,
wwo
->
lpPlayPtr
,
wwo
->
lpLoopPtr
,
wwo
->
lpQueuePtr
->
reserved
,
wwo
->
dwWrittenTotal
,
force
);
}
else
{
TRACE
(
"lpWaveHdr=(%p), lpPlayPtr=(%p), lpLoopPtr=(%p), dwWrittenTotal=(%ld), force=(%d)
\n
"
,
wwo
->
lpQueuePtr
,
wwo
->
lpPlayPtr
,
wwo
->
lpLoopPtr
,
wwo
->
dwWrittenTotal
,
force
);
}
/* Start from lpQueuePtr and keep notifying until:
* - we hit an unwritten wavehdr
* - we hit the beginning of a running loop
* - we hit a wavehdr which hasn't finished playing
*/
while
((
lpWaveHdr
=
wwo
->
lpQueuePtr
)
&&
(
force
||
(
lpWaveHdr
!=
wwo
->
lpPlayPtr
&&
lpWaveHdr
!=
wwo
->
lpLoopPtr
&&
lpWaveHdr
->
reserved
<=
wwo
->
dwWrittenTotal
)))
{
wwo
->
lpQueuePtr
=
lpWaveHdr
->
lpNext
;
lpWaveHdr
->
dwFlags
&=
~
WHDR_INQUEUE
;
lpWaveHdr
->
dwFlags
|=
WHDR_DONE
;
wodNotifyClient
(
wwo
,
WOM_DONE
,
(
DWORD
)
lpWaveHdr
,
0
);
}
return
(
lpWaveHdr
&&
lpWaveHdr
!=
wwo
->
lpPlayPtr
&&
lpWaveHdr
!=
wwo
->
lpLoopPtr
)
?
wodPlayer_NotifyWait
(
wwo
,
lpWaveHdr
)
:
INFINITE
;
}
/**************************************************************************
* wodPlayer_Reset [internal]
*
* wodPlayer helper. Resets current output stream.
*/
static
void
wodPlayer_Reset
(
WINE_WAVEOUT
*
wwo
,
BOOL
reset
)
{
wodUpdatePlayedTotal
(
wwo
);
wodPlayer_NotifyCompletions
(
wwo
,
FALSE
);
/* updates current notify list */
/* we aren't able to flush any data that has already been written */
/* to esd, otherwise we would do the flushing here */
if
(
reset
)
{
enum
win_wm_message
msg
;
DWORD
param
;
HANDLE
ev
;
/* remove any buffer */
wodPlayer_NotifyCompletions
(
wwo
,
TRUE
);
wwo
->
lpPlayPtr
=
wwo
->
lpQueuePtr
=
wwo
->
lpLoopPtr
=
NULL
;
wwo
->
state
=
WINE_WS_STOPPED
;
wwo
->
dwPlayedTotal
=
wwo
->
dwWrittenTotal
=
0
;
wwo
->
dwPartialOffset
=
0
;
/* Clear partial wavehdr */
/* remove any existing message in the ring */
EnterCriticalSection
(
&
wwo
->
msgRing
.
msg_crst
);
/* return all pending headers in queue */
while
(
ESD_RetrieveRingMessage
(
&
wwo
->
msgRing
,
&
msg
,
&
param
,
&
ev
))
{
TRACE
(
"flushing msg
\n
"
);
if
(
msg
!=
WINE_WM_HEADER
)
{
FIXME
(
"shouldn't have headers left
\n
"
);
SetEvent
(
ev
);
continue
;
}
((
LPWAVEHDR
)
param
)
->
dwFlags
&=
~
WHDR_INQUEUE
;
((
LPWAVEHDR
)
param
)
->
dwFlags
|=
WHDR_DONE
;
wodNotifyClient
(
wwo
,
WOM_DONE
,
param
,
0
);
}
ResetEvent
(
wwo
->
msgRing
.
msg_event
);
LeaveCriticalSection
(
&
wwo
->
msgRing
.
msg_crst
);
}
else
{
if
(
wwo
->
lpLoopPtr
)
{
/* complicated case, not handled yet (could imply modifying the loop counter */
FIXME
(
"Pausing while in loop isn't correctly handled yet, except strange results
\n
"
);
wwo
->
lpPlayPtr
=
wwo
->
lpLoopPtr
;
wwo
->
dwPartialOffset
=
0
;
wwo
->
dwWrittenTotal
=
wwo
->
dwPlayedTotal
;
/* this is wrong !!! */
}
else
{
/* the data already written is going to be played, so take */
/* this fact into account here */
wwo
->
dwPlayedTotal
=
wwo
->
dwWrittenTotal
;
}
wwo
->
state
=
WINE_WS_PAUSED
;
}
}
/**************************************************************************
* wodPlayer_ProcessMessages [internal]
*/
static
void
wodPlayer_ProcessMessages
(
WINE_WAVEOUT
*
wwo
)
{
LPWAVEHDR
lpWaveHdr
;
enum
win_wm_message
msg
;
DWORD
param
;
HANDLE
ev
;
while
(
ESD_RetrieveRingMessage
(
&
wwo
->
msgRing
,
&
msg
,
&
param
,
&
ev
))
{
TRACE
(
"Received %s %lx
\n
"
,
wodPlayerCmdString
[
msg
-
WM_USER
-
1
],
param
);
switch
(
msg
)
{
case
WINE_WM_PAUSING
:
wodPlayer_Reset
(
wwo
,
FALSE
);
SetEvent
(
ev
);
break
;
case
WINE_WM_RESTARTING
:
wwo
->
state
=
WINE_WS_PLAYING
;
SetEvent
(
ev
);
break
;
case
WINE_WM_HEADER
:
lpWaveHdr
=
(
LPWAVEHDR
)
param
;
/* insert buffer at the end of queue */
{
LPWAVEHDR
*
wh
;
for
(
wh
=
&
(
wwo
->
lpQueuePtr
);
*
wh
;
wh
=
&
((
*
wh
)
->
lpNext
));
*
wh
=
lpWaveHdr
;
}
if
(
!
wwo
->
lpPlayPtr
)
wodPlayer_BeginWaveHdr
(
wwo
,
lpWaveHdr
);
if
(
wwo
->
state
==
WINE_WS_STOPPED
)
wwo
->
state
=
WINE_WS_PLAYING
;
break
;
case
WINE_WM_RESETTING
:
wodPlayer_Reset
(
wwo
,
TRUE
);
SetEvent
(
ev
);
break
;
case
WINE_WM_UPDATE
:
wodUpdatePlayedTotal
(
wwo
);
SetEvent
(
ev
);
break
;
case
WINE_WM_BREAKLOOP
:
if
(
wwo
->
state
==
WINE_WS_PLAYING
&&
wwo
->
lpLoopPtr
!=
NULL
)
{
/* ensure exit at end of current loop */
wwo
->
dwLoops
=
1
;
}
SetEvent
(
ev
);
break
;
case
WINE_WM_CLOSING
:
/* sanity check: this should not happen since the device must have been reset before */
if
(
wwo
->
lpQueuePtr
||
wwo
->
lpPlayPtr
)
ERR
(
"out of sync
\n
"
);
wwo
->
hThread
=
0
;
wwo
->
state
=
WINE_WS_CLOSED
;
SetEvent
(
ev
);
ExitThread
(
0
);
/* shouldn't go here */
default:
FIXME
(
"unknown message %d
\n
"
,
msg
);
break
;
}
}
}
/**************************************************************************
* wodPlayer_FeedDSP [internal]
* Feed as much sound data as we can into the DSP and return the number of
* milliseconds before it will be necessary to feed the DSP again.
*/
static
DWORD
wodPlayer_FeedDSP
(
WINE_WAVEOUT
*
wwo
)
{
DWORD
availInQ
;
wodUpdatePlayedTotal
(
wwo
);
/* better way to set availInQ? */
availInQ
=
ESD_BUF_SIZE
;
TRACE
(
"availInQ = %ld
\n
"
,
availInQ
);
/* input queue empty */
if
(
!
wwo
->
lpPlayPtr
)
{
TRACE
(
"Run out of wavehdr:s... flushing
\n
"
);
return
INFINITE
;
}
#if 0
/* no more room... no need to try to feed */
if(!availInQ)
{
TRACE("no more room, no need to try to feed\n");
return wwo->dwSleepTime;
}
#endif
/* Feed from partial wavehdr */
if
(
wwo
->
lpPlayPtr
&&
wwo
->
dwPartialOffset
!=
0
)
{
TRACE
(
"feeding from partial wavehdr
\n
"
);
wodPlayer_WriteMaxFrags
(
wwo
,
&
availInQ
);
}
/* Feed wavehdrs until we run out of wavehdrs or DSP space */
if
(
!
wwo
->
dwPartialOffset
)
{
while
(
wwo
->
lpPlayPtr
&&
availInQ
)
{
TRACE
(
"feeding waveheaders until we run out of space
\n
"
);
/* note the value that dwPlayedTotal will return when this wave finishes playing */
wwo
->
lpPlayPtr
->
reserved
=
wwo
->
dwWrittenTotal
+
wwo
->
lpPlayPtr
->
dwBufferLength
;
TRACE
(
"reserved=(%ld) dwWrittenTotal=(%ld) dwBufferLength=(%ld)
\n
"
,
wwo
->
lpPlayPtr
->
reserved
,
wwo
->
dwWrittenTotal
,
wwo
->
lpPlayPtr
->
dwBufferLength
);
wodPlayer_WriteMaxFrags
(
wwo
,
&
availInQ
);
}
}
if
(
!
wwo
->
lpPlayPtr
)
{
TRACE
(
"Ran out of wavehdrs
\n
"
);
return
INFINITE
;
}
return
wwo
->
dwSleepTime
;
}
/**************************************************************************
* wodPlayer [internal]
*/
static
DWORD
CALLBACK
wodPlayer
(
LPVOID
pmt
)
{
WORD
uDevID
=
(
DWORD
)
pmt
;
WINE_WAVEOUT
*
wwo
=
(
WINE_WAVEOUT
*
)
&
WOutDev
[
uDevID
];
DWORD
dwNextFeedTime
=
INFINITE
;
/* Time before DSP needs feeding */
DWORD
dwNextNotifyTime
=
INFINITE
;
/* Time before next wave completion */
DWORD
dwSleepTime
;
wwo
->
state
=
WINE_WS_STOPPED
;
SetEvent
(
wwo
->
hStartUpEvent
);
for
(;;)
{
/** Wait for the shortest time before an action is required. If there
* are no pending actions, wait forever for a command.
*/
dwSleepTime
=
min
(
dwNextFeedTime
,
dwNextNotifyTime
);
TRACE
(
"waiting %lums (%lu,%lu)
\n
"
,
dwSleepTime
,
dwNextFeedTime
,
dwNextNotifyTime
);
WaitForSingleObject
(
wwo
->
msgRing
.
msg_event
,
dwSleepTime
);
wodPlayer_ProcessMessages
(
wwo
);
if
(
wwo
->
state
==
WINE_WS_PLAYING
)
{
dwNextFeedTime
=
wodPlayer_FeedDSP
(
wwo
);
dwNextNotifyTime
=
wodPlayer_NotifyCompletions
(
wwo
,
FALSE
);
}
else
{
dwNextFeedTime
=
dwNextNotifyTime
=
INFINITE
;
}
}
}
/**************************************************************************
* wodGetDevCaps [internal]
*/
static
DWORD
wodGetDevCaps
(
WORD
wDevID
,
LPWAVEOUTCAPSA
lpCaps
,
DWORD
dwSize
)
{
TRACE
(
"(%u, %p, %lu);
\n
"
,
wDevID
,
lpCaps
,
dwSize
);
if
(
lpCaps
==
NULL
)
return
MMSYSERR_NOTENABLED
;
if
(
wDevID
>=
MAX_WAVEOUTDRV
)
{
TRACE
(
"MAX_WAVOUTDRV reached !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
memcpy
(
lpCaps
,
&
WOutDev
[
wDevID
].
caps
,
min
(
dwSize
,
sizeof
(
*
lpCaps
)));
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodOpen [internal]
*/
static
DWORD
wodOpen
(
WORD
wDevID
,
LPWAVEOPENDESC
lpDesc
,
DWORD
dwFlags
)
{
WINE_WAVEOUT
*
wwo
;
/* output to esound... */
int
out_bits
=
ESD_BITS8
,
out_channels
=
ESD_MONO
,
out_rate
;
int
out_mode
=
ESD_STREAM
,
out_func
=
ESD_PLAY
;
esd_format_t
out_format
;
TRACE
(
"(%u, %p, %08lX);
\n
"
,
wDevID
,
lpDesc
,
dwFlags
);
if
(
lpDesc
==
NULL
)
{
WARN
(
"Invalid Parameter !
\n
"
);
return
MMSYSERR_INVALPARAM
;
}
if
(
wDevID
>=
MAX_WAVEOUTDRV
)
{
TRACE
(
"MAX_WAVOUTDRV reached !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
/* if this device is already open tell the app that it is allocated */
if
(
WOutDev
[
wDevID
].
esd_fd
!=
-
1
)
{
TRACE
(
"device already allocated
\n
"
);
return
MMSYSERR_ALLOCATED
;
}
/* only PCM format is supported so far... */
if
(
lpDesc
->
lpFormat
->
wFormatTag
!=
WAVE_FORMAT_PCM
||
lpDesc
->
lpFormat
->
nChannels
==
0
||
lpDesc
->
lpFormat
->
nSamplesPerSec
<
DSBFREQUENCY_MIN
||
lpDesc
->
lpFormat
->
nSamplesPerSec
>
DSBFREQUENCY_MAX
||
(
lpDesc
->
lpFormat
->
wBitsPerSample
!=
8
&&
lpDesc
->
lpFormat
->
wBitsPerSample
!=
16
))
{
WARN
(
"Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !
\n
"
,
lpDesc
->
lpFormat
->
wFormatTag
,
lpDesc
->
lpFormat
->
nChannels
,
lpDesc
->
lpFormat
->
nSamplesPerSec
);
return
WAVERR_BADFORMAT
;
}
if
(
dwFlags
&
WAVE_FORMAT_QUERY
)
{
TRACE
(
"Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !
\n
"
,
lpDesc
->
lpFormat
->
wFormatTag
,
lpDesc
->
lpFormat
->
nChannels
,
lpDesc
->
lpFormat
->
nSamplesPerSec
);
return
MMSYSERR_NOERROR
;
}
wwo
=
&
WOutDev
[
wDevID
];
/* direct sound not supported, ignore the flag */
dwFlags
&=
~
WAVE_DIRECTSOUND
;
wwo
->
wFlags
=
HIWORD
(
dwFlags
&
CALLBACK_TYPEMASK
);
memcpy
(
&
wwo
->
waveDesc
,
lpDesc
,
sizeof
(
WAVEOPENDESC
));
memcpy
(
&
wwo
->
format
,
lpDesc
->
lpFormat
,
sizeof
(
PCMWAVEFORMAT
));
if
(
wwo
->
format
.
wBitsPerSample
==
0
)
{
WARN
(
"Resetting zeroed wBitsPerSample
\n
"
);
wwo
->
format
.
wBitsPerSample
=
8
*
(
wwo
->
format
.
wf
.
nAvgBytesPerSec
/
wwo
->
format
.
wf
.
nSamplesPerSec
)
/
wwo
->
format
.
wf
.
nChannels
;
}
if
(
wwo
->
format
.
wBitsPerSample
==
8
)
out_bits
=
ESD_BITS8
;
else
if
(
wwo
->
format
.
wBitsPerSample
==
16
)
out_bits
=
ESD_BITS16
;
wwo
->
bytes_per_frame
=
(
wwo
->
format
.
wBitsPerSample
*
wwo
->
format
.
wf
.
nChannels
)
/
8
;
if
(
wwo
->
format
.
wf
.
nChannels
==
1
)
out_channels
=
ESD_MONO
;
else
if
(
wwo
->
format
.
wf
.
nChannels
==
2
)
out_channels
=
ESD_STEREO
;
out_format
=
out_bits
|
out_channels
|
out_mode
|
out_func
;
out_rate
=
(
int
)
wwo
->
format
.
wf
.
nSamplesPerSec
;
TRACE
(
"esd output format = 0x%08x, rate = %d
\n
"
,
out_format
,
out_rate
);
wwo
->
esd_fd
=
esd_play_stream
(
out_format
,
out_rate
,
esd_host
,
"wineesd"
);
/* clear these so we don't have any confusion ;-) */
wwo
->
sound_buffer
=
0
;
wwo
->
buffer_size
=
0
;
if
(
wwo
->
esd_fd
<
0
)
return
MMSYSERR_ALLOCATED
;
wwo
->
dwBufferSize
=
ESD_BUF_SIZE
;
TRACE
(
"Buffer size is now (%ld)
\n
"
,
wwo
->
dwBufferSize
);
wwo
->
dwPlayedTotal
=
0
;
wwo
->
dwWrittenTotal
=
0
;
wwo
->
dwSleepTime
=
(
1024
*
1000
*
BUFFER_REFILL_THRESHOLD
)
/
wwo
->
format
.
wf
.
nAvgBytesPerSec
;
/* Initialize volume to full level */
wwo
->
volume_left
=
100
;
wwo
->
volume_right
=
100
;
ESD_InitRingMessage
(
&
wwo
->
msgRing
);
/* create player thread */
if
(
!
(
dwFlags
&
WAVE_DIRECTSOUND
))
{
wwo
->
hStartUpEvent
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
wwo
->
hThread
=
CreateThread
(
NULL
,
0
,
wodPlayer
,
(
LPVOID
)(
DWORD
)
wDevID
,
0
,
&
(
wwo
->
dwThreadID
));
WaitForSingleObject
(
wwo
->
hStartUpEvent
,
INFINITE
);
CloseHandle
(
wwo
->
hStartUpEvent
);
}
else
{
wwo
->
hThread
=
INVALID_HANDLE_VALUE
;
wwo
->
dwThreadID
=
0
;
}
wwo
->
hStartUpEvent
=
INVALID_HANDLE_VALUE
;
TRACE
(
"esd=0x%lx, dwBufferSize=%ld
\n
"
,
(
long
)
wwo
->
esd_fd
,
wwo
->
dwBufferSize
);
TRACE
(
"wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!
\n
"
,
wwo
->
format
.
wBitsPerSample
,
wwo
->
format
.
wf
.
nAvgBytesPerSec
,
wwo
->
format
.
wf
.
nSamplesPerSec
,
wwo
->
format
.
wf
.
nChannels
,
wwo
->
format
.
wf
.
nBlockAlign
);
return
wodNotifyClient
(
wwo
,
WOM_OPEN
,
0L
,
0L
);
}
/**************************************************************************
* wodClose [internal]
*/
static
DWORD
wodClose
(
WORD
wDevID
)
{
DWORD
ret
=
MMSYSERR_NOERROR
;
WINE_WAVEOUT
*
wwo
;
TRACE
(
"(%u);
\n
"
,
wDevID
);
if
(
wDevID
>=
MAX_WAVEOUTDRV
||
WOutDev
[
wDevID
].
esd_fd
==
-
1
)
{
WARN
(
"bad device ID !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
wwo
=
&
WOutDev
[
wDevID
];
if
(
wwo
->
lpQueuePtr
)
{
WARN
(
"buffers still playing !
\n
"
);
ret
=
WAVERR_STILLPLAYING
;
}
else
{
TRACE
(
"imhere[3-close]
\n
"
);
if
(
wwo
->
hThread
!=
INVALID_HANDLE_VALUE
)
{
ESD_AddRingMessage
(
&
wwo
->
msgRing
,
WINE_WM_CLOSING
,
0
,
TRUE
);
}
ESD_DestroyRingMessage
(
&
wwo
->
msgRing
);
ESD_CloseWaveOutDevice
(
wwo
);
/* close the stream and clean things up */
ret
=
wodNotifyClient
(
wwo
,
WOM_CLOSE
,
0L
,
0L
);
}
return
ret
;
}
/**************************************************************************
* wodWrite [internal]
*
*/
static
DWORD
wodWrite
(
WORD
wDevID
,
LPWAVEHDR
lpWaveHdr
,
DWORD
dwSize
)
{
TRACE
(
"(%u, %p, %08lX);
\n
"
,
wDevID
,
lpWaveHdr
,
dwSize
);
/* first, do the sanity checks... */
if
(
wDevID
>=
MAX_WAVEOUTDRV
||
WOutDev
[
wDevID
].
esd_fd
==
-
1
)
{
WARN
(
"bad dev ID !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
if
(
lpWaveHdr
->
lpData
==
NULL
||
!
(
lpWaveHdr
->
dwFlags
&
WHDR_PREPARED
))
{
TRACE
(
"unprepared
\n
"
);
return
WAVERR_UNPREPARED
;
}
if
(
lpWaveHdr
->
dwFlags
&
WHDR_INQUEUE
)
{
TRACE
(
"still playing
\n
"
);
return
WAVERR_STILLPLAYING
;
}
lpWaveHdr
->
dwFlags
&=
~
WHDR_DONE
;
lpWaveHdr
->
dwFlags
|=
WHDR_INQUEUE
;
lpWaveHdr
->
lpNext
=
0
;
TRACE
(
"adding ring message
\n
"
);
ESD_AddRingMessage
(
&
WOutDev
[
wDevID
].
msgRing
,
WINE_WM_HEADER
,
(
DWORD
)
lpWaveHdr
,
FALSE
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodPrepare [internal]
*/
static
DWORD
wodPrepare
(
WORD
wDevID
,
LPWAVEHDR
lpWaveHdr
,
DWORD
dwSize
)
{
TRACE
(
"(%u, %p, %08lX);
\n
"
,
wDevID
,
lpWaveHdr
,
dwSize
);
if
(
wDevID
>=
MAX_WAVEOUTDRV
)
{
WARN
(
"bad device ID !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
if
(
lpWaveHdr
->
dwFlags
&
WHDR_INQUEUE
)
return
WAVERR_STILLPLAYING
;
lpWaveHdr
->
dwFlags
|=
WHDR_PREPARED
;
lpWaveHdr
->
dwFlags
&=
~
WHDR_DONE
;
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodUnprepare [internal]
*/
static
DWORD
wodUnprepare
(
WORD
wDevID
,
LPWAVEHDR
lpWaveHdr
,
DWORD
dwSize
)
{
TRACE
(
"(%u, %p, %08lX);
\n
"
,
wDevID
,
lpWaveHdr
,
dwSize
);
if
(
wDevID
>=
MAX_WAVEOUTDRV
)
{
WARN
(
"bad device ID !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
if
(
lpWaveHdr
->
dwFlags
&
WHDR_INQUEUE
)
return
WAVERR_STILLPLAYING
;
lpWaveHdr
->
dwFlags
&=
~
WHDR_PREPARED
;
lpWaveHdr
->
dwFlags
|=
WHDR_DONE
;
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodPause [internal]
*/
static
DWORD
wodPause
(
WORD
wDevID
)
{
TRACE
(
"(%u);!
\n
"
,
wDevID
);
if
(
wDevID
>=
MAX_WAVEOUTDRV
||
WOutDev
[
wDevID
].
esd_fd
==
-
1
)
{
WARN
(
"bad device ID !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
TRACE
(
"imhere[3-PAUSING]
\n
"
);
ESD_AddRingMessage
(
&
WOutDev
[
wDevID
].
msgRing
,
WINE_WM_PAUSING
,
0
,
TRUE
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodRestart [internal]
*/
static
DWORD
wodRestart
(
WORD
wDevID
)
{
TRACE
(
"(%u);
\n
"
,
wDevID
);
if
(
wDevID
>=
MAX_WAVEOUTDRV
||
WOutDev
[
wDevID
].
esd_fd
==
-
1
)
{
WARN
(
"bad device ID !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
if
(
WOutDev
[
wDevID
].
state
==
WINE_WS_PAUSED
)
{
TRACE
(
"imhere[3-RESTARTING]
\n
"
);
ESD_AddRingMessage
(
&
WOutDev
[
wDevID
].
msgRing
,
WINE_WM_RESTARTING
,
0
,
TRUE
);
}
/* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */
/* FIXME: Myst crashes with this ... hmm -MM
return wodNotifyClient(wwo, WOM_DONE, 0L, 0L);
*/
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodReset [internal]
*/
static
DWORD
wodReset
(
WORD
wDevID
)
{
TRACE
(
"(%u);
\n
"
,
wDevID
);
if
(
wDevID
>=
MAX_WAVEOUTDRV
||
WOutDev
[
wDevID
].
esd_fd
==
-
1
)
{
WARN
(
"bad device ID !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
TRACE
(
"imhere[3-RESET]
\n
"
);
ESD_AddRingMessage
(
&
WOutDev
[
wDevID
].
msgRing
,
WINE_WM_RESETTING
,
0
,
TRUE
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodGetPosition [internal]
*/
static
DWORD
wodGetPosition
(
WORD
wDevID
,
LPMMTIME
lpTime
,
DWORD
uSize
)
{
double
time
;
DWORD
val
;
WINE_WAVEOUT
*
wwo
;
TRACE
(
"(%u, %p, %lu);
\n
"
,
wDevID
,
lpTime
,
uSize
);
if
(
wDevID
>=
MAX_WAVEOUTDRV
||
WOutDev
[
wDevID
].
esd_fd
==
-
1
)
{
WARN
(
"bad device ID !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
if
(
lpTime
==
NULL
)
return
MMSYSERR_INVALPARAM
;
wwo
=
&
WOutDev
[
wDevID
];
ESD_AddRingMessage
(
&
wwo
->
msgRing
,
WINE_WM_UPDATE
,
0
,
TRUE
);
val
=
wwo
->
dwPlayedTotal
;
TRACE
(
"wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu
\n
"
,
lpTime
->
wType
,
wwo
->
format
.
wBitsPerSample
,
wwo
->
format
.
wf
.
nSamplesPerSec
,
wwo
->
format
.
wf
.
nChannels
,
wwo
->
format
.
wf
.
nAvgBytesPerSec
);
TRACE
(
"dwPlayedTotal=%lu
\n
"
,
val
);
switch
(
lpTime
->
wType
)
{
case
TIME_BYTES
:
lpTime
->
u
.
cb
=
val
;
TRACE
(
"TIME_BYTES=%lu
\n
"
,
lpTime
->
u
.
cb
);
break
;
case
TIME_SAMPLES
:
lpTime
->
u
.
sample
=
val
*
8
/
wwo
->
format
.
wBitsPerSample
/
wwo
->
format
.
wf
.
nChannels
;
TRACE
(
"TIME_SAMPLES=%lu
\n
"
,
lpTime
->
u
.
sample
);
break
;
case
TIME_SMPTE
:
time
=
(
double
)
val
/
(
double
)
wwo
->
format
.
wf
.
nAvgBytesPerSec
;
lpTime
->
u
.
smpte
.
hour
=
time
/
(
60
*
60
);
time
-=
lpTime
->
u
.
smpte
.
hour
*
(
60
*
60
);
lpTime
->
u
.
smpte
.
min
=
time
/
60
;
time
-=
lpTime
->
u
.
smpte
.
min
*
60
;
lpTime
->
u
.
smpte
.
sec
=
time
;
time
-=
lpTime
->
u
.
smpte
.
sec
;
lpTime
->
u
.
smpte
.
frame
=
ceil
(
time
*
30
);
lpTime
->
u
.
smpte
.
fps
=
30
;
TRACE
(
"TIME_SMPTE=%02u:%02u:%02u:%02u
\n
"
,
lpTime
->
u
.
smpte
.
hour
,
lpTime
->
u
.
smpte
.
min
,
lpTime
->
u
.
smpte
.
sec
,
lpTime
->
u
.
smpte
.
frame
);
break
;
default:
FIXME
(
"Format %d not supported ! use TIME_MS !
\n
"
,
lpTime
->
wType
);
lpTime
->
wType
=
TIME_MS
;
case
TIME_MS
:
lpTime
->
u
.
ms
=
val
*
1000
.
0
/
wwo
->
format
.
wf
.
nAvgBytesPerSec
;
TRACE
(
"TIME_MS=%lu
\n
"
,
lpTime
->
u
.
ms
);
break
;
}
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodBreakLoop [internal]
*/
static
DWORD
wodBreakLoop
(
WORD
wDevID
)
{
TRACE
(
"(%u);
\n
"
,
wDevID
);
if
(
wDevID
>=
MAX_WAVEOUTDRV
||
WOutDev
[
wDevID
].
esd_fd
==
-
1
)
{
WARN
(
"bad device ID !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
ESD_AddRingMessage
(
&
WOutDev
[
wDevID
].
msgRing
,
WINE_WM_BREAKLOOP
,
0
,
TRUE
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodGetVolume [internal]
*/
static
DWORD
wodGetVolume
(
WORD
wDevID
,
LPDWORD
lpdwVol
)
{
DWORD
left
,
right
;
left
=
WOutDev
[
wDevID
].
volume_left
;
right
=
WOutDev
[
wDevID
].
volume_right
;
TRACE
(
"(%u, %p);
\n
"
,
wDevID
,
lpdwVol
);
*
lpdwVol
=
((
left
*
0xFFFFl
)
/
100
)
+
(((
right
*
0xFFFFl
)
/
100
)
<<
16
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodSetVolume [internal]
*/
static
DWORD
wodSetVolume
(
WORD
wDevID
,
DWORD
dwParam
)
{
DWORD
left
,
right
;
left
=
(
LOWORD
(
dwParam
)
*
100
)
/
0xFFFFl
;
right
=
(
HIWORD
(
dwParam
)
*
100
)
/
0xFFFFl
;
TRACE
(
"(%u, %08lX);
\n
"
,
wDevID
,
dwParam
);
WOutDev
[
wDevID
].
volume_left
=
left
;
WOutDev
[
wDevID
].
volume_right
=
right
;
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodGetNumDevs [internal]
*/
static
DWORD
wodGetNumDevs
(
void
)
{
return
MAX_WAVEOUTDRV
;
}
/**************************************************************************
* wodDevInterfaceSize [internal]
*/
static
DWORD
wodDevInterfaceSize
(
UINT
wDevID
,
LPDWORD
dwParam1
)
{
TRACE
(
"(%u, %p)
\n
"
,
wDevID
,
dwParam1
);
*
dwParam1
=
MultiByteToWideChar
(
CP_ACP
,
0
,
WOutDev
[
wDevID
].
interface_name
,
-
1
,
NULL
,
0
)
*
sizeof
(
WCHAR
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* wodDevInterface [internal]
*/
static
DWORD
wodDevInterface
(
UINT
wDevID
,
PWCHAR
dwParam1
,
DWORD
dwParam2
)
{
if
(
dwParam2
>=
MultiByteToWideChar
(
CP_ACP
,
0
,
WOutDev
[
wDevID
].
interface_name
,
-
1
,
NULL
,
0
)
*
sizeof
(
WCHAR
))
{
MultiByteToWideChar
(
CP_ACP
,
0
,
WOutDev
[
wDevID
].
interface_name
,
-
1
,
dwParam1
,
dwParam2
/
sizeof
(
WCHAR
));
return
MMSYSERR_NOERROR
;
}
return
MMSYSERR_INVALPARAM
;
}
/**************************************************************************
* wodMessage (WINEESD.@)
*/
DWORD
WINAPI
ESD_wodMessage
(
UINT
wDevID
,
UINT
wMsg
,
DWORD
dwUser
,
DWORD
dwParam1
,
DWORD
dwParam2
)
{
TRACE
(
"(%u, %04X, %08lX, %08lX, %08lX);
\n
"
,
wDevID
,
wMsg
,
dwUser
,
dwParam1
,
dwParam2
);
switch
(
wMsg
)
{
case
DRVM_INIT
:
case
DRVM_EXIT
:
case
DRVM_ENABLE
:
case
DRVM_DISABLE
:
/* FIXME: Pretend this is supported */
return
0
;
case
WODM_OPEN
:
return
wodOpen
(
wDevID
,
(
LPWAVEOPENDESC
)
dwParam1
,
dwParam2
);
case
WODM_CLOSE
:
return
wodClose
(
wDevID
);
case
WODM_WRITE
:
return
wodWrite
(
wDevID
,
(
LPWAVEHDR
)
dwParam1
,
dwParam2
);
case
WODM_PAUSE
:
return
wodPause
(
wDevID
);
case
WODM_GETPOS
:
return
wodGetPosition
(
wDevID
,
(
LPMMTIME
)
dwParam1
,
dwParam2
);
case
WODM_BREAKLOOP
:
return
wodBreakLoop
(
wDevID
);
case
WODM_PREPARE
:
return
wodPrepare
(
wDevID
,
(
LPWAVEHDR
)
dwParam1
,
dwParam2
);
case
WODM_UNPREPARE
:
return
wodUnprepare
(
wDevID
,
(
LPWAVEHDR
)
dwParam1
,
dwParam2
);
case
WODM_GETDEVCAPS
:
return
wodGetDevCaps
(
wDevID
,
(
LPWAVEOUTCAPSA
)
dwParam1
,
dwParam2
);
case
WODM_GETNUMDEVS
:
return
wodGetNumDevs
();
case
WODM_GETPITCH
:
return
MMSYSERR_NOTSUPPORTED
;
case
WODM_SETPITCH
:
return
MMSYSERR_NOTSUPPORTED
;
case
WODM_GETPLAYBACKRATE
:
return
MMSYSERR_NOTSUPPORTED
;
case
WODM_SETPLAYBACKRATE
:
return
MMSYSERR_NOTSUPPORTED
;
case
WODM_GETVOLUME
:
return
wodGetVolume
(
wDevID
,
(
LPDWORD
)
dwParam1
);
case
WODM_SETVOLUME
:
return
wodSetVolume
(
wDevID
,
dwParam1
);
case
WODM_RESTART
:
return
wodRestart
(
wDevID
);
case
WODM_RESET
:
return
wodReset
(
wDevID
);
case
DRV_QUERYDEVICEINTERFACESIZE
:
return
wodDevInterfaceSize
(
wDevID
,
(
LPDWORD
)
dwParam1
);
case
DRV_QUERYDEVICEINTERFACE
:
return
wodDevInterface
(
wDevID
,
(
PWCHAR
)
dwParam1
,
dwParam2
);
case
DRV_QUERYDSOUNDIFACE
:
return
wodDsCreate
(
wDevID
,
(
PIDSDRIVER
*
)
dwParam1
);
case
DRV_QUERYDSOUNDDESC
:
return
wodDsDesc
(
wDevID
,
(
PDSDRIVERDESC
)
dwParam1
);
default:
FIXME
(
"unknown message %d!
\n
"
,
wMsg
);
}
return
MMSYSERR_NOTSUPPORTED
;
}
/*======================================================================*
* Low level WAVE IN implementation *
*======================================================================*/
/**************************************************************************
* widGetNumDevs [internal]
*/
static
DWORD
widGetNumDevs
(
void
)
{
TRACE
(
"%d
\n
"
,
MAX_WAVEINDRV
);
return
MAX_WAVEINDRV
;
}
/**************************************************************************
* widDevInterfaceSize [internal]
*/
static
DWORD
widDevInterfaceSize
(
UINT
wDevID
,
LPDWORD
dwParam1
)
{
TRACE
(
"(%u, %p)
\n
"
,
wDevID
,
dwParam1
);
*
dwParam1
=
MultiByteToWideChar
(
CP_ACP
,
0
,
WInDev
[
wDevID
].
interface_name
,
-
1
,
NULL
,
0
)
*
sizeof
(
WCHAR
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* widDevInterface [internal]
*/
static
DWORD
widDevInterface
(
UINT
wDevID
,
PWCHAR
dwParam1
,
DWORD
dwParam2
)
{
if
(
dwParam2
>=
MultiByteToWideChar
(
CP_ACP
,
0
,
WInDev
[
wDevID
].
interface_name
,
-
1
,
NULL
,
0
)
*
sizeof
(
WCHAR
))
{
MultiByteToWideChar
(
CP_ACP
,
0
,
WInDev
[
wDevID
].
interface_name
,
-
1
,
dwParam1
,
dwParam2
/
sizeof
(
WCHAR
));
return
MMSYSERR_NOERROR
;
}
return
MMSYSERR_INVALPARAM
;
}
/**************************************************************************
* widNotifyClient [internal]
*/
static
DWORD
widNotifyClient
(
WINE_WAVEIN
*
wwi
,
WORD
wMsg
,
DWORD
dwParam1
,
DWORD
dwParam2
)
{
TRACE
(
"wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX
\n
"
,
wMsg
,
dwParam1
,
dwParam2
);
switch
(
wMsg
)
{
case
WIM_OPEN
:
case
WIM_CLOSE
:
case
WIM_DATA
:
if
(
wwi
->
wFlags
!=
DCB_NULL
&&
!
DriverCallback
(
wwi
->
waveDesc
.
dwCallback
,
wwi
->
wFlags
,
(
HDRVR
)
wwi
->
waveDesc
.
hWave
,
wMsg
,
wwi
->
waveDesc
.
dwInstance
,
dwParam1
,
dwParam2
))
{
WARN
(
"can't notify client !
\n
"
);
return
MMSYSERR_ERROR
;
}
break
;
default:
FIXME
(
"Unknown callback message %u
\n
"
,
wMsg
);
return
MMSYSERR_INVALPARAM
;
}
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* widGetDevCaps [internal]
*/
static
DWORD
widGetDevCaps
(
WORD
wDevID
,
LPWAVEINCAPSA
lpCaps
,
DWORD
dwSize
)
{
TRACE
(
"(%u, %p, %lu);
\n
"
,
wDevID
,
lpCaps
,
dwSize
);
if
(
lpCaps
==
NULL
)
return
MMSYSERR_NOTENABLED
;
if
(
wDevID
>=
MAX_WAVEINDRV
)
{
TRACE
(
"MAX_WAVINDRV reached !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
memcpy
(
lpCaps
,
&
WInDev
[
wDevID
].
caps
,
min
(
dwSize
,
sizeof
(
*
lpCaps
)));
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* widRecorder [internal]
*/
static
DWORD
CALLBACK
widRecorder
(
LPVOID
pmt
)
{
WORD
uDevID
=
(
DWORD
)
pmt
;
WINE_WAVEIN
*
wwi
=
(
WINE_WAVEIN
*
)
&
WInDev
[
uDevID
];
WAVEHDR
*
lpWaveHdr
;
DWORD
dwSleepTime
;
DWORD
bytesRead
;
enum
win_wm_message
msg
;
DWORD
param
;
HANDLE
ev
;
SetEvent
(
wwi
->
hStartUpEvent
);
/* make sleep time to be # of ms to record one packet */
dwSleepTime
=
(
1024
*
1000
)
/
wwi
->
format
.
wf
.
nAvgBytesPerSec
;
TRACE
(
"sleeptime=%ld ms
\n
"
,
dwSleepTime
);
for
(;;)
{
TRACE
(
"wwi->lpQueuePtr=(%p), wwi->state=(%d)
\n
"
,
wwi
->
lpQueuePtr
,
wwi
->
state
);
/* read all data is esd input buffer. */
if
((
wwi
->
lpQueuePtr
!=
NULL
)
&&
(
wwi
->
state
==
WINE_WS_PLAYING
))
{
lpWaveHdr
=
wwi
->
lpQueuePtr
;
TRACE
(
"read as much as we can
\n
"
);
while
(
wwi
->
lpQueuePtr
)
{
TRACE
(
"attempt to read %ld bytes
\n
"
,
lpWaveHdr
->
dwBufferLength
-
lpWaveHdr
->
dwBytesRecorded
);
bytesRead
=
read
(
wwi
->
esd_fd
,
lpWaveHdr
->
lpData
+
lpWaveHdr
->
dwBytesRecorded
,
lpWaveHdr
->
dwBufferLength
-
lpWaveHdr
->
dwBytesRecorded
);
TRACE
(
"bytesRead=%ld
\n
"
,
bytesRead
);
if
(
bytesRead
==
-
1
&&
errno
==
EAGAIN
)
bytesRead
=
0
;
if
(
bytesRead
==
0
)
break
;
/* So we can stop recording smoothly */
if
(
bytesRead
<
0
)
bytesRead
=
0
;
lpWaveHdr
->
dwBytesRecorded
+=
bytesRead
;
wwi
->
dwRecordedTotal
+=
bytesRead
;
/* buffer full. notify client */
if
(
lpWaveHdr
->
dwBytesRecorded
>=
lpWaveHdr
->
dwBufferLength
)
{
/* must copy the value of next waveHdr, because we have no idea of what
* will be done with the content of lpWaveHdr in callback
*/
LPWAVEHDR
lpNext
=
lpWaveHdr
->
lpNext
;
TRACE
(
"waveHdr full.
\n
"
);
lpWaveHdr
->
dwFlags
&=
~
WHDR_INQUEUE
;
lpWaveHdr
->
dwFlags
|=
WHDR_DONE
;
widNotifyClient
(
wwi
,
WIM_DATA
,
(
DWORD
)
lpWaveHdr
,
0
);
lpWaveHdr
=
wwi
->
lpQueuePtr
=
lpNext
;
}
}
}
/* wait for dwSleepTime or an event in thread's queue */
WaitForSingleObject
(
wwi
->
msgRing
.
msg_event
,
dwSleepTime
);
while
(
ESD_RetrieveRingMessage
(
&
wwi
->
msgRing
,
&
msg
,
&
param
,
&
ev
))
{
TRACE
(
"msg=%s param=0x%lx
\n
"
,
wodPlayerCmdString
[
msg
-
WM_USER
-
1
],
param
);
switch
(
msg
)
{
case
WINE_WM_PAUSING
:
wwi
->
state
=
WINE_WS_PAUSED
;
/* Put code here to "pause" esd recording
*/
SetEvent
(
ev
);
break
;
case
WINE_WM_STARTING
:
wwi
->
state
=
WINE_WS_PLAYING
;
/* Put code here to "start" esd recording
*/
SetEvent
(
ev
);
break
;
case
WINE_WM_HEADER
:
lpWaveHdr
=
(
LPWAVEHDR
)
param
;
/* insert buffer at end of queue */
{
LPWAVEHDR
*
wh
;
int
num_headers
=
0
;
for
(
wh
=
&
(
wwi
->
lpQueuePtr
);
*
wh
;
wh
=
&
((
*
wh
)
->
lpNext
))
{
num_headers
++
;
}
*
wh
=
lpWaveHdr
;
}
break
;
case
WINE_WM_STOPPING
:
if
(
wwi
->
state
!=
WINE_WS_STOPPED
)
{
/* Put code here to "stop" esd recording
*/
/* return current buffer to app */
lpWaveHdr
=
wwi
->
lpQueuePtr
;
if
(
lpWaveHdr
)
{
LPWAVEHDR
lpNext
=
lpWaveHdr
->
lpNext
;
TRACE
(
"stop %p %p
\n
"
,
lpWaveHdr
,
lpWaveHdr
->
lpNext
);
lpWaveHdr
->
dwFlags
&=
~
WHDR_INQUEUE
;
lpWaveHdr
->
dwFlags
|=
WHDR_DONE
;
widNotifyClient
(
wwi
,
WIM_DATA
,
(
DWORD
)
lpWaveHdr
,
0
);
wwi
->
lpQueuePtr
=
lpNext
;
}
}
wwi
->
state
=
WINE_WS_STOPPED
;
SetEvent
(
ev
);
break
;
case
WINE_WM_RESETTING
:
wwi
->
state
=
WINE_WS_STOPPED
;
wwi
->
dwRecordedTotal
=
0
;
/* return all buffers to the app */
for
(
lpWaveHdr
=
wwi
->
lpQueuePtr
;
lpWaveHdr
;
lpWaveHdr
=
lpWaveHdr
->
lpNext
)
{
TRACE
(
"reset %p %p
\n
"
,
lpWaveHdr
,
lpWaveHdr
->
lpNext
);
lpWaveHdr
->
dwFlags
&=
~
WHDR_INQUEUE
;
lpWaveHdr
->
dwFlags
|=
WHDR_DONE
;
widNotifyClient
(
wwi
,
WIM_DATA
,
(
DWORD
)
lpWaveHdr
,
0
);
}
wwi
->
lpQueuePtr
=
NULL
;
SetEvent
(
ev
);
break
;
case
WINE_WM_CLOSING
:
wwi
->
hThread
=
0
;
wwi
->
state
=
WINE_WS_CLOSED
;
SetEvent
(
ev
);
ExitThread
(
0
);
/* shouldn't go here */
default:
FIXME
(
"unknown message %d
\n
"
,
msg
);
break
;
}
}
}
ExitThread
(
0
);
/* just for not generating compilation warnings... should never be executed */
return
0
;
}
/**************************************************************************
* widOpen [internal]
*/
static
DWORD
widOpen
(
WORD
wDevID
,
LPWAVEOPENDESC
lpDesc
,
DWORD
dwFlags
)
{
WINE_WAVEIN
*
wwi
;
/* input esound... */
int
in_bits
=
ESD_BITS16
,
in_channels
=
ESD_STEREO
,
in_rate
;
#ifdef WID_USE_ESDMON
int
in_mode
=
ESD_STREAM
,
in_func
=
ESD_PLAY
;
#else
int
in_mode
=
ESD_STREAM
,
in_func
=
ESD_RECORD
;
#endif
esd_format_t
in_format
;
int
mode
;
TRACE
(
"(%u, %p %08lX);
\n
"
,
wDevID
,
lpDesc
,
dwFlags
);
if
(
lpDesc
==
NULL
)
{
WARN
(
"Invalid Parametr (lpDesc == NULL)!
\n
"
);
return
MMSYSERR_INVALPARAM
;
}
if
(
wDevID
>=
MAX_WAVEINDRV
)
{
TRACE
(
"MAX_WAVEINDRV reached !
\n
"
);
return
MMSYSERR_BADDEVICEID
;
}
/* if this device is already open tell the app that it is allocated */
if
(
WInDev
[
wDevID
].
esd_fd
!=
-
1
)
{
TRACE
(
"device already allocated
\n
"
);
return
MMSYSERR_ALLOCATED
;
}
/* only PCM format is support so far... */
if
(
lpDesc
->
lpFormat
->
wFormatTag
!=
WAVE_FORMAT_PCM
||
lpDesc
->
lpFormat
->
nChannels
==
0
||
lpDesc
->
lpFormat
->
nSamplesPerSec
<
DSBFREQUENCY_MIN
||
lpDesc
->
lpFormat
->
nSamplesPerSec
>
DSBFREQUENCY_MAX
||
(
lpDesc
->
lpFormat
->
wBitsPerSample
!=
8
&&
lpDesc
->
lpFormat
->
wBitsPerSample
!=
16
))
{
WARN
(
"Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !
\n
"
,
lpDesc
->
lpFormat
->
wFormatTag
,
lpDesc
->
lpFormat
->
nChannels
,
lpDesc
->
lpFormat
->
nSamplesPerSec
);
return
WAVERR_BADFORMAT
;
}
if
(
dwFlags
&
WAVE_FORMAT_QUERY
)
{
TRACE
(
"Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !
\n
"
,
lpDesc
->
lpFormat
->
wFormatTag
,
lpDesc
->
lpFormat
->
nChannels
,
lpDesc
->
lpFormat
->
nSamplesPerSec
);
return
MMSYSERR_NOERROR
;
}
wwi
=
&
WInDev
[
wDevID
];
/* direct sound not supported, ignore the flag */
dwFlags
&=
~
WAVE_DIRECTSOUND
;
wwi
->
wFlags
=
HIWORD
(
dwFlags
&
CALLBACK_TYPEMASK
);
memcpy
(
&
wwi
->
waveDesc
,
lpDesc
,
sizeof
(
WAVEOPENDESC
));
memcpy
(
&
wwi
->
format
,
lpDesc
->
lpFormat
,
sizeof
(
PCMWAVEFORMAT
));
if
(
wwi
->
format
.
wBitsPerSample
==
0
)
{
WARN
(
"Resetting zerod wBitsPerSample
\n
"
);
wwi
->
format
.
wBitsPerSample
=
8
*
(
wwi
->
format
.
wf
.
nAvgBytesPerSec
/
wwi
->
format
.
wf
.
nSamplesPerSec
)
/
wwi
->
format
.
wf
.
nChannels
;
}
if
(
wwi
->
format
.
wBitsPerSample
==
8
)
in_bits
=
ESD_BITS8
;
else
if
(
wwi
->
format
.
wBitsPerSample
==
16
)
in_bits
=
ESD_BITS16
;
wwi
->
bytes_per_frame
=
(
wwi
->
format
.
wBitsPerSample
*
wwi
->
format
.
wf
.
nChannels
)
/
8
;
if
(
wwi
->
format
.
wf
.
nChannels
==
1
)
in_channels
=
ESD_MONO
;
else
if
(
wwi
->
format
.
wf
.
nChannels
==
2
)
in_channels
=
ESD_STEREO
;
in_format
=
in_bits
|
in_channels
|
in_mode
|
in_func
;
in_rate
=
(
int
)
wwi
->
format
.
wf
.
nSamplesPerSec
;
TRACE
(
"esd input format = 0x%08x, rate = %d
\n
"
,
in_format
,
in_rate
);
#ifdef WID_USE_ESDMON
wwi
->
esd_fd
=
esd_monitor_stream
(
in_format
,
in_rate
,
esd_host
,
"wineesd"
);
#else
wwi
->
esd_fd
=
esd_record_stream
(
in_format
,
in_rate
,
esd_host
,
"wineesd"
);
#endif
TRACE
(
"(wwi->esd_fd=%d)
\n
"
,
wwi
->
esd_fd
);
wwi
->
state
=
WINE_WS_STOPPED
;
if
(
wwi
->
lpQueuePtr
)
{
WARN
(
"Should have an empty queue (%p)
\n
"
,
wwi
->
lpQueuePtr
);
wwi
->
lpQueuePtr
=
NULL
;
}
if
(
wwi
->
esd_fd
<
0
)
return
MMSYSERR_ALLOCATED
;
/* Set the esd socket O_NONBLOCK, so we can stop recording smoothly */
mode
=
fcntl
(
wwi
->
esd_fd
,
F_GETFL
);
mode
|=
O_NONBLOCK
;
fcntl
(
wwi
->
esd_fd
,
F_SETFL
,
mode
);
wwi
->
dwRecordedTotal
=
0
;
wwi
->
wFlags
=
HIWORD
(
dwFlags
&
CALLBACK_TYPEMASK
);
ESD_InitRingMessage
(
&
wwi
->
msgRing
);
/* create recorder thread */
if
(
!
(
dwFlags
&
WAVE_DIRECTSOUND
))
{
wwi
->
hStartUpEvent
=
CreateEventA
(
NULL
,
FALSE
,
FALSE
,
NULL
);
wwi
->
hThread
=
CreateThread
(
NULL
,
0
,
widRecorder
,
(
LPVOID
)(
DWORD
)
wDevID
,
0
,
&
(
wwi
->
dwThreadID
));
WaitForSingleObject
(
wwi
->
hStartUpEvent
,
INFINITE
);
CloseHandle
(
wwi
->
hStartUpEvent
);
}
else
{
wwi
->
hThread
=
INVALID_HANDLE_VALUE
;
wwi
->
dwThreadID
=
0
;
}
wwi
->
hStartUpEvent
=
INVALID_HANDLE_VALUE
;
TRACE
(
"wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!
\n
"
,
wwi
->
format
.
wBitsPerSample
,
wwi
->
format
.
wf
.
nAvgBytesPerSec
,
wwi
->
format
.
wf
.
nSamplesPerSec
,
wwi
->
format
.
wf
.
nChannels
,
wwi
->
format
.
wf
.
nBlockAlign
);
return
widNotifyClient
(
wwi
,
WIM_OPEN
,
0L
,
0L
);
}
/**************************************************************************
* widClose [internal]
*/
static
DWORD
widClose
(
WORD
wDevID
)
{
WINE_WAVEIN
*
wwi
;
TRACE
(
"(%u);
\n
"
,
wDevID
);
if
(
wDevID
>=
MAX_WAVEINDRV
||
WInDev
[
wDevID
].
state
==
WINE_WS_CLOSED
)
{
WARN
(
"can't close !
\n
"
);
return
MMSYSERR_INVALHANDLE
;
}
wwi
=
&
WInDev
[
wDevID
];
if
(
wwi
->
lpQueuePtr
!=
NULL
)
{
WARN
(
"still buffers open !
\n
"
);
return
WAVERR_STILLPLAYING
;
}
ESD_AddRingMessage
(
&
wwi
->
msgRing
,
WINE_WM_CLOSING
,
0
,
TRUE
);
ESD_CloseWaveInDevice
(
wwi
);
wwi
->
state
=
WINE_WS_CLOSED
;
ESD_DestroyRingMessage
(
&
wwi
->
msgRing
);
return
widNotifyClient
(
wwi
,
WIM_CLOSE
,
0L
,
0L
);
}
/**************************************************************************
* widAddBuffer [internal]
*/
static
DWORD
widAddBuffer
(
WORD
wDevID
,
LPWAVEHDR
lpWaveHdr
,
DWORD
dwSize
)
{
TRACE
(
"(%u, %p, %08lX);
\n
"
,
wDevID
,
lpWaveHdr
,
dwSize
);
if
(
wDevID
>=
MAX_WAVEINDRV
||
WInDev
[
wDevID
].
state
==
WINE_WS_CLOSED
)
{
WARN
(
"can't do it !
\n
"
);
return
MMSYSERR_INVALHANDLE
;
}
if
(
!
(
lpWaveHdr
->
dwFlags
&
WHDR_PREPARED
))
{
TRACE
(
"never been prepared !
\n
"
);
return
WAVERR_UNPREPARED
;
}
if
(
lpWaveHdr
->
dwFlags
&
WHDR_INQUEUE
)
{
TRACE
(
"header already in use !
\n
"
);
return
WAVERR_STILLPLAYING
;
}
lpWaveHdr
->
dwFlags
|=
WHDR_INQUEUE
;
lpWaveHdr
->
dwFlags
&=
~
WHDR_DONE
;
lpWaveHdr
->
dwBytesRecorded
=
0
;
lpWaveHdr
->
lpNext
=
NULL
;
ESD_AddRingMessage
(
&
WInDev
[
wDevID
].
msgRing
,
WINE_WM_HEADER
,
(
DWORD
)
lpWaveHdr
,
FALSE
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* widPrepare [internal]
*/
static
DWORD
widPrepare
(
WORD
wDevID
,
LPWAVEHDR
lpWaveHdr
,
DWORD
dwSize
)
{
TRACE
(
"(%u, %p, %08lX);
\n
"
,
wDevID
,
lpWaveHdr
,
dwSize
);
if
(
wDevID
>=
MAX_WAVEINDRV
)
return
MMSYSERR_INVALHANDLE
;
if
(
lpWaveHdr
->
dwFlags
&
WHDR_INQUEUE
)
return
WAVERR_STILLPLAYING
;
lpWaveHdr
->
dwFlags
|=
WHDR_PREPARED
;
lpWaveHdr
->
dwFlags
&=
~
WHDR_DONE
;
lpWaveHdr
->
dwBytesRecorded
=
0
;
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* widUnprepare [internal]
*/
static
DWORD
widUnprepare
(
WORD
wDevID
,
LPWAVEHDR
lpWaveHdr
,
DWORD
dwSize
)
{
TRACE
(
"(%u, %p, %08lX);
\n
"
,
wDevID
,
lpWaveHdr
,
dwSize
);
if
(
wDevID
>=
MAX_WAVEINDRV
)
{
WARN
(
"bad device ID !
\n
"
);
return
MMSYSERR_INVALHANDLE
;
}
if
(
lpWaveHdr
->
dwFlags
&
WHDR_INQUEUE
)
{
TRACE
(
"Still playing...
\n
"
);
return
WAVERR_STILLPLAYING
;
}
lpWaveHdr
->
dwFlags
&=
~
WHDR_PREPARED
;
lpWaveHdr
->
dwFlags
|=
WHDR_DONE
;
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* widStart [internal]
*/
static
DWORD
widStart
(
WORD
wDevID
)
{
TRACE
(
"(%u);
\n
"
,
wDevID
);
if
(
wDevID
>=
MAX_WAVEINDRV
||
WInDev
[
wDevID
].
state
==
WINE_WS_CLOSED
)
{
WARN
(
"can't start recording !
\n
"
);
return
MMSYSERR_INVALHANDLE
;
}
ESD_AddRingMessage
(
&
WInDev
[
wDevID
].
msgRing
,
WINE_WM_STARTING
,
0
,
TRUE
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* widStop [internal]
*/
static
DWORD
widStop
(
WORD
wDevID
)
{
TRACE
(
"(%u);
\n
"
,
wDevID
);
if
(
wDevID
>=
MAX_WAVEINDRV
||
WInDev
[
wDevID
].
state
==
WINE_WS_CLOSED
)
{
WARN
(
"can't stop !
\n
"
);
return
MMSYSERR_INVALHANDLE
;
}
ESD_AddRingMessage
(
&
WInDev
[
wDevID
].
msgRing
,
WINE_WM_STOPPING
,
0
,
TRUE
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* widReset [internal]
*/
static
DWORD
widReset
(
WORD
wDevID
)
{
TRACE
(
"(%u);
\n
"
,
wDevID
);
if
(
wDevID
>=
MAX_WAVEINDRV
||
WInDev
[
wDevID
].
state
==
WINE_WS_CLOSED
)
{
WARN
(
"can't reset !
\n
"
);
return
MMSYSERR_INVALHANDLE
;
}
ESD_AddRingMessage
(
&
WInDev
[
wDevID
].
msgRing
,
WINE_WM_RESETTING
,
0
,
TRUE
);
return
MMSYSERR_NOERROR
;
}
/**************************************************************************
* widMessage (WINEESD.6)
*/
DWORD
WINAPI
ESD_widMessage
(
UINT
wDevID
,
UINT
wMsg
,
DWORD
dwUser
,
DWORD
dwParam1
,
DWORD
dwParam2
)
{
TRACE
(
"(%u, %04X, %08lX, %08lX, %08lX);
\n
"
,
wDevID
,
wMsg
,
dwUser
,
dwParam1
,
dwParam2
);
switch
(
wMsg
)
{
case
DRVM_INIT
:
case
DRVM_EXIT
:
case
DRVM_ENABLE
:
case
DRVM_DISABLE
:
/* FIXME: Pretend this is supported */
return
0
;
case
WIDM_OPEN
:
return
widOpen
(
wDevID
,
(
LPWAVEOPENDESC
)
dwParam1
,
dwParam2
);
case
WIDM_CLOSE
:
return
widClose
(
wDevID
);
case
WIDM_ADDBUFFER
:
return
widAddBuffer
(
wDevID
,
(
LPWAVEHDR
)
dwParam1
,
dwParam2
);
case
WIDM_PREPARE
:
return
widPrepare
(
wDevID
,
(
LPWAVEHDR
)
dwParam1
,
dwParam2
);
case
WIDM_UNPREPARE
:
return
widUnprepare
(
wDevID
,
(
LPWAVEHDR
)
dwParam1
,
dwParam2
);
case
WIDM_GETDEVCAPS
:
return
widGetDevCaps
(
wDevID
,
(
LPWAVEINCAPSA
)
dwParam1
,
dwParam2
);
case
WIDM_GETNUMDEVS
:
return
widGetNumDevs
();
case
WIDM_RESET
:
return
widReset
(
wDevID
);
case
WIDM_START
:
return
widStart
(
wDevID
);
case
WIDM_STOP
:
return
widStop
(
wDevID
);
case
DRV_QUERYDEVICEINTERFACESIZE
:
return
widDevInterfaceSize
(
wDevID
,
(
LPDWORD
)
dwParam1
);
case
DRV_QUERYDEVICEINTERFACE
:
return
widDevInterface
(
wDevID
,
(
PWCHAR
)
dwParam1
,
dwParam2
);
default:
FIXME
(
"unknown message %d!
\n
"
,
wMsg
);
}
return
MMSYSERR_NOTSUPPORTED
;
}
/*======================================================================*
* Low level DSOUND implementation *
*======================================================================*/
static
DWORD
wodDsCreate
(
UINT
wDevID
,
PIDSDRIVER
*
drv
)
{
/* we can't perform memory mapping as we don't have a file stream
interface with esd like we do with oss */
MESSAGE
(
"This sound card's driver does not support direct access
\n
"
);
MESSAGE
(
"The (slower) DirectSound HEL mode will be used instead.
\n
"
);
return
MMSYSERR_NOTSUPPORTED
;
}
static
DWORD
wodDsDesc
(
UINT
wDevID
,
PDSDRIVERDESC
desc
)
{
memset
(
desc
,
0
,
sizeof
(
*
desc
));
strcpy
(
desc
->
szDesc
,
"Wine EsounD DirectSound Driver"
);
strcpy
(
desc
->
szDrvname
,
"wineesd.drv"
);
return
MMSYSERR_NOERROR
;
}
#else
/* !HAVE_ESD */
/**************************************************************************
* wodMessage (WINEESD.@)
*/
DWORD
WINAPI
ESD_wodMessage
(
WORD
wDevID
,
WORD
wMsg
,
DWORD
dwUser
,
DWORD
dwParam1
,
DWORD
dwParam2
)
{
FIXME
(
"(%u, %04X, %08lX, %08lX, %08lX):stub
\n
"
,
wDevID
,
wMsg
,
dwUser
,
dwParam1
,
dwParam2
);
return
MMSYSERR_NOTENABLED
;
}
/**************************************************************************
* widMessage (WINEESD.6)
*/
DWORD
WINAPI
ESD_widMessage
(
UINT
wDevID
,
UINT
wMsg
,
DWORD
dwUser
,
DWORD
dwParam1
,
DWORD
dwParam2
)
{
FIXME
(
"(%u, %04X, %08lX, %08lX, %08lX):stub
\n
"
,
wDevID
,
wMsg
,
dwUser
,
dwParam1
,
dwParam2
);
return
MMSYSERR_NOTENABLED
;
}
#endif
/* HAVE_ESD */
dlls/winmm/wineesd/esound.c
0 → 100644
View file @
7a15eb93
/*
* Wine Driver for EsounD Sound Server
* http://www.tux.org/~ricdude/EsounD.html
*
* Copyright 2004 Zhangrong Huang <hzhr@users.sourceforge.net>
*
* Code massively copied from Eric Pouech's OSS driver
* and Chris Morgan aRts driver
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmddk.h"
#include "esound.h"
#ifdef HAVE_ESD
static
int
esd
=
0
;
/**************************************************************************
* ESD_drvOpen [internal]
*/
static
DWORD
ESD_drvOpen
(
LPSTR
str
)
{
if
(
esd
)
return
0
;
/* I know, this is ugly, but who cares... */
esd
=
1
;
return
1
;
}
/**************************************************************************
* ESD_drvClose [internal]
*/
static
DWORD
ESD_drvClose
(
DWORD
dwDevID
)
{
if
(
esd
)
{
esd
=
0
;
return
1
;
}
return
0
;
}
#endif
/* #ifdef HAVE_ESD */
/**************************************************************************
* DriverProc (WINEESD.@)
*/
LONG
CALLBACK
ESD_DriverProc
(
DWORD
dwDevID
,
HDRVR
hDriv
,
DWORD
wMsg
,
DWORD
dwParam1
,
DWORD
dwParam2
)
{
/* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
/* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
switch
(
wMsg
)
{
#ifdef HAVE_ESD
case
DRV_LOAD
:
if
(
ESD_WaveInit
()
<
0
)
return
0
;
return
1
;
case
DRV_FREE
:
return
ESD_WaveClose
();
case
DRV_OPEN
:
return
ESD_drvOpen
((
LPSTR
)
dwParam1
);
case
DRV_CLOSE
:
return
ESD_drvClose
(
dwDevID
);
case
DRV_ENABLE
:
return
1
;
case
DRV_DISABLE
:
return
1
;
case
DRV_QUERYCONFIGURE
:
return
1
;
case
DRV_CONFIGURE
:
MessageBoxA
(
0
,
"EsounD MultiMedia Driver!"
,
"EsounD Driver"
,
MB_OK
);
return
1
;
case
DRV_INSTALL
:
return
DRVCNF_RESTART
;
case
DRV_REMOVE
:
return
DRVCNF_RESTART
;
#endif
default:
return
DefDriverProc
(
dwDevID
,
hDriv
,
wMsg
,
dwParam1
,
dwParam2
);
}
}
dlls/winmm/wineesd/esound.h
0 → 100644
View file @
7a15eb93
/* Definition for EsounD drivers : wine multimedia system
*
* Copyright 2004 Zhangrong Huang <hzhr@users.sourceforge.net>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_ESD_H
#define __WINE_ESD_H
#ifndef __WINE_CONFIG_H
# error You must include config.h to use this header
#endif
#ifdef HAVE_SYS_ERRNO_H
#include <sys/errno.h>
#endif
extern
LONG
ESD_WaveInit
(
void
);
extern
LONG
ESD_WaveClose
(
void
);
#endif
/* __WINE_ESD_H */
dlls/winmm/wineesd/wineesd.drv.spec
0 → 100644
View file @
7a15eb93
@ stdcall DriverProc(long long long long long) ESD_DriverProc
@ stdcall wodMessage(long long long long long) ESD_wodMessage
@ stdcall widMessage(long long long long long) ESD_widMessage
include/config.h.in
View file @
7a15eb93
...
...
@@ -86,6 +86,9 @@
/* Define to 1 if you have the `epoll_create' function. */
#undef HAVE_EPOLL_CREATE
/* Define if you have EsounD sound server */
#undef HAVE_ESD
/* Define to 1 if you have the `ffs' function. */
#undef HAVE_FFS
...
...
programs/winecfg/audio.c
View file @
7a15eb93
...
...
@@ -210,6 +210,15 @@ static const char *audioAutoDetect(void)
numFound
++
;
}
/* try to detect EsounD */
argv_new
[
2
]
=
"ps awx|grep esd|grep -v grep|grep esd > /dev/null"
;
if
(
!
spawnvp
(
_P_WAIT
,
"/bin/sh"
,
argv_new
))
{
driversFound
[
numFound
]
=
"esd"
;
name
[
numFound
]
=
"EsounD"
;
numFound
++
;
}
/* try to detect nas */
/* TODO */
...
...
programs/winecfg/properties.c
View file @
7a15eb93
...
...
@@ -60,6 +60,7 @@ static const DLL_DESC sDLLType[] = {
static
const
AUDIO_DRIVER
sAudioDrivers
[]
=
{
{
"ALSA"
,
"alsa"
},
{
"aRts"
,
"arts"
},
{
"EsounD"
,
"esd"
},
{
"OSS"
,
"oss"
},
{
"JACK"
,
"jack"
},
{
"NAS"
,
"nas"
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment