]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/mmedia/sndfile.cpp
Aliases for [G|S]etCaretLineBack
[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$
58b9c9ba 7// wxWindows licence
e8482f24 8// --------------------------------------------------------------------------
92a19c2e 9#include "wx/wxprec.h"
e8482f24
GL
10
11#ifndef WX_PRECOMP
c3be59bc 12#include "wx/stream.h"
e8482f24
GL
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"
c42b1de6 21#include "wx/mmedia/sndmsad.h"
e8482f24
GL
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
dea7e44a 81// converter (G72X to PCM). If nothing works, it returns false.
e8482f24
GL
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());
dea7e44a 92 return true;
e8482f24
GL
93 }
94
95 switch(format.GetType()) {
96 case wxSOUND_NOFORMAT:
dea7e44a 97 return false;
e8482f24
GL
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;
c42b1de6
GL
110 case wxSOUND_MSADPCM:
111 m_router = new wxSoundStreamMSAdpcm(*m_sndio);
112 m_router->SetSoundFormat(format);
113 break;
e8482f24 114 default:
dea7e44a 115 return false;
e8482f24
GL
116
117 }
118 wxSoundStream::SetSoundFormat(m_router->GetSoundFormat());
dea7e44a 119 return true;
e8482f24
GL
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))
dea7e44a 142 return true;
e8482f24
GL
143
144 m_snderror = m_sndio->GetError();
145 m_lastcount = m_sndio->GetLastAccess();
dea7e44a 146 return false;
e8482f24
GL
147 }
148
149 if (m_router->StartProduction(evt))
dea7e44a 150 return true;
e8482f24
GL
151
152 m_snderror = m_router->GetError();
153 m_lastcount = m_router->GetLastAccess();
dea7e44a 154 return false;
e8482f24
GL
155}
156
157// --------------------------------------------------------------------------
158// StopProduction(). See sndbase.h
159// --------------------------------------------------------------------------
160bool wxSoundRouterStream::StopProduction()
161{
162 if (!m_router) {
163 if (m_sndio->StopProduction())
dea7e44a 164 return true;
e8482f24
GL
165
166 m_snderror = m_sndio->GetError();
167 m_lastcount = m_sndio->GetLastAccess();
dea7e44a 168 return false;
e8482f24
GL
169 }
170
171 if (m_router->StopProduction())
dea7e44a 172 return true;
e8482f24
GL
173
174 m_snderror = m_router->GetError();
175 m_lastcount = m_router->GetLastAccess();
dea7e44a 176 return false;
e8482f24
GL
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;
dea7e44a 190 m_prepared = false;
e8482f24
GL
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;
dea7e44a 200 m_prepared = false;
e8482f24
GL
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)
dea7e44a 212 return false;
e8482f24
GL
213
214 if (!m_prepared)
215 if (!PrepareToPlay())
dea7e44a 216 return false;
e8482f24
GL
217
218 m_state = wxSOUND_FILE_PLAYING;
219
220 if (!StartProduction(wxSOUND_OUTPUT))
dea7e44a 221 return false;
e8482f24 222
dea7e44a 223 return true;
e8482f24
GL
224}
225
226bool wxSoundFileStream::Record(wxUint32 time)
227{
228 if (m_state != wxSOUND_FILE_STOPPED)
dea7e44a 229 return false;
e8482f24
GL
230
231 if (!PrepareToRecord(time))
dea7e44a 232 return false;
e8482f24
GL
233
234 FinishPreparation(m_sndformat->GetBytesFromTime(time));
235
236 m_state = wxSOUND_FILE_RECORDING;
237 if (!StartProduction(wxSOUND_INPUT))
dea7e44a 238 return false;
e8482f24 239
dea7e44a 240 return true;
e8482f24
GL
241}
242
243bool wxSoundFileStream::Stop()
244{
245 if (m_state == wxSOUND_FILE_STOPPED)
dea7e44a 246 return false;
e8482f24
GL
247
248 if (!StopProduction())
dea7e44a 249 return false;
e8482f24 250
dea7e44a 251 m_prepared = false;
e8482f24
GL
252
253 if (m_state == wxSOUND_FILE_RECORDING)
254 if (!FinishRecording()) {
255 m_state = wxSOUND_FILE_STOPPED;
dea7e44a 256 return false;
e8482f24
GL
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;
dea7e44a 266 return true;
e8482f24
GL
267}
268
269bool wxSoundFileStream::Pause()
270{
271 if (m_state == wxSOUND_FILE_PAUSED || m_state == wxSOUND_FILE_STOPPED)
dea7e44a 272 return false;
e8482f24
GL
273
274 if (!StopProduction())
dea7e44a 275 return false;
e8482f24
GL
276
277 m_oldstate = m_state;
278 m_state = wxSOUND_FILE_PAUSED;
dea7e44a 279 return true;
e8482f24
GL
280}
281
282bool wxSoundFileStream::Resume()
283{
284 if (m_state == wxSOUND_FILE_PLAYING || m_state == wxSOUND_FILE_RECORDING ||
285 m_state == wxSOUND_FILE_STOPPED)
dea7e44a 286 return false;
e8482f24
GL
287
288 if (!StartProduction( (m_oldstate == wxSOUND_FILE_PLAYING) ?
289 wxSOUND_OUTPUT : wxSOUND_INPUT))
dea7e44a 290 return false;
e8482f24
GL
291
292 m_state = m_oldstate;
293
dea7e44a 294 return true;
e8482f24
GL
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))
dea7e44a 324 return false;
e8482f24 325
dea7e44a 326 return true;
e8482f24
GL
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;
dea7e44a 337 m_prepared = true;
e8482f24
GL
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}