diff --git a/configure.in b/configure.in index 3cb58ad..bd926ce 100644 --- a/configure.in +++ b/configure.in @@ -567,13 +567,25 @@ if test "x$enable_alsa" != "xno"; then [ #include #if defined(SND_LIB_MAJOR) && defined(SND_LIB_MINOR) -#if SND_LIB_MAJOR>0 || (SND_LIB_MAJOR==0 && SND_LIB_MINOR>=5) +#if SND_LIB_MAJOR>0 || (SND_LIB_MAJOR==0 && SND_LIB_MINOR==5) QF_maGiC_VALUE #endif #endif ], - SNDTYPE="ALSA" - SOUND_LIBS="-lasound" + SNDTYPE="ALSA_0_5" + SOUND_LIBS="-lasound", + AC_EGREP_CPP([QF_maGiC_VALUE], + [ +#include +#if defined(SND_LIB_MAJOR) && defined(SND_LIB_MINOR) +#if SND_LIB_MAJOR>0 || (SND_LIB_MAJOR==0 && SND_LIB_MINOR>=6) +QF_maGiC_VALUE +#endif +#endif + ], + SNDTYPE="ALSA_0_6" + SOUND_LIBS="-lasound" + ) ) fi fi @@ -650,12 +662,13 @@ else fi AC_SUBST(SOUND_LIBS) AC_SUBST(SOUND_CFLAGS) -AM_CONDITIONAL(SNDTYPE_ALSA, test "$SNDTYPE" = "ALSA") +AM_CONDITIONAL(SNDTYPE_ALSA_0_5, test "$SNDTYPE" = "ALSA_0_5") +AM_CONDITIONAL(SNDTYPE_ALSA_0_6, test "$SNDTYPE" = "ALSA_0_6") AM_CONDITIONAL(SNDTYPE_MME, test "$SNDTYPE" = "MME") AM_CONDITIONAL(SNDTYPE_OSS, test "$SNDTYPE" = "OSS") AM_CONDITIONAL(SNDTYPE_SUN, test "$SNDTYPE" = "SUN") AM_CONDITIONAL(SNDTYPE_WIN32, test "$SNDTYPE" = "WIN32") -AM_CONDITIONAL(SNDTYPE_NULL, test "$SNDTYPE" != "ALSA" -a "$SNDTYPE" != "MME" -a "$SNDTYPE" != "OSS" -a "$SNDTYPE" != "SUN" -a "$SNDTYPE" != "WIN32") +AM_CONDITIONAL(SNDTYPE_NULL, test "$SNDTYPE" != "ALSA_0_5" -a "$SNDTYPE" != "ALSA_0_6" -a "$SNDTYPE" != "MME" -a "$SNDTYPE" != "OSS" -a "$SNDTYPE" != "SUN" -a "$SNDTYPE" != "WIN32") dnl ================================================================== dnl Checks for CD-ROM diff --git a/source/Makefile.am b/source/Makefile.am index c805ec7..a797bcb 100644 --- a/source/Makefile.am +++ b/source/Makefile.am @@ -67,8 +67,11 @@ EXTRA_libqfsys_a_SOURCES= dirent.c fnmatch.c sys_unix.c sys_win.c # # ... Digital audio # -if SNDTYPE_ALSA -libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa.c $(sound_ASM) +if SNDTYPE_ALSA_0_5 +libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_5.c $(sound_ASM) +endif +if SNDTYPE_ALSA_0_6 +libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_6.c $(sound_ASM) endif if SNDTYPE_MME libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_mme.c $(sound_ASM) @@ -85,8 +88,9 @@ endif if SNDTYPE_NULL libqfsnd_a_SOURCES= snd_null.c $(sound_ASM) endif -EXTRA_libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa.c snd_oss.c \ - snd_sun.c snd_win.c snd_null.c $(sound_ASM) +EXTRA_libqfsnd_a_SOURCES= snd_dma.c snd_mem.c snd_mix.c snd_alsa_0_5.c \ + snd_alsa_0_6.c snd_oss.c snd_sun.c snd_win.c snd_null.c \ + $(sound_ASM) # # ... CD audio diff --git a/source/snd_alsa.c b/source/snd_alsa_0_5.c similarity index 100% rename from source/snd_alsa.c rename to source/snd_alsa_0_5.c diff --git a/source/snd_alsa_0_6.c b/source/snd_alsa_0_6.c new file mode 100644 index 0000000..23c971b --- /dev/null +++ b/source/snd_alsa_0_6.c @@ -0,0 +1,318 @@ +/* + snd_alsa.c + + (description) + + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_IOCTL_H +# include +#endif +#ifdef HAVE_SYS_MMAN_H +# include +#endif +#if defined HAVE_SYS_SOUNDCARD_H +# include +#elif defined HAVE_LINUX_SOUNDCARD_H +# include +#elif HAVE_MACHINE_SOUNDCARD_H +# include +#endif + +#include + +#ifndef MAP_FAILED +# define MAP_FAILED ((void*)-1) +#endif + +static int snd_inited; + +static snd_pcm_t *pcm_handle; +static snd_pcm_info_t cinfo; +static snd_pcm_params_info_t cpinfo; +static snd_pcm_params_t params; +static snd_pcm_setup_t setup; +static snd_pcm_mmap_control_t *mmap_control = NULL; +static snd_pcm_mmap_status_t *mmap_status = NULL; +static char *mmap_data = NULL; +static int card=-1,dev=-1,subdev=-1;; + +int check_card(int card) +{ + snd_ctl_t *handle; + snd_ctl_hw_info_t info; + int rc; + + if ((rc = snd_ctl_hw_open(&handle, card)) < 0) { + Con_Printf("Error: control open (%i): %s\n", card, snd_strerror(rc)); + return rc; + } + if ((rc = snd_ctl_hw_info(handle, &info)) < 0) { + Con_Printf("Error: control hardware info (%i): %s\n", card, + snd_strerror(rc)); + snd_ctl_close(handle); + return rc; + } + snd_ctl_close(handle); + if (dev==-1) { + for (dev = 0; dev < info.pcmdevs; dev++) { + if ((rc=snd_pcm_hw_open_subdevice(&pcm_handle,card,dev,subdev, + SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK))==0) { + return 0; + } + } + } else { + if (dev>=0 && dev =2) { + stereo=1; + frame_size*=2; + } else { + stereo=0; + } + + memset(¶ms, 0, sizeof(params)); + params.mode = SND_PCM_MODE_FRAME; + params.format.interleave=1; + params.format.format=format; + params.format.rate=rate; + params.format.channels=stereo+1; + params.start_mode = SND_PCM_START_GO; + params.xrun_mode = SND_PCM_XRUN_RESTART; + + params.buffer_size = (2<<16) / frame_size; + params.frag_size=frag_size; + params.avail_min = frag_size; + params.align = frag_size; + + params.xrun_max = 1024; + params.fill_mode = SND_PCM_FILL_SILENCE; + params.fill_max = 1024; + params.boundary = params.buffer_size; + + err_msg="audio params"; + if ((rc=snd_pcm_params(pcm_handle, ¶ms))<0) + goto error; + + err_msg="audio mmap"; + if ((rc=snd_pcm_mmap(pcm_handle, &mmap_status, &mmap_control, (void **)&mmap_data))<0) + goto error; + err_msg="audio prepare"; + if ((rc=snd_pcm_prepare(pcm_handle))<0) + goto error; + + memset(&setup, 0, sizeof(setup)); + err_msg="audio setup"; + if ((rc=snd_pcm_setup(pcm_handle, &setup))<0) + goto error; + + shm=&sn; + memset((dma_t*)shm,0,sizeof(*shm)); + shm->splitbuffer = 0; + shm->channels=setup.format.channels; + shm->submission_chunk=frag_size; // don't mix less than this # + shm->samplepos=0; // in mono samples + shm->samplebits=setup.format.format==SND_PCM_SFMT_S16_LE?16:8; + shm->samples=setup.buffer_size*frame_size/(shm->samplebits/8); // mono samples in buffer + shm->speed=setup.format.rate; + shm->buffer=(unsigned char*)mmap_data; + Con_Printf("%5d stereo\n", shm->channels - 1); + Con_Printf("%5d samples\n", shm->samples); + Con_Printf("%5d samplepos\n", shm->samplepos); + Con_Printf("%5d samplebits\n", shm->samplebits); + Con_Printf("%5d submission_chunk\n", shm->submission_chunk); + Con_Printf("%5d speed\n", shm->speed); + Con_Printf("0x%x dma buffer\n", (int)shm->buffer); + Con_Printf("%5d total_channels\n", total_channels); + + snd_inited=1; + return 1; + error: + Con_Printf("Error: %s: %s\n", err_msg, snd_strerror(rc)); + error_2: + snd_pcm_close(pcm_handle); + return 0; +} + +int SNDDMA_GetDMAPos(void) +{ + size_t hw_ptr; + if (!snd_inited) return 0; + hw_ptr = snd_pcm_hw_ptr (pcm_handle, 1); + //printf("%7d %7d\n", mmap_control->appl_ptr, hw_ptr); + hw_ptr *= shm->channels; + shm->samplepos = hw_ptr; + return shm->samplepos; +} + +void SNDDMA_Shutdown(void) +{ + if (snd_inited) + { + snd_pcm_close(pcm_handle); + snd_inited = 0; + } +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +=============== +*/ +void SNDDMA_Submit(void) +{ + int count=paintedtime-soundtime; + int rc; + + mmap_control->appl_ptr=mmap_status->hw_ptr+count; + switch (mmap_status->state) { + case SND_PCM_STATE_PREPARED: + if ((rc=snd_pcm_go(pcm_handle))<0) { + fprintf(stderr, "unable to start playback. %s\n", + snd_strerror(rc)); + exit(1); + } + break; + case SND_PCM_STATE_RUNNING: + break; + case SND_PCM_STATE_UNDERRUN: + printf("sound underrun\n"); + if ((rc=snd_pcm_prepare (pcm_handle))<0) { + fprintf(stderr, "underrun: playback channel prepare error. %s\n", + snd_strerror(rc)); + exit(1); + } + break; + } +} +