Ongoing work (moving to another machine)
[xiph/unicode.git] / snatch / oss.c
blob86bfaaf2f34b22ad7eb691e70b966b6a9367a64f
1 /* All the code for dealing with OSS */
3 #include <linux/soundcard.h>
5 static char *ossname;
6 static int oss_fd=-1;
7 static int oss_fd_fakeopen=0;
9 static int oss_fmt_translate(int format){
10 int i;
11 for(i=0;i<10;i++)
12 if(format==((1<<i)>>1))return(i);
13 return(0);
16 static void oss_hook_init(void){
18 /* oss device? */
19 ossname=nstrdup(getenv("SNATCH_OSS_DEVICE"));
20 if(!ossname){
21 if(debug)
22 fprintf(stderr,
23 "----env: SNATCH_OSS_DEVICE\n"
24 " not set. Using default (/dev/dsp*).\n");
25 ossname=nstrdup("/dev/dsp*");
26 }else{
27 if(debug)
28 fprintf(stderr,
29 "----env: SNATCH_OSS_DEVICE\n"
30 " set (%s)\n",ossname);
34 /* The OSS audio device is subverted through open(). If we didn't
35 care about allowing a fake audio open() to 'succeed' even when the
36 real device is busy, then we could just watch for the ioctl(), grab
37 the fd() then, and not need to bother with any silly string
38 matching. However, we *do* care, so we do this the more complex,
39 slightly more error prone way. */
41 static int oss_identify(const char *pathname){
42 if( (ossname[strlen(ossname)-1]=='*' &&
43 !strncmp(pathname,ossname,strlen(ossname)-1)) ||
44 (ossname[strlen(ossname)-1]!='*' &&
45 !strcmp(pathname,ossname)))return(1);
46 return(0);
49 static int oss_open_hook(const char *pathname){
50 int ret;
51 if(oss_fd>-1){
52 /* umm... an oss fd is already open. report the problem and
53 continue */
54 fprintf(stderr,
55 "\n"
56 "WARNING: RealPlayer is attempting to open more than one\n"
57 " OSS audio device (in this case, %s).\n"
58 " This behavior is unexpected; ignoring this open()\n"
59 " request.\n",pathname);
60 return(-1);
61 }else{
63 /* are we faking the audio? */
64 if(fake_audiop){
65 ret=(*libc_open)("/dev/null",O_RDWR,0);
66 oss_fd_fakeopen=1;
67 }else{
68 ret=(*libc_open)(pathname,O_RDWR,0);
69 oss_fd_fakeopen=0;
72 oss_fd=ret;
73 audio_fd=ret;
74 audio_channels=-1;
75 audio_rate=-1;
76 audio_format=-1;
77 audio_samplepos=0;
78 audio_timezero=bigtime(NULL,NULL);
80 if(debug)
81 fprintf(stderr,
82 " ...: Caught RealPlayer opening OSS audio device "
83 "%s (fd %d).\n",
84 pathname,ret);
85 if(debug && fake_audiop)
86 fprintf(stderr,
87 " ...: Faking the audio open and writes as requested.\n");
89 return(ret);
92 static void oss_close_hook(int fd){
93 if(fd==oss_fd)oss_fd=-1;
96 /* watch OSS audio ioctl()s to track playback rate/channels/depth */
98 static int oss_ioctl_hook_p(int fd){
99 if(fd==oss_fd)return(1);
100 return(0);
103 static int oss_ioctl_hook(int fd,int rq,void *arg){
104 int ret=0;
105 if(!fake_audiop && !oss_fd_fakeopen)
106 ret=(*libc_ioctl)(fd,rq,arg);
108 switch(rq){
109 case SNDCTL_DSP_RESET:
110 audio_timezero=0;
111 audio_samplepos=0;
112 break;
113 case SNDCTL_DSP_SPEED:
114 audio_rate=*(int *)arg;
115 if(debug)
116 fprintf(stderr,
117 " ...: Audio output sampling rate set to %dHz.\n",
118 audio_rate);
119 CloseOutputFile(0);
120 break;
121 case SNDCTL_DSP_CHANNELS:
122 audio_channels=*(int *)arg;
123 if(debug)
124 fprintf(stderr,
125 " ...: Audio output set to %d channels.\n",
126 audio_channels);
127 CloseOutputFile(0);
128 break;
129 case SNDCTL_DSP_SETFMT:
130 audio_format=oss_fmt_translate(*(int *)arg);
131 if(debug)
132 fprintf(stderr,
133 " ...: Audio output format set to %s.\n",
134 audio_fmts[audio_format]);
135 CloseOutputFile(0);
136 break;
137 case SNDCTL_DSP_GETOSPACE:
138 if(fake_audiop){
139 audio_buf_info *temp=arg;
140 temp->fragments=32;
141 temp->fragstotal=32;
142 temp->fragsize=2048;
143 temp->bytes=64*1024;
145 if(debug)
146 fprintf(stderr," ...: OSS output buffer size requested; faking 64k\n");
147 ret=0;
149 break;
150 case SNDCTL_DSP_GETODELAY: /* Must reject the ODELAY if we're not going to
151 properly simulate it! */
152 if(fake_audiop){
153 if(debug)
154 fprintf(stderr,
155 " ...: Rejecting SNDCTL_DSP_GETODELAY ioctl()\n");
156 *(int *)arg=0;
157 ret=-1;
159 break;
162 return(ret);