~ubuntu-branches/ubuntu/precise/openarena/precise

« back to all changes in this revision

Viewing changes to code/unix/linux_snd.c

  • Committer: Bazaar Package Importer
  • Author(s): Ansgar Burchardt
  • Date: 2008-09-05 21:14:51 UTC
  • mfrom: (1.2.1 upstream) (2.1.5 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080905211451-243bmbl6l6gdav7l
* Remove non-free code/tools/lcc (Closes: #496346)
  + Remove hunk from patch 10_fix_build_and_binary_on_alpha
  + debian/rules: Add BUILD_GAME_QVM=0 to $(MAKE) call
    (thanks to Peter De Wachter)
* Remove code/libs containing binary libraries for Mac OS X and Win32
* debian/copyright: Explain which parts of upstream's sources were removed
* debian/rules: replace ${source:Upstream-Version} by 0.7.7
  because the variable also contains the `+dfsg1' part
* Add -fsigned-char to compiler options (Closes: #487970)
  (thanks to Peter De Wachter)
* Add myself to Uploaders
* debian/control: Remove article from beginning of short description,
  don't start short description with a capital letter
* debian/openarena.6: Escape minus signs
  + fixes lintian warnings: hyphen-used-as-minus-sign

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
===========================================================================
3
 
Copyright (C) 1999-2005 Id Software, Inc.
4
 
 
5
 
This file is part of Quake III Arena source code.
6
 
 
7
 
Quake III Arena source code is free software; you can redistribute it
8
 
and/or modify it under the terms of the GNU General Public License as
9
 
published by the Free Software Foundation; either version 2 of the License,
10
 
or (at your option) any later version.
11
 
 
12
 
Quake III Arena source code is distributed in the hope that it will be
13
 
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
GNU General Public License for more details.
16
 
 
17
 
You should have received a copy of the GNU General Public License
18
 
along with Quake III Arena source code; if not, write to the Free Software
19
 
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
 
===========================================================================
21
 
*/
22
 
 
23
 
#if !USE_SDL_SOUND
24
 
 
25
 
#include <unistd.h>
26
 
#include <fcntl.h>
27
 
#include <stdlib.h>
28
 
#include <sys/types.h>
29
 
#include <sys/ioctl.h>
30
 
#include <sys/mman.h>
31
 
#include <sys/shm.h>
32
 
#include <sys/wait.h>
33
 
#ifdef __linux__ // rb0101023 - guard this
34
 
#include <linux/soundcard.h>
35
 
#endif
36
 
#ifdef __FreeBSD__ // rb0101023 - added
37
 
#include <sys/soundcard.h>
38
 
#endif
39
 
#include <stdio.h>
40
 
 
41
 
#include "../qcommon/q_shared.h"
42
 
#include "../client/snd_local.h"
43
 
 
44
 
int audio_fd;
45
 
int snd_inited=0;
46
 
 
47
 
cvar_t *sndbits;
48
 
cvar_t *sndspeed;
49
 
cvar_t *sndchannels;
50
 
 
51
 
cvar_t *snddevice;
52
 
 
53
 
/* Some devices may work only with 48000 */
54
 
static int tryrates[] = { 22050, 11025, 44100, 48000, 8000 };
55
 
 
56
 
static qboolean use_custom_memset = qfalse;
57
 
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371 
58
 
void Snd_Memset (void* dest, const int val, const size_t count)
59
 
{
60
 
  int *pDest;
61
 
  int i, iterate;
62
 
 
63
 
  if (!use_custom_memset)
64
 
  {
65
 
    Com_Memset(dest,val,count);
66
 
    return;
67
 
  }
68
 
  iterate = count / sizeof(int);
69
 
  pDest = (int*)dest;
70
 
  for(i=0; i<iterate; i++)
71
 
  {
72
 
    pDest[i] = val;
73
 
  }
74
 
}
75
 
 
76
 
qboolean SNDDMA_Init(void)
77
 
{
78
 
        int rc;
79
 
    int fmt;
80
 
        int tmp;
81
 
    int i;
82
 
    // char *s; // bk001204 - unused
83
 
        struct audio_buf_info info;
84
 
        int caps;
85
 
 
86
 
        if (snd_inited)
87
 
                return 1;
88
 
 
89
 
        if (!snddevice) {
90
 
                sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
91
 
                sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
92
 
                sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
93
 
                snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
94
 
        }
95
 
 
96
 
        // open /dev/dsp, confirm capability to mmap, and get size of dma buffer
97
 
        if (!audio_fd) {
98
 
                audio_fd = open(snddevice->string, O_RDWR);
99
 
 
100
 
                if (audio_fd < 0) {
101
 
                        perror(snddevice->string);
102
 
                        Com_Printf("Could not open %s\n", snddevice->string);
103
 
                        return 0;
104
 
                        }
105
 
        }
106
 
 
107
 
        if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps) == -1) {
108
 
                perror(snddevice->string);
109
 
        Com_Printf("Sound driver too old\n");
110
 
                close(audio_fd);
111
 
                return 0;
112
 
        }
113
 
 
114
 
        if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
115
 
                Com_Printf("Sorry but your soundcard can't do this\n");
116
 
                close(audio_fd);
117
 
                return 0;
118
 
        }
119
 
 
120
 
 
121
 
        /* SNDCTL_DSP_GETOSPACE moved to be called later */
122
 
    
123
 
        // set sample bits & speed
124
 
  dma.samplebits = (int)sndbits->value;
125
 
        if (dma.samplebits != 16 && dma.samplebits != 8) {
126
 
        ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
127
 
        if (fmt & AFMT_S16_LE) 
128
 
                        dma.samplebits = 16;
129
 
        else if (fmt & AFMT_U8) 
130
 
                        dma.samplebits = 8;
131
 
    }
132
 
 
133
 
        dma.speed = (int)sndspeed->value;
134
 
        if (!dma.speed) {
135
 
        for (i=0 ; i<sizeof(tryrates)/4 ; i++)
136
 
            if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) 
137
 
                                break;
138
 
        dma.speed = tryrates[i];
139
 
    }
140
 
 
141
 
        dma.channels = (int)sndchannels->value;
142
 
        if (dma.channels < 1 || dma.channels > 2)
143
 
                dma.channels = 2;
144
 
        
145
 
/*  mmap() call moved forward */
146
 
 
147
 
        tmp = 0;
148
 
        if (dma.channels == 2)
149
 
                tmp = 1;
150
 
    rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
151
 
    if (rc < 0) {
152
 
                perror(snddevice->string);
153
 
        Com_Printf("Could not set %s to stereo=%d", snddevice->string, dma.channels);
154
 
                close(audio_fd);
155
 
        return 0;
156
 
    }
157
 
 
158
 
        if (tmp)
159
 
                dma.channels = 2;
160
 
        else
161
 
                dma.channels = 1;
162
 
 
163
 
    rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &dma.speed);
164
 
    if (rc < 0) {
165
 
                perror(snddevice->string);
166
 
        Com_Printf("Could not set %s speed to %d", snddevice->string, dma.speed);
167
 
                close(audio_fd);
168
 
        return 0;
169
 
    }
170
 
 
171
 
    if (dma.samplebits == 16) {
172
 
        rc = AFMT_S16_LE;
173
 
        rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
174
 
        if (rc < 0) {
175
 
                        perror(snddevice->string);
176
 
                        Com_Printf("Could not support 16-bit data.  Try 8-bit.\n");
177
 
                        close(audio_fd);
178
 
                        return 0;
179
 
                }
180
 
    } else if (dma.samplebits == 8) {
181
 
        rc = AFMT_U8;
182
 
        rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
183
 
        if (rc < 0) {
184
 
                        perror(snddevice->string);
185
 
                        Com_Printf("Could not support 8-bit data.\n");
186
 
                        close(audio_fd);
187
 
                        return 0;
188
 
                }
189
 
    } else {
190
 
                perror(snddevice->string);
191
 
                Com_Printf("%d-bit sound not supported.", dma.samplebits);
192
 
                close(audio_fd);
193
 
                return 0;
194
 
        }
195
 
 
196
 
    if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1) {   
197
 
        perror("GETOSPACE");
198
 
                Com_Printf("Um, can't do GETOSPACE?\n");
199
 
                close(audio_fd);
200
 
                return 0;
201
 
    }
202
 
 
203
 
        dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8);
204
 
        dma.submission_chunk = 1;
205
 
 
206
 
        // memory map the dma buffer
207
 
 
208
 
  // TTimo 2001/10/08 added PROT_READ to the mmap
209
 
  // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
210
 
  // checking Alsa bug, doesn't allow dma alloc with PROT_READ?
211
 
 
212
 
        if (!dma.buffer)
213
 
                dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal
214
 
                        * info.fragsize, PROT_WRITE|PROT_READ, MAP_FILE|MAP_SHARED, audio_fd, 0);
215
 
 
216
 
  if (dma.buffer == MAP_FAILED)
217
 
  {
218
 
    Com_Printf("Could not mmap dma buffer PROT_WRITE|PROT_READ\n");
219
 
    Com_Printf("trying mmap PROT_WRITE (with associated better compatibility / less performance code)\n");
220
 
                dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal
221
 
                        * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
222
 
    // NOTE TTimo could add a variable to force using regular memset on systems that are known to be safe
223
 
    use_custom_memset = qtrue;
224
 
  }
225
 
 
226
 
        if (dma.buffer == MAP_FAILED) {
227
 
                perror(snddevice->string);
228
 
                Com_Printf("Could not mmap %s\n", snddevice->string);
229
 
                close(audio_fd);
230
 
                return 0;
231
 
        }
232
 
 
233
 
        // toggle the trigger & start her up
234
 
 
235
 
  tmp = 0;
236
 
  rc  = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
237
 
        if (rc < 0) {
238
 
                perror(snddevice->string);
239
 
                Com_Printf("Could not toggle.\n");
240
 
                close(audio_fd);
241
 
                return 0;
242
 
        }
243
 
 
244
 
  tmp = PCM_ENABLE_OUTPUT;
245
 
  rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
246
 
        if (rc < 0) {
247
 
                perror(snddevice->string);
248
 
                Com_Printf("Could not toggle.\n");
249
 
                close(audio_fd);
250
 
 
251
 
                return 0;
252
 
        }
253
 
 
254
 
        snd_inited = 1;
255
 
        return 1;
256
 
}
257
 
 
258
 
int SNDDMA_GetDMAPos(void)
259
 
{
260
 
        struct count_info count;
261
 
 
262
 
        if (!snd_inited) return 0;
263
 
 
264
 
        if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count) == -1) {
265
 
                perror(snddevice->string);
266
 
                Com_Printf("Uh, sound dead.\n");
267
 
                close(audio_fd);
268
 
                snd_inited = 0;
269
 
                return 0;
270
 
        }
271
 
        return count.ptr / (dma.samplebits / 8);
272
 
}
273
 
 
274
 
void SNDDMA_Shutdown(void)
275
 
{
276
 
}
277
 
 
278
 
/*
279
 
==============
280
 
SNDDMA_Submit
281
 
 
282
 
Send sound to device if buffer isn't really the dma buffer
283
 
===============
284
 
*/
285
 
void SNDDMA_Submit(void)
286
 
{
287
 
}
288
 
 
289
 
void SNDDMA_BeginPainting (void)
290
 
{
291
 
}
292
 
 
293
 
#endif // !USE_SDL_SOUND
294