From 9fc0fe377b42853e23cb771a2d9a742b9c91a996 Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Sun, 14 Feb 1999 17:46:47 +0000 Subject: [PATCH] * Stream: update in doc, fix in code. * wxMMedia: various fixes, WAV and AIFF should work on Linux, preparing it for Windows. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1692 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/stream.tex | 7 ++++- src/common/stream.cpp | 4 +-- utils/wxMMedia/mmdata.cpp | 4 +-- utils/wxMMedia/mmfile.cpp | 4 +-- utils/wxMMedia/sndaiff.cpp | 50 +++++++++++++++++++++++++----- utils/wxMMedia/sndau.cpp | 2 -- utils/wxMMedia/sndfrag.cpp | 63 ++++++++++++++++---------------------- utils/wxMMedia/sndfrag.h | 41 +++++++++++-------------- utils/wxMMedia/snduss.cpp | 3 +- utils/wxMMedia/sndwin.cpp | 16 +++++----- 10 files changed, 109 insertions(+), 85 deletions(-) diff --git a/docs/latex/wx/stream.tex b/docs/latex/wx/stream.tex index 7818a9ae86..56b43ae61a 100644 --- a/docs/latex/wx/stream.tex +++ b/docs/latex/wx/stream.tex @@ -284,7 +284,12 @@ Returns the current position (counted in bytes) in the stream buffer. \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} diff --git a/src/common/stream.cpp b/src/common/stream.cpp index 95947e6032..305c8c5128 100644 --- a/src/common/stream.cpp +++ b/src/common/stream.cpp @@ -251,8 +251,8 @@ void wxStreamBuffer::PutChar(char c) return; } - if (!GetDataLeft() && !FlushBuffer()) { - CHECK_ERROR(wxStream_READ_ERR); + if (GetDataLeft() == 0 && !FlushBuffer()) { + CHECK_ERROR(wxStream_WRITE_ERR); return; } diff --git a/utils/wxMMedia/mmdata.cpp b/utils/wxMMedia/mmdata.cpp index a89cae04e4..abcf3eaea9 100644 --- a/utils/wxMMedia/mmdata.cpp +++ b/utils/wxMMedia/mmdata.cpp @@ -66,7 +66,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxSndAiffCodec, wxSndFileCodec) 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) @@ -88,7 +88,7 @@ MMD_REGISTER_FILE("audio/x-wav", "Wav Player", wxSndWavCodec, "wav") 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 diff --git a/utils/wxMMedia/mmfile.cpp b/utils/wxMMedia/mmfile.cpp index 47e31efe09..b079b6b6a8 100644 --- a/utils/wxMMedia/mmfile.cpp +++ b/utils/wxMMedia/mmfile.cpp @@ -85,7 +85,7 @@ void wxMMediaFile::SetFile(wxInputStream& str, bool preload, bool seekable) m_o_temp = new wxOutputStream(streamb); m_i_temp = new wxInputStream(streamb); - m_o_temp->Write(is); + m_o_temp->Write(str); streamb->ResetBuffer(); } } @@ -116,7 +116,7 @@ void wxMMediaFile::CleanUpPrevious() 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; diff --git a/utils/wxMMedia/sndaiff.cpp b/utils/wxMMedia/sndaiff.cpp index 2e4b0cb84e..c890726a53 100644 --- a/utils/wxMMedia/sndaiff.cpp +++ b/utils/wxMMedia/sndaiff.cpp @@ -103,7 +103,7 @@ wxUint32 wxSndAiffCodec::PrepareToPlay() 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); @@ -113,9 +113,6 @@ wxUint32 wxSndAiffCodec::PrepareToPlay() ParseCOMM(); else m_istream->SeekI(m_chunksize, wxFromCurrent); - - if (m_spos && m_sndformat.GetSampleRate()) - break; } m_sndmode = wxSND_OUTPUT; @@ -183,13 +180,51 @@ bool wxSndAiffCodec::OnWriteData(char *buf, wxUint32 size) 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); @@ -199,7 +234,6 @@ bool wxSndAiffCodec::PrepareToRecord(wxUint32 m_fsize) WriteCOMM(); WriteSSND(m_fsize); -*/ return TRUE; } diff --git a/utils/wxMMedia/sndau.cpp b/utils/wxMMedia/sndau.cpp index 9c46880411..3ab950113b 100644 --- a/utils/wxMMedia/sndau.cpp +++ b/utils/wxMMedia/sndau.cpp @@ -51,8 +51,6 @@ wxUint32 wxSndAuCodec::PrepareToPlay() int offset, srate, codec, ch_count; size_t len; - m_istream->SeekI(0); - m_istream->Read(temp_buf, 4); temp_buf[4] = 0; diff --git a/utils/wxMMedia/sndfrag.cpp b/utils/wxMMedia/sndfrag.cpp index 9b4e46ffdc..2b0db71d6d 100644 --- a/utils/wxMMedia/sndfrag.cpp +++ b/utils/wxMMedia/sndfrag.cpp @@ -24,7 +24,7 @@ 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) { } @@ -53,7 +53,7 @@ void wxFragmentBuffer::AbortBuffer(wxSndBuffer *buf) } wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer( - xFragBufPtr *list, wxUint8 max_queue) + wxFragBufPtr *list, wxUint8 max_queue) { if (!list) return NULL; @@ -69,8 +69,6 @@ wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer( bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf) { wxFragBufPtr *ptr; - char *raw_buf; - wxUint32 rawbuf_size; wxSoundCodec *codec = buf->GetCurrentCodec(); if (!m_iodrv->OnSetupDriver(*buf, wxSND_OUTPUT)) @@ -80,7 +78,7 @@ bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf) // 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); @@ -90,7 +88,7 @@ bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf) 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); @@ -102,7 +100,7 @@ bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *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); } @@ -111,32 +109,24 @@ bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf) 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; @@ -145,16 +135,18 @@ bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer *buf) } 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; } @@ -186,11 +178,7 @@ void wxFragmentBuffer::ClearBuffer(wxFragBufPtr *ptr) { wxNode *node; wxSndBuffer *buf; - char *data; - wxUint32 size, data_read; - - data = ptr->data; - size = ptr->size; + wxSoundCodec *codec; node = ptr->buffers->First(); @@ -200,10 +188,13 @@ void wxFragmentBuffer::ClearBuffer(wxFragBufPtr *ptr) 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)) diff --git a/utils/wxMMedia/sndfrag.h b/utils/wxMMedia/sndfrag.h index d0679087e4..520f48ee4a 100644 --- a/utils/wxMMedia/sndfrag.h +++ b/utils/wxMMedia/sndfrag.h @@ -32,65 +32,60 @@ protected: 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(); diff --git a/utils/wxMMedia/snduss.cpp b/utils/wxMMedia/snduss.cpp index 100cd2a855..81c2a7f4ec 100644 --- a/utils/wxMMedia/snduss.cpp +++ b/utils/wxMMedia/snduss.cpp @@ -49,7 +49,8 @@ wxUssSound::~wxUssSound() m_sleep_cond.Signal(); m_sleep_mtx.Unlock(); } - Join(); + while (IsAlive()) + Yield(); } if (m_fd != -1) diff --git a/utils/wxMMedia/sndwin.cpp b/utils/wxMMedia/sndwin.cpp index 8161ed881f..417ce57063 100644 --- a/utils/wxMMedia/sndwin.cpp +++ b/utils/wxMMedia/sndwin.cpp @@ -42,12 +42,10 @@ void wxSndWinFragment::AllocIOBuffer(void) 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;ih_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); @@ -214,19 +212,18 @@ void wxWinSound::PrepareHeader(wxFragmentBuffer::wxFragBufPtr& frag, 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, @@ -246,6 +243,8 @@ 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); @@ -282,6 +281,7 @@ LRESULT APIENTRY _EXPORT wxSoundHandlerWndProc(HWND hWnd, UINT message, printf("wave Close ack\n"); break; default: + // TODO: Useful ? return DefWindowProc(hWnd, message, wParam, lParam); } return (LRESULT)0; -- 2.45.2