1 // --------------------------------------------------------------------------
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
8 // --------------------------------------------------------------------------
10 // --------------------------------------------------------------------------
11 // System dependent headers
12 // --------------------------------------------------------------------------
14 #include <sys/soundcard.h>
15 #include <sys/types.h>
17 #include <sys/ioctl.h>
24 // --------------------------------------------------------------------------
26 // --------------------------------------------------------------------------
28 #include "wx/string.h"
29 #include "wx/mmedia/sndbase.h"
30 #include "wx/mmedia/sndoss.h"
31 #include "wx/mmedia/sndpcm.h"
33 wxSoundStreamOSS::wxSoundStreamOSS(const wxString
& dev_name
)
35 wxSoundFormatPcm pcm_default
;
37 // Open the OSS device
38 m_fd
= open(dev_name
.mb_str(), O_WRONLY
);
42 m_snderror
= wxSOUND_INVDEV
;
46 // Remember the device name
49 // Initialize the default format
50 wxSoundStreamOSS::SetSoundFormat(pcm_default
);
52 // Get the default best size for OSS
53 ioctl(m_fd
, SNDCTL_DSP_GETBLKSIZE
, &m_bufsize
);
55 m_snderror
= wxSOUND_NOERROR
;
65 wxSoundStreamOSS::~wxSoundStreamOSS()
71 wxUint32
wxSoundStreamOSS::GetBestSize() const
76 wxSoundStream
& wxSoundStreamOSS::Read(void *buffer
, wxUint32 len
)
81 m_snderror
= wxSOUND_NOTSTARTED
;
86 ret
= read(m_fd
, buffer
, len
);
87 m_lastcount
= (wxUint32
)ret
;
91 m_snderror
= wxSOUND_IOERROR
;
93 m_snderror
= wxSOUND_NOERROR
;
98 wxSoundStream
& wxSoundStreamOSS::Write(const void *buffer
, wxUint32 len
)
103 m_snderror
= wxSOUND_NOTSTARTED
;
108 ret
= write(m_fd
, buffer
, len
);
113 m_snderror
= wxSOUND_IOERROR
;
115 m_snderror
= wxSOUND_NOERROR
;
116 m_lastcount
= (wxUint32
)ret
;
122 bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase
& format
)
125 wxSoundFormatPcm
*pcm_format
;
127 if (format
.GetType() != wxSOUND_PCM
) {
128 m_snderror
= wxSOUND_INVFRMT
;
133 m_snderror
= wxSOUND_INVDEV
;
140 m_sndformat
= format
.Clone();
142 m_snderror
= wxSOUND_MEMERROR
;
145 pcm_format
= (wxSoundFormatPcm
*)m_sndformat
;
147 // We temporary open the OSS device
149 m_fd
= open(m_devname
.mb_str(), O_WRONLY
);
151 m_snderror
= wxSOUND_INVDEV
;
156 // Set the sample rate field.
157 tmp
= pcm_format
->GetSampleRate();
158 ioctl(m_fd
, SNDCTL_DSP_SPEED
, &tmp
);
160 pcm_format
->SetSampleRate(tmp
);
162 // Detect the best format
163 DetectBest(pcm_format
);
165 SetupFormat(pcm_format
);
167 tmp
= pcm_format
->GetChannels();
168 ioctl(m_fd
, SNDCTL_DSP_CHANNELS
, &tmp
);
169 pcm_format
->SetChannels(tmp
);
171 // Close the OSS device
175 m_snderror
= wxSOUND_NOERROR
;
176 if (*pcm_format
!= format
) {
177 m_snderror
= wxSOUND_NOEXACT
;
184 bool wxSoundStreamOSS::SetupFormat(wxSoundFormatPcm
*pcm_format
)
188 switch(pcm_format
->GetBPS()) {
190 if (pcm_format
->Signed())
196 switch (pcm_format
->GetOrder()) {
198 if (pcm_format
->Signed())
203 case wxLITTLE_ENDIAN
:
204 if (pcm_format
->Signed())
213 ioctl(m_fd
, SNDCTL_DSP_SETFMT
, &tmp
);
218 pcm_format
->SetBPS(8);
219 pcm_format
->Signed(false);
222 pcm_format
->SetBPS(8);
223 pcm_format
->Signed(true);
226 pcm_format
->SetBPS(16);
227 pcm_format
->Signed(false);
228 pcm_format
->SetOrder(wxLITTLE_ENDIAN
);
231 pcm_format
->SetBPS(16);
232 pcm_format
->Signed(false);
233 pcm_format
->SetOrder(wxBIG_ENDIAN
);
236 pcm_format
->SetBPS(16);
237 pcm_format
->Signed(true);
238 pcm_format
->SetOrder(wxLITTLE_ENDIAN
);
241 pcm_format
->SetBPS(16);
242 pcm_format
->Signed(true);
243 pcm_format
->SetOrder(wxBIG_ENDIAN
);
250 static void _wxSound_OSS_CBack(gpointer data
, int source
,
251 GdkInputCondition condition
)
253 wxSoundStreamOSS
*oss
= (wxSoundStreamOSS
*)data
;
257 oss
->WakeUpEvt(wxSOUND_INPUT
);
259 case GDK_INPUT_WRITE
:
260 oss
->WakeUpEvt(wxSOUND_OUTPUT
);
268 void wxSoundStreamOSS::WakeUpEvt(int evt
)
274 bool wxSoundStreamOSS::StartProduction(int evt
)
276 wxSoundFormatBase
*old_frmt
;
281 old_frmt
= m_sndformat
->Clone();
283 m_snderror
= wxSOUND_MEMERROR
;
287 if (evt
== wxSOUND_OUTPUT
)
288 m_fd
= open(m_devname
.mb_str(), O_WRONLY
);
289 else if (evt
== wxSOUND_INPUT
)
290 m_fd
= open(m_devname
.mb_str(), O_RDONLY
);
293 m_snderror
= wxSOUND_INVDEV
;
297 SetSoundFormat(*old_frmt
);
302 if (evt
== wxSOUND_OUTPUT
) {
304 m_tag
= gdk_input_add(m_fd
, GDK_INPUT_WRITE
, _wxSound_OSS_CBack
, (gpointer
)this);
306 trig
= PCM_ENABLE_OUTPUT
;
309 m_tag
= gdk_input_add(m_fd
, GDK_INPUT_READ
, _wxSound_OSS_CBack
, (gpointer
)this);
311 trig
= PCM_ENABLE_INPUT
;
314 ioctl(m_fd
, SNDCTL_DSP_SETTRIGGER
, &trig
);
322 bool wxSoundStreamOSS::StopProduction()
328 gdk_input_remove(m_tag
);
337 bool wxSoundStreamOSS::QueueFilled() const
343 // Detect the closest format (The best).
345 void wxSoundStreamOSS::DetectBest(wxSoundFormatPcm
*pcm
)
347 #define MASK_16BITS (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)
350 wxSoundFormatPcm best_pcm
;
352 // We change neither the number of channels nor the sample rate
354 best_pcm
.SetSampleRate(pcm
->GetSampleRate());
355 best_pcm
.SetChannels(pcm
->GetChannels());
357 // Get the supported format by the sound card
358 ioctl(m_fd
, SNDCTL_DSP_GETFMTS
, &fmt_mask
);
360 // It supports 16 bits
361 if (pcm
->GetBPS() == 16 && ((fmt_mask
& MASK_16BITS
) != 0))
364 // It supports big endianness
365 if (pcm
->GetOrder() == wxBIG_ENDIAN
&&
366 ((fmt_mask
& (AFMT_S16_BE
| AFMT_U16_BE
)) != 0))
367 best_pcm
.SetOrder(wxBIG_ENDIAN
);
369 // It supports little endianness
370 if (pcm
->GetOrder() == wxLITTLE_ENDIAN
&&
371 ((fmt_mask
& (AFMT_S16_LE
| AFMT_U16_LE
)) != 0))
372 best_pcm
.SetOrder(wxLITTLE_ENDIAN
);
374 // It supports signed samples
376 ((fmt_mask
& (AFMT_S16_LE
| AFMT_S16_BE
| AFMT_S8
)) != 0))
377 best_pcm
.Signed(true);
379 // It supports unsigned samples
380 if (!pcm
->Signed() &&
381 ((fmt_mask
& (AFMT_U16_LE
| AFMT_U16_BE
| AFMT_U8
)) != 0))
382 best_pcm
.Signed(false);
384 // Finally recopy the new format