]> git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia/sndfrag.cpp
file I forgot to commit last time (wxCritSection)
[wxWidgets.git] / utils / wxMMedia / sndfrag.cpp
1 ////////////////////////////////////////////////////////////////////////////////
2 // Name: sndfrag.cpp
3 // Purpose: wxMMedia
4 // Author: Guilhem Lavaux
5 // Created: 1997
6 // Updated: 1998
7 // Copyright: (C) 1997, 1998, Guilhem Lavaux
8 // License: wxWindows license
9 ////////////////////////////////////////////////////////////////////////////////
10 #ifdef __GNUG__
11 #pragma implementation "sndfrag.h"
12 #endif
13 #include <stdio.h>
14 #ifdef WX_PRECOMP
15 #include "wx_prec.h"
16 #else
17 #include "wx/wx.h"
18 #endif
19 #include "sndfrag.h"
20
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24
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)
29 {
30 }
31
32 wxFragmentBuffer::~wxFragmentBuffer()
33 {
34 }
35
36 void wxFragmentBuffer::AbortBuffer(wxSndBuffer *buf)
37 {
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.
42 ;
43 m_lstoptrs[i].state = wxBUFFER_TOFREE;
44 }
45
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)
49 // Do something.
50 ;
51 m_lstiptrs[i].state = wxBUFFER_TOFREE;
52 }
53 }
54
55 wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer(
56 xFragBufPtr *list, wxUint8 max_queue)
57 {
58 if (!list)
59 return NULL;
60
61 for (wxUint8 i=0;i<max_queue;i++) {
62 if (list[i].state == wxBUFFER_FREE)
63 return &list[i];
64 }
65
66 return NULL;
67 }
68
69 bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf)
70 {
71 wxFragBufPtr *ptr;
72 char *raw_buf;
73 wxUint32 rawbuf_size;
74 wxSoundCodec *codec = buf->GetCurrentCodec();
75
76 if (!m_iodrv->OnSetupDriver(*buf, wxSND_OUTPUT))
77 return FALSE;
78
79 while (1) {
80 // Find the first free (at least partly free) output buffer
81 ptr = FindFreeBuffer(m_lstoptrs, m_maxoq);
82 // No free : go out !
83 if (!ptr)
84 return FALSE;
85
86 codec->SetOutStream(ptr->sndbuf);
87 codec->InitIO(m_drvformat);
88
89 // Fill it up
90 codec->Decode();
91
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);
97 }
98 return TRUE;
99 }
100
101 // Data: append it to the list
102 ptr->buffers->Append(buf);
103
104 // Output buffer full: send it to the driver
105 if (ptr->sndbuf->GetDataLeft()) {
106 ptr->state = wxBUFFER_FFILLED;
107 OnBufferFilled(ptr, wxSND_OUTPUT);
108 }
109 }
110 }
111
112 bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer *buf)
113 {
114 /*
115 wxFragBufPtr *ptr;
116 char *raw_buf;
117 wxUint32 rawbuf_size;
118
119 if (!m_iodrv->OnSetupDriver(*buf, wxSND_INPUT))
120 return FALSE;
121
122 while (1) {
123 ptr = FindFreeBuffer(m_lstiptrs, m_maxiq);
124 if (!ptr)
125 return FALSE;
126
127 raw_buf = ptr->data + ptr->ptr;
128 rawbuf_size = ptr->size - ptr->ptr;
129
130 rawbuf_size = (buf->Available() < rawbuf_size) ? buf->Available() : rawbuf_size;
131
132 if (!rawbuf_size) {
133
134 if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
135 buf->Set(wxSND_UNQUEUEING);
136 m_iodrv->m_buffers.DeleteObject(buf);
137 }
138
139 if (!LastBuffer() && ptr->ptr) {
140 ptr->state = wxBUFFER_FFILLED;
141 if (!OnBufferFilled(ptr, wxSND_INPUT))
142 return FALSE;
143 }
144 return TRUE;
145 }
146 ptr->buffers->Append(buf);
147
148 ptr->ptr += rawbuf_size;
149
150
151 if (ptr->ptr == ptr->size) {
152 ptr->state = wxBUFFER_FFILLED;
153 if (!OnBufferFilled(ptr, wxSND_INPUT))
154 return FALSE;
155 }
156 }
157 */
158
159 return TRUE;
160 }
161
162 void wxFragmentBuffer::FreeBufToFree(bool force)
163 {
164 wxUint8 i;
165 // Garbage collecting
166
167 m_dontq = TRUE;
168 m_buf2free = FALSE;
169
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]);
174 }
175
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]);
180 }
181
182 m_dontq = FALSE;
183 }
184
185 void wxFragmentBuffer::ClearBuffer(wxFragBufPtr *ptr)
186 {
187 wxNode *node;
188 wxSndBuffer *buf;
189 char *data;
190 wxUint32 size, data_read;
191
192 data = ptr->data;
193 size = ptr->size;
194
195 node = ptr->buffers->First();
196
197 while (node) {
198 buf = (wxSndBuffer *)node->Data();
199
200 if (buf->GetMode() == wxSND_OUTPUT) {
201 buf->OnBufferOutFinished();
202 } else {
203 data_read = buf->OnBufferInFinished(data, size);
204
205 data += data_read;
206 size -= data_read;
207 }
208
209 if (buf->IsSet(wxSND_UNQUEUEING))
210 buf->Clear(wxSND_UNQUEUEING | wxSND_BUFLOCKED | wxSND_BUFREADY);
211
212 delete node;
213 node = ptr->buffers->First();
214 }
215
216 ptr->sndbuf->ResetBuffer();
217 ptr->state = wxBUFFER_FREE;
218 }
219
220 void wxFragmentBuffer::OnBufferFinished(wxFragBufPtr *ptr)
221 {
222 wxNode *node;
223 wxSndBuffer *buf;
224 bool ret = TRUE;
225
226 if (m_freeing) {
227 ptr->state = wxBUFFER_TOFREE;
228 m_buf2free = TRUE;
229 return;
230 }
231 m_freeing = TRUE;
232
233 // Clean up the old buffer.
234 if (ptr && ptr->state != wxBUFFER_FREE)
235 ClearBuffer(ptr);
236
237 // Garbage collecting ...
238 if (m_buf2free)
239 FreeBufToFree();
240
241 // If we are queueing, return immediately.
242 if (m_dontq) {
243 m_freeing = FALSE;
244 return;
245 }
246
247 node = m_iodrv->m_buffers.First();
248
249 while (node && ret) {
250 buf = (wxSndBuffer *)node->Data();
251 node = node->Next();
252
253 buf->HardLock();
254
255 // Stop request on this buffer.
256 if (buf->IsSet(wxSND_BUFSTOP)) {
257 buf->Clear(wxSND_BUFSTOP);
258 continue;
259 }
260 if (buf->GetMode() == wxSND_OUTPUT)
261 ret = NotifyOutputBuffer(buf);
262 else
263 ret = NotifyInputBuffer(buf);
264
265 buf->HardUnlock();
266 }
267 m_freeing = FALSE;
268 }