* 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}
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}

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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()
{
/*
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];
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);
WRITE32(total_size);
@ -199,7 +234,6 @@ bool wxSndAiffCodec::PrepareToRecord(wxUint32 m_fsize)
WriteCOMM();
WriteSSND(m_fsize);
*/
return TRUE;
}

View File

@ -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;

View File

@ -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();
data += data_read;
size -= data_read;
codec->SetInStream(ptr->sndbuf);
codec->InitIO(m_drvformat);
// As there is an "auto-stopper" in the codec, we don't worry ...
codec->Encode();
}
if (buf->IsSet(wxSND_UNQUEUEING))

View File

@ -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();

View File

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

View File

@ -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;