1 // -------------------------------------------------------------------------- 
   5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000 
   7 // -------------------------------------------------------------------------- 
   9 #pragma implementation "sndoss.cpp" 
  12 // -------------------------------------------------------------------------- 
  13 // System dependent headers 
  14 // -------------------------------------------------------------------------- 
  16 #include <sys/soundcard.h> 
  17 #include <sys/types.h> 
  19 #include <sys/ioctl.h> 
  26 // -------------------------------------------------------------------------- 
  28 // -------------------------------------------------------------------------- 
  30 #include "wx/string.h" 
  31 #include "wx/mmedia/sndbase.h" 
  32 #include "wx/mmedia/sndoss.h" 
  33 #include "wx/mmedia/sndpcm.h" 
  35 wxSoundStreamOSS::wxSoundStreamOSS(const wxString
& dev_name
) 
  37     wxSoundFormatPcm pcm_default
; 
  39     // Open the OSS device 
  40     m_fd 
= open(dev_name
.mb_str(), O_WRONLY
); 
  44         m_snderror 
= wxSOUND_INVDEV
; 
  48     // Remember the device name 
  51     // Initialize the default format 
  52     wxSoundStreamOSS::SetSoundFormat(pcm_default
); 
  54     // Get the default best size for OSS 
  55     ioctl(m_fd
, SNDCTL_DSP_GETBLKSIZE
, &m_bufsize
); 
  57     m_snderror 
= wxSOUND_NOERROR
; 
  67 wxSoundStreamOSS::~wxSoundStreamOSS() 
  73 wxUint32 
wxSoundStreamOSS::GetBestSize() const 
  78 wxSoundStream
& wxSoundStreamOSS::Read(void *buffer
, wxUint32 len
) 
  83         m_snderror 
= wxSOUND_NOTSTARTED
; 
  88     m_lastcount 
= (wxUint32
)ret 
= read(m_fd
, buffer
, len
); 
  92         m_snderror 
= wxSOUND_IOERROR
; 
  94         m_snderror 
= wxSOUND_NOERROR
; 
  99 wxSoundStream
& wxSoundStreamOSS::Write(const void *buffer
, wxUint32 len
) 
 104         m_snderror 
= wxSOUND_NOTSTARTED
; 
 109     ret 
= write(m_fd
, buffer
, len
); 
 114         m_snderror  
= wxSOUND_IOERROR
; 
 116         m_snderror 
= wxSOUND_NOERROR
; 
 117         m_lastcount 
= (wxUint32
)ret
; 
 123 bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase
& format
) 
 126     wxSoundFormatPcm 
*pcm_format
; 
 128     if (format
.GetType() != wxSOUND_PCM
) { 
 129         m_snderror 
= wxSOUND_INVFRMT
; 
 134         m_snderror 
= wxSOUND_INVDEV
; 
 141     m_sndformat 
= format
.Clone(); 
 143         m_snderror 
= wxSOUND_MEMERROR
; 
 146     pcm_format 
= (wxSoundFormatPcm 
*)m_sndformat
; 
 148     // We temporary open the OSS device 
 150         m_fd 
= open(m_devname
.mb_str(), O_WRONLY
); 
 152             m_snderror 
= wxSOUND_INVDEV
; 
 157     // Set the sample rate field. 
 158     tmp 
= pcm_format
->GetSampleRate(); 
 159     ioctl(m_fd
, SNDCTL_DSP_SPEED
, &tmp
); 
 161     pcm_format
->SetSampleRate(tmp
); 
 163     // Detect the best format 
 164     DetectBest(pcm_format
); 
 166     SetupFormat(pcm_format
); 
 168     tmp 
= pcm_format
->GetChannels(); 
 169     ioctl(m_fd
, SNDCTL_DSP_CHANNELS
, &tmp
); 
 170     pcm_format
->SetChannels(tmp
); 
 172     // Close the OSS device 
 176     m_snderror 
= wxSOUND_NOERROR
; 
 177     if (*pcm_format 
!= format
) { 
 178         m_snderror 
= wxSOUND_NOEXACT
; 
 185 bool wxSoundStreamOSS::SetupFormat(wxSoundFormatPcm 
*pcm_format
) 
 189     switch(pcm_format
->GetBPS()) { 
 191             if (pcm_format
->Signed()) 
 197             switch (pcm_format
->GetOrder()) { 
 199                     if (pcm_format
->Signed()) 
 204                 case wxLITTLE_ENDIAN
: 
 205                     if (pcm_format
->Signed()) 
 214     ioctl(m_fd
, SNDCTL_DSP_SETFMT
, &tmp
); 
 219             pcm_format
->SetBPS(8); 
 220             pcm_format
->Signed(false); 
 223             pcm_format
->SetBPS(8); 
 224             pcm_format
->Signed(true); 
 227             pcm_format
->SetBPS(16); 
 228             pcm_format
->Signed(false); 
 229             pcm_format
->SetOrder(wxLITTLE_ENDIAN
); 
 232             pcm_format
->SetBPS(16); 
 233             pcm_format
->Signed(false); 
 234             pcm_format
->SetOrder(wxBIG_ENDIAN
); 
 237             pcm_format
->SetBPS(16); 
 238             pcm_format
->Signed(true); 
 239             pcm_format
->SetOrder(wxLITTLE_ENDIAN
); 
 242             pcm_format
->SetBPS(16); 
 243             pcm_format
->Signed(true); 
 244             pcm_format
->SetOrder(wxBIG_ENDIAN
); 
 251 static void _wxSound_OSS_CBack(gpointer data
, int source
, 
 252                                GdkInputCondition condition
) 
 254     wxSoundStreamOSS 
*oss 
= (wxSoundStreamOSS 
*)data
; 
 258             oss
->WakeUpEvt(wxSOUND_INPUT
); 
 260         case GDK_INPUT_WRITE
: 
 261             oss
->WakeUpEvt(wxSOUND_OUTPUT
); 
 269 void wxSoundStreamOSS::WakeUpEvt(int evt
) 
 275 bool wxSoundStreamOSS::StartProduction(int evt
) 
 277     wxSoundFormatBase 
*old_frmt
; 
 282     old_frmt 
= m_sndformat
->Clone(); 
 284         m_snderror 
= wxSOUND_MEMERROR
; 
 288     if (evt 
== wxSOUND_OUTPUT
) 
 289         m_fd 
= open(m_devname
.mb_str(), O_WRONLY
); 
 290     else if (evt 
== wxSOUND_INPUT
) 
 291         m_fd 
= open(m_devname
.mb_str(), O_RDONLY
); 
 294         m_snderror 
= wxSOUND_INVDEV
; 
 298     SetSoundFormat(*old_frmt
); 
 303     if (evt 
== wxSOUND_OUTPUT
) { 
 305         m_tag 
= gdk_input_add(m_fd
, GDK_INPUT_WRITE
, _wxSound_OSS_CBack
, (gpointer
)this); 
 307         trig 
= PCM_ENABLE_OUTPUT
; 
 310         m_tag 
= gdk_input_add(m_fd
, GDK_INPUT_READ
, _wxSound_OSS_CBack
, (gpointer
)this); 
 312         trig 
= PCM_ENABLE_INPUT
; 
 315   ioctl(m_fd
, SNDCTL_DSP_SETTRIGGER
, &trig
); 
 323 bool wxSoundStreamOSS::StopProduction() 
 329   gdk_input_remove(m_tag
); 
 338 bool wxSoundStreamOSS::QueueFilled() const 
 344 // Detect the closest format (The best). 
 346 void wxSoundStreamOSS::DetectBest(wxSoundFormatPcm 
*pcm
) 
 348 #define MASK_16BITS (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE) 
 351   wxSoundFormatPcm best_pcm
; 
 353   // We change neither the number of channels nor the sample rate 
 355   best_pcm
.SetSampleRate(pcm
->GetSampleRate()); 
 356   best_pcm
.SetChannels(pcm
->GetChannels()); 
 358   // Get the supported format by the sound card 
 359   ioctl(m_fd
, SNDCTL_DSP_GETFMTS
, &fmt_mask
); 
 361   // It supports 16 bits 
 362   if (pcm
->GetBPS() == 16 && ((fmt_mask 
& MASK_16BITS
) != 0)) 
 365   // It supports big endianness 
 366   if (pcm
->GetOrder() == wxBIG_ENDIAN 
&& 
 367       ((fmt_mask 
& (AFMT_S16_BE 
| AFMT_U16_BE
)) != 0)) 
 368     best_pcm
.SetOrder(wxBIG_ENDIAN
); 
 370   // It supports little endianness 
 371   if (pcm
->GetOrder() == wxLITTLE_ENDIAN 
&& 
 372       ((fmt_mask 
& (AFMT_S16_LE 
| AFMT_U16_LE
)) != 0)) 
 373     best_pcm
.SetOrder(wxLITTLE_ENDIAN
); 
 375   // It supports signed samples 
 377       ((fmt_mask 
& (AFMT_S16_LE 
| AFMT_S16_BE 
| AFMT_S8
)) != 0)) 
 378     best_pcm
.Signed(true); 
 380   // It supports unsigned samples 
 381   if (!pcm
->Signed() && 
 382       ((fmt_mask 
& (AFMT_U16_LE 
| AFMT_U16_BE 
| AFMT_U8
)) != 0)) 
 383     best_pcm
.Signed(false); 
 385   // Finally recopy the new format