]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia2/lib/sndoss.cpp
makefile typo
[wxWidgets.git] / utils / wxMMedia2 / lib / sndoss.cpp
CommitLineData
526ddb13
GL
1// --------------------------------------------------------------------------
2// Name: sndoss.cpp
3// Purpose:
4// Date: 08/11/1999
5// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
6// CVSID: $Id$
7// --------------------------------------------------------------------------
8#ifdef __GNUG__
9#pragma implementation "sndoss.cpp"
10#endif
11
12#include <sys/soundcard.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <sys/ioctl.h>
16#include <fcntl.h>
17#include <unistd.h>
18#include <wx/defs.h>
19#include <wx/string.h>
20#include "sndbase.h"
21#include "sndoss.h"
22#include "sndpcm.h"
23#ifdef __WXGTK__
24#include <gdk/gdk.h>
25#endif
26
27wxSoundStreamOSS::wxSoundStreamOSS(const wxString& dev_name)
28{
29 wxSoundFormatPcm pcm_default;
30
31 m_fd = open(dev_name.mb_str(), O_RDWR);
32
33 if (m_fd == -1) {
34 m_snderror = wxSOUND_INVDEV;
35 return;
36 }
37
38 m_devname = dev_name;
39
40 wxSoundStreamOSS::SetSoundFormat(pcm_default);
41
42 ioctl(m_fd, SNDCTL_DSP_GETBLKSIZE, &m_bufsize);
43
44 m_snderror = wxSOUND_NOERR;
45
46 close(m_fd);
47
48 m_oss_stop = TRUE;
49}
50
51wxSoundStreamOSS::~wxSoundStreamOSS()
52{
53 if (m_fd > 0)
54 close(m_fd);
55}
56
57wxUint32 wxSoundStreamOSS::GetBestSize() const
58{
59 return m_bufsize;
60}
61
62wxSoundStream& wxSoundStreamOSS::Read(void *buffer, size_t len)
63{
64 int ret;
65
66 m_lastcount = (size_t)ret = read(m_fd, buffer, len);
67
68 if (ret < 0)
69 m_snderror = wxSOUND_IOERR;
70 else
71 m_snderror = wxSOUND_NOERR;
72
73 return *this;
74}
75
76wxSoundStream& wxSoundStreamOSS::Write(const void *buffer, size_t len)
77{
78 int ret;
79
80 m_lastcount = (size_t)ret = write(m_fd, buffer, len);
81
82 if (ret < 0)
83 m_snderror = wxSOUND_IOERR;
84 else
85 m_snderror = wxSOUND_NOERR;
86
87 return *this;
88}
89
90bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase& format)
91{
92 int tmp;
93 wxSoundFormatPcm *pcm_format;
94
95 if (format.GetType() != wxSOUND_PCM) {
96 m_snderror = wxSOUND_INVFRMT;
97 return FALSE;
98 }
99
100 if (m_fd == -1) {
101 m_snderror = wxSOUND_INVDEV;
102 return FALSE;
103 }
104
105 if (m_sndformat)
106 delete m_sndformat;
107
108 m_sndformat = format.Clone();
109 if (!m_sndformat) {
110 m_snderror = wxSOUND_MEMERR;
111 return FALSE;
112 }
113 pcm_format = (wxSoundFormatPcm *)m_sndformat;
114
115 // Set the sample rate field.
116 tmp = pcm_format->GetSampleRate();
117 ioctl(m_fd, SNDCTL_DSP_SPEED, &tmp);
118
119 pcm_format->SetSampleRate(tmp);
120
121 // Detect the best format
122 DetectBest(pcm_format);
123 SetupFormat(pcm_format);
124
125 tmp = pcm_format->GetChannels();
126 ioctl(m_fd, SNDCTL_DSP_CHANNELS, &tmp);
127 pcm_format->SetChannels(tmp);
128
129 m_snderror = wxSOUND_NOERR;
130 if (*pcm_format != format) {
131 m_snderror = wxSOUND_NOTEXACT;
132 return FALSE;
133 }
134 return TRUE;
135}
136
137bool wxSoundStreamOSS::SetupFormat(wxSoundFormatPcm *pcm_format)
138{
139 int tmp;
140
141 switch(pcm_format->GetBPS()) {
142 case 8:
143 if (pcm_format->Signed())
144 tmp = AFMT_S8;
145 else
146 tmp = AFMT_U8;
147 break;
148 case 16:
149 switch (pcm_format->GetOrder()) {
150 case wxBIG_ENDIAN:
151 if (pcm_format->Signed())
152 tmp = AFMT_S16_BE;
153 else
154 tmp = AFMT_U16_BE;
155 break;
156 case wxLITTLE_ENDIAN:
157 if (pcm_format->Signed())
158 tmp = AFMT_S16_LE;
159 else
160 tmp = AFMT_U16_LE;
161 break;
162 }
163 break;
164 }
165
166 ioctl(m_fd, SNDCTL_DSP_SETFMT, &tmp);
167
168 // Demangling.
169 switch (tmp) {
170 case AFMT_U8:
171 pcm_format->SetBPS(8);
172 pcm_format->Signed(FALSE);
173 break;
174 case AFMT_S8:
175 pcm_format->SetBPS(8);
176 pcm_format->Signed(TRUE);
177 break;
178 case AFMT_U16_LE:
179 pcm_format->SetBPS(16);
180 pcm_format->Signed(FALSE);
181 pcm_format->SetOrder(wxLITTLE_ENDIAN);
182 break;
183 case AFMT_U16_BE:
184 pcm_format->SetBPS(16);
185 pcm_format->Signed(FALSE);
186 pcm_format->SetOrder(wxBIG_ENDIAN);
187 break;
188 case AFMT_S16_LE:
189 pcm_format->SetBPS(16);
190 pcm_format->Signed(TRUE);
191 pcm_format->SetOrder(wxLITTLE_ENDIAN);
192 break;
193 case AFMT_S16_BE:
194 pcm_format->SetBPS(16);
195 pcm_format->Signed(TRUE);
196 pcm_format->SetOrder(wxBIG_ENDIAN);
197 break;
198 }
199 return TRUE;
200}
201
202#ifdef __WXGTK__
203static void _wxSound_OSS_CBack(gpointer data, int source,
204 GdkInputCondition condition)
205{
206 wxSoundStreamOSS *oss = (wxSoundStreamOSS *)data;
207
208 switch (condition) {
209 case GDK_INPUT_READ:
210 oss->WakeUpEvt(wxSOUND_INPUT);
211 break;
212 case GDK_INPUT_WRITE:
213 oss->WakeUpEvt(wxSOUND_OUTPUT);
214 break;
215 default:
216 break;
217 }
218}
219#endif
220
221void wxSoundStreamOSS::WakeUpEvt(int evt)
222{
223 OnSoundEvent(evt);
224}
225
226bool wxSoundStreamOSS::StartProduction(int evt)
227{
228 wxSoundFormatBase *old_frmt;
229
230 if (!m_oss_stop)
231 StopProduction();
232
233 old_frmt = m_sndformat->Clone();
234
235 if (evt == wxSOUND_OUTPUT)
236 m_fd = open(m_devname.mb_str(), O_WRONLY);
237 else if (evt == wxSOUND_INPUT)
238 m_fd = open(m_devname.mb_str(), O_RDONLY);
239
240 if (m_fd == -1) {
241 m_snderror = wxSOUND_INVDEV;
242 return FALSE;
243 }
244
245 SetSoundFormat(*old_frmt);
246 delete old_frmt;
247
248#ifdef __WXGTK__
249 int trig;
250
251 if (evt == wxSOUND_OUTPUT) {
252 m_tag = gdk_input_add(m_fd, GDK_INPUT_WRITE, _wxSound_OSS_CBack, (gpointer)this);
253 trig = PCM_ENABLE_OUTPUT;
254 } else {
255 m_tag = gdk_input_add(m_fd, GDK_INPUT_READ, _wxSound_OSS_CBack, (gpointer)this);
256 trig = PCM_ENABLE_INPUT;
257 }
258#else
259 while (!m_oss_stop)
260 OnSoundEvent(evt);
261#endif
262
263 ioctl(m_fd, SNDCTL_DSP_SETTRIGGER, &trig);
264
265 m_oss_stop = FALSE;
266
267 return TRUE;
268}
269
270bool wxSoundStreamOSS::StopProduction()
271{
272 if (m_oss_stop)
273 return FALSE;
274
275#ifdef __WXGTK__
276 gdk_input_remove(m_tag);
277#endif
278
279 close(m_fd);
280 m_oss_stop = TRUE;
281 return TRUE;
282}
283
284//
285// Detect the closest format (The best).
286//
287void wxSoundStreamOSS::DetectBest(wxSoundFormatPcm *pcm)
288{
289#define MASK_16BITS (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)
290
291 int fmt_mask;
292 wxSoundFormatPcm best_pcm;
293
294 // We change neither the number of channels nor the sample rate
295
296 best_pcm.SetSampleRate(pcm->GetSampleRate());
297 best_pcm.SetChannels(pcm->GetChannels());
298
299 // Get the supported format by the sound card
300 ioctl(m_fd, SNDCTL_DSP_GETFMTS, &fmt_mask);
301
302 // It supports 16 bits
303 if (pcm->GetBPS() == 16 && ((fmt_mask & MASK_16BITS) != 0))
304 best_pcm.SetBPS(16);
305
306 // It supports big endianness
307 if (pcm->GetOrder() == wxBIG_ENDIAN && ((fmt_mask & (AFMT_S16_BE | AFMT_U16_BE)) != 0))
308 best_pcm.SetOrder(wxBIG_ENDIAN);
309
310 // It supports little endianness
311 if (pcm->GetOrder() == wxLITTLE_ENDIAN && ((fmt_mask & (AFMT_S16_LE | AFMT_U16_LE)) != 0))
312 best_pcm.SetOrder(wxLITTLE_ENDIAN);
313
314 // It supports signed samples
315 if (pcm->Signed() && ((fmt_mask & (AFMT_S16_LE | AFMT_S16_BE | AFMT_S8)) != 0))
316 best_pcm.Signed(TRUE);
317
318 // It supports unsigned samples
319 if (!pcm->Signed() && ((fmt_mask & (AFMT_U16_LE | AFMT_U16_BE | AFMT_U8)) != 0))
320 best_pcm.Signed(FALSE);
321
322 // Finally recopy the new format
323 *pcm = best_pcm;
324}