1999-08-14 08:06:35 -04:00
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
// Name: sndesd.cpp
|
|
|
|
// Purpose:
|
|
|
|
// Date: 08/11/1999
|
|
|
|
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
|
|
|
// CVSID: $Id$
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
#ifdef __GNUG__
|
|
|
|
#pragma implementation "sndesd.cpp"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <wx/defs.h>
|
|
|
|
#include <wx/string.h>
|
|
|
|
#include <esd.h>
|
|
|
|
#include "sndbase.h"
|
|
|
|
#include "sndesd.h"
|
|
|
|
#include "sndpcm.h"
|
|
|
|
#ifdef __WXGTK__
|
|
|
|
#include <gdk/gdk.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define MY_ESD_NAME "wxWindows/wxSoundStreamESD"
|
|
|
|
|
|
|
|
wxSoundStreamESD::wxSoundStreamESD(const wxString& hostname)
|
|
|
|
{
|
|
|
|
wxSoundFormatPcm pcm_default;
|
|
|
|
|
|
|
|
m_fd = esd_monitor_stream(ESD_MONO | ESD_BITS8 | ESD_RECORD, 22050,
|
|
|
|
hostname.mb_str(), MY_ESD_NAME);
|
|
|
|
|
|
|
|
if (m_fd == -1) {
|
|
|
|
m_snderror = wxSOUND_INVDEV;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
esd_close(m_fd);
|
|
|
|
|
|
|
|
m_hostname = hostname;
|
|
|
|
|
|
|
|
SetSoundFormat(pcm_default);
|
|
|
|
|
|
|
|
m_snderror = wxSOUND_NOERR;
|
|
|
|
m_esd_stop = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
wxSoundStreamESD::~wxSoundStreamESD()
|
|
|
|
{
|
|
|
|
if (m_fd > 0)
|
|
|
|
esd_close(m_fd);
|
|
|
|
}
|
|
|
|
|
1999-08-27 13:40:40 -04:00
|
|
|
wxSoundStream& wxSoundStreamESD::Read(void *buffer, wxUint32 len)
|
1999-08-14 08:06:35 -04:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
1999-08-27 13:40:40 -04:00
|
|
|
m_lastcount = (wxUint32)ret = read(m_fd, buffer, len);
|
1999-08-14 08:06:35 -04:00
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
m_snderror = wxSOUND_IOERR;
|
|
|
|
else
|
|
|
|
m_snderror = wxSOUND_NOERR;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
1999-08-27 13:40:40 -04:00
|
|
|
wxSoundStream& wxSoundStreamESD::Write(const void *buffer, wxUint32 len)
|
1999-08-14 08:06:35 -04:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
1999-08-27 13:40:40 -04:00
|
|
|
m_lastcount = (wxUint32)ret = write(m_fd, buffer, len);
|
1999-08-14 08:06:35 -04:00
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
m_snderror = wxSOUND_IOERR;
|
|
|
|
else
|
|
|
|
m_snderror = wxSOUND_NOERR;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool wxSoundStreamESD::SetSoundFormat(const wxSoundFormatBase& format)
|
|
|
|
{
|
|
|
|
wxSoundFormatPcm *pcm_format;
|
|
|
|
|
|
|
|
if (format.GetType() != wxSOUND_PCM) {
|
|
|
|
m_snderror = wxSOUND_INVFRMT;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_fd == -1) {
|
|
|
|
m_snderror = wxSOUND_INVDEV;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_sndformat)
|
|
|
|
delete m_sndformat;
|
|
|
|
|
|
|
|
m_sndformat = format.Clone();
|
|
|
|
if (!m_sndformat) {
|
|
|
|
m_snderror = wxSOUND_MEMERR;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
pcm_format = (wxSoundFormatPcm *)m_sndformat;
|
|
|
|
|
|
|
|
// Detect the best format
|
|
|
|
DetectBest(pcm_format);
|
|
|
|
|
|
|
|
m_snderror = wxSOUND_NOERR;
|
|
|
|
if (*pcm_format != format) {
|
|
|
|
m_snderror = wxSOUND_NOTEXACT;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __WXGTK__
|
|
|
|
static void _wxSound_OSS_CBack(gpointer data, int source,
|
|
|
|
GdkInputCondition condition)
|
|
|
|
{
|
|
|
|
wxSoundStreamESD *esd = (wxSoundStreamESD *)data;
|
|
|
|
|
|
|
|
switch (condition) {
|
|
|
|
case GDK_INPUT_READ:
|
|
|
|
esd->WakeUpEvt(wxSOUND_INPUT);
|
|
|
|
break;
|
|
|
|
case GDK_INPUT_WRITE:
|
|
|
|
esd->WakeUpEvt(wxSOUND_OUTPUT);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void wxSoundStreamESD::WakeUpEvt(int evt)
|
|
|
|
{
|
|
|
|
OnSoundEvent(evt);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool wxSoundStreamESD::StartProduction(int evt)
|
|
|
|
{
|
|
|
|
wxSoundFormatPcm *pcm;
|
|
|
|
int flag = 0;
|
|
|
|
|
|
|
|
if (!m_esd_stop)
|
|
|
|
StopProduction();
|
|
|
|
|
|
|
|
pcm = (wxSoundFormatPcm *)m_sndformat;
|
|
|
|
|
|
|
|
flag |= (pcm->GetBPS() == 16) ? ESD_BITS16 : ESD_BITS8;
|
|
|
|
flag |= (pcm->GetChannels() == 2) ? ESD_STEREO : ESD_MONO;
|
|
|
|
|
|
|
|
if (evt == wxSOUND_OUTPUT) {
|
|
|
|
flag |= ESD_PLAY | ESD_STREAM;
|
|
|
|
m_fd = esd_play_stream(flag, pcm->GetSampleRate(), m_hostname.mb_str(),
|
|
|
|
MY_ESD_NAME);
|
|
|
|
} else {
|
|
|
|
flag |= ESD_RECORD | ESD_STREAM;
|
|
|
|
m_fd = esd_record_stream(flag, pcm->GetSampleRate(), m_hostname.mb_str(),
|
|
|
|
MY_ESD_NAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef __WXGTK__
|
|
|
|
if (evt == wxSOUND_OUTPUT)
|
|
|
|
m_tag = gdk_input_add(m_fd, GDK_INPUT_WRITE, _wxSound_OSS_CBack, (gpointer)this);
|
|
|
|
else
|
|
|
|
m_tag = gdk_input_add(m_fd, GDK_INPUT_READ, _wxSound_OSS_CBack, (gpointer)this);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
m_esd_stop = FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool wxSoundStreamESD::StopProduction()
|
|
|
|
{
|
|
|
|
if (m_esd_stop)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
gdk_input_remove(m_tag);
|
|
|
|
esd_close(m_fd);
|
|
|
|
m_esd_stop = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Detect the closest format (The best).
|
|
|
|
//
|
|
|
|
void wxSoundStreamESD::DetectBest(wxSoundFormatPcm *pcm)
|
|
|
|
{
|
|
|
|
wxSoundFormatPcm best_pcm;
|
|
|
|
|
|
|
|
// We change neither the number of channels nor the sample rate
|
|
|
|
|
|
|
|
best_pcm.SetSampleRate(pcm->GetSampleRate());
|
|
|
|
best_pcm.SetChannels(pcm->GetChannels());
|
|
|
|
|
|
|
|
// It supports 16 bits
|
|
|
|
if (pcm->GetBPS() == 16)
|
|
|
|
best_pcm.SetBPS(16);
|
|
|
|
|
|
|
|
best_pcm.SetOrder(wxLITTLE_ENDIAN);
|
|
|
|
best_pcm.Signed(TRUE);
|
|
|
|
|
|
|
|
// Finally recopy the new format
|
|
|
|
*pcm = best_pcm;
|
|
|
|
}
|