]>
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 wxFragBufPtr
*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
)
75 if (!m_iodrv
->OnSetupDriver(*buf
, wxSND_OUTPUT
))
79 // Find the first free (at least partly free) output buffer
80 ptr
= FindFreeBuffer(m_lstoptrs
, m_maxoq
);
85 // Find the end of the buffer
86 raw_buf
= ptr
->data
+ ptr
->ptr
;
87 rawbuf_size
= ptr
->size
- ptr
->ptr
;
90 buf
->OnNeedOutputData(raw_buf
, rawbuf_size
);
92 // No data to fill the buffer: dequeue the current wxSndBuffer
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 ptr
->ptr
+= rawbuf_size
;
106 // Output buffer full: send it to the driver
107 if (ptr
->ptr
== ptr
->size
) {
108 ptr
->state
= wxBUFFER_FFILLED
;
109 OnBufferFilled(ptr
, wxSND_OUTPUT
);
114 bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer
*buf
)
118 wxUint32 rawbuf_size
;
120 if (!m_iodrv
->OnSetupDriver(*buf
, wxSND_INPUT
))
124 ptr
= FindFreeBuffer(m_lstiptrs
, m_maxiq
);
128 raw_buf
= ptr
->data
+ ptr
->ptr
;
129 rawbuf_size
= ptr
->size
- ptr
->ptr
;
131 rawbuf_size
= (buf
->Available() < rawbuf_size
) ? buf
->Available() : rawbuf_size
;
135 if (buf
->IsNotSet(wxSND_KEEPQUEUED
)) {
136 buf
->Set(wxSND_UNQUEUEING
);
137 m_iodrv
->m_buffers
.DeleteObject(buf
);
140 // Get data now when there isn't anymore buffer in the queue
141 if (!LastBuffer() && ptr
->ptr
) {
142 ptr
->state
= wxBUFFER_FFILLED
;
143 if (!OnBufferFilled(ptr
, wxSND_INPUT
))
148 ptr
->buffers
->Append(buf
);
150 ptr
->ptr
+= rawbuf_size
;
152 // Input buffer full => get data
153 if (ptr
->ptr
== ptr
->size
) {
154 ptr
->state
= wxBUFFER_FFILLED
;
155 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();
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
);