1 // --------------------------------------------------------------------------
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
7 // --------------------------------------------------------------------------
9 #pragma implementation "sndoss.cpp"
12 #include <sys/soundcard.h>
13 #include <sys/types.h>
15 #include <sys/ioctl.h>
19 #include <wx/string.h>
27 wxSoundStreamOSS::wxSoundStreamOSS(const wxString
& dev_name
)
29 wxSoundFormatPcm pcm_default
;
31 m_fd
= open(dev_name
.mb_str(), O_RDWR
);
34 m_snderror
= wxSOUND_INVDEV
;
40 wxSoundStreamOSS::SetSoundFormat(pcm_default
);
42 ioctl(m_fd
, SNDCTL_DSP_GETBLKSIZE
, &m_bufsize
);
44 m_snderror
= wxSOUND_NOERR
;
52 wxSoundStreamOSS::~wxSoundStreamOSS()
58 wxUint32
wxSoundStreamOSS::GetBestSize() const
63 wxSoundStream
& wxSoundStreamOSS::Read(void *buffer
, size_t len
)
67 m_lastcount
= (size_t)ret
= read(m_fd
, buffer
, len
);
71 m_snderror
= wxSOUND_IOERR
;
73 m_snderror
= wxSOUND_NOERR
;
78 wxSoundStream
& wxSoundStreamOSS::Write(const void *buffer
, size_t len
)
82 m_lastcount
= (size_t)ret
= write(m_fd
, buffer
, len
);
86 m_snderror
= wxSOUND_IOERR
;
88 m_snderror
= wxSOUND_NOERR
;
93 bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase
& format
)
96 wxSoundFormatPcm
*pcm_format
;
98 if (format
.GetType() != wxSOUND_PCM
) {
99 m_snderror
= wxSOUND_INVFRMT
;
104 m_snderror
= wxSOUND_INVDEV
;
111 m_sndformat
= format
.Clone();
113 m_snderror
= wxSOUND_MEMERR
;
116 pcm_format
= (wxSoundFormatPcm
*)m_sndformat
;
118 // Set the sample rate field.
119 tmp
= pcm_format
->GetSampleRate();
120 ioctl(m_fd
, SNDCTL_DSP_SPEED
, &tmp
);
122 pcm_format
->SetSampleRate(tmp
);
124 // Detect the best format
125 DetectBest(pcm_format
);
126 SetupFormat(pcm_format
);
128 tmp
= pcm_format
->GetChannels();
129 ioctl(m_fd
, SNDCTL_DSP_CHANNELS
, &tmp
);
130 pcm_format
->SetChannels(tmp
);
132 m_snderror
= wxSOUND_NOERR
;
133 if (*pcm_format
!= format
) {
134 m_snderror
= wxSOUND_NOTEXACT
;
140 bool wxSoundStreamOSS::SetupFormat(wxSoundFormatPcm
*pcm_format
)
144 switch(pcm_format
->GetBPS()) {
146 if (pcm_format
->Signed())
152 switch (pcm_format
->GetOrder()) {
154 if (pcm_format
->Signed())
159 case wxLITTLE_ENDIAN
:
160 if (pcm_format
->Signed())
169 ioctl(m_fd
, SNDCTL_DSP_SETFMT
, &tmp
);
174 pcm_format
->SetBPS(8);
175 pcm_format
->Signed(FALSE
);
178 pcm_format
->SetBPS(8);
179 pcm_format
->Signed(TRUE
);
182 pcm_format
->SetBPS(16);
183 pcm_format
->Signed(FALSE
);
184 pcm_format
->SetOrder(wxLITTLE_ENDIAN
);
187 pcm_format
->SetBPS(16);
188 pcm_format
->Signed(FALSE
);
189 pcm_format
->SetOrder(wxBIG_ENDIAN
);
192 pcm_format
->SetBPS(16);
193 pcm_format
->Signed(TRUE
);
194 pcm_format
->SetOrder(wxLITTLE_ENDIAN
);
197 pcm_format
->SetBPS(16);
198 pcm_format
->Signed(TRUE
);
199 pcm_format
->SetOrder(wxBIG_ENDIAN
);
206 static void _wxSound_OSS_CBack(gpointer data
, int source
,
207 GdkInputCondition condition
)
209 wxSoundStreamOSS
*oss
= (wxSoundStreamOSS
*)data
;
213 oss
->WakeUpEvt(wxSOUND_INPUT
);
215 case GDK_INPUT_WRITE
:
216 oss
->WakeUpEvt(wxSOUND_OUTPUT
);
224 void wxSoundStreamOSS::WakeUpEvt(int evt
)
230 bool wxSoundStreamOSS::StartProduction(int evt
)
232 wxSoundFormatBase
*old_frmt
;
237 old_frmt
= m_sndformat
->Clone();
239 if (evt
== wxSOUND_OUTPUT
)
240 m_fd
= open(m_devname
.mb_str(), O_WRONLY
);
241 else if (evt
== wxSOUND_INPUT
)
242 m_fd
= open(m_devname
.mb_str(), O_RDONLY
);
245 m_snderror
= wxSOUND_INVDEV
;
249 SetSoundFormat(*old_frmt
);
255 if (evt
== wxSOUND_OUTPUT
) {
256 m_tag
= gdk_input_add(m_fd
, GDK_INPUT_WRITE
, _wxSound_OSS_CBack
, (gpointer
)this);
257 trig
= PCM_ENABLE_OUTPUT
;
259 m_tag
= gdk_input_add(m_fd
, GDK_INPUT_READ
, _wxSound_OSS_CBack
, (gpointer
)this);
260 trig
= PCM_ENABLE_INPUT
;
267 ioctl(m_fd
, SNDCTL_DSP_SETTRIGGER
, &trig
);
275 bool wxSoundStreamOSS::StopProduction()
281 gdk_input_remove(m_tag
);
290 bool wxSoundStreamOSS::QueueFilled() const
296 // Detect the closest format (The best).
298 void wxSoundStreamOSS::DetectBest(wxSoundFormatPcm
*pcm
)
300 #define MASK_16BITS (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)
303 wxSoundFormatPcm best_pcm
;
305 // We change neither the number of channels nor the sample rate
307 best_pcm
.SetSampleRate(pcm
->GetSampleRate());
308 best_pcm
.SetChannels(pcm
->GetChannels());
310 // Get the supported format by the sound card
311 ioctl(m_fd
, SNDCTL_DSP_GETFMTS
, &fmt_mask
);
313 // It supports 16 bits
314 if (pcm
->GetBPS() == 16 && ((fmt_mask
& MASK_16BITS
) != 0))
317 // It supports big endianness
318 if (pcm
->GetOrder() == wxBIG_ENDIAN
&& ((fmt_mask
& (AFMT_S16_BE
| AFMT_U16_BE
)) != 0))
319 best_pcm
.SetOrder(wxBIG_ENDIAN
);
321 // It supports little endianness
322 if (pcm
->GetOrder() == wxLITTLE_ENDIAN
&& ((fmt_mask
& (AFMT_S16_LE
| AFMT_U16_LE
)) != 0))
323 best_pcm
.SetOrder(wxLITTLE_ENDIAN
);
325 // It supports signed samples
326 if (pcm
->Signed() && ((fmt_mask
& (AFMT_S16_LE
| AFMT_S16_BE
| AFMT_S8
)) != 0))
327 best_pcm
.Signed(TRUE
);
329 // It supports unsigned samples
330 if (!pcm
->Signed() && ((fmt_mask
& (AFMT_U16_LE
| AFMT_U16_BE
| AFMT_U8
)) != 0))
331 best_pcm
.Signed(FALSE
);
333 // Finally recopy the new format