* 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
This commit is contained in:
Guilhem Lavaux
1999-02-14 17:46:47 +00:00
parent 20239453d5
commit 9fc0fe377b
10 changed files with 109 additions and 85 deletions

View File

@@ -284,7 +284,12 @@ Returns the current position (counted in bytes) in the stream buffer.
\func{void}{SetIntPosition}{\void} \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} \membersection{wxStreamBuffer::GetLastAccess}

View File

@@ -251,8 +251,8 @@ void wxStreamBuffer::PutChar(char c)
return; return;
} }
if (!GetDataLeft() && !FlushBuffer()) { if (GetDataLeft() == 0 && !FlushBuffer()) {
CHECK_ERROR(wxStream_READ_ERR); CHECK_ERROR(wxStream_WRITE_ERR);
return; return;
} }

View File

@@ -66,7 +66,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxSndAiffCodec, wxSndFileCodec)
IMPLEMENT_ABSTRACT_CLASS(wxVideoBaseDriver, wxMMediaFile) IMPLEMENT_ABSTRACT_CLASS(wxVideoBaseDriver, wxMMediaFile)
IMPLEMENT_DYNAMIC_CLASS(wxVideoOutput, wxWindow) IMPLEMENT_DYNAMIC_CLASS(wxVideoOutput, wxWindow)
#if defined(__X__) || defined(__WXGTK__) #if defined(__X__) || defined(__WXGTK__)
IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver) // IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver)
#endif #endif
#ifdef __WINDOWS__ #ifdef __WINDOWS__
IMPLEMENT_DYNAMIC_CLASS(wxVideoWindows, wxVideoBaseDriver) 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-aiff", "Aiff Player", wxSndAiffCodec, "aif")
MMD_REGISTER_FILE("audio/x-au", "Sun Audio File Player", wxSndAuCodec, "au") MMD_REGISTER_FILE("audio/x-au", "Sun Audio File Player", wxSndAuCodec, "au")
#if defined(__X__) || defined(__WXGTK__) #if defined(__X__) || defined(__WXGTK__)
MMD_REGISTER_FILE("video/*", "Video Player", wxVideoXANIM, "mov") // MMD_REGISTER_FILE("video/*", "Video Player", wxVideoXANIM, "mov")
#else #else
MMD_REGISTER_FILE("video/avi", "AVI Player", wxVideoWindows, "avi") MMD_REGISTER_FILE("video/avi", "AVI Player", wxVideoWindows, "avi")
#endif #endif

View File

@@ -85,7 +85,7 @@ void wxMMediaFile::SetFile(wxInputStream& str, bool preload, bool seekable)
m_o_temp = new wxOutputStream(streamb); m_o_temp = new wxOutputStream(streamb);
m_i_temp = new wxInputStream(streamb); m_i_temp = new wxInputStream(streamb);
m_o_temp->Write(is); m_o_temp->Write(str);
streamb->ResetBuffer(); streamb->ResetBuffer();
} }
} }
@@ -116,7 +116,7 @@ void wxMMediaFile::CleanUpPrevious()
if (m_ostream) if (m_ostream)
m_ostream->Write(*m_i_temp); m_ostream->Write(*m_i_temp);
delete m_i_temp->StreamBuffer(); delete (m_i_temp->InputStreamBuffer());
delete m_i_temp; delete m_i_temp;
delete m_o_temp; delete m_o_temp;

View File

@@ -103,7 +103,7 @@ wxUint32 wxSndAiffCodec::PrepareToPlay()
m_spos = 0; m_spos = 0;
m_slen = 0; m_slen = 0;
m_sndformat.SetSampleRate(0); m_sndformat.SetSampleRate(0);
while (1) { while (!m_spos || !m_sndformat.GetSampleRate()) {
READ_STRING(chunk_name, 4); READ_STRING(chunk_name, 4);
READ32(m_chunksize); READ32(m_chunksize);
@@ -113,9 +113,6 @@ wxUint32 wxSndAiffCodec::PrepareToPlay()
ParseCOMM(); ParseCOMM();
else else
m_istream->SeekI(m_chunksize, wxFromCurrent); m_istream->SeekI(m_chunksize, wxFromCurrent);
if (m_spos && m_sndformat.GetSampleRate())
break;
} }
m_sndmode = wxSND_OUTPUT; m_sndmode = wxSND_OUTPUT;
@@ -183,13 +180,51 @@ bool wxSndAiffCodec::OnWriteData(char *buf, wxUint32 size)
return ( !(m_ostream->Write(buf, size).LastError()) ); return ( !(m_ostream->Write(buf, size).LastError()) );
} }
bool wxSndAiffCodec::PrepareToRecord(wxUint32 m_fsize) void wxSndAiffCodec::WriteCOMM()
{
/*
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();
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)
{ {
/* /*
wxUint32 total_size;
char tmp_buf[10]; char tmp_buf[10];
m_ostream->SeekO(0, wxBeginPosition); 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); m_ostream->Write("FORM", 4);
WRITE32(total_size); WRITE32(total_size);
@@ -199,7 +234,6 @@ bool wxSndAiffCodec::PrepareToRecord(wxUint32 m_fsize)
WriteCOMM(); WriteCOMM();
WriteSSND(m_fsize); WriteSSND(m_fsize);
*/
return TRUE; return TRUE;
} }

View File

@@ -51,8 +51,6 @@ wxUint32 wxSndAuCodec::PrepareToPlay()
int offset, srate, codec, ch_count; int offset, srate, codec, ch_count;
size_t len; size_t len;
m_istream->SeekI(0);
m_istream->Read(temp_buf, 4); m_istream->Read(temp_buf, 4);
temp_buf[4] = 0; temp_buf[4] = 0;

View File

@@ -24,7 +24,7 @@
wxFragmentBuffer::wxFragmentBuffer(wxSound& io_drv) wxFragmentBuffer::wxFragmentBuffer(wxSound& io_drv)
: m_iodrv(&io_drv), m_maxoq(0), m_maxiq(0), : 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) m_buf2free(FALSE), m_dontq(FALSE), m_freeing(FALSE)
{ {
} }
@@ -53,7 +53,7 @@ void wxFragmentBuffer::AbortBuffer(wxSndBuffer *buf)
} }
wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer( wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer(
xFragBufPtr *list, wxUint8 max_queue) wxFragBufPtr *list, wxUint8 max_queue)
{ {
if (!list) if (!list)
return NULL; return NULL;
@@ -69,8 +69,6 @@ wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer(
bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf) bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf)
{ {
wxFragBufPtr *ptr; wxFragBufPtr *ptr;
char *raw_buf;
wxUint32 rawbuf_size;
wxSoundCodec *codec = buf->GetCurrentCodec(); wxSoundCodec *codec = buf->GetCurrentCodec();
if (!m_iodrv->OnSetupDriver(*buf, wxSND_OUTPUT)) 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 // Find the first free (at least partly free) output buffer
ptr = FindFreeBuffer(m_lstoptrs, m_maxoq); ptr = FindFreeBuffer(m_lstoptrs, m_maxoq);
// No free : go out ! // No free : go out !
if (!ptr) if (ptr == NULL)
return FALSE; return FALSE;
codec->SetOutStream(ptr->sndbuf); codec->SetOutStream(ptr->sndbuf);
@@ -90,7 +88,7 @@ bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf)
codec->Decode(); codec->Decode();
// No data to fill the buffer: dequeue the current wxSndBuffer // No data to fill the buffer: dequeue the current wxSndBuffer
if (!codec->Available()) { if (codec->Available() == 0) {
if (buf->IsNotSet(wxSND_KEEPQUEUED)) { if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
buf->Set(wxSND_UNQUEUEING); buf->Set(wxSND_UNQUEUEING);
m_iodrv->m_buffers.DeleteObject(buf); m_iodrv->m_buffers.DeleteObject(buf);
@@ -102,7 +100,7 @@ bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf)
ptr->buffers->Append(buf); ptr->buffers->Append(buf);
// Output buffer full: send it to the driver // Output buffer full: send it to the driver
if (ptr->sndbuf->GetDataLeft()) { if (ptr->sndbuf->GetDataLeft() == 0) {
ptr->state = wxBUFFER_FFILLED; ptr->state = wxBUFFER_FFILLED;
OnBufferFilled(ptr, wxSND_OUTPUT); OnBufferFilled(ptr, wxSND_OUTPUT);
} }
@@ -111,32 +109,24 @@ bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf)
bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer *buf) bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer *buf)
{ {
/* wxFragBufPtr *ptr;
wxFragBufPtr *ptr; size_t inc;
char *raw_buf;
wxUint32 rawbuf_size;
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; 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)) { if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
buf->Set(wxSND_UNQUEUEING); buf->Set(wxSND_UNQUEUEING);
m_iodrv->m_buffers.DeleteObject(buf); m_iodrv->m_buffers.DeleteObject(buf);
} }
if (!LastBuffer() && ptr->ptr) { if (LastBuffer() == NULL && ptr->sndbuf->GetIntPosition() != 0) {
ptr->state = wxBUFFER_FFILLED; ptr->state = wxBUFFER_FFILLED;
if (!OnBufferFilled(ptr, wxSND_INPUT)) if (!OnBufferFilled(ptr, wxSND_INPUT))
return FALSE; return FALSE;
@@ -145,16 +135,18 @@ bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer *buf)
} }
ptr->buffers->Append(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; ptr->state = wxBUFFER_FFILLED;
if (!OnBufferFilled(ptr, wxSND_INPUT)) if (!OnBufferFilled(ptr, wxSND_INPUT))
return FALSE; return FALSE;
} }
} }
*/
return TRUE; return TRUE;
} }
@@ -186,11 +178,7 @@ void wxFragmentBuffer::ClearBuffer(wxFragBufPtr *ptr)
{ {
wxNode *node; wxNode *node;
wxSndBuffer *buf; wxSndBuffer *buf;
char *data; wxSoundCodec *codec;
wxUint32 size, data_read;
data = ptr->data;
size = ptr->size;
node = ptr->buffers->First(); node = ptr->buffers->First();
@@ -200,10 +188,13 @@ void wxFragmentBuffer::ClearBuffer(wxFragBufPtr *ptr)
if (buf->GetMode() == wxSND_OUTPUT) { if (buf->GetMode() == wxSND_OUTPUT) {
buf->OnBufferOutFinished(); buf->OnBufferOutFinished();
} else { } else {
data_read = buf->OnBufferInFinished(data, size); codec = buf->GetCurrentCodec();
data += data_read; codec->SetInStream(ptr->sndbuf);
size -= data_read; codec->InitIO(m_drvformat);
// As there is an "auto-stopper" in the codec, we don't worry ...
codec->Encode();
} }
if (buf->IsSet(wxSND_UNQUEUEING)) if (buf->IsSet(wxSND_UNQUEUEING))

View File

@@ -32,65 +32,60 @@ protected:
typedef enum { typedef enum {
wxBUFFER_FREE, wxBUFFER_FREE,
wxBUFFER_FFILLED, wxBUFFER_FFILLED,
wxBUFFER_TOFREE wxBUFFER_TOFREE,
wxBUFFER_PLAYING
} BufState; } BufState;
public: public:
/// ///
typedef struct { 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; char *user_data;
/// // Buffers included in this fragment.
wxUint32 size, ptr;
///
wxList *buffers; wxList *buffers;
/// // State of the fragment.
BufState state; BufState state;
} wxFragBufPtr; } wxFragBufPtr;
protected: protected:
/// //
wxFragBufPtr *m_optrs, *m_iptrs; wxFragBufPtr *m_optrs, *m_iptrs;
/// //
wxFragBufPtr *m_lstoptrs, *m_lstiptrs; wxFragBufPtr *m_lstoptrs, *m_lstiptrs;
/// //
bool m_buf2free, m_dontq, m_freeing; bool m_buf2free, m_dontq, m_freeing;
/// //
wxSoundDataFormat m_drvformat; wxSoundDataFormat m_drvformat;
public: public:
///
wxFragmentBuffer(wxSound& io_drv); wxFragmentBuffer(wxSound& io_drv);
///
virtual ~wxFragmentBuffer(); virtual ~wxFragmentBuffer();
/// // These functions initializes the fragments. They must initialize
// m_lstoptrs, m_lstiptrs, m_maxoq, m_maxiq.
virtual void AllocIOBuffer() = 0; virtual void AllocIOBuffer() = 0;
///
virtual void FreeIOBuffer() = 0; virtual void FreeIOBuffer() = 0;
///
void AbortBuffer(wxSndBuffer *buf); void AbortBuffer(wxSndBuffer *buf);
/// // Find a free (or partly free) fragment.
wxFragBufPtr *FindFreeBuffer(wxFragBufPtr *list, wxUint8 max_queue); wxFragBufPtr *FindFreeBuffer(wxFragBufPtr *list, wxUint8 max_queue);
/// // Add this sound buffer to an "OUTPUT" fragment.
bool NotifyOutputBuffer(wxSndBuffer *buf); bool NotifyOutputBuffer(wxSndBuffer *buf);
/// // Add this sound buffer to an "INPUT" fragment.
bool NotifyInputBuffer(wxSndBuffer *buf); bool NotifyInputBuffer(wxSndBuffer *buf);
/// // Called when a fragment is finished.
void OnBufferFinished(wxFragBufPtr *ptr); 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; virtual bool OnBufferFilled(wxFragBufPtr *ptr, wxSndMode mode) = 0;
///
inline wxSndBuffer *LastBuffer() { inline wxSndBuffer *LastBuffer() {
wxNode *node = m_iodrv->m_buffers.Last(); wxNode *node = m_iodrv->m_buffers.Last();
if (!node) return NULL; if (!node) return NULL;
return (wxSndBuffer *)node->Data(); return (wxSndBuffer *)node->Data();
} }
///
inline wxSndBuffer *FirstBuffer() { inline wxSndBuffer *FirstBuffer() {
wxNode *node = m_iodrv->m_buffers.First(); wxNode *node = m_iodrv->m_buffers.First();

View File

@@ -49,7 +49,8 @@ wxUssSound::~wxUssSound()
m_sleep_cond.Signal(); m_sleep_cond.Signal();
m_sleep_mtx.Unlock(); m_sleep_mtx.Unlock();
} }
Join(); while (IsAlive())
Yield();
} }
if (m_fd != -1) if (m_fd != -1)

View File

@@ -42,12 +42,10 @@ void wxSndWinFragment::AllocIOBuffer(void)
m_maxoq = 5; m_maxoq = 5;
m_maxiq = 5; m_maxiq = 5;
m_lstoptrs = m_optrs = new wxFragBufPtr[m_maxoq]; m_lstoptrs = new wxFragBufPtr[m_maxoq];
m_lstiptrs = m_iptrs = new wxFragBufPtr[m_maxiq]; m_lstiptrs = new wxFragBufPtr[m_maxiq];
for (i=0;i<m_maxoq;i++) { 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].buffers = new wxList();
m_lstoptrs[i].state = wxBUFFER_FREE; m_lstoptrs[i].state = wxBUFFER_FREE;
@@ -198,7 +196,7 @@ void wxWinSound::PrepareHeader(wxFragmentBuffer::wxFragBufPtr& frag,
info = new wxSndWinInfo; 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->h_hdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
info->data = (char *)GlobalLock(info->h_data); info->data = (char *)GlobalLock(info->h_data);
@@ -214,19 +212,18 @@ void wxWinSound::PrepareHeader(wxFragmentBuffer::wxFragBufPtr& frag,
MMRESULT result = waveInPrepareHeader(internal->devin_id, hdr, MMRESULT result = waveInPrepareHeader(internal->devin_id, hdr,
sizeof(WAVEHDR)); sizeof(WAVEHDR));
printf("prepareIn = %d\n", result);
if (result != MMSYSERR_NOERROR) if (result != MMSYSERR_NOERROR)
wxExit(); wxExit();
} else { } else {
MMRESULT result = waveOutPrepareHeader(internal->devout_id, hdr, MMRESULT result = waveOutPrepareHeader(internal->devout_id, hdr,
sizeof(WAVEHDR)); sizeof(WAVEHDR));
printf("prepareOut = %d\n", result);
if (result != MMSYSERR_NOERROR) if (result != MMSYSERR_NOERROR)
wxExit(); wxExit();
} }
frag.sndbuf = new wxStreamBuffer();
frag.sndbuf->SetBufferIO(info->data, info->data + MMD_WIN_IO_BSIZE);
frag.user_data = (char *)info; frag.user_data = (char *)info;
frag.data = info->data;
} }
void wxWinSound::UnprepareHeader(wxFragmentBuffer::wxFragBufPtr& frag, 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)); result = waveOutUnprepareHeader(internal->devout_id, info->hdr, sizeof(*info->hdr));
} }
delete frag.sndbuf;
printf("unprepare = %d\n", result); printf("unprepare = %d\n", result);
GlobalUnlock(info->h_hdr); GlobalUnlock(info->h_hdr);
@@ -282,6 +281,7 @@ LRESULT APIENTRY _EXPORT wxSoundHandlerWndProc(HWND hWnd, UINT message,
printf("wave Close ack\n"); printf("wave Close ack\n");
break; break;
default: default:
// TODO: Useful ?
return DefWindowProc(hWnd, message, wParam, lParam); return DefWindowProc(hWnd, message, wParam, lParam);
} }
return (LRESULT)0; return (LRESULT)0;