]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/mmedia/sndfile.cpp
Added info about versions for XFree86/OS2.
[wxWidgets.git] / contrib / src / mmedia / sndfile.cpp
1 // --------------------------------------------------------------------------
2 // Name: sndfile.cpp
3 // Purpose:
4 // Date: 08/11/1999
5 // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
6 // CVSID: $Id$
7 // --------------------------------------------------------------------------
8 #include <wx/wxprec.h>
9
10 #ifndef WX_PRECOMP
11 #include <wx/defs.h>
12 #include <wx/stream.h>
13 #endif
14
15 #include "wx/mmedia/sndbase.h"
16 #include "wx/mmedia/sndcodec.h"
17 #include "wx/mmedia/sndfile.h"
18 #include "wx/mmedia/sndcpcm.h"
19 #include "wx/mmedia/sndulaw.h"
20 #include "wx/mmedia/sndg72x.h"
21
22 // --------------------------------------------------------------------------
23 // Sound codec router
24 // A very important class: it ensures that everybody is satisfied.
25 // It is supposed to create as many codec as it is necessary to transform
26 // a signal in a specific format in an another.
27 // --------------------------------------------------------------------------
28 wxSoundRouterStream::wxSoundRouterStream(wxSoundStream& sndio)
29 : wxSoundStreamCodec(sndio)
30 {
31 m_router = NULL;
32 }
33
34 wxSoundRouterStream::~wxSoundRouterStream()
35 {
36 if (m_router)
37 delete m_router;
38 }
39
40 // --------------------------------------------------------------------------
41 // Read(void *buffer, wxUint32 len): It reads data synchronously. See sndbase.h
42 // for possible errors and behaviours ...
43 // --------------------------------------------------------------------------
44 wxSoundStream& wxSoundRouterStream::Read(void *buffer, wxUint32 len)
45 {
46 if (m_router) {
47 m_router->Read(buffer, len);
48 m_snderror = m_router->GetError();
49 m_lastcount = m_router->GetLastAccess();
50 } else {
51 m_sndio->Read(buffer, len);
52 m_snderror = m_sndio->GetError();
53 m_lastcount = m_sndio->GetLastAccess();
54 }
55 return *this;
56 }
57
58 // --------------------------------------------------------------------------
59 // Write(const void *buffer, wxUint32 len): It writes data synchronously
60 // --------------------------------------------------------------------------
61 wxSoundStream& wxSoundRouterStream::Write(const void *buffer, wxUint32 len)
62 {
63 if (m_router) {
64 m_router->Write(buffer, len);
65 m_snderror = m_router->GetError();
66 m_lastcount = m_router->GetLastAccess();
67 } else {
68 m_sndio->Write(buffer, len);
69 m_snderror = m_sndio->GetError();
70 m_lastcount = m_sndio->GetLastAccess();
71 }
72 return *this;
73 }
74
75 // --------------------------------------------------------------------------
76 // SetSoundFormat(const wxSoundFormatBase& format) first tries to setup the
77 // sound driver using the specified format. If this fails, it uses personnal
78 // codec converters: for the moment there is a PCM converter (PCM to PCM:
79 // with optional resampling, ...), an ULAW converter (ULAW to PCM), a G72X
80 // converter (G72X to PCM). If nothing works, it returns FALSE.
81 // --------------------------------------------------------------------------
82 bool wxSoundRouterStream::SetSoundFormat(const wxSoundFormatBase& format)
83 {
84 if (m_router)
85 delete m_router;
86
87 // First, we try to setup the sound device
88 if (m_sndio->SetSoundFormat(format)) {
89 // We are lucky, it is working.
90 wxSoundStream::SetSoundFormat(m_sndio->GetSoundFormat());
91 return TRUE;
92 }
93
94 switch(format.GetType()) {
95 case wxSOUND_NOFORMAT:
96 return FALSE;
97 case wxSOUND_PCM:
98 m_router = new wxSoundStreamPcm(*m_sndio);
99 m_router->SetSoundFormat(format);
100 break;
101 case wxSOUND_ULAW:
102 m_router = new wxSoundStreamUlaw(*m_sndio);
103 m_router->SetSoundFormat(format);
104 break;
105 case wxSOUND_G72X:
106 m_router = new wxSoundStreamG72X(*m_sndio);
107 m_router->SetSoundFormat(format);
108 break;
109 default:
110 return FALSE;
111
112 }
113 wxSoundStream::SetSoundFormat(m_router->GetSoundFormat());
114 return TRUE;
115 }
116
117 // --------------------------------------------------------------------------
118 // GetBestSize() returns the specific best buffer size a sound driver
119 // can manage. It means that it will be easier for it to manage the buffer
120 // and so it will be faster and in some case more accurate for real-time event.
121 // --------------------------------------------------------------------------
122 wxUint32 wxSoundRouterStream::GetBestSize() const
123 {
124 if (m_router)
125 return m_router->GetBestSize();
126 else
127 return m_sndio->GetBestSize();
128 }
129
130 // --------------------------------------------------------------------------
131 // StartProduction(int evt). See sndbase.h
132 // --------------------------------------------------------------------------
133 bool wxSoundRouterStream::StartProduction(int evt)
134 {
135 if (!m_router) {
136 if (m_sndio->StartProduction(evt))
137 return TRUE;
138
139 m_snderror = m_sndio->GetError();
140 m_lastcount = m_sndio->GetLastAccess();
141 return FALSE;
142 }
143
144 if (m_router->StartProduction(evt))
145 return TRUE;
146
147 m_snderror = m_router->GetError();
148 m_lastcount = m_router->GetLastAccess();
149 return FALSE;
150 }
151
152 // --------------------------------------------------------------------------
153 // StopProduction(). See sndbase.h
154 // --------------------------------------------------------------------------
155 bool wxSoundRouterStream::StopProduction()
156 {
157 if (!m_router) {
158 if (m_sndio->StopProduction())
159 return TRUE;
160
161 m_snderror = m_sndio->GetError();
162 m_lastcount = m_sndio->GetLastAccess();
163 return FALSE;
164 }
165
166 if (m_router->StopProduction())
167 return TRUE;
168
169 m_snderror = m_router->GetError();
170 m_lastcount = m_router->GetLastAccess();
171 return FALSE;
172 }
173
174 // --------------------------------------------------------------------------
175 // wxSoundFileStream: generic reader
176 // --------------------------------------------------------------------------
177
178 wxSoundFileStream::wxSoundFileStream(wxInputStream& stream,
179 wxSoundStream& io_sound)
180 : m_codec(io_sound), m_sndio(&io_sound),
181 m_input(&stream), m_output(NULL), m_state(wxSOUND_FILE_STOPPED)
182 {
183 m_length = 0;
184 m_bytes_left = 0;
185 m_prepared = FALSE;
186 }
187
188 wxSoundFileStream::wxSoundFileStream(wxOutputStream& stream,
189 wxSoundStream& io_sound)
190 : m_codec(io_sound), m_sndio(&io_sound),
191 m_input(NULL), m_output(&stream), m_state(wxSOUND_FILE_STOPPED)
192 {
193 m_length = 0;
194 m_bytes_left = 0;
195 m_prepared = FALSE;
196 }
197
198 wxSoundFileStream::~wxSoundFileStream()
199 {
200 if (m_state != wxSOUND_FILE_STOPPED)
201 Stop();
202 }
203
204 bool wxSoundFileStream::Play()
205 {
206 if (m_state != wxSOUND_FILE_STOPPED)
207 return FALSE;
208
209 if (!m_prepared)
210 if (!PrepareToPlay())
211 return FALSE;
212
213 m_state = wxSOUND_FILE_PLAYING;
214
215 if (!StartProduction(wxSOUND_OUTPUT))
216 return FALSE;
217
218 return TRUE;
219 }
220
221 bool wxSoundFileStream::Record(wxUint32 time)
222 {
223 if (m_state != wxSOUND_FILE_STOPPED)
224 return FALSE;
225
226 if (!PrepareToRecord(time))
227 return FALSE;
228
229 FinishPreparation(m_sndformat->GetBytesFromTime(time));
230
231 m_state = wxSOUND_FILE_RECORDING;
232 if (!StartProduction(wxSOUND_INPUT))
233 return FALSE;
234
235 return TRUE;
236 }
237
238 bool wxSoundFileStream::Stop()
239 {
240 if (m_state == wxSOUND_FILE_STOPPED)
241 return FALSE;
242
243 if (!StopProduction())
244 return FALSE;
245
246 m_prepared = FALSE;
247
248 if (m_state == wxSOUND_FILE_RECORDING)
249 if (!FinishRecording()) {
250 m_state = wxSOUND_FILE_STOPPED;
251 return FALSE;
252 }
253
254 if (m_input)
255 m_input->SeekI(0, wxFromStart);
256
257 if (m_output)
258 m_output->SeekO(0, wxFromStart);
259
260 m_state = wxSOUND_FILE_STOPPED;
261 return TRUE;
262 }
263
264 bool wxSoundFileStream::Pause()
265 {
266 if (m_state == wxSOUND_FILE_PAUSED || m_state == wxSOUND_FILE_STOPPED)
267 return FALSE;
268
269 if (!StopProduction())
270 return FALSE;
271
272 m_oldstate = m_state;
273 m_state = wxSOUND_FILE_PAUSED;
274 return TRUE;
275 }
276
277 bool wxSoundFileStream::Resume()
278 {
279 if (m_state == wxSOUND_FILE_PLAYING || m_state == wxSOUND_FILE_RECORDING ||
280 m_state == wxSOUND_FILE_STOPPED)
281 return FALSE;
282
283 if (!StartProduction( (m_oldstate == wxSOUND_FILE_PLAYING) ?
284 wxSOUND_OUTPUT : wxSOUND_INPUT))
285 return FALSE;
286
287 m_state = m_oldstate;
288
289 return TRUE;
290 }
291
292 wxSoundStream& wxSoundFileStream::Read(void *buffer, wxUint32 len)
293 {
294 if (!m_prepared || m_state != wxSOUND_FILE_PLAYING) {
295 m_snderror = wxSOUND_NOTSTARTED;
296 m_lastcount = 0;
297 return *this;
298 }
299 m_lastcount = GetData(buffer, len);
300 return *this;
301 }
302
303 wxSoundStream& wxSoundFileStream::Write(const void *buffer, wxUint32 len)
304 {
305 if (!m_prepared || m_state != wxSOUND_FILE_RECORDING) {
306 m_snderror = wxSOUND_NOTSTARTED;
307 m_lastcount = 0;
308 return *this;
309 }
310 m_lastcount = PutData(buffer, len);
311 return *this;
312 }
313
314 bool wxSoundFileStream::StartProduction(int evt)
315 {
316 m_sndio->SetEventHandler(this);
317
318 if (!m_codec.StartProduction(evt))
319 return FALSE;
320
321 return TRUE;
322 }
323
324 bool wxSoundFileStream::StopProduction()
325 {
326 return m_codec.StopProduction();
327 }
328
329 void wxSoundFileStream::FinishPreparation(wxUint32 len)
330 {
331 m_bytes_left = m_length = len;
332 m_prepared = TRUE;
333 }
334
335 wxString wxSoundFileStream::GetCodecName() const
336 {
337 return wxString(wxT("wxSoundFileStream base codec"));
338 }
339
340 wxUint32 wxSoundFileStream::GetLength()
341 {
342 if (m_input && !m_prepared && GetError() == wxSOUND_NOERROR)
343 return (PrepareToPlay()) ? m_length : 0;
344
345 return m_length;
346 }
347
348 wxUint32 wxSoundFileStream::GetPosition()
349 {
350 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERROR)
351 PrepareToPlay();
352
353 return m_length-m_bytes_left;
354 }
355
356 wxUint32 wxSoundFileStream::SetPosition(wxUint32 new_position)
357 {
358 if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERROR)
359 PrepareToPlay();
360
361 if (!m_prepared)
362 return 0;
363
364 if (!RepositionStream(new_position))
365 return m_length-m_bytes_left;
366
367 if (new_position >= m_length) {
368 m_bytes_left = 0;
369 return m_length;
370 }
371
372 m_bytes_left = m_length-new_position;
373 return new_position;
374 }
375
376 void wxSoundFileStream::OnSoundEvent(int evt)
377 {
378 wxUint32 len = m_codec.GetBestSize();
379 char *buffer;
380
381 buffer = new char[len];
382 wxSoundStream::OnSoundEvent(evt);
383
384 while (!m_sndio->QueueFilled()) {
385 switch(evt) {
386 case wxSOUND_INPUT:
387 if (len > m_bytes_left)
388 len = m_bytes_left;
389
390 len = m_codec.Read(buffer, len).GetLastAccess();
391 PutData(buffer, len);
392 m_bytes_left -= len;
393 if (m_bytes_left == 0) {
394 Stop();
395 delete[] buffer;
396 return;
397 }
398 break;
399 case wxSOUND_OUTPUT:
400 if (len > m_bytes_left)
401 len = m_bytes_left;
402
403 len = GetData(buffer, len);
404 m_bytes_left -= len;
405 if (m_bytes_left == 0) {
406 Stop();
407 delete[] buffer;
408 return;
409 }
410 m_codec.Write(buffer, len);
411 break;
412 }
413 }
414 delete[] buffer;
415 }
416
417 bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)
418 {
419 wxSoundStream::SetSoundFormat(format);
420 return m_codec.SetSoundFormat(format);
421 }