wxFragmentBuffer::wxFragmentBuffer(wxSound& io_drv)
: m_iodrv(&io_drv), m_maxoq(0), m_maxiq(0),
- m_optrs(NULL), m_iptrs(NULL), m_lstoptrs(NULL), m_lstiptrs(NULL),
+ m_lstoptrs(NULL), m_lstiptrs(NULL),
m_buf2free(FALSE), m_dontq(FALSE), m_freeing(FALSE)
{
}
}
wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer(
- wxFragBufPtr *list, wxUint8 max_queue)
+ wxFragBufPtr *list, wxUint8 max_queue)
{
if (!list)
return NULL;
bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf)
{
wxFragBufPtr *ptr;
- char *raw_buf;
- wxUint32 rawbuf_size;
+ wxSoundCodec *codec = buf->GetCurrentCodec();
if (!m_iodrv->OnSetupDriver(*buf, wxSND_OUTPUT))
return FALSE;
// Find the first free (at least partly free) output buffer
ptr = FindFreeBuffer(m_lstoptrs, m_maxoq);
// No free : go out !
- if (!ptr)
+ if (ptr == NULL)
return FALSE;
- // Find the end of the buffer
- raw_buf = ptr->data + ptr->ptr;
- rawbuf_size = ptr->size - ptr->ptr;
+ // Normally, these three functions could be called only once.
+ codec->SetOutStream(ptr->sndbuf);
+ codec->InitIO(m_drvformat);
+ codec->InitMode(wxSoundCodec::DECODING);
// Fill it up
- buf->OnNeedOutputData(raw_buf, rawbuf_size);
+ codec->Decode();
// No data to fill the buffer: dequeue the current wxSndBuffer
- if (!rawbuf_size) {
+ if (codec->Available() == 0) {
if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
buf->Set(wxSND_UNQUEUEING);
m_iodrv->m_buffers.DeleteObject(buf);
// Data: append it to the list
ptr->buffers->Append(buf);
- ptr->ptr += rawbuf_size;
-
// Output buffer full: send it to the driver
- if (ptr->ptr == ptr->size) {
+ if (ptr->sndbuf->GetDataLeft() == 0) {
ptr->state = wxBUFFER_FFILLED;
OnBufferFilled(ptr, wxSND_OUTPUT);
}
bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer *buf)
{
wxFragBufPtr *ptr;
- char *raw_buf;
- wxUint32 rawbuf_size;
-
+ size_t inc;
+
if (!m_iodrv->OnSetupDriver(*buf, wxSND_INPUT))
return FALSE;
-
+
while (1) {
ptr = FindFreeBuffer(m_lstiptrs, m_maxiq);
- if (!ptr)
+ if (ptr == NULL)
return FALSE;
-
- raw_buf = ptr->data + ptr->ptr;
- rawbuf_size = ptr->size - ptr->ptr;
-
- rawbuf_size = (buf->Available() < rawbuf_size) ? buf->Available() : rawbuf_size;
-
- if (!rawbuf_size) {
+ if (buf->Available() == 0) {
if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
buf->Set(wxSND_UNQUEUEING);
m_iodrv->m_buffers.DeleteObject(buf);
}
- // Get data now when there isn't anymore buffer in the queue
- if (!LastBuffer() && ptr->ptr) {
+ if (LastBuffer() == NULL && ptr->sndbuf->GetIntPosition() != 0) {
ptr->state = wxBUFFER_FFILLED;
if (!OnBufferFilled(ptr, wxSND_INPUT))
return FALSE;
}
ptr->buffers->Append(buf);
- ptr->ptr += rawbuf_size;
+ // TODO: Add an "incrementer" in wxStreamBuffer.
+ inc = (buf->Available() < ptr->sndbuf->GetDataLeft()) ?
+ buf->Available() : ptr->sndbuf->GetDataLeft();
+
+ ptr->sndbuf->SetIntPosition(ptr->sndbuf->GetIntPosition() + inc);
- // Input buffer full => get data
- if (ptr->ptr == ptr->size) {
+ if (ptr->sndbuf->GetDataLeft() == 0) {
ptr->state = wxBUFFER_FFILLED;
if (!OnBufferFilled(ptr, wxSND_INPUT))
return FALSE;
}
}
+
return TRUE;
}
{
wxNode *node;
wxSndBuffer *buf;
- char *data;
- wxUint32 size, data_read;
-
- data = ptr->data;
- size = ptr->size;
+ wxSoundCodec *codec;
node = ptr->buffers->First();
if (buf->GetMode() == wxSND_OUTPUT) {
buf->OnBufferOutFinished();
} else {
- data_read = buf->OnBufferInFinished(data, size);
+ codec = buf->GetCurrentCodec();
+
+ // Normally, these three functions could be called only once.
+ codec->SetInStream(ptr->sndbuf);
+ codec->InitIO(m_drvformat);
+ codec->InitMode(wxSoundCodec::ENCODING);
- data += data_read;
- size -= data_read;
+ // As there is an "auto-stopper" in the codec, we don't worry ...
+ codec->Encode();
}
if (buf->IsSet(wxSND_UNQUEUEING))
node = ptr->buffers->First();
}
- ptr->ptr = 0;
+ ptr->sndbuf->ResetBuffer();
ptr->state = wxBUFFER_FREE;
}
buf->Clear(wxSND_BUFSTOP);
continue;
}
- if (buf->GetMode() == wxSND_OUTPUT)
+ switch (buf->GetMode()) {
+ case wxSND_OUTPUT:
ret = NotifyOutputBuffer(buf);
- else
+ break;
+ case wxSND_INPUT:
ret = NotifyInputBuffer(buf);
+ break;
+ case wxSND_DUPLEX:
+ case wxSND_OTHER_IO:
+ // ret = NotifyDuplexBuffer(buf);
+ break;
+ }
buf->HardUnlock();
}