]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia/sndfrag.cpp
1. Parser improvements
[wxWidgets.git] / utils / wxMMedia / sndfrag.cpp
CommitLineData
4d6306eb
GL
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
25wxFragmentBuffer::wxFragmentBuffer(wxSound& io_drv)
26 : m_iodrv(&io_drv), m_maxoq(0), m_maxiq(0),
9fc0fe37 27 m_lstoptrs(NULL), m_lstiptrs(NULL),
4d6306eb
GL
28 m_buf2free(FALSE), m_dontq(FALSE), m_freeing(FALSE)
29{
30}
31
32wxFragmentBuffer::~wxFragmentBuffer()
33{
34}
35
36void 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
55wxFragmentBuffer::wxFragBufPtr *wxFragmentBuffer::FindFreeBuffer(
9fc0fe37 56 wxFragBufPtr *list, wxUint8 max_queue)
4d6306eb
GL
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
69bool wxFragmentBuffer::NotifyOutputBuffer(wxSndBuffer *buf)
70{
71 wxFragBufPtr *ptr;
926c550d 72 wxSoundCodec *codec = buf->GetCurrentCodec();
4d6306eb
GL
73
74 if (!m_iodrv->OnSetupDriver(*buf, wxSND_OUTPUT))
75 return FALSE;
76
77 while (1) {
78 // Find the first free (at least partly free) output buffer
79 ptr = FindFreeBuffer(m_lstoptrs, m_maxoq);
80 // No free : go out !
9fc0fe37 81 if (ptr == NULL)
4d6306eb
GL
82 return FALSE;
83
926c550d
GL
84 codec->SetOutStream(ptr->sndbuf);
85 codec->InitIO(m_drvformat);
4d6306eb
GL
86
87 // Fill it up
926c550d 88 codec->Decode();
4d6306eb
GL
89
90 // No data to fill the buffer: dequeue the current wxSndBuffer
9fc0fe37 91 if (codec->Available() == 0) {
4d6306eb
GL
92 if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
93 buf->Set(wxSND_UNQUEUEING);
94 m_iodrv->m_buffers.DeleteObject(buf);
95 }
96 return TRUE;
97 }
98
99 // Data: append it to the list
100 ptr->buffers->Append(buf);
101
4d6306eb 102 // Output buffer full: send it to the driver
9fc0fe37 103 if (ptr->sndbuf->GetDataLeft() == 0) {
4d6306eb
GL
104 ptr->state = wxBUFFER_FFILLED;
105 OnBufferFilled(ptr, wxSND_OUTPUT);
106 }
107 }
108}
109
110bool wxFragmentBuffer::NotifyInputBuffer(wxSndBuffer *buf)
111{
9fc0fe37
GL
112 wxFragBufPtr *ptr;
113 size_t inc;
926c550d 114
9fc0fe37
GL
115 if (!m_iodrv->OnSetupDriver(*buf, wxSND_INPUT))
116 return FALSE;
117
118 while (1) {
119 ptr = FindFreeBuffer(m_lstiptrs, m_maxiq);
120 if (ptr == NULL)
4d6306eb 121 return FALSE;
4d6306eb 122
9fc0fe37 123 if (buf->Available() == 0) {
4d6306eb
GL
124 if (buf->IsNotSet(wxSND_KEEPQUEUED)) {
125 buf->Set(wxSND_UNQUEUEING);
126 m_iodrv->m_buffers.DeleteObject(buf);
127 }
128
9fc0fe37 129 if (LastBuffer() == NULL && ptr->sndbuf->GetIntPosition() != 0) {
4d6306eb
GL
130 ptr->state = wxBUFFER_FFILLED;
131 if (!OnBufferFilled(ptr, wxSND_INPUT))
132 return FALSE;
133 }
134 return TRUE;
135 }
136 ptr->buffers->Append(buf);
137
9fc0fe37
GL
138 // TODO: Add an "incrementer" in wxStreamBuffer.
139 inc = (buf->Available() < ptr->sndbuf->GetDataLeft()) ?
140 buf->Available() : ptr->sndbuf->GetDataLeft();
4d6306eb 141
9fc0fe37 142 ptr->sndbuf->SetIntPosition(ptr->sndbuf->GetIntPosition() + inc);
926c550d 143
9fc0fe37 144 if (ptr->sndbuf->GetDataLeft() == 0) {
4d6306eb
GL
145 ptr->state = wxBUFFER_FFILLED;
146 if (!OnBufferFilled(ptr, wxSND_INPUT))
147 return FALSE;
148 }
149 }
926c550d 150
4d6306eb
GL
151 return TRUE;
152}
153
154void wxFragmentBuffer::FreeBufToFree(bool force)
155{
156 wxUint8 i;
157 // Garbage collecting
158
159 m_dontq = TRUE;
160 m_buf2free = FALSE;
161
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]);
166 }
167
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]);
172 }
173
174 m_dontq = FALSE;
175}
176
177void wxFragmentBuffer::ClearBuffer(wxFragBufPtr *ptr)
178{
179 wxNode *node;
180 wxSndBuffer *buf;
9fc0fe37 181 wxSoundCodec *codec;
4d6306eb
GL
182
183 node = ptr->buffers->First();
184
185 while (node) {
186 buf = (wxSndBuffer *)node->Data();
187
188 if (buf->GetMode() == wxSND_OUTPUT) {
189 buf->OnBufferOutFinished();
190 } else {
9fc0fe37
GL
191 codec = buf->GetCurrentCodec();
192
193 codec->SetInStream(ptr->sndbuf);
194 codec->InitIO(m_drvformat);
4d6306eb 195
9fc0fe37
GL
196 // As there is an "auto-stopper" in the codec, we don't worry ...
197 codec->Encode();
4d6306eb
GL
198 }
199
200 if (buf->IsSet(wxSND_UNQUEUEING))
201 buf->Clear(wxSND_UNQUEUEING | wxSND_BUFLOCKED | wxSND_BUFREADY);
202
203 delete node;
204 node = ptr->buffers->First();
205 }
206
926c550d 207 ptr->sndbuf->ResetBuffer();
4d6306eb
GL
208 ptr->state = wxBUFFER_FREE;
209}
210
211void wxFragmentBuffer::OnBufferFinished(wxFragBufPtr *ptr)
212{
213 wxNode *node;
214 wxSndBuffer *buf;
215 bool ret = TRUE;
216
217 if (m_freeing) {
218 ptr->state = wxBUFFER_TOFREE;
219 m_buf2free = TRUE;
220 return;
221 }
222 m_freeing = TRUE;
223
224 // Clean up the old buffer.
225 if (ptr && ptr->state != wxBUFFER_FREE)
226 ClearBuffer(ptr);
227
228 // Garbage collecting ...
229 if (m_buf2free)
230 FreeBufToFree();
231
232 // If we are queueing, return immediately.
233 if (m_dontq) {
234 m_freeing = FALSE;
235 return;
236 }
237
238 node = m_iodrv->m_buffers.First();
239
240 while (node && ret) {
241 buf = (wxSndBuffer *)node->Data();
242 node = node->Next();
243
244 buf->HardLock();
245
246 // Stop request on this buffer.
247 if (buf->IsSet(wxSND_BUFSTOP)) {
248 buf->Clear(wxSND_BUFSTOP);
249 continue;
250 }
251 if (buf->GetMode() == wxSND_OUTPUT)
252 ret = NotifyOutputBuffer(buf);
253 else
254 ret = NotifyInputBuffer(buf);
255
256 buf->HardUnlock();
257 }
258 m_freeing = FALSE;
259}