]> git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia/sndfile.cpp
* Fixes and updates on wxMMedia.
[wxWidgets.git] / utils / wxMMedia / sndfile.cpp
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
28 wxSndFileCodec::wxSndFileCodec()
29 : wxMMediaFile(), wxSndBuffer(),
30 m_fstate(wxSFILE_STOPPED)
31 {
32 }
33
34 wxSndFileCodec::wxSndFileCodec(wxOutputStream& s, bool seekable)
35 : wxMMediaFile(s, seekable),
36 wxSndBuffer(),
37 m_fstate(wxSFILE_STOPPED)
38 {
39 }
40
41 wxSndFileCodec::wxSndFileCodec(wxInputStream& s, bool preload, bool seekable)
42 : wxMMediaFile(s, preload, seekable),
43 wxSndBuffer(),
44 m_fstate(wxSFILE_STOPPED)
45 {
46 }
47
48 wxSndFileCodec::wxSndFileCodec(const wxString& fname)
49 : wxMMediaFile(fname), wxSndBuffer(),
50 m_fstate(wxSFILE_STOPPED)
51 {
52 }
53
54 wxSndFileCodec::~wxSndFileCodec()
55 {
56 }
57
58 void wxSndFileCodec::Play(wxSound& snd)
59 {
60 if (m_fstate != wxSFILE_STOPPED || IsSet(wxSND_BUFLOCKED))
61 return;
62
63 if (m_fstate != wxSFILE_PREPARED_TO_PLAY)
64 if (!(m_fsize = PrepareToPlay()))
65 return;
66
67 m_fpos = 0;
68 m_fstate = wxSFILE_PLAYING;
69
70 Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
71 snd.QueueBuffer(*this);
72 }
73
74 void wxSndFileCodec::Stop(wxSound& snd)
75 {
76 if (m_fstate == wxSFILE_STOPPED)
77 return;
78
79 snd.UnqueueBuffer(*this);
80 Clear(wxSND_BUFREADY | wxSND_KEEPQUEUED);
81 m_fstate = wxSFILE_STOPPED;
82 }
83
84 void wxSndFileCodec::Record(wxSound& snd,
85 const wxSoundDataFormat& format,
86 wxUint32 seconds)
87 {
88 wxUint32 byterate;
89
90 if (m_fstate != wxSFILE_STOPPED)
91 return;
92
93 m_sndformat = format;
94 byterate = m_sndformat.GetCodec()->GetByteRate();
95
96 m_fsize = seconds*byterate;
97 if (!PrepareToRecord(m_fsize))
98 return;
99 if (IsSet(wxSND_BUFLOCKED))
100 return;
101
102 wxUint32 sec1 = m_fsize / byterate,
103 sec2 = sec1 % 3600;
104
105 m_sndtime.hours = sec1 / 3600;
106 m_sndtime.minutes = sec2 / 60;
107 m_sndtime.seconds = sec2 % 60;
108
109 m_fdone = m_fpos = 0;
110 m_fstate = wxSFILE_RECORDING;
111
112 m_sndmode = wxSND_INPUT;
113
114 Set(wxSND_BUFREADY | wxSND_KEEPQUEUED);
115 snd.QueueBuffer(*this);
116 }
117
118 void wxSndFileCodec::OnNeedOutputData(char *data, wxUint32& size)
119 {
120 wxUint32 datas_left = m_fsize-m_fpos;
121
122 if (m_fstate != wxSFILE_PLAYING) {
123 size = 0;
124 return;
125 }
126
127 if (!datas_left) {
128 size = 0;
129 m_fpos = 0;
130 m_fstate = wxSFILE_STOPPED;
131 Clear(wxSND_KEEPQUEUED);
132 return;
133 }
134
135 if (size > datas_left)
136 size = datas_left;
137
138 if (!OnNeedData(data, size)) {
139 size = 0;
140 m_fpos = 0;
141 m_fstate = wxSFILE_STOPPED;
142 Clear(wxSND_KEEPQUEUED);
143 return;
144 }
145
146 m_fpos += size;
147 }
148
149 void wxSndFileCodec::OnBufferInFinished(char *iobuf, wxUint32& size)
150 {
151 wxUint32 datas_left = m_fsize-m_fdone;
152
153 if (m_fstate != wxSFILE_RECORDING) {
154 size = 0;
155 return;
156 }
157
158 if (!datas_left) {
159 size = 0;
160 Clear(wxSND_KEEPQUEUED); // To be sure.
161 return;
162 }
163
164 if (size > datas_left)
165 size = datas_left;
166
167 OnWriteData(iobuf, size);
168 m_fdone += size;
169 }
170
171 wxMMtime wxSndFileCodec::GetPosition()
172 {
173 wxMMtime mm_time;
174 wxUint32 sec1, sec2;
175 wxUint32 byterate;
176
177 byterate = m_sndformat.GetCodec()->GetByteRate();
178
179 if (m_fpos && byterate) {
180 sec1 = m_fpos / byterate;
181 sec2 = sec1 % 3600;
182 mm_time.hours = sec1 / 3600;
183 mm_time.minutes = sec2 / 60;
184 mm_time.seconds = sec2 % 60;
185 } else {
186 mm_time.hours = 0;
187 mm_time.minutes = 0;
188 mm_time.seconds = 0;
189 }
190
191 return mm_time;
192 }
193
194 wxMMtime wxSndFileCodec::GetLength()
195 {
196 if (m_sndtime.hours == -1 && m_istream)
197 m_fsize = PrepareToPlay();
198
199 return m_sndtime;
200 }
201
202 bool wxSndFileCodec::TranslateBuffer(wxSndBuffer& buf)
203 {
204 #define TMP_BUFSIZE 10240
205
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
257 bool 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
279 wxUint32 wxSndFileCodec::GetSize() const
280 {
281 return m_fsize;
282 }
283
284 wxUint32 wxSndFileCodec::Available() const
285 {
286 if (m_fstate == wxSFILE_STOPPED)
287 return 0;
288 return m_fsize-m_fpos;
289 }
290
291 //
292 // Simple API
293 //
294 static wxSoundDevice *dev_snd = NULL;
295
296 bool wxSndFileCodec::StartPlay()
297 {
298 if (!dev_snd)
299 dev_snd = new wxSoundDevice;
300
301 Play(*dev_snd);
302
303 return TRUE;
304 }
305
306 void wxSndFileCodec::StopPlay()
307 {
308 if (!dev_snd)
309 return;
310
311 Stop(*dev_snd);
312 m_fpos = 0;
313 }
314
315 class wxSoundModule : public wxModule {
316 DECLARE_DYNAMIC_CLASS(wxSoundModule)
317 public:
318 virtual bool OnInit() { return TRUE; }
319 virtual void OnExit() {
320 if (dev_snd)
321 delete dev_snd;
322 }
323 };
324
325 IMPLEMENT_DYNAMIC_CLASS(wxSoundModule, wxModule)