]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia/sndfile.cpp
mbstowcs hack for CodeWarrior's MSL
[wxWidgets.git] / utils / wxMMedia / sndfile.cpp
CommitLineData
4d6306eb
GL
1////////////////////////////////////////////////////////////////////////////////
2// Name: sndfile.cpp
3// Purpose: wxMMedia
4// Author: Guilhem Lavaux
5// Created: 1997
6// Updated: 1998
7// Copyright: (C) 1997, 1998, Guilhem Lavaux
8// License: wxWindows license
9////////////////////////////////////////////////////////////////////////////////
10#ifdef __GNUG__
11#pragma implementation "sndfile.h"
12#endif
13
14#include "mmedia.h"
15#include "sndfile.h"
16#ifdef WX_PRECOMP
17#include <wx/wxprec.h>
18#else
19#include <wx/wx.h>
20#endif
21#include <wx/module.h>
22#include "sndfrmt.h"
23
24#ifdef __BORLANDC__
25#pragma hdrstop
26#endif
27
28wxSndFileCodec::wxSndFileCodec()
29 : wxMMediaFile(), wxSndBuffer(),
30 m_fstate(wxSFILE_STOPPED)
31{
32}
33
34wxSndFileCodec::wxSndFileCodec(wxOutputStream& s, bool seekable)
35 : wxMMediaFile(s, seekable),
36 wxSndBuffer(),
37 m_fstate(wxSFILE_STOPPED)
38{
39}
40
41wxSndFileCodec::wxSndFileCodec(wxInputStream& s, bool preload, bool seekable)
42 : wxMMediaFile(s, preload, seekable),
43 wxSndBuffer(),
44 m_fstate(wxSFILE_STOPPED)
45{
46}
47
48wxSndFileCodec::wxSndFileCodec(const wxString& fname)
49 : wxMMediaFile(fname), wxSndBuffer(),
50 m_fstate(wxSFILE_STOPPED)
51{
52}
53
54wxSndFileCodec::~wxSndFileCodec()
55{
56}
57
58void wxSndFileCodec::Play(wxSound& snd)
59{
60 if (m_fstate != wxSFILE_STOPPED || IsSet(wxSND_BUFLOCKED))
61 return;
62
63 if (!(m_fsize = PrepareToPlay()))
64 return;
65
66 m_fpos = 0;
67 m_fstate = wxSFILE_PLAYING;
68
69 Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
70 snd.QueueBuffer(*this);
71}
72
73void wxSndFileCodec::Stop(wxSound& snd)
74{
75 if (m_fstate == wxSFILE_STOPPED)
76 return;
77
78 snd.UnqueueBuffer(*this);
79 Clear(wxSND_BUFREADY | wxSND_KEEPQUEUED);
80 m_fstate = wxSFILE_STOPPED;
81}
82
83void wxSndFileCodec::Record(wxSound& snd,
84 const wxSoundDataFormat& format,
85 wxUint32 seconds)
86{
87 wxUint32 byterate;
88
89 if (m_fstate != wxSFILE_STOPPED)
90 return;
91
92 m_sndformat = format;
93 byterate = m_sndformat.GetCodec()->GetByteRate();
94
95 m_fsize = seconds*byterate;
96 if (!PrepareToRecord(m_fsize))
97 return;
98 if (IsSet(wxSND_BUFLOCKED))
99 return;
100
101 wxUint32 sec1 = m_fsize / byterate,
102 sec2 = sec1 % 3600;
103
104 m_sndtime.hours = sec1 / 3600;
105 m_sndtime.minutes = sec2 / 60;
106 m_sndtime.seconds = sec2 % 60;
107
108 m_fdone = m_fpos = 0;
109 m_fstate = wxSFILE_RECORDING;
110
111 m_sndmode = wxSND_INPUT;
112
113 Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
114 snd.QueueBuffer(*this);
115}
116
117void wxSndFileCodec::OnNeedOutputData(char *data, wxUint32& size)
118{
119 wxUint32 datas_left = m_fsize-m_fpos;
120
121 if (m_fstate != wxSFILE_PLAYING) {
122 size = 0;
123 return;
124 }
125
126 if (!datas_left) {
127 size = 0;
128 m_fpos = 0;
129 m_fstate = wxSFILE_STOPPED;
130 Clear(wxSND_KEEPQUEUED);
131 return;
132 }
133
134 if (size > datas_left)
135 size = datas_left;
136
137 if (!OnNeedData(data, size)) {
138 size = 0;
139 m_fpos = 0;
140 m_fstate = wxSFILE_STOPPED;
141 Clear(wxSND_KEEPQUEUED);
142 return;
143 }
144
145 m_fpos += size;
146}
147
148void wxSndFileCodec::OnBufferInFinished(char *iobuf, wxUint32& size)
149{
150 wxUint32 datas_left = m_fsize-m_fdone;
151
152 if (m_fstate != wxSFILE_RECORDING) {
153 size = 0;
154 return;
155 }
156
157 if (!datas_left) {
158 size = 0;
159 Clear(wxSND_KEEPQUEUED); // To be sure.
160 return;
161 }
162
163 if (size > datas_left)
164 size = datas_left;
165
166 OnWriteData(iobuf, size);
167 m_fdone += size;
168}
169
170wxMMtime wxSndFileCodec::GetPosition()
171{
172 wxMMtime mm_time;
173 wxUint32 sec1, sec2;
174 wxUint32 byterate;
175
176 byterate = m_sndformat.GetCodec()->GetByteRate();
177
178 if (m_fpos && byterate) {
179 sec1 = m_fpos / byterate;
180 sec2 = sec1 % 3600;
181 mm_time.hours = sec1 / 3600;
182 mm_time.minutes = sec2 / 60;
183 mm_time.seconds = sec2 % 60;
184 } else {
185 mm_time.hours = 0;
186 mm_time.minutes = 0;
187 mm_time.seconds = 0;
188 }
189
190 return mm_time;
191}
192
193wxMMtime wxSndFileCodec::GetLength()
194{
195 if (m_sndtime.hours == -1 && m_istream)
196 PrepareToPlay();
197
198 return m_sndtime;
199}
200
201bool wxSndFileCodec::TranslateBuffer(wxSndBuffer& buf)
202{
203#define TMP_BUFSIZE 10240
204
205 wxUint32 buf_size;
206 wxStreamBuffer *tmp_buf;
207 wxSoundCodec *codec_in, *codec_out;
208 wxSoundDataFormat std_format;
209
210 if (!m_ostream || !buf.RestartBuffer(wxSND_OUTPUT))
211 return FALSE;
212
213 m_sndformat = buf.GetFormat();
214 codec_in = buf.GetCurrentCodec();
215
216 m_fdone = 0;
217
218 if (!PrepareToRecord(m_fsize))
219 return FALSE;
220
221 codec_out = GetCurrentCodec();
222 m_fsize = (int)(((float)buf.GetSize() / codec_in->GetByteRate()) *
223 codec_out->GetByteRate());
224
225 if (!PrepareToRecord(m_fsize))
226 return FALSE;
227
228 codec_out = GetCurrentCodec();
229 codec_in->InitIO(m_sndformat);
230 codec_out->InitIO(m_sndformat);
231
232 tmp_buf = new wxStreamBuffer(wxStreamBuffer::read_write);
233 tmp_buf->Fixed(TRUE);
234 tmp_buf->Flushable(FALSE);
235 tmp_buf->SetBufferIO(TMP_BUFSIZE);
236
237 m_fstate = wxSFILE_RECORDING;
238
239 while (m_fdone < m_fsize) {
240 tmp_buf->ResetBuffer();
241 codec_in->SetOutStream(tmp_buf);
242 codec_in->Decode();
243
244 tmp_buf->ResetBuffer();
245 codec_out->SetInStream(tmp_buf);
246 codec_out->Encode();
247
248 buf.OnBufferOutFinished();
249 }
250 delete tmp_buf;
251
252 m_fstate = wxSFILE_STOPPED;
253
254 return TRUE;
255}
256
257bool wxSndFileCodec::RestartBuffer(wxSndMode mode)
258{
259 if (IsSet(wxSND_BUFLOCKED))
260 return FALSE;
261
262 m_fdone = 0;
263 m_fpos = 0;
264
265 if (mode == wxSND_OUTPUT && m_istream) {
266 m_fsize = PrepareToPlay();
267 m_fstate = wxSFILE_PLAYING;
268 return TRUE;
269 }
270 if (mode == wxSND_INPUT && m_ostream) {
271 m_fsize = 0;
272 m_fstate = wxSFILE_RECORDING;
273 return TRUE;
274 }
275
276 return FALSE;
277}
278
279wxUint32 wxSndFileCodec::GetSize() const
280{
281 return m_fsize;
282}
283
284wxUint32 wxSndFileCodec::Available() const
285{
eb4e516d
GL
286 if (m_fstate == wxSFILE_STOPPED)
287 return 0;
4d6306eb
GL
288 return m_fsize-m_fpos;
289}
290
291//
292// Simple API
293//
294static wxSoundDevice *dev_snd = NULL;
295
296bool wxSndFileCodec::StartPlay()
297{
298 if (!dev_snd)
299 dev_snd = new wxSoundDevice;
300
301 Play(*dev_snd);
302
303 return TRUE;
304}
305
306void wxSndFileCodec::StopPlay()
307{
308 if (!dev_snd)
309 return;
310
311 Stop(*dev_snd);
312 m_fpos = 0;
313}
314
315class wxSoundModule : public wxModule {
316 DECLARE_DYNAMIC_CLASS(wxSoundModule)
317public:
318 virtual bool OnInit() { return TRUE; }
319 virtual void OnExit() {
320 if (dev_snd)
321 delete dev_snd;
322 }
323};
324
325IMPLEMENT_DYNAMIC_CLASS(wxSoundModule, wxModule)