]> git.saurik.com Git - wxWidgets.git/blame_incremental - utils/wxMMedia/sndfile.cpp
fixed somebody's poorly done StreamSize-->GetSize transition
[wxWidgets.git] / utils / wxMMedia / sndfile.cpp
... / ...
CommitLineData
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_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
74void 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
84void 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
118void 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
149void 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
171wxMMtime 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
194wxMMtime wxSndFileCodec::GetLength()
195{
196 if (m_sndtime.hours == -1 && m_istream)
197 m_fsize = PrepareToPlay();
198
199 return m_sndtime;
200}
201
202bool 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
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{
286 if (m_fstate == wxSFILE_STOPPED)
287 return 0;
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)