|
|
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.