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