mirror of
https://git.code.sf.net/p/quake/quake2forge
synced 2024-11-10 07:12:01 +00:00
- Roll back the patch from about changeset 67, with the
adding of pthreads; that's all gone now, it sucked. - Add a libao sound output, this has been mostly tested: - it works with wav output on my powerbook (where oss out is broken) - it works but sounds really jumpy when playing 44100Hz samples through a shitty onboard soundcard that only supports 48000Hz output... the dma buffer gets played too fast.
This commit is contained in:
parent
2012da9a05
commit
f581c7d17d
6 changed files with 300 additions and 333 deletions
189
acinclude.m4
189
acinclude.m4
|
@ -226,192 +226,3 @@ int main (int argc, char *argv[])
|
|||
AC_SUBST(SDL_LIBS)
|
||||
rm -f conf.sdltest
|
||||
])
|
||||
|
||||
dnl ACX_PTHREAD macro by Steven G. Johnson <stevenj@alum.mit.edu> and
|
||||
dnl Alejandro Forero Cuervo <bachue@bachue.com>. Found at:
|
||||
dnl http://www.gnu.org/software/ac-archive/Installed_Packages/acx_pthread.html
|
||||
AC_DEFUN([ACX_PTHREAD], [
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
acx_pthread_ok=no
|
||||
|
||||
# We used to check for pthread.h first, but this fails if pthread.h
|
||||
# requires special compiler flags (e.g. on True64 or Sequent).
|
||||
# It gets checked for in the link test anyway.
|
||||
|
||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||
# etcetera environment variables, and if threads linking works using
|
||||
# them:
|
||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||
AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
|
||||
AC_MSG_RESULT($acx_pthread_ok)
|
||||
if test x"$acx_pthread_ok" = xno; then
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
fi
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
fi
|
||||
|
||||
# We must check for the threads library under a number of different
|
||||
# names; the ordering is very important because some systems
|
||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||
# libraries is broken (non-POSIX).
|
||||
|
||||
# Create a list of thread flags to try. Items starting with a "-" are
|
||||
# C compiler flags, and other items are library names, except for "none"
|
||||
# which indicates that we try without any flags at all.
|
||||
|
||||
acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
|
||||
# pthreads: AIX (must check this before -lpthread)
|
||||
# none: in case threads are in libc; should be tried before -Kthread and
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||
# -pthreads: Solaris/gcc
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||
# also defines -D_REENTRANT)
|
||||
# pthread: Linux, etcetera
|
||||
# --thread-safe: KAI C++
|
||||
|
||||
case "${host_cpu}-${host_os}" in
|
||||
*solaris*)
|
||||
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (We need to link with -pthread or
|
||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||
# a function called by this macro, so we could check for that, but
|
||||
# who knows whether they'll stub that too in a future libc.) So,
|
||||
# we'll just look for -pthreads and -lpthread first:
|
||||
|
||||
acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test x"$acx_pthread_ok" = xno; then
|
||||
for flag in $acx_pthread_flags; do
|
||||
|
||||
case $flag in
|
||||
none)
|
||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||
;;
|
||||
|
||||
-*)
|
||||
AC_MSG_CHECKING([whether pthreads work with $flag])
|
||||
PTHREAD_CFLAGS="$flag"
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||
PTHREAD_LIBS="-l$flag"
|
||||
;;
|
||||
esac
|
||||
|
||||
save_LIBS="$LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
|
||||
# Check for various functions. We must include pthread.h,
|
||||
# since some functions may be macros. (On the Sequent, we
|
||||
# need a special flag -Kthread to make this header compile.)
|
||||
# We check for pthread_join because it is in -lpthread on IRIX
|
||||
# while pthread_create is in libc. We check for pthread_attr_init
|
||||
# due to DEC craziness with -lpthreads. We check for
|
||||
# pthread_cleanup_push because it is one of the few pthread
|
||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||
# We try pthread_create on general principles.
|
||||
AC_TRY_LINK([#include <pthread.h>],
|
||||
[pthread_t th; pthread_join(th, 0);
|
||||
pthread_attr_init(0); pthread_cleanup_push(0, 0);
|
||||
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
|
||||
[acx_pthread_ok=yes])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
|
||||
AC_MSG_RESULT($acx_pthread_ok)
|
||||
if test "x$acx_pthread_ok" = xyes; then
|
||||
break;
|
||||
fi
|
||||
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
done
|
||||
fi
|
||||
|
||||
# Various other checks:
|
||||
if test "x$acx_pthread_ok" = xyes; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
|
||||
# Detect AIX lossage: threads are created detached by default
|
||||
# and the JOINABLE attribute has a nonstandard name (UNDETACHED).
|
||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||
AC_TRY_LINK([#include <pthread.h>],
|
||||
[int attr=PTHREAD_CREATE_JOINABLE;],
|
||||
ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
|
||||
if test x"$ok" = xunknown; then
|
||||
AC_TRY_LINK([#include <pthread.h>],
|
||||
[int attr=PTHREAD_CREATE_UNDETACHED;],
|
||||
ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
|
||||
fi
|
||||
if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
|
||||
AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
|
||||
[Define to the necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
fi
|
||||
AC_MSG_RESULT(${ok})
|
||||
if test x"$ok" = xunknown; then
|
||||
AC_MSG_WARN([we do not know how to create joinable pthreads])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
||||
flag=no
|
||||
case "${host_cpu}-${host_os}" in
|
||||
*-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
|
||||
*solaris* | alpha*-osf*) flag="-D_REENTRANT";;
|
||||
esac
|
||||
AC_MSG_RESULT(${flag})
|
||||
if test "x$flag" != xno; then
|
||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||
fi
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
|
||||
# More AIX lossage: must compile with cc_r
|
||||
AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
|
||||
else
|
||||
PTHREAD_CC="$CC"
|
||||
fi
|
||||
|
||||
AC_SUBST(PTHREAD_LIBS)
|
||||
AC_SUBST(PTHREAD_CFLAGS)
|
||||
AC_SUBST(PTHREAD_CC)
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test x"$acx_pthread_ok" = xyes; then
|
||||
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
|
||||
:
|
||||
else
|
||||
acx_pthread_ok=no
|
||||
$2
|
||||
fi
|
||||
|
||||
])dnl ACX_PTHREAD
|
||||
|
|
63
configure.in
63
configure.in
|
@ -76,9 +76,6 @@ OSS_LIBS=""
|
|||
AC_CHECK_LIB([ossaudio], [_oss_ioctl], [OSS_LIBS="-lossaudio"])
|
||||
AC_SUBST(OSS_LIBS)
|
||||
|
||||
dnl Check for POSIX threads
|
||||
ACX_PTHREAD(,AC_MSG_ERROR(["POSIX threads required!"]))
|
||||
|
||||
dnl -----------------
|
||||
dnl Check for SVGAlib
|
||||
dnl -----------------
|
||||
|
@ -311,6 +308,64 @@ dnl ---------------------
|
|||
|
||||
HAVE_ZIP=disabled
|
||||
|
||||
dnl ---------------
|
||||
dnl Check for libao
|
||||
dnl ---------------
|
||||
|
||||
HAVE_AO=no
|
||||
AC_ARG_WITH(ao,
|
||||
AC_HELP_STRING([--with-ao(=DIR)],
|
||||
[use libao (optionally, found in DIR)]),
|
||||
dnl argument was given, check for --without
|
||||
if test "x${with_ao}" != xno ; then
|
||||
ac_with_ao=yes
|
||||
else
|
||||
ac_with_ao=no
|
||||
fi,
|
||||
ac_with_ao=auto
|
||||
)
|
||||
if test "x${ac_with_ao}" != xno ; then
|
||||
dnl --with-ao was explicitly given, so look in the given dir
|
||||
if test "x${ac_with_ao}" != xauto ; then
|
||||
AO_CFLAGS="$AO_CFLAGS -I$withval/include"
|
||||
AO_LIBS="$AO_LIBS -L$withval/lib"
|
||||
fi
|
||||
dnl set CPPFLAGS for coming tests
|
||||
save_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $AO_CFLAGS"
|
||||
dnl test for installed library first, for people who may have
|
||||
dnl the libs installed by no headers
|
||||
AC_CHECK_LIB(ao, ao_initialize,
|
||||
AO_LIBS="$AO_LIBS -lao"
|
||||
HAVE_AO=maybe,
|
||||
HAVE_AO=no,
|
||||
[$AO_LIBS])
|
||||
dnl check the header
|
||||
if test "x$HAVE_AO" = xmaybe ; then
|
||||
AC_CHECK_HEADER(ao/ao.h,
|
||||
HAVE_AO=yes,
|
||||
HAVE_AO=no
|
||||
)
|
||||
fi
|
||||
dnl sum up
|
||||
if test "x$HAVE_AO" = xyes ; then
|
||||
AC_DEFINE(HAVE_AO, 1, [Define this if you have libao])
|
||||
AC_SUBST(AO_LIBS)
|
||||
AC_SUBST(AO_CFLAGS)
|
||||
else
|
||||
dnl if we were explicitly told to use ao and it's not there
|
||||
if test "x${ac_with_ao}" = xyes ; then
|
||||
AC_MSG_WARN([
|
||||
*** You have explicitly asked for libao support, but the required libraries
|
||||
*** and development files could not be found.])
|
||||
fi
|
||||
fi
|
||||
dnl clean up
|
||||
CPPFLAGS="$save_CPPFLAGS"
|
||||
else
|
||||
HAVE_AO=disabled
|
||||
fi
|
||||
|
||||
dnl -----------------------
|
||||
dnl Checks for header files
|
||||
dnl -----------------------
|
||||
|
@ -700,6 +755,8 @@ AC_MSG_RESULT([ SDL: ............. $HAVE_SDL])
|
|||
dnl AC_MSG_RESULT([ Framebuffer: ..... $HAVE_FB])
|
||||
dnl AC_MSG_RESULT([ AAlib: ........... $HAVE_AA])
|
||||
|
||||
AC_MSG_RESULT([ libao .............. $HAVE_AO])
|
||||
|
||||
AC_MSG_RESULT([
|
||||
Installation directories:
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ endif
|
|||
if BUILD_SDLQUAKE2
|
||||
SOUND = cd_sdl.c snd_sdl.c snd_dma.c snd_mix.c snd_mem.c
|
||||
else
|
||||
SOUND = cd.c snd.c snd_dma.c snd_mix.c snd_mem.c
|
||||
SOUND = cd.c snd_ao.c snd_dma.c snd_mix.c snd_mem.c
|
||||
endif
|
||||
|
||||
quake2_SOURCES = main.c q_sh.c vid_menu.c vid_so.c q_glob.c net_udp.c \
|
||||
|
@ -83,21 +83,17 @@ EXTRA_ref_tdfx_la_SOURCES = rw_in_svgalib.c gl_fxmesa.c
|
|||
EXTRA_ref_softx_la_SOURCES = rw_x11.c
|
||||
|
||||
EXTRA_quake2_SOURCES = snd_mixa.S cd_sdl.c snd_sdl.c snd_dma.c \
|
||||
snd_mix.c snd_mem.c cd.c snd.c
|
||||
snd_mix.c snd_mem.c cd.c snd_ao.c
|
||||
|
||||
if BUILD_SDLQUAKE2
|
||||
quake2_CFLAGS = $(std_cflags) @PTHREAD_CFLAGS@ @SDL_CFLAGS@
|
||||
quake2_CFLAGS = $(std_cflags) @SDL_CFLAGS@
|
||||
else
|
||||
quake2_CFLAGS = $(std_cflags) @PTHREAD_CFLAGS@
|
||||
quake2_CFLAGS = $(std_cflags)
|
||||
endif
|
||||
# the macro puts -pthread into cflags, but we want to link
|
||||
# with this flag too, so stick it into the ldflags if it's there...
|
||||
# extra cflags at link time can't hurt
|
||||
quake2_LDFLAGS = @PTHREAD_CFLAGS@
|
||||
if BUILD_SDLQUAKE2
|
||||
quake2_LDADD = @PTHREAD_LIBS@ @DL_LIBS@ @OSS_LIBS@ @SDL_LIBS@ @SYSTEM_LIBS@ -lm
|
||||
quake2_LDADD = @DL_LIBS@ @AO_LIBS@ @SDL_LIBS@ @SYSTEM_LIBS@ -lm
|
||||
else
|
||||
quake2_LDADD = @PTHREAD_LIBS@ @DL_LIBS@ @OSS_LIBS@ @SYSTEM_LIBS@ -lm
|
||||
quake2_LDADD = @DL_LIBS@ @AO_LIBS@ @SYSTEM_LIBS@ -lm
|
||||
endif
|
||||
|
||||
# ref_glx
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include <mntent.h>
|
||||
#elif defined(__FreeBSD__) || defined(__bsd__) || defined (__NetBSD__)
|
||||
#include <fstab.h>
|
||||
#include <pthread.h>
|
||||
#elif defined(__sun__)
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
@ -327,7 +326,6 @@ XilSystemState xil_state;
|
|||
|
||||
int main (int argc, char **argv) {
|
||||
int time, oldtime, newtime;
|
||||
sigset_t sigs;
|
||||
|
||||
#ifdef SOL8_XIL_WORKAROUND
|
||||
{
|
||||
|
@ -353,11 +351,6 @@ int main (int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
/* block the SIGPOLL signal so that only the audio thread gets it */
|
||||
sigemptyset(&sigs);
|
||||
sigaddset(&sigs, SIGPOLL);
|
||||
pthread_sigmask(SIG_BLOCK, &sigs, NULL);
|
||||
|
||||
/* go back to real user for config loads */
|
||||
saved_euid = geteuid();
|
||||
seteuid(getuid());
|
||||
|
|
180
src/snd.c
180
src/snd.c
|
@ -31,7 +31,6 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/shm.h>
|
||||
|
@ -55,12 +54,6 @@
|
|||
#include "client.h"
|
||||
#include "snd_loc.h"
|
||||
|
||||
#define FRAGSIZEEXP 9
|
||||
#define FRAGSIZE (1<<FRAGSIZEEXP)
|
||||
|
||||
#define AUDIOBUFFERSIZE 4096
|
||||
#define AUDIOBUFFERS 64
|
||||
|
||||
#ifdef __sgi
|
||||
|
||||
/* must be a power of 2! */
|
||||
|
@ -80,8 +73,6 @@ long long sgisnd_lastframewritten = 0;
|
|||
|
||||
static int audio_fd = -1;
|
||||
static volatile int snd_inited;
|
||||
static volatile int frags_sent;
|
||||
static int mmapped = 0;
|
||||
|
||||
static int tryrates[] = { 11025, 22051, 44100, 48000, 8000 };
|
||||
|
||||
|
@ -95,19 +86,6 @@ cvar_t *snddevice;
|
|||
cvar_t * s_loadas8bit;
|
||||
cvar_t * s_khz;
|
||||
|
||||
static pthread_t audio;
|
||||
|
||||
void * thesound(void * arg) {
|
||||
while (snd_inited) {
|
||||
write(audio_fd, dma.buffer + frags_sent * FRAGSIZE, FRAGSIZE);
|
||||
frags_sent++;
|
||||
frags_sent &= (dma.samples * (dma.samplebits/8) / FRAGSIZE) - 1;
|
||||
}
|
||||
pthread_exit(0L);
|
||||
/* Not reached */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qboolean SNDDMA_Init(void) {
|
||||
/* merged in from snd_irix.c -- jaq */
|
||||
#ifdef __sgi
|
||||
|
@ -193,7 +171,7 @@ qboolean SNDDMA_Init(void) {
|
|||
|
||||
alFreeConfig(ac);
|
||||
return true;
|
||||
#else /* __sgi */
|
||||
#else /* !__sgi */
|
||||
int rc;
|
||||
int fmt;
|
||||
int tmp;
|
||||
|
@ -214,7 +192,7 @@ qboolean SNDDMA_Init(void) {
|
|||
snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
|
||||
}
|
||||
|
||||
// open /dev/dsp, check capability to mmap, and get size of dma buffer
|
||||
// open /dev/dsp, confirm capability to mmap, and get size of dma buffer
|
||||
|
||||
/* snd_bsd.c had "if (!audio_fd)" */
|
||||
if (audio_fd == -1)
|
||||
|
@ -248,37 +226,23 @@ qboolean SNDDMA_Init(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps) == -1
|
||||
|| !(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
|
||||
Com_Printf("SNDDMA_Init: Sound device does not support mmap");
|
||||
} else {
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == -1) {
|
||||
perror(snddevice->string);
|
||||
Com_Printf("SNDDMA_Init: Sound driver too old.\n");
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
} else
|
||||
mmapped = 1;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1)
|
||||
{
|
||||
perror(snddevice->string);
|
||||
Com_Printf("SNDDMA_Init: Sound driver too old.\n");
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
|
||||
if (!mmapped) {
|
||||
int frags = 2 << 16 | FRAGSIZEEXP;
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frags) == -1) {
|
||||
perror(snddevice->string);
|
||||
Com_Printf("SNDDMA_Init: Could not set sound fragments");
|
||||
/* NOMMAP - jaq
|
||||
if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP))
|
||||
{
|
||||
Com_Printf("SNDDMA_Init: Sorry, but your soundcard doesn't support trigger or mmap. (%08x)\n", caps);
|
||||
*/
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
/* NOMMAP - jaq
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1)
|
||||
{
|
||||
perror("GETOSPACE");
|
||||
|
@ -287,7 +251,6 @@ qboolean SNDDMA_Init(void) {
|
|||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// set sample bits & speed
|
||||
|
||||
|
@ -390,67 +353,49 @@ qboolean SNDDMA_Init(void) {
|
|||
|
||||
// toggle the trigger & start her up
|
||||
|
||||
if (!mmapped) {
|
||||
dma.submission_chunk = AUDIOBUFFERSIZE;
|
||||
dma.samples = AUDIOBUFFERS * dma.submission_chunk * dma.channels;
|
||||
dma.samplepos = 0;
|
||||
|
||||
if ((dma.buffer = malloc(dma.samples * (dma.samplebits/8))) == 0) {
|
||||
perror(snddevice->string);
|
||||
Com_Printf("Could not allocate shm->buffer");
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
snd_inited = 1;
|
||||
|
||||
pthread_create(&audio, 0L, thesound, 0L);
|
||||
} else {
|
||||
tmp = 0;
|
||||
tmp = 0;
|
||||
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
|
||||
dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8);
|
||||
dma.submission_chunk = 1;
|
||||
dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8);
|
||||
dma.submission_chunk = 1;
|
||||
|
||||
// memory map the dma buffer
|
||||
// memory map the dma buffer
|
||||
|
||||
if (!dma.buffer) {
|
||||
dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal * info.fragsize,
|
||||
if (!dma.buffer) {
|
||||
dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal * info.fragsize,
|
||||
#if defined(__FreeBSD__) && (__FreeBSD_version < 500000)
|
||||
PROT_READ|PROT_WRITE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
#else
|
||||
PROT_WRITE,
|
||||
PROT_WRITE,
|
||||
#endif
|
||||
MAP_FILE|MAP_SHARED, audio_fd, 0);
|
||||
}
|
||||
if (!dma.buffer || dma.buffer == MAP_FAILED) {
|
||||
perror(snddevice->string);
|
||||
Com_Printf("SNDDMA_Init: Could not mmap %s.\n", snddevice->string);
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
perror(snddevice->string);
|
||||
Com_Printf("SNDDMA_Init: Could not toggle. (1)\n");
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
tmp = PCM_ENABLE_OUTPUT;
|
||||
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
|
||||
if (rc < 0) {
|
||||
perror(snddevice->string);
|
||||
Com_Printf("SNDDMA_Init: Could not toggle. (2)\n");
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dma.samplepos = 0;
|
||||
snd_inited = 1;
|
||||
MAP_FILE|MAP_SHARED, audio_fd, 0);
|
||||
}
|
||||
if (!dma.buffer || dma.buffer == MAP_FAILED) {
|
||||
perror(snddevice->string);
|
||||
Com_Printf("SNDDMA_Init: Could not mmap %s.\n", snddevice->string);
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
perror(snddevice->string);
|
||||
Com_Printf("SNDDMA_Init: Could not toggle. (1)\n");
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
tmp = PCM_ENABLE_OUTPUT;
|
||||
rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
|
||||
if (rc < 0) {
|
||||
perror(snddevice->string);
|
||||
Com_Printf("SNDDMA_Init: Could not toggle. (2)\n");
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dma.samplepos = 0;
|
||||
snd_inited = 1;
|
||||
return 1;
|
||||
#endif /* !__sgi */
|
||||
}
|
||||
|
@ -481,9 +426,6 @@ int SNDDMA_GetDMAPos(void) {
|
|||
|
||||
if (!snd_inited) return 0;
|
||||
|
||||
if (!mmapped)
|
||||
return (frags_sent * FRAGSIZE) / (dma.samplebits/8) + FRAGSIZE/16;
|
||||
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1)
|
||||
{
|
||||
perror(snddevice->string);
|
||||
|
@ -515,22 +457,12 @@ void SNDDMA_Shutdown(void) {
|
|||
}
|
||||
#else
|
||||
if (snd_inited) {
|
||||
if (!mmapped) {
|
||||
snd_inited = 0L;
|
||||
pthread_join(audio, 0L);
|
||||
munmap (dma.buffer, dma.samples *dma.samplebits / 8);
|
||||
dma.buffer = 0L;
|
||||
|
||||
if (dma.buffer) {
|
||||
free(dma.buffer);
|
||||
dma.buffer = 0L;
|
||||
}
|
||||
} else {
|
||||
munmap (dma.buffer, dma.samples *dma.samplebits / 8);
|
||||
dma.buffer = 0L;
|
||||
}
|
||||
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
snd_inited = 0;
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
snd_inited = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
178
src/snd_ao.c
Normal file
178
src/snd_ao.c
Normal file
|
@ -0,0 +1,178 @@
|
|||
/* libao sound output
|
||||
*
|
||||
* Copyright (c) 2004 Jamie Wilkinson <jaq@spacepants.org>
|
||||
* for The Quakeforge Project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AO
|
||||
# include <ao/ao.h>
|
||||
#endif
|
||||
|
||||
#include "client.h"
|
||||
#include "snd_loc.h"
|
||||
|
||||
static int snd_inited;
|
||||
static int samplesize;
|
||||
|
||||
cvar_t * sndbits;
|
||||
cvar_t * sndspeed;
|
||||
cvar_t * sndchannels;
|
||||
cvar_t * snddevice;
|
||||
|
||||
ao_device * device;
|
||||
|
||||
/* SNDDMA_Init: initialises cycling through a DMA bufffer and returns
|
||||
* information on it
|
||||
*/
|
||||
qboolean SNDDMA_Init(void) {
|
||||
int driver_id;
|
||||
ao_sample_format format;
|
||||
ao_option * options = NULL;
|
||||
|
||||
if (!snddevice) {
|
||||
sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
|
||||
sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
|
||||
sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
|
||||
snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
|
||||
}
|
||||
|
||||
ao_initialize();
|
||||
|
||||
#if 1
|
||||
if ((driver_id = ao_default_driver_id()) == -1) {
|
||||
#else
|
||||
if ((driver_id = ao_driver_id("wav")) == -1) {
|
||||
#endif
|
||||
Com_Printf("Couldn't find a default driver for sound output\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*ao_append_option(&options, "debug", "");*/
|
||||
|
||||
format.bits = dma.samplebits = sndbits->value;
|
||||
format.rate = dma.speed = 44100;
|
||||
format.channels = dma.channels = sndchannels->value;
|
||||
format.byte_format = AO_FMT_NATIVE;
|
||||
|
||||
switch (dma.speed) {
|
||||
case 44100:
|
||||
dma.samples = 2048 * dma.channels;
|
||||
break;
|
||||
case 22050:
|
||||
dma.samples = 1024 * dma.channels;
|
||||
break;
|
||||
default:
|
||||
dma.samples = 512 * dma.channels;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if ((device = ao_open_live(driver_id, &format, options)) == NULL) {
|
||||
#else
|
||||
if ((device = ao_open_file(driver_id, "foo.wav", 1, &format, options)) == NULL) {
|
||||
#endif
|
||||
switch (errno) {
|
||||
case AO_ENODRIVER:
|
||||
Com_Printf("W: No ao driver for %d\n", driver_id);
|
||||
break;
|
||||
case AO_ENOTLIVE:
|
||||
Com_Printf("W: Not a valid live output device\n");
|
||||
break;
|
||||
case AO_EBADOPTION:
|
||||
Com_Printf("W: Valid option has invalid key\n");
|
||||
break;
|
||||
case AO_EOPENDEVICE:
|
||||
Com_Printf("W: Cannot open device\n");
|
||||
break;
|
||||
case AO_EFAIL:
|
||||
Com_Printf("W: Something broke during ao_open_live\n");
|
||||
break;
|
||||
case AO_ENOTFILE:
|
||||
Com_Printf("W: Not a file\n");
|
||||
break;
|
||||
case AO_EOPENFILE:
|
||||
Com_Printf("W: Can't open file\n");
|
||||
break;
|
||||
case AO_EFILEEXISTS:
|
||||
Com_Printf("W: File exists already\n");
|
||||
break;
|
||||
default:
|
||||
Com_Printf("W: whoa, bad trip dude\n");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
samplesize = dma.samplebits >> 3;
|
||||
dma.buffer = malloc(dma.samples * samplesize);
|
||||
memset(dma.buffer, 0, dma.samples * samplesize);
|
||||
|
||||
snd_inited = 1;
|
||||
dma.samplepos = 0;
|
||||
dma.submission_chunk = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* SNDDMA_GetDMAPos: get the current DMA position
|
||||
*/
|
||||
int SNDDMA_GetDMAPos(void) {
|
||||
if (snd_inited)
|
||||
return dma.samplepos;
|
||||
else
|
||||
Com_Printf("Sound not initialised\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SNDDMA_Shutdown: shutdown the DMA xfer
|
||||
*/
|
||||
void SNDDMA_Shutdown(void) {
|
||||
if (snd_inited) {
|
||||
ao_close(device);
|
||||
ao_shutdown();
|
||||
free(dma.buffer);
|
||||
dma.buffer = 0;
|
||||
snd_inited = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* SNDDMA_Submit: send sound to device if buffer isn't really the dma buffer
|
||||
*/
|
||||
void SNDDMA_Submit(void) {
|
||||
if (!snd_inited)
|
||||
return;
|
||||
|
||||
/* ao_play returns success, not number of samples successfully output
|
||||
* unlike alsa or arts, so we can only assume that the whole buffer
|
||||
* made it out... though this makes updating dma.samplepos easy */
|
||||
if (ao_play(device, dma.buffer, dma.samples * samplesize) == 0) {
|
||||
Com_Printf("W: error occurred while playing buffer\n");
|
||||
ao_close(device);
|
||||
ao_shutdown();
|
||||
snd_inited = 0;
|
||||
}
|
||||
dma.samplepos += dma.samples;
|
||||
}
|
||||
|
||||
void SNDDMA_BeginPainting(void) {
|
||||
}
|
Loading…
Reference in a new issue