wxStreamBuffer::wxStreamBuffer(wxStreamBase& stream, BufMode mode)
: m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL),
- m_buffer_size(0), m_fixed(TRUE), m_flushable(TRUE), m_stream(&stream),
+ m_buffer_size(0), m_wback(NULL), m_wbacksize(0), m_wbackcur(0),
+ m_fixed(TRUE), m_flushable(TRUE), m_stream(&stream),
m_mode(mode), m_destroybuf(FALSE), m_destroystream(FALSE)
{
}
wxStreamBuffer::wxStreamBuffer(BufMode mode)
: m_buffer_start(NULL), m_buffer_end(NULL), m_buffer_pos(NULL),
- m_buffer_size(0), m_fixed(TRUE), m_flushable(FALSE), m_stream(NULL),
+ m_buffer_size(0), m_wback(NULL), m_wbacksize(0), m_wbackcur(0),
+ m_fixed(TRUE), m_flushable(FALSE), m_stream(NULL),
m_mode(mode), m_destroybuf(FALSE), m_destroystream(TRUE)
{
m_stream = new wxStreamBase();
m_mode = buffer.m_mode;
m_destroybuf = FALSE;
m_destroystream = FALSE;
+ m_wback = NULL;
+ m_wbacksize = 0;
+ m_wbackcur = 0;
}
wxStreamBuffer::~wxStreamBuffer()
{
+ if (m_wback)
+ free(m_wback);
if (m_destroybuf)
wxDELETEA(m_buffer_start);
if (m_destroystream)
if (!temp_b)
return NULL;
- return (char *)((size_t)m_wback+(m_wbacksize-needed_size));
+ m_wback = temp_b;
+ printf("Buffer(0x%x)->Write: 0x%x, %d\n", this, m_wback, m_wbacksize);
+ return (char *)(m_wback+(m_wbacksize-needed_size));
}
size_t wxStreamBuffer::GetWBack(char *buf, size_t bsize)
{
size_t s_toget = m_wbacksize-m_wbackcur;
+ printf("Buffer(0x%x): 0x%x, %d\n", this, m_wback, m_wbacksize);
if (bsize < s_toget)
s_toget = bsize;
size_t wxStreamBuffer::Write(wxStreamBuffer *sbuf)
{
char buf[BUF_TEMP_SIZE];
- size_t s = 0, bytes_count = BUF_TEMP_SIZE;
- size_t s_size;
+ size_t s = 0, bytes_count = BUF_TEMP_SIZE, b_count2;
while (bytes_count == BUF_TEMP_SIZE) {
- s_size = (sbuf->GetDataLeft() < GetDataLeft()) ? sbuf->GetDataLeft() : GetDataLeft();
- if (s_size < bytes_count)
- bytes_count = s_size;
- bytes_count = sbuf->Read(buf, bytes_count);
- bytes_count = Write(buf, bytes_count);
+ b_count2 = sbuf->Read(buf, bytes_count);
+ bytes_count = Write(buf, b_count2);
+ if (b_count2 > bytes_count)
+ sbuf->WriteBack(buf+bytes_count, b_count2-bytes_count);
s += bytes_count;
}
return s;
wxUint32 wxSndFileCodec::Available() const
{
+ if (m_fstate == wxSFILE_STOPPED)
+ return 0;
return m_fsize-m_fpos;
}
wxSoundCodec::~wxSoundCodec()
{
+ if (m_mode != WAITING)
+ ExitMode();
}
void wxSoundCodec::InitIO(const wxSoundDataFormat& format)
m_io_format = format;
}
-void wxSoundCodec::InitMode(int mode)
+void wxSoundCodec::InitMode(ModeType mode)
{
wxStreamBuffer *buf_snd;
- m_mode = (mode == 0) ? ENCODING : DECODING;
+ m_mode = mode;
if (!m_chain_codec) {
- if (mode == ENCODING) {
+ if (m_mode == ENCODING) {
m_out_sound = new wxStreamBuffer(*this, wxStreamBuffer::write);
m_out_sound->SetBufferIO(1024);
} else {
m_out_sound = m_chain_codec->GetOutStream();
}
}
+ m_mode = WAITING;
}
bool wxSoundCodec::ChainCodecBefore(wxSoundDataFormat& format)
class wxSoundCodec : public wxObject, public wxStreamBase {
DECLARE_ABSTRACT_CLASS(wxSoundCodec)
+ public:
+ typedef enum {
+ WAITING = 0,
+ ENCODING,
+ DECODING
+ } ModeType;
public:
wxSoundCodec();
virtual ~wxSoundCodec();
size_t Available();
void InitIO(const wxSoundDataFormat& format);
- void InitMode(int mode);
- void ExitMode();
inline void SetInStream(wxStreamBuffer *s)
{ m_in_sound = s; }
virtual size_t GetByteRate() const = 0;
virtual wxSoundDataFormat GetPreferredFormat(int codec = 0) const = 0;
+ virtual void InitMode(ModeType mode);
+ virtual void ExitMode();
virtual void Decode() = 0;
virtual void Encode() = 0;
wxStreamBuffer *m_in_sound, *m_out_sound;
wxSoundCodec *m_chain_codec;
bool m_init, m_chain_before;
-
- enum {
- ENCODING = 0,
- DECODING
- } m_mode;
+ ModeType m_mode;
};
#endif
void wxSoundPcmCodec::Decode()
{
- InitMode(DECODING);
if (m_io_format == m_orig_format) {
CopyToOutput();
- ExitMode();
return;
}
default:
break;
}
- ExitMode();
}
// ---------------------------------------------------------------------------
void wxSoundPcmCodec::Encode()
{
- InitMode(ENCODING);
if (m_io_format == m_orig_format) {
CopyToOutput();
- ExitMode();
return;
}
default:
break;
}
- ExitMode();
}
bool wxUssSound::DoInput(wxSndBuffer *buf)
{
wxUint32 bufsize;
- wxSoundCodec *codec = buf->GetFormat().GetCodec();
+ wxSoundCodec *codec = buf->GetCurrentCodec();
m_sndbuf->ResetBuffer();
codec->SetInStream(m_sndbuf);
buf->Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
return false;
}
- read(m_fd, m_sndbuf, bufsize);
+ read(m_fd, m_sndbuf->GetBufferStart(), bufsize);
codec->Encode();
return true;
wxSoundCodec *codec = buf->GetCurrentCodec();
m_sndbuf->ResetBuffer();
- codec->SetOutStream(m_sndbuf);
- codec->InitIO(m_ussformat);
if (!codec->Available()) {
buf->Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
- return false;
+ return FALSE;
}
codec->Decode();
- write(m_fd, m_sndbuf, m_sndbuf->GetIntPosition());
+ write(m_fd, m_sndbuf->GetBufferStart(), m_sndbuf->GetIntPosition());
// Well ... it's not accurate ! :-|
buf->OnBufferOutFinished();
- return true;
+ return TRUE;
+}
+
+bool wxUssSound::InitBuffer(wxSndBuffer *buf)
+{
+ wxSoundCodec *codec;
+
+ if (!OnSetupDriver(*buf, buf->GetMode())) {
+ if (buf->IsNotSet(wxSND_BUFREADY))
+ return FALSE;
+ }
+
+ codec = buf->GetCurrentCodec();
+ codec->SetOutStream(m_sndbuf);
+ codec->InitIO(m_ussformat);
+ // TODO: We need more tests here.
+ codec->InitMode((m_mode == wxSND_OUTPUT) ? wxSoundCodec::DECODING : wxSoundCodec::ENCODING);
+
+ return TRUE;
}
void *wxUssSound::Entry()
wxNode *node;
wxSndBuffer *buf;
- while (!m_stop_thrd) {
- node = m_buffers.First();
- if (!node) {
- USS_Sleep();
- continue;
- }
- buf = (wxSndBuffer *)node->Data();
- if (!OnSetupDriver(*buf, buf->GetMode()))
- continue;
+ node = m_buffers.First();
+ if (!node) {
+ m_stop_thrd = FALSE;
+ return NULL;
+ }
+
+ buf = (wxSndBuffer *)node->Data();
+ InitBuffer(buf);
+ while (!m_stop_thrd) {
buf->HardLock();
if (buf->IsSet(wxSND_BUFSTOP)) {
buf->HardUnlock();
- delete node;
- continue;
+ goto sound_clean_buffer;
}
switch(m_mode) {
case wxSND_INPUT:
if (!DoInput(buf))
- delete node;
+ goto sound_clean_buffer;
break;
case wxSND_OUTPUT:
if (!DoOutput(buf))
- delete node;
+ goto sound_clean_buffer;
break;
case wxSND_DUPLEX:
case wxSND_OTHER_IO:
+ goto sound_clean_buffer;
break;
}
buf->HardUnlock();
+ continue;
+ sound_clean_buffer:
+ buf->GetCurrentCodec()->ExitMode();
+ delete node;
+ node = m_buffers.First();
+ if (!node)
+ USS_Sleep();
+ if (node)
+ buf = (wxSndBuffer *)node->Data();
}
return NULL;
}
wxSoundDataFormat format;
wxSoundCodec *codec;
- codec = buf.GetFormat().GetCodec();
+ codec = buf.GetCurrentCodec();
format = codec->GetPreferredFormat(WXSOUND_PCM);
if ((format.GetSampleRate() != m_srate) ||
m_buffers.DeleteObject(&buf);
buf.Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
buf.SetError(wxSND_CANTSET);
- return false;
+ return FALSE;
}
m_mode = wxSND_OTHER_IO;
}
if (buf.GetMode() != m_mode) {
m_mode = buf.GetMode();
- return false;
+ return FALSE;
}
- return true;
+ return TRUE;
}
wxUint32 wxUssSound::GetNbFragments()
wxCondition m_sleep_cond;
///
+ bool InitBuffer(wxSndBuffer *buf);
bool DoInput(wxSndBuffer *buf);
bool DoOutput(wxSndBuffer *buf);