]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/mmedia/sndfile.cpp
wxHtmlHelpController made compatible with other controllers
[wxWidgets.git] / contrib / src / mmedia / sndfile.cpp
CommitLineData
e8482f24
GL
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// --------------------------------------------------------------------------
28wxSoundRouterStream::wxSoundRouterStream(wxSoundStream& sndio)
29 : wxSoundStreamCodec(sndio)
30{
31 m_router = NULL;
32}
33
34wxSoundRouterStream::~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// --------------------------------------------------------------------------
44wxSoundStream& 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// --------------------------------------------------------------------------
61wxSoundStream& 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// --------------------------------------------------------------------------
82bool 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// --------------------------------------------------------------------------
122wxUint32 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// --------------------------------------------------------------------------
133bool 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// --------------------------------------------------------------------------
155bool 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
178wxSoundFileStream::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
188wxSoundFileStream::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
198wxSoundFileStream::~wxSoundFileStream()
199{
200 if (m_state != wxSOUND_FILE_STOPPED)
201 Stop();
202}
203
204bool 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
221bool 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
238bool 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
264bool 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
277bool 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
292wxSoundStream& 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
303wxSoundStream& 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
314bool 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
324bool wxSoundFileStream::StopProduction()
325{
326 return m_codec.StopProduction();
327}
328
329void wxSoundFileStream::FinishPreparation(wxUint32 len)
330{
331 m_bytes_left = m_length = len;
332 m_prepared = TRUE;
333}
334
335wxString wxSoundFileStream::GetCodecName() const
336{
337 return wxString(wxT("wxSoundFileStream base codec"));
338}
339
340wxUint32 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
348wxUint32 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
356wxUint32 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
376void 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
417bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)
418{
419 wxSoundStream::SetSoundFormat(format);
420 return m_codec.SetSoundFormat(format);
421}