spu: reduce use of globals
[pcsx_rearmed.git] / plugins / dfsound / oss.c
1 /***************************************************************************
2                             oss.c  -  description
3                              -------------------
4     begin                : Wed May 15 2002
5     copyright            : (C) 2002 by Pete Bernert
6     email                : BlackDove@addcom.de
7  ***************************************************************************/
8 /***************************************************************************
9  *                                                                         *
10  *   This program is free software; you can redistribute it and/or modify  *
11  *   it under the terms of the GNU General Public License as published by  *
12  *   the Free Software Foundation; either version 2 of the License, or     *
13  *   (at your option) any later version. See also the license.txt file for *
14  *   additional informations.                                              *
15  *                                                                         *
16  ***************************************************************************/
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <sys/ioctl.h>
24 #include <unistd.h>
25 #include <sys/soundcard.h>
26 #include "out.h"
27
28 ////////////////////////////////////////////////////////////////////////
29 // oss globals
30 ////////////////////////////////////////////////////////////////////////
31
32 #define OSS_MODE_STEREO     1
33 #define OSS_MODE_MONO       0
34
35 #define OSS_SPEED_44100     44100
36
37 static int oss_audio_fd = -1;
38 extern int errno;
39
40 ////////////////////////////////////////////////////////////////////////
41 // SETUP SOUND
42 ////////////////////////////////////////////////////////////////////////
43
44 static int oss_init(void)
45 {
46  int pspeed=44100;
47  int pstereo;
48  int format;
49  int fragsize = 0;
50  int myfrag;
51  int oss_speed, oss_stereo;
52
53  pstereo = OSS_MODE_STEREO;
54  oss_speed = pspeed;
55  oss_stereo = pstereo;
56
57  if((oss_audio_fd=open("/dev/dsp",O_WRONLY,0))==-1)
58   {
59    printf("OSS device not available\n");
60    return -1;
61   }
62
63  if(ioctl(oss_audio_fd,SNDCTL_DSP_RESET,0)==-1)
64   {
65    printf("Sound reset failed\n");
66    return -1;
67   }
68
69  // we use 64 fragments with 1024 bytes each
70  // rearmed: now using 10*4096 for better latency
71
72  fragsize=12;
73  myfrag=(10<<16)|fragsize;
74
75  if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFRAGMENT,&myfrag)==-1)
76   {
77    printf("Sound set fragment failed!\n");
78    return -1;
79   }
80
81  format = AFMT_S16_NE;
82
83  if(ioctl(oss_audio_fd,SNDCTL_DSP_SETFMT,&format) == -1)
84   {
85    printf("Sound format not supported!\n");
86    return -1;
87   }
88
89  if(format!=AFMT_S16_NE)
90   {
91    printf("Sound format not supported!\n");
92    return -1;
93   }
94
95  if(ioctl(oss_audio_fd,SNDCTL_DSP_STEREO,&oss_stereo)==-1 || !oss_stereo)
96   {
97    printf("Stereo mode not supported!\n");
98    return -1;
99   }
100
101  if(ioctl(oss_audio_fd,SNDCTL_DSP_SPEED,&oss_speed)==-1)
102   {
103    printf("Sound frequency not supported\n");
104    return -1;
105   }
106
107  if(oss_speed!=pspeed)
108   {
109    printf("Sound frequency not supported\n");
110    return -1;
111   }
112
113  return 0;
114 }
115
116 ////////////////////////////////////////////////////////////////////////
117 // REMOVE SOUND
118 ////////////////////////////////////////////////////////////////////////
119
120 static void oss_finish(void)
121 {
122  if(oss_audio_fd != -1 )
123   {
124    close(oss_audio_fd);
125    oss_audio_fd = -1;
126   }
127 }
128
129 ////////////////////////////////////////////////////////////////////////
130 // GET BUFFERED STATUS
131 ////////////////////////////////////////////////////////////////////////
132
133 static int oss_busy(void)
134 {
135  audio_buf_info info;
136  unsigned long l;
137
138  if(oss_audio_fd == -1) return 1;
139  if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==-1)
140   l=0;
141  else
142   {
143    if(info.fragments<(info.fragstotal>>1))             // can we write in at least the half of fragments?
144         l=1;                                           // -> no? wait
145    else l=0;                                           // -> else go on
146   }
147
148  return l;
149 }
150
151 ////////////////////////////////////////////////////////////////////////
152 // FEED SOUND DATA
153 ////////////////////////////////////////////////////////////////////////
154
155 static void oss_feed(void *buf, int bytes)
156 {
157  audio_buf_info info;
158  char sbuf[4096];
159
160  if(oss_audio_fd == -1) return;
161  if(ioctl(oss_audio_fd,SNDCTL_DSP_GETOSPACE,&info)==0)
162   {
163    if(info.fragments==info.fragstotal)
164     {
165      memset(sbuf, 0, sizeof(sbuf));
166      write(oss_audio_fd, sbuf, sizeof(sbuf));
167      write(oss_audio_fd, sbuf, sizeof(sbuf));
168     }
169   }
170
171  write(oss_audio_fd, buf, bytes);
172 }
173
174 void out_register_oss(struct out_driver *drv)
175 {
176         drv->name = "oss";
177         drv->init = oss_init;
178         drv->finish = oss_finish;
179         drv->busy = oss_busy;
180         drv->feed = oss_feed;
181 }