\func{void}{SetIntPosition}{\void}
-Sets the current position in the stream buffer.
+Sets the current position (in bytes) in the stream buffer.
+
+\wxheading{Warning}
+
+Since it is a very low-level function, there is no check on the position:
+specify an invalid position can induce unexpected results.
\membersection{wxStreamBuffer::GetLastAccess}
return;
}
- if (!GetDataLeft() && !FlushBuffer()) {
- CHECK_ERROR(wxStream_READ_ERR);
+ if (GetDataLeft() == 0 && !FlushBuffer()) {
+ CHECK_ERROR(wxStream_WRITE_ERR);
return;
}
IMPLEMENT_ABSTRACT_CLASS(wxVideoBaseDriver, wxMMediaFile)
IMPLEMENT_DYNAMIC_CLASS(wxVideoOutput, wxWindow)
#if defined(__X__) || defined(__WXGTK__)
-IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver)
+// IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver)
#endif
#ifdef __WINDOWS__
IMPLEMENT_DYNAMIC_CLASS(wxVideoWindows, wxVideoBaseDriver)
MMD_REGISTER_FILE("audio/x-aiff", "Aiff Player", wxSndAiffCodec, "aif")
MMD_REGISTER_FILE("audio/x-au", "Sun Audio File Player", wxSndAuCodec, "au")
#if defined(__X__) || defined(__WXGTK__)
-MMD_REGISTER_FILE("video/*", "Video Player", wxVideoXANIM, "mov")
+// MMD_REGISTER_FILE("video/*", "Video Player", wxVideoXANIM, "mov")
#else
MMD_REGISTER_FILE("video/avi", "AVI Player", wxVideoWindows, "avi")
#endif
m_o_temp = new wxOutputStream(streamb);
m_i_temp = new wxInputStream(streamb);
- m_o_temp->Write(is);
+ m_o_temp->Write(str);
streamb->ResetBuffer();
}
}
if (m_ostream)
m_ostream->Write(*m_i_temp);
- delete m_i_temp->StreamBuffer();
+ delete (m_i_temp->InputStreamBuffer());
delete m_i_temp;
delete m_o_temp;
m_spos = 0;
m_slen = 0;
m_sndformat.SetSampleRate(0);
- while (1) {
+ while (!m_spos || !m_sndformat.GetSampleRate()) {
READ_STRING(chunk_name, 4);
READ32(m_chunksize);
ParseCOMM();
else
m_istream->SeekI(m_chunksize, wxFromCurrent);
-
- if (m_spos && m_sndformat.GetSampleRate())
- break;
}
m_sndmode = wxSND_OUTPUT;
return ( !(m_ostream->Write(buf, size).LastError()) );
}
-bool wxSndAiffCodec::PrepareToRecord(wxUint32 m_fsize)
+void wxSndAiffCodec::WriteCOMM()
{
/*
- wxUint32 total_size;
+ wxDataOutputStream data_s(*m_ostream);
char tmp_buf[10];
+ wxUint16 channels;
+ wxUint32 srate, num_samples;
+ wxUint16 bps;
+
+ m_chunksize = 18;
+ WRITE32(m_chunksize);
+ channels = m_sndformat.GetChannels();
+ srate = m_sndformat.GetSampleRate();
+ bps = m_sndformat.GetBps();
- m_ostream->SeekO(0, wxBeginPosition);
+ WRITE16(channels);
+ WRITE32(num_samples);
+ WRITE16(bps);
+
+ data_s.WriteDouble((double)srate);
+
+ m_sndformat.SetByteOrder(wxSND_SAMPLE_BE);
+ m_sndformat.SetSign(wxSND_SAMPLE_UNSIGNED);
+ ChangeCodec(WXSOUND_PCM);
+*/
+}
+
+void wxSndAiffCodec::WriteSSND(wxUint32 fsize)
+{
+/*
+ char tmp_buf[10];
+
+ WRITE32(m_spos);
+// WRITE32(dummy ??);
+
+ m_slen = m_chunksize - m_spos;
+ m_spos += m_istream->TellI();
+*/
+}
+
+
+bool wxSndAiffCodec::PrepareToRecord(wxUint32 m_fsize)
+{
+ wxUint32 total_size = m_fsize + 0;
+ char tmp_buf[10];
m_ostream->Write("FORM", 4);
WRITE32(total_size);
WriteCOMM();
WriteSSND(m_fsize);
-*/
return TRUE;
}
int offset, srate, codec, ch_count;
size_t len;
- m_istream->SeekI(0);
-
m_istream->Read(temp_buf, 4);
temp_buf[4] = 0;
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(
- xFragBufPtr *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))
// 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;
codec->SetOutStream(ptr->sndbuf);
codec->Decode();
// No data to fill the buffer: dequeue the current wxSndBuffer
- if (!codec->Available()) {
+ if (codec->Available() == 0) {
if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
buf->Set(wxSND_UNQUEUEING);
m_iodrv->m_buffers.DeleteObject(buf);
ptr->buffers->Append(buf);
// Output buffer full: send it to the driver
- if (ptr->sndbuf->GetDataLeft()) {
+ 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;
+ wxFragBufPtr *ptr;
+ size_t inc;
- if (!m_iodrv->OnSetupDriver(*buf, wxSND_INPUT))
+ if (!m_iodrv->OnSetupDriver(*buf, wxSND_INPUT))
+ return FALSE;
+
+ while (1) {
+ ptr = FindFreeBuffer(m_lstiptrs, m_maxiq);
+ if (ptr == NULL)
return FALSE;
-
- while (1) {
- ptr = FindFreeBuffer(m_lstiptrs, m_maxiq);
- if (!ptr)
- 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);
}
- 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);
- 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();
+
+ codec->SetInStream(ptr->sndbuf);
+ codec->InitIO(m_drvformat);
- 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))
typedef enum {
wxBUFFER_FREE,
wxBUFFER_FFILLED,
- wxBUFFER_TOFREE
+ wxBUFFER_TOFREE,
+ wxBUFFER_PLAYING
} BufState;
public:
///
typedef struct {
- char *data;
- ///
+ // Local stream buffer for this fragment.
+ wxStreamBuffer *sndbuf;
+ // Data the driver would like to pass to the callback.
char *user_data;
- ///
- wxUint32 size, ptr;
- ///
+ // Buffers included in this fragment.
wxList *buffers;
- ///
+ // State of the fragment.
BufState state;
} wxFragBufPtr;
protected:
- ///
+ //
wxFragBufPtr *m_optrs, *m_iptrs;
- ///
+ //
wxFragBufPtr *m_lstoptrs, *m_lstiptrs;
- ///
+ //
bool m_buf2free, m_dontq, m_freeing;
- ///
+ //
wxSoundDataFormat m_drvformat;
public:
- ///
wxFragmentBuffer(wxSound& io_drv);
- ///
virtual ~wxFragmentBuffer();
- ///
+ // These functions initializes the fragments. They must initialize
+ // m_lstoptrs, m_lstiptrs, m_maxoq, m_maxiq.
virtual void AllocIOBuffer() = 0;
- ///
virtual void FreeIOBuffer() = 0;
- ///
void AbortBuffer(wxSndBuffer *buf);
- ///
+ // Find a free (or partly free) fragment.
wxFragBufPtr *FindFreeBuffer(wxFragBufPtr *list, wxUint8 max_queue);
- ///
+ // Add this sound buffer to an "OUTPUT" fragment.
bool NotifyOutputBuffer(wxSndBuffer *buf);
- ///
+ // Add this sound buffer to an "INPUT" fragment.
bool NotifyInputBuffer(wxSndBuffer *buf);
- ///
+ // Called when a fragment is finished.
void OnBufferFinished(wxFragBufPtr *ptr);
- ///
+ // Called when a fragment is full and it should be flushed in the sound card.
virtual bool OnBufferFilled(wxFragBufPtr *ptr, wxSndMode mode) = 0;
- ///
inline wxSndBuffer *LastBuffer() {
wxNode *node = m_iodrv->m_buffers.Last();
if (!node) return NULL;
return (wxSndBuffer *)node->Data();
}
- ///
inline wxSndBuffer *FirstBuffer() {
wxNode *node = m_iodrv->m_buffers.First();
m_sleep_cond.Signal();
m_sleep_mtx.Unlock();
}
- Join();
+ while (IsAlive())
+ Yield();
}
if (m_fd != -1)
m_maxoq = 5;
m_maxiq = 5;
- m_lstoptrs = m_optrs = new wxFragBufPtr[m_maxoq];
- m_lstiptrs = m_iptrs = new wxFragBufPtr[m_maxiq];
+ m_lstoptrs = new wxFragBufPtr[m_maxoq];
+ m_lstiptrs = new wxFragBufPtr[m_maxiq];
for (i=0;i<m_maxoq;i++) {
- m_lstoptrs[i].size = MMD_WIN_IO_BSIZE;
- m_lstoptrs[i].ptr = 0;
m_lstoptrs[i].buffers = new wxList();
m_lstoptrs[i].state = wxBUFFER_FREE;
info = new wxSndWinInfo;
- info->h_data = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, frag.size);
+ info->h_data = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, MMD_WIN_IO_BSIZE);
info->h_hdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
info->data = (char *)GlobalLock(info->h_data);
MMRESULT result = waveInPrepareHeader(internal->devin_id, hdr,
sizeof(WAVEHDR));
- printf("prepareIn = %d\n", result);
if (result != MMSYSERR_NOERROR)
wxExit();
} else {
MMRESULT result = waveOutPrepareHeader(internal->devout_id, hdr,
sizeof(WAVEHDR));
- printf("prepareOut = %d\n", result);
if (result != MMSYSERR_NOERROR)
wxExit();
}
+ frag.sndbuf = new wxStreamBuffer();
+ frag.sndbuf->SetBufferIO(info->data, info->data + MMD_WIN_IO_BSIZE);
frag.user_data = (char *)info;
- frag.data = info->data;
}
void wxWinSound::UnprepareHeader(wxFragmentBuffer::wxFragBufPtr& frag,
result = waveOutUnprepareHeader(internal->devout_id, info->hdr, sizeof(*info->hdr));
}
+ delete frag.sndbuf;
+
printf("unprepare = %d\n", result);
GlobalUnlock(info->h_hdr);
printf("wave Close ack\n");
break;
default:
+ // TODO: Useful ?
return DefWindowProc(hWnd, message, wParam, lParam);
}
return (LRESULT)0;