From 9fc0fe377b42853e23cb771a2d9a742b9c91a996 Mon Sep 17 00:00:00 2001
From: Guilhem Lavaux <lavaux@easynet.fr>
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;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;
 
@@ -198,7 +196,7 @@ void wxWinSound::PrepareHeader(wxFragmentBuffer::wxFragBufPtr& frag,
 
   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);
@@ -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.50.0

