]>
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_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
)
72 wxSoundCodec
*codec
= buf
->GetCurrentCodec();
74 if (!m_iodrv
->OnSetupDriver(*buf
, wxSND_OUTPUT
))
78 // Find the first free (at least partly free) output buffer
79 ptr
= FindFreeBuffer(m_lstoptrs
, m_maxoq
);
84 codec
->SetOutStream(ptr
->sndbuf
);
85 codec
->InitIO(m_drvformat
);
90 // No data to fill the buffer: dequeue the current wxSndBuffer
91 if (codec
->Available() == 0) {
92 if (buf
->IsNotSet(wxSND_KEEPQUEUED
)) {
93 buf
->Set(wxSND_UNQUEUEING
);
94 m_iodrv
->m_buffers
.DeleteObject(buf
);
99 // Data: append it to the list
100 ptr
->buffers
->Append(buf
);
102 // Output buffer full: send it to the driver
103 if (ptr
->sndbuf
->GetDataLeft() == 0) {
104 ptr
->state
= wxBUFFER_FFILLED
;
105 OnBufferFilled(ptr
, wxSND_OUTPUT
);
110 bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer
*buf
)
115 if (!m_iodrv
->OnSetupDriver(*buf
, wxSND_INPUT
))
119 ptr
= FindFreeBuffer(m_lstiptrs
, m_maxiq
);
123 if (buf
->Available() == 0) {
124 if (buf
->IsNotSet(wxSND_KEEPQUEUED
)) {
125 buf
->Set(wxSND_UNQUEUEING
);
126 m_iodrv
->m_buffers
.DeleteObject(buf
);
129 if (LastBuffer() == NULL
&& ptr
->sndbuf
->GetIntPosition() != 0) {
130 ptr
->state
= wxBUFFER_FFILLED
;
131 if (!OnBufferFilled(ptr
, wxSND_INPUT
))
136 ptr
->buffers
->Append(buf
);
138 // TODO: Add an "incrementer" in wxStreamBuffer.
139 inc
= (buf
->Available() < ptr
->sndbuf
->GetDataLeft()) ?
140 buf
->Available() : ptr
->sndbuf
->GetDataLeft();
142 ptr
->sndbuf
->SetIntPosition(ptr
->sndbuf
->GetIntPosition() + inc
);
144 if (ptr
->sndbuf
->GetDataLeft() == 0) {
145 ptr
->state
= wxBUFFER_FFILLED
;
146 if (!OnBufferFilled(ptr
, wxSND_INPUT
))
154 void wxFragmentBuffer::FreeBufToFree(bool force
)
157 // Garbage collecting
162 for (i
=0;i
<m_maxoq
;i
++) {
163 if ((m_lstoptrs
[i
].state
== wxBUFFER_TOFREE
) ||
164 (force
&& m_lstoptrs
[i
].state
== wxBUFFER_FFILLED
))
165 ClearBuffer(&m_lstoptrs
[i
]);
168 for (i
=0;i
<m_maxiq
;i
++) {
169 if ((m_lstiptrs
[i
].state
== wxBUFFER_TOFREE
) ||
170 (force
&& m_lstoptrs
[i
].state
== wxBUFFER_FFILLED
))
171 ClearBuffer(&m_lstiptrs
[i
]);
177 void wxFragmentBuffer::ClearBuffer(wxFragBufPtr
*ptr
)
183 node
= ptr
->buffers
->First();
186 buf
= (wxSndBuffer
*)node
->Data();
188 if (buf
->GetMode() == wxSND_OUTPUT
) {
189 buf
->OnBufferOutFinished();
191 codec
= buf
->GetCurrentCodec();
193 codec
->SetInStream(ptr
->sndbuf
);
194 codec
->InitIO(m_drvformat
);
196 // As there is an "auto-stopper" in the codec, we don't worry ...
200 if (buf
->IsSet(wxSND_UNQUEUEING
))
201 buf
->Clear(wxSND_UNQUEUEING
| wxSND_BUFLOCKED
| wxSND_BUFREADY
);
204 node
= ptr
->buffers
->First();
207 ptr
->sndbuf
->ResetBuffer();
208 ptr
->state
= wxBUFFER_FREE
;
211 void wxFragmentBuffer::OnBufferFinished(wxFragBufPtr
*ptr
)
218 ptr
->state
= wxBUFFER_TOFREE
;
224 // Clean up the old buffer.
225 if (ptr
&& ptr
->state
!= wxBUFFER_FREE
)
228 // Garbage collecting ...
232 // If we are queueing, return immediately.
238 node
= m_iodrv
->m_buffers
.First();
240 while (node
&& ret
) {
241 buf
= (wxSndBuffer
*)node
->Data();
246 // Stop request on this buffer.
247 if (buf
->IsSet(wxSND_BUFSTOP
)) {
248 buf
->Clear(wxSND_BUFSTOP
);
251 if (buf
->GetMode() == wxSND_OUTPUT
)
252 ret
= NotifyOutputBuffer(buf
);
254 ret
= NotifyInputBuffer(buf
);