|
|
1.1.1.2 ! root 1: /* ! 2: Copyright (C) 1997-2001 Id Software, Inc. ! 3: ! 4: This program is free software; you can redistribute it and/or ! 5: modify it under the terms of the GNU General Public License ! 6: as published by the Free Software Foundation; either version 2 ! 7: of the License, or (at your option) any later version. ! 8: ! 9: This program is distributed in the hope that it will be useful, ! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ! 12: ! 13: See the GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ! 18: ! 19: */ 1.1 root 20: #include <unistd.h> 21: #include <fcntl.h> 22: #include <stdlib.h> 23: #include <sys/types.h> 24: #include <sys/ioctl.h> 25: #include <sys/mman.h> 26: #include <sys/shm.h> 27: #include <sys/wait.h> 28: #include <linux/soundcard.h> 29: #include <stdio.h> 30: 31: #include "../client/client.h" 32: #include "../client/snd_loc.h" 33: 34: int audio_fd; 35: int snd_inited; 36: 37: cvar_t *sndbits; 38: cvar_t *sndspeed; 39: cvar_t *sndchannels; 40: cvar_t *snddevice; 41: 42: static int tryrates[] = { 11025, 22051, 44100, 8000 }; 43: 44: qboolean SNDDMA_Init(void) 45: { 46: 47: int rc; 48: int fmt; 49: int tmp; 50: int i; 51: char *s; 52: struct audio_buf_info info; 53: int caps; 54: extern uid_t saved_euid; 55: 56: if (snd_inited) 57: return; 58: 59: if (!snddevice) { 60: sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE); 61: sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE); 62: sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE); 63: snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE); 64: } 65: 66: // open /dev/dsp, confirm capability to mmap, and get size of dma buffer 67: 68: if (!audio_fd) { 69: seteuid(saved_euid); 70: 71: audio_fd = open(snddevice->string, O_RDWR); 72: 73: seteuid(getuid()); 74: 75: if (audio_fd < 0) 76: { 77: perror(snddevice->string); 78: Com_Printf("Could not open %s\n", snddevice->string); 79: return 0; 80: } 81: } 82: 83: rc = ioctl(audio_fd, SNDCTL_DSP_RESET, 0); 84: if (rc < 0) 85: { 86: perror(snddevice->string); 87: Com_Printf("Could not reset %s\n", snddevice->string); 88: close(audio_fd); 89: return 0; 90: } 91: 92: if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps)==-1) 93: { 94: perror(snddevice->string); 95: Com_Printf("Sound driver too old\n"); 96: close(audio_fd); 97: return 0; 98: } 99: 100: if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) 101: { 102: Com_Printf("Sorry but your soundcard can't do this\n"); 103: close(audio_fd); 104: return 0; 105: } 106: 107: if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1) 108: { 109: perror("GETOSPACE"); 110: Com_Printf("Um, can't do GETOSPACE?\n"); 111: close(audio_fd); 112: return 0; 113: } 114: 115: // set sample bits & speed 116: 117: dma.samplebits = (int)sndbits->value; 118: if (dma.samplebits != 16 && dma.samplebits != 8) 119: { 120: ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt); 121: if (fmt & AFMT_S16_LE) dma.samplebits = 16; 122: else if (fmt & AFMT_U8) dma.samplebits = 8; 123: } 124: 125: dma.speed = (int)sndspeed->value; 126: if (!dma.speed) { 127: for (i=0 ; i<sizeof(tryrates)/4 ; i++) 128: if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) break; 129: dma.speed = tryrates[i]; 130: } 131: 132: dma.channels = (int)sndchannels->value; 133: if (dma.channels < 1 || dma.channels > 2) 134: dma.channels = 2; 135: 136: dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8); 137: dma.submission_chunk = 1; 138: 139: // memory map the dma buffer 140: 141: if (!dma.buffer) 142: dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal 143: * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0); 144: if (!dma.buffer) 145: { 146: perror(snddevice->string); 147: Com_Printf("Could not mmap %s\n", snddevice->string); 148: close(audio_fd); 149: return 0; 150: } 151: 152: tmp = 0; 153: if (dma.channels == 2) 154: tmp = 1; 155: rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp); 156: if (rc < 0) 157: { 158: perror(snddevice->string); 159: Com_Printf("Could not set %s to stereo=%d", snddevice->string, dma.channels); 160: close(audio_fd); 161: return 0; 162: } 163: if (tmp) 164: dma.channels = 2; 165: else 166: dma.channels = 1; 167: 168: rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &dma.speed); 169: if (rc < 0) 170: { 171: perror(snddevice->string); 172: Com_Printf("Could not set %s speed to %d", snddevice->string, dma.speed); 173: close(audio_fd); 174: return 0; 175: } 176: 177: if (dma.samplebits == 16) 178: { 179: rc = AFMT_S16_LE; 180: rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc); 181: if (rc < 0) 182: { 183: perror(snddevice->string); 184: Com_Printf("Could not support 16-bit data. Try 8-bit.\n"); 185: close(audio_fd); 186: return 0; 187: } 188: } 189: else if (dma.samplebits == 8) 190: { 191: rc = AFMT_U8; 192: rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc); 193: if (rc < 0) 194: { 195: perror(snddevice->string); 196: Com_Printf("Could not support 8-bit data.\n"); 197: close(audio_fd); 198: return 0; 199: } 200: } 201: else 202: { 203: perror(snddevice->string); 204: Com_Printf("%d-bit sound not supported.", dma.samplebits); 205: close(audio_fd); 206: return 0; 207: } 208: 209: // toggle the trigger & start her up 210: 211: tmp = 0; 212: rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); 213: if (rc < 0) 214: { 215: perror(snddevice->string); 216: Com_Printf("Could not toggle.\n"); 217: close(audio_fd); 218: return 0; 219: } 220: tmp = PCM_ENABLE_OUTPUT; 221: rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp); 222: if (rc < 0) 223: { 224: perror(snddevice->string); 225: Com_Printf("Could not toggle.\n"); 226: close(audio_fd); 227: return 0; 228: } 229: 230: dma.samplepos = 0; 231: 232: snd_inited = 1; 233: return 1; 234: 235: } 236: 237: int SNDDMA_GetDMAPos(void) 238: { 239: 240: struct count_info count; 241: 242: if (!snd_inited) return 0; 243: 244: if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count)==-1) 245: { 246: perror(snddevice->string); 247: Com_Printf("Uh, sound dead.\n"); 248: close(audio_fd); 249: snd_inited = 0; 250: return 0; 251: } 252: // dma.samplepos = (count.bytes / (dma.samplebits / 8)) & (dma.samples-1); 253: // fprintf(stderr, "%d \r", count.ptr); 254: dma.samplepos = count.ptr / (dma.samplebits / 8); 255: 256: return dma.samplepos; 257: 258: } 259: 260: void SNDDMA_Shutdown(void) 261: { 262: #if 0 263: if (snd_inited) 264: { 265: close(audio_fd); 266: snd_inited = 0; 267: } 268: #endif 269: } 270: 271: /* 272: ============== 273: SNDDMA_Submit 274: 275: Send sound to device if buffer isn't really the dma buffer 276: =============== 277: */ 278: void SNDDMA_Submit(void) 279: { 280: } 281: 282: void SNDDMA_BeginPainting (void) 283: { 284: } 285:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.