]>
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 // Normally, these three functions could be called only once.
85 codec
->SetOutStream(ptr
->sndbuf
);
86 codec
->InitIO(m_drvformat
);
87 codec
->InitMode(wxSoundCodec::DECODING
);
92 // No data to fill the buffer: dequeue the current wxSndBuffer
93 if (codec
->Available() == 0) {
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() == 0) {
106 ptr
->state
= wxBUFFER_FFILLED
;
107 OnBufferFilled(ptr
, wxSND_OUTPUT
);
112 bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer
*buf
)
117 if (!m_iodrv
->OnSetupDriver(*buf
, wxSND_INPUT
))
121 ptr
= FindFreeBuffer(m_lstiptrs
, m_maxiq
);
125 if (buf
->Available() == 0) {
126 if (buf
->IsNotSet(wxSND_KEEPQUEUED
)) {
127 buf
->Set(wxSND_UNQUEUEING
);
128 m_iodrv
->m_buffers
.DeleteObject(buf
);
131 if (LastBuffer() == NULL
&& ptr
->sndbuf
->GetIntPosition() != 0) {
132 ptr
->state
= wxBUFFER_FFILLED
;
133 if (!OnBufferFilled(ptr
, wxSND_INPUT
))
138 ptr
->buffers
->Append(buf
);
140 // TODO: Add an "incrementer" in wxStreamBuffer.
141 inc
= (buf
->Available() < ptr
->sndbuf
->GetDataLeft()) ?
142 buf
->Available() : ptr
->sndbuf
->GetDataLeft();
144 ptr
->sndbuf
->SetIntPosition(ptr
->sndbuf
->GetIntPosition() + inc
);
146 if (ptr
->sndbuf
->GetDataLeft() == 0) {
147 ptr
->state
= wxBUFFER_FFILLED
;
148 if (!OnBufferFilled(ptr
, wxSND_INPUT
))
156 void wxFragmentBuffer::FreeBufToFree(bool force
)
159 // Garbage collecting
164 for (i
=0;i
<m_maxoq
;i
++) {
165 if ((m_lstoptrs
[i
].state
== wxBUFFER_TOFREE
) ||
166 (force
&& m_lstoptrs
[i
].state
== wxBUFFER_FFILLED
))
167 ClearBuffer(&m_lstoptrs
[i
]);
170 for (i
=0;i
<m_maxiq
;i
++) {
171 if ((m_lstiptrs
[i
].state
== wxBUFFER_TOFREE
) ||
172 (force
&& m_lstoptrs
[i
].state
== wxBUFFER_FFILLED
))
173 ClearBuffer(&m_lstiptrs
[i
]);
179 void wxFragmentBuffer::ClearBuffer(wxFragBufPtr
*ptr
)
185 node
= ptr
->buffers
->First();
188 buf
= (wxSndBuffer
*)node
->Data();
190 if (buf
->GetMode() == wxSND_OUTPUT
) {
191 buf
->OnBufferOutFinished();
193 codec
= buf
->GetCurrentCodec();
195 // Normally, these three functions could be called only once.
196 codec
->SetInStream(ptr
->sndbuf
);
197 codec
->InitIO(m_drvformat
);
198 codec
->InitMode(wxSoundCodec::ENCODING
);
200 // As there is an "auto-stopper" in the codec, we don't worry ...
204 if (buf
->IsSet(wxSND_UNQUEUEING
))
205 buf
->Clear(wxSND_UNQUEUEING
| wxSND_BUFLOCKED
| wxSND_BUFREADY
);
208 node
= ptr
->buffers
->First();
211 ptr
->sndbuf
->ResetBuffer();
212 ptr
->state
= wxBUFFER_FREE
;
215 void wxFragmentBuffer::OnBufferFinished(wxFragBufPtr
*ptr
)
222 ptr
->state
= wxBUFFER_TOFREE
;
228 // Clean up the old buffer.
229 if (ptr
&& ptr
->state
!= wxBUFFER_FREE
)
232 // Garbage collecting ...
236 // If we are queueing, return immediately.
242 node
= m_iodrv
->m_buffers
.First();
244 while (node
&& ret
) {
245 buf
= (wxSndBuffer
*)node
->Data();
250 // Stop request on this buffer.
251 if (buf
->IsSet(wxSND_BUFSTOP
)) {
252 buf
->Clear(wxSND_BUFSTOP
);
255 switch (buf
->GetMode()) {
257 ret
= NotifyOutputBuffer(buf
);
260 ret
= NotifyInputBuffer(buf
);
264 // ret = NotifyDuplexBuffer(buf);