]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/mmedia/sndfile.cpp
added dependency handling
[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 #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 // --------------------------------------------------------------------------
29 wxSoundRouterStream::wxSoundRouterStream(wxSoundStream& sndio)
30 : wxSoundStreamCodec(sndio)
31 {
32 m_router = NULL;
33 }
34
35 wxSoundRouterStream::~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 // --------------------------------------------------------------------------
45 wxSoundStream& 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 // --------------------------------------------------------------------------
62 wxSoundStream& 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 // --------------------------------------------------------------------------
83 bool 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 // --------------------------------------------------------------------------
127 wxUint32 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 // --------------------------------------------------------------------------
138 bool 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 // --------------------------------------------------------------------------
160 bool 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
183 wxSoundFileStream::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
193 wxSoundFileStream::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
203 wxSoundFileStream::~wxSoundFileStream()
204 {
205 if (m_state != wxSOUND_FILE_STOPPED)
206 Stop();
207 }
208
209 bool 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
226 bool 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
243 bool 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
269 bool 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
282 bool 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
297 wxSoundStream& 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
308 wxSoundStream& 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
319 bool 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
329 bool wxSoundFileStream::StopProduction()
330 {
331 return m_codec.StopProduction();
332 }
333
334 void wxSoundFileStream::FinishPreparation(wxUint32 len)
335 {
336 m_bytes_left = m_length = len;
337 m_prepared = TRUE;
338 }
339
340 wxString wxSoundFileStream::GetCodecName() const
341 {
342 return wxString(wxT("wxSoundFileStream base codec"));
343 }
344
345 wxUint32 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
353 wxUint32 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
361 wxUint32 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
381 void 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
422 bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)
423 {
424 wxSoundStream::SetSoundFormat(format);
425 return m_codec.SetSoundFormat(format);
426 }