From d67ab6206c2b1967f5170c5a45bc15b65ac135ef Mon Sep 17 00:00:00 2001 From: taniwha Date: Sat, 16 Sep 2000 19:53:55 +0000 Subject: [PATCH] add ALSA support git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@31 d7cf8633-e32d-0410-b094-e92efae38249 --- makefile | 6 +- snd_alsa.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 snd_alsa.c diff --git a/makefile b/makefile index e8782235..8563f131 100644 --- a/makefile +++ b/makefile @@ -1,10 +1,12 @@ -OBJECTS= cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o cpu_noasm.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_refrag.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o net_vcr.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o sbar.o snd_dma.o snd_mem.o snd_mix.o snd_linux.o sv_main.o sv_move.o sv_phys.o sv_user.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o +SND=snd_alsa.o +OBJECTS= cd_linux.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o cpu_noasm.o crc.o cvar.o fractalnoise.o gl_draw.o gl_poly.o gl_refrag.o gl_rmain.o gl_rmisc.o gl_rsurf.o gl_screen.o gl_warp.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o net_vcr.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_part.o sbar.o snd_dma.o snd_mem.o snd_mix.o $(SND) sv_main.o sv_move.o sv_phys.o sv_user.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o OPTIMIZATIONS= -O6 -ffast-math -funroll-loops -fomit-frame-pointer -fexpensive-optimizations CFLAGS= -Wall -Werror -I/usr/X11R6/include -I/usr/include/glide $(OPTIMIZATIONS) #CFLAGS= -Wall -Werror -I/usr/X11/include -ggdb $(OPTIMIZATIONS) -LDFLAGS= -L/usr/X11R6/lib -lm -lX11 -lXext -lXIE -lXxf86dga -lXxf86vm -lGL -ldl +#LDFLAGS= -L/usr/X11R6/lib -lm -lX11 -lXext -lXIE -lXxf86dga -lXxf86vm -lGL -ldl +LDFLAGS= -L/usr/X11R6/lib -lm -lX11 -lXext -lXIE -lXxf86dga -lXxf86vm -lGL -ldl -lasound all: darkplaces-glx darkplaces-3dfx diff --git a/snd_alsa.c b/snd_alsa.c new file mode 100644 index 00000000..3f957580 --- /dev/null +++ b/snd_alsa.c @@ -0,0 +1,302 @@ +/* + 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 "quakedef.h" + +#include +#include +#include + +#ifndef MAP_FAILED +# define MAP_FAILED ((void*)-1) +#endif + +extern int soundtime; + +static int snd_inited; + +static snd_pcm_t *pcm_handle; +static struct snd_pcm_channel_info cinfo; +static struct snd_pcm_channel_params params; +static struct snd_pcm_channel_setup setup; +static snd_pcm_mmap_control_t *mmap_control = NULL; +static char *mmap_data = NULL; +static int card=-1,dev=-1; + +int check_card(int card) +{ + snd_ctl_t *handle; + snd_ctl_hw_info_t info; + int rc; + + if ((rc = snd_ctl_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_open(&pcm_handle,card,dev, + SND_PCM_OPEN_PLAYBACK + | SND_PCM_OPEN_NONBLOCK))==0) { + return 0; + } + } + } else { + if (dev>=0 && dev =2) { + stereo=1; + } else { + stereo=0; + frag_size/=2; + } + +// err_msg="audio flush"; +// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) +// goto error; + err_msg="audio munmap"; + if ((rc=snd_pcm_munmap(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) + goto error; + + memset(¶ms, 0, sizeof(params)); + params.channel = SND_PCM_CHANNEL_PLAYBACK; + params.mode = SND_PCM_MODE_BLOCK; + params.format.interleave=1; + params.format.format=format; + params.format.rate=rate; + params.format.voices=stereo+1; + params.start_mode = SND_PCM_START_GO; + params.stop_mode = SND_PCM_STOP_ROLLOVER; + params.buf.block.frag_size=frag_size; + params.buf.block.frags_min=1; + params.buf.block.frags_max=-1; +// err_msg="audio flush"; +// if ((rc=snd_pcm_channel_flush(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) +// goto error; + err_msg="audio params"; + if ((rc=snd_pcm_channel_params(pcm_handle, ¶ms))<0) + goto error; + + err_msg="audio mmap"; + if ((rc=snd_pcm_mmap(pcm_handle, SND_PCM_CHANNEL_PLAYBACK, &mmap_control, (void **)&mmap_data))<0) + goto error; + err_msg="audio prepare"; + if ((rc=snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) + goto error; + + memset(&setup, 0, sizeof(setup)); + setup.mode = SND_PCM_MODE_BLOCK; + setup.channel = SND_PCM_CHANNEL_PLAYBACK; + err_msg="audio setup"; + if ((rc=snd_pcm_channel_setup(pcm_handle, &setup))<0) + goto error; + + shm=&sn; + memset((dma_t*)shm,0,sizeof(*shm)); + shm->splitbuffer = 0; + shm->channels=setup.format.voices; + shm->submission_chunk=128; // 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.buf.block.frags*setup.buf.block.frag_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) +{ + if (!snd_inited) return 0; + shm->samplepos=(mmap_control->status.frag_io+1)*setup.buf.block.frag_size/(shm->samplebits/8); + 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 i,s,e; + int rc; + + count+=setup.buf.block.frag_size-1; + count/=setup.buf.block.frag_size; + s=soundtime/setup.buf.block.frag_size; + e=s+count; + for (i=s; ifragments[i % setup.buf.block.frags].data=1; + switch (mmap_control->status.status) { + case SND_PCM_STATUS_PREPARED: + if ((rc=snd_pcm_channel_go(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) { + fprintf(stderr, "unable to start playback. %s\n", + snd_strerror(rc)); + exit(1); + } + break; + case SND_PCM_STATUS_RUNNING: + break; + case SND_PCM_STATUS_UNDERRUN: + if ((rc=snd_pcm_plugin_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK))<0) { + fprintf(stderr, "underrun: playback channel prepare error. %s\n", + snd_strerror(rc)); + exit(1); + } + break; + default: + break; + } +} + -- 2.39.2