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