Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

linux_snd.c File Reference

#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <stdio.h>
#include "../game/q_shared.h"
#include "../client/snd_local.h"

Include dependency graph for linux_snd.c:

Include dependency graph

Go to the source code of this file.

Functions

void Snd_Memset (void *dest, const int val, const size_t count)
void SNDDMA_BeginPainting (void)
int SNDDMA_GetDMAPos (void)
qboolean SNDDMA_Init (void)
void SNDDMA_Shutdown (void)
void SNDDMA_Submit (void)

Variables

int audio_fd
int snd_inited = 0
cvar_tsndbits
cvar_tsndchannels
cvar_tsnddevice
cvar_tsndspeed
int tryrates [] = { 22050, 11025, 44100, 48000, 8000 }
qboolean use_custom_memset = qfalse


Function Documentation

void Snd_Memset void *  dest,
const int  val,
const size_t  count
 

Definition at line 55 of file linux_snd.c.

References Com_Memset(), count, and i.

00056 {
00057   int *pDest;
00058   int i, iterate;
00059 
00060   if (!use_custom_memset)
00061   {
00062     Com_Memset(dest,val,count);
00063     return;
00064   }
00065   iterate = count / sizeof(int);
00066   pDest = (int*)dest;
00067   for(i=0; i<iterate; i++)
00068   {
00069     pDest[i] = val;
00070   }
00071 }

Here is the call graph for this function:

void SNDDMA_BeginPainting void   ) 
 

Definition at line 291 of file linux_snd.c.

00292 {
00293 }

int SNDDMA_GetDMAPos void   ) 
 

Definition at line 260 of file linux_snd.c.

References audio_fd, close(), Com_Printf(), count, dma, perror(), dma_t::samplebits, snd_inited, snddevice, and cvar_s::string.

00261 {
00262     struct count_info count;
00263 
00264     if (!snd_inited) return 0;
00265 
00266     if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &count) == -1) {
00267         perror(snddevice->string);
00268         Com_Printf("Uh, sound dead.\n");
00269         close(audio_fd);
00270         snd_inited = 0;
00271         return 0;
00272     }
00273     return count.ptr / (dma.samplebits / 8);
00274 }

Here is the call graph for this function:

qboolean SNDDMA_Init void   ) 
 

Definition at line 73 of file linux_snd.c.

References audio_fd, dma_t::buffer, dma_t::channels, close(), Com_Printf(), CVAR_ARCHIVE, Cvar_Get(), dma, i, NULL, open(), perror(), qboolean, dma_t::samplebits, dma_t::samples, saved_euid, snd_inited, sndbits, sndchannels, snddevice, sndspeed, dma_t::speed, cvar_s::string, dma_t::submission_chunk, tryrates, use_custom_memset, and cvar_s::value.

00074 {
00075     int rc;
00076     int fmt;
00077     int tmp;
00078     int i;
00079     // char *s; // bk001204 - unused
00080     struct audio_buf_info info;
00081     int caps;
00082     extern uid_t saved_euid;
00083 
00084     if (snd_inited)
00085         return 1;
00086 
00087     if (!snddevice) {
00088         sndbits = Cvar_Get("sndbits", "16", CVAR_ARCHIVE);
00089         sndspeed = Cvar_Get("sndspeed", "0", CVAR_ARCHIVE);
00090         sndchannels = Cvar_Get("sndchannels", "2", CVAR_ARCHIVE);
00091         snddevice = Cvar_Get("snddevice", "/dev/dsp", CVAR_ARCHIVE);
00092     }
00093 
00094     // open /dev/dsp, confirm capability to mmap, and get size of dma buffer
00095     if (!audio_fd) {
00096         seteuid(saved_euid);
00097 
00098         audio_fd = open(snddevice->string, O_RDWR);
00099 
00100         seteuid(getuid());
00101 
00102         if (audio_fd < 0) {
00103             perror(snddevice->string);
00104             Com_Printf("Could not open %s\n", snddevice->string);
00105             return 0;
00106             }
00107     }
00108 
00109     if (ioctl(audio_fd, SNDCTL_DSP_GETCAPS, &caps) == -1) {
00110         perror(snddevice->string);
00111         Com_Printf("Sound driver too old\n");
00112         close(audio_fd);
00113         return 0;
00114     }
00115 
00116     if (!(caps & DSP_CAP_TRIGGER) || !(caps & DSP_CAP_MMAP)) {
00117         Com_Printf("Sorry but your soundcard can't do this\n");
00118         close(audio_fd);
00119         return 0;
00120     }
00121 
00122 
00123     /* SNDCTL_DSP_GETOSPACE moved to be called later */
00124     
00125     // set sample bits & speed
00126   dma.samplebits = (int)sndbits->value;
00127     if (dma.samplebits != 16 && dma.samplebits != 8) {
00128         ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &fmt);
00129         if (fmt & AFMT_S16_LE) 
00130             dma.samplebits = 16;
00131         else if (fmt & AFMT_U8) 
00132             dma.samplebits = 8;
00133     }
00134 
00135     dma.speed = (int)sndspeed->value;
00136     if (!dma.speed) {
00137         for (i=0 ; i<sizeof(tryrates)/4 ; i++)
00138             if (!ioctl(audio_fd, SNDCTL_DSP_SPEED, &tryrates[i])) 
00139                 break;
00140         dma.speed = tryrates[i];
00141     }
00142 
00143     dma.channels = (int)sndchannels->value;
00144     if (dma.channels < 1 || dma.channels > 2)
00145         dma.channels = 2;
00146         
00147 /*  mmap() call moved forward */
00148 
00149     tmp = 0;
00150     if (dma.channels == 2)
00151         tmp = 1;
00152     rc = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
00153     if (rc < 0) {
00154         perror(snddevice->string);
00155         Com_Printf("Could not set %s to stereo=%d", snddevice->string, dma.channels);
00156         close(audio_fd);
00157         return 0;
00158     }
00159 
00160     if (tmp)
00161         dma.channels = 2;
00162     else
00163         dma.channels = 1;
00164 
00165     rc = ioctl(audio_fd, SNDCTL_DSP_SPEED, &dma.speed);
00166     if (rc < 0) {
00167         perror(snddevice->string);
00168         Com_Printf("Could not set %s speed to %d", snddevice->string, dma.speed);
00169         close(audio_fd);
00170         return 0;
00171     }
00172 
00173     if (dma.samplebits == 16) {
00174         rc = AFMT_S16_LE;
00175         rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
00176         if (rc < 0) {
00177             perror(snddevice->string);
00178             Com_Printf("Could not support 16-bit data.  Try 8-bit.\n");
00179             close(audio_fd);
00180             return 0;
00181         }
00182     } else if (dma.samplebits == 8) {
00183         rc = AFMT_U8;
00184         rc = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &rc);
00185         if (rc < 0) {
00186             perror(snddevice->string);
00187             Com_Printf("Could not support 8-bit data.\n");
00188             close(audio_fd);
00189             return 0;
00190         }
00191     } else {
00192         perror(snddevice->string);
00193         Com_Printf("%d-bit sound not supported.", dma.samplebits);
00194         close(audio_fd);
00195         return 0;
00196     }
00197 
00198     if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info)==-1) {   
00199         perror("GETOSPACE");
00200         Com_Printf("Um, can't do GETOSPACE?\n");
00201         close(audio_fd);
00202         return 0;
00203     }
00204 
00205     dma.samples = info.fragstotal * info.fragsize / (dma.samplebits/8);
00206     dma.submission_chunk = 1;
00207 
00208     // memory map the dma buffer
00209 
00210   // TTimo 2001/10/08 added PROT_READ to the mmap
00211   // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
00212   // checking Alsa bug, doesn't allow dma alloc with PROT_READ?
00213 
00214     if (!dma.buffer)
00215         dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal
00216             * info.fragsize, PROT_WRITE|PROT_READ, MAP_FILE|MAP_SHARED, audio_fd, 0);
00217 
00218   if (dma.buffer == MAP_FAILED)
00219   {
00220     Com_Printf("Could not mmap dma buffer PROT_WRITE|PROT_READ\n");
00221     Com_Printf("trying mmap PROT_WRITE (with associated better compatibility / less performance code)\n");
00222         dma.buffer = (unsigned char *) mmap(NULL, info.fragstotal
00223             * info.fragsize, PROT_WRITE, MAP_FILE|MAP_SHARED, audio_fd, 0);
00224     // NOTE TTimo could add a variable to force using regular memset on systems that are known to be safe
00225     use_custom_memset = qtrue;
00226   }
00227 
00228     if (dma.buffer == MAP_FAILED) {
00229         perror(snddevice->string);
00230         Com_Printf("Could not mmap %s\n", snddevice->string);
00231         close(audio_fd);
00232         return 0;
00233     }
00234 
00235     // toggle the trigger & start her up
00236 
00237   tmp = 0;
00238   rc  = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
00239     if (rc < 0) {
00240         perror(snddevice->string);
00241         Com_Printf("Could not toggle.\n");
00242         close(audio_fd);
00243         return 0;
00244     }
00245 
00246   tmp = PCM_ENABLE_OUTPUT;
00247   rc = ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &tmp);
00248     if (rc < 0) {
00249         perror(snddevice->string);
00250         Com_Printf("Could not toggle.\n");
00251         close(audio_fd);
00252 
00253         return 0;
00254     }
00255 
00256     snd_inited = 1;
00257     return 1;
00258 }

Here is the call graph for this function:

void SNDDMA_Shutdown void   ) 
 

Definition at line 276 of file linux_snd.c.

00277 {
00278 }

void SNDDMA_Submit void   ) 
 

Definition at line 287 of file linux_snd.c.

00288 {
00289 }


Variable Documentation

int audio_fd
 

Definition at line 41 of file linux_snd.c.

Referenced by SNDDMA_GetDMAPos(), and SNDDMA_Init().

int snd_inited = 0
 

Definition at line 42 of file linux_snd.c.

Referenced by SNDDMA_GetDMAPos(), and SNDDMA_Init().

cvar_t* sndbits
 

Definition at line 44 of file linux_snd.c.

Referenced by SNDDMA_Init().

cvar_t* sndchannels
 

Definition at line 46 of file linux_snd.c.

Referenced by SNDDMA_Init().

cvar_t* snddevice
 

Definition at line 48 of file linux_snd.c.

Referenced by SNDDMA_GetDMAPos(), and SNDDMA_Init().

cvar_t* sndspeed
 

Definition at line 45 of file linux_snd.c.

Referenced by SNDDMA_Init().

int tryrates[] = { 22050, 11025, 44100, 48000, 8000 } [static]
 

Definition at line 51 of file linux_snd.c.

Referenced by SNDDMA_Init().

qboolean use_custom_memset = qfalse [static]
 

Definition at line 53 of file linux_snd.c.

Referenced by SNDDMA_Init().


Generated on Thu Aug 25 15:38:41 2005 for Quake III Arena by  doxygen 1.3.9.1