]>
git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia/sndfrag.cpp
1 ////////////////////////////////////////////////////////////////////////////////
4 // Author: Guilhem Lavaux
7 // Copyright: (C) 1997, 1998, Guilhem Lavaux
8 // License: wxWindows license
9 ////////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "sndfrag.h"
25 wxFragmentBuffer::wxFragmentBuffer(wxSound
& io_drv
)
26 : m_iodrv(&io_drv
), m_maxoq(0), m_maxiq(0),
27 m_optrs(NULL
), m_iptrs(NULL
), m_lstoptrs(NULL
), m_lstiptrs(NULL
),
28 m_buf2free(FALSE
), m_dontq(FALSE
), m_freeing(FALSE
)
32 wxFragmentBuffer::~wxFragmentBuffer()
36 void wxFragmentBuffer::AbortBuffer(wxSndBuffer
*buf
)
38 for (wxUint8 i
=0;i
<m_maxoq
;i
++)
39 if (m_lstoptrs
[i
].buffers
->Member(buf
)) {
40 if (m_lstoptrs
[i
].state
== wxBUFFER_PLAYING
)
41 // TODO: Do something.
43 m_lstoptrs
[i
].state
= wxBUFFER_TOFREE
;
46 for (wxUint8 i
=0;i
<m_maxiq
;i
++)
47 if (m_lstiptrs
[i
].buffers
->Member(buf
)) {
48 if (m_lstiptrs
[i
].state
== wxBUFFER_PLAYING
)
51 m_lstiptrs
[i
].state
= wxBUFFER_TOFREE
;
55 wxFragmentBuffer::wxFragBufPtr
*wxFragmentBuffer::FindFreeBuffer(
56 xFragBufPtr
*list
, wxUint8 max_queue
)
61 for (wxUint8 i
=0;i
<max_queue
;i
++) {
62 if (list
[i
].state
== wxBUFFER_FREE
)
69 bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer
*buf
)
74 wxSoundCodec
*codec
= buf
->GetCurrentCodec();
76 if (!m_iodrv
->OnSetupDriver(*buf
, wxSND_OUTPUT
))
80 // Find the first free (at least partly free) output buffer
81 ptr
= FindFreeBuffer(m_lstoptrs
, m_maxoq
);
86 codec
->SetOutStream(ptr
->sndbuf
);
87 codec
->InitIO(m_drvformat
);
92 // No data to fill the buffer: dequeue the current wxSndBuffer
93 if (!codec
->Available()) {
94 if (buf
->IsNotSet(wxSND_KEEPQUEUED
)) {
95 buf
->Set(wxSND_UNQUEUEING
);
96 m_iodrv
->m_buffers
.DeleteObject(buf
);
101 // Data: append it to the list
102 ptr
->buffers
->Append(buf
);
104 // Output buffer full: send it to the driver
105 if (ptr
->sndbuf
->GetDataLeft()) {
106 ptr
->state
= wxBUFFER_FFILLED
;
107 OnBufferFilled(ptr
, wxSND_OUTPUT
);
112 bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer
*buf
)
117 wxUint32 rawbuf_size;
119 if (!m_iodrv->OnSetupDriver(*buf, wxSND_INPUT))
123 ptr = FindFreeBuffer(m_lstiptrs, m_maxiq);
127 raw_buf = ptr->data + ptr->ptr;
128 rawbuf_size = ptr->size - ptr->ptr;
130 rawbuf_size = (buf->Available() < rawbuf_size) ? buf->Available() : rawbuf_size;
134 if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
135 buf->Set(wxSND_UNQUEUEING);
136 m_iodrv->m_buffers.DeleteObject(buf);
139 if (!LastBuffer() && ptr->ptr) {
140 ptr->state = wxBUFFER_FFILLED;
141 if (!OnBufferFilled(ptr, wxSND_INPUT))
146 ptr->buffers->Append(buf);
148 ptr->ptr += rawbuf_size;
151 if (ptr->ptr == ptr->size) {
152 ptr->state = wxBUFFER_FFILLED;
153 if (!OnBufferFilled(ptr, wxSND_INPUT))
162 void wxFragmentBuffer::FreeBufToFree(bool force
)
165 // Garbage collecting
170 for (i
=0;i
<m_maxoq
;i
++) {
171 if ((m_lstoptrs
[i
].state
== wxBUFFER_TOFREE
) ||
172 (force
&& m_lstoptrs
[i
].state
== wxBUFFER_FFILLED
))
173 ClearBuffer(&m_lstoptrs
[i
]);
176 for (i
=0;i
<m_maxiq
;i
++) {
177 if ((m_lstiptrs
[i
].state
== wxBUFFER_TOFREE
) ||
178 (force
&& m_lstoptrs
[i
].state
== wxBUFFER_FFILLED
))
179 ClearBuffer(&m_lstiptrs
[i
]);
185 void wxFragmentBuffer::ClearBuffer(wxFragBufPtr
*ptr
)
190 wxUint32 size
, data_read
;
195 node
= ptr
->buffers
->First();
198 buf
= (wxSndBuffer
*)node
->Data();
200 if (buf
->GetMode() == wxSND_OUTPUT
) {
201 buf
->OnBufferOutFinished();
203 data_read
= buf
->OnBufferInFinished(data
, size
);
209 if (buf
->IsSet(wxSND_UNQUEUEING
))
210 buf
->Clear(wxSND_UNQUEUEING
| wxSND_BUFLOCKED
| wxSND_BUFREADY
);
213 node
= ptr
->buffers
->First();
216 ptr
->sndbuf
->ResetBuffer();
217 ptr
->state
= wxBUFFER_FREE
;
220 void wxFragmentBuffer::OnBufferFinished(wxFragBufPtr
*ptr
)
227 ptr
->state
= wxBUFFER_TOFREE
;
233 // Clean up the old buffer.
234 if (ptr
&& ptr
->state
!= wxBUFFER_FREE
)
237 // Garbage collecting ...
241 // If we are queueing, return immediately.
247 node
= m_iodrv
->m_buffers
.First();
249 while (node
&& ret
) {
250 buf
= (wxSndBuffer
*)node
->Data();
255 // Stop request on this buffer.
256 if (buf
->IsSet(wxSND_BUFSTOP
)) {
257 buf
->Clear(wxSND_BUFSTOP
);
260 if (buf
->GetMode() == wxSND_OUTPUT
)
261 ret
= NotifyOutputBuffer(buf
);
263 ret
= NotifyInputBuffer(buf
);