]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/mmedia/sndesd.cpp
added protection against corrupted GIFs in ReadGIF
[wxWidgets.git] / contrib / src / mmedia / sndesd.cpp
CommitLineData
e8482f24
GL
1// --------------------------------------------------------------------------
2// Name: sndesd.cpp
3// Purpose:
4// Date: 08/11/1999
5// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
6// CVSID: $Id$
58b9c9ba 7// wxWindows licence
e8482f24 8// --------------------------------------------------------------------------
e8482f24
GL
9
10#include "wx/wxprec.h"
11
12#ifndef WX_PRECOMP
13 #include "wx/defs.h"
14 #include "wx/string.h"
15#endif
16
17#ifdef __BORLANDC__
18 #pragma hdrstop
19#endif
20
21// --------------------------------------------------------------------------
22// MMedia headers
23// --------------------------------------------------------------------------
24
25#include "wx/mmedia/sndbase.h"
26#include "wx/mmedia/sndesd.h"
27#include "wx/mmedia/sndpcm.h"
28
29// --------------------------------------------------------------------------
30// System headers
31// --------------------------------------------------------------------------
32
a7b1654d 33#ifdef HAVE_ESD_H
e8482f24
GL
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <unistd.h>
37#include <esd.h>
38#ifdef __WXGTK__
39#include <gdk/gdk.h>
40#endif
a7b1654d 41#endif
e8482f24
GL
42
43// --------------------------------------------------------------------------
44
be5a51fb 45#define MY_ESD_NAME "wxWidgets/wxSoundStreamESD"
e8482f24
GL
46
47// --------------------------------------------------------------------------
48// wxSoundStreamESD: ESD sound driver
49
50// --------------------------------------------------------------------------
51// Constructors/Destructors
52// --------------------------------------------------------------------------
53
54wxSoundStreamESD::wxSoundStreamESD(const wxString& hostname)
55{
a7b1654d
MB
56#ifndef HAVE_ESD_H
57 m_snderror = wxSOUND_INVDEV;
58 return;
59#else
e8482f24 60 wxSoundFormatPcm pcm_default;
b7ecdec5 61
e8482f24 62 // First, we make some basic test: is there ESD on this computer ?
dea7e44a 63 m_esd_ok = false;
b7ecdec5 64
e8482f24 65 if (hostname.IsNull())
b7ecdec5 66 m_fd_output = esd_play_stream(ESD_PLAY | ESD_STREAM, 22050,
e8482f24
GL
67 hostname.mb_str(), MY_ESD_NAME);
68 else
b7ecdec5 69 m_fd_output = esd_play_stream(ESD_PLAY | ESD_STREAM, 22050,
e8482f24
GL
70 NULL, MY_ESD_NAME);
71 if (m_fd_output == -1) {
72 // Answer: no. We return with an error.
73 m_snderror = wxSOUND_INVDEV;
74 return;
75 }
b7ecdec5 76
e8482f24
GL
77 // Close this unuseful stream.
78 esd_close(m_fd_output);
b7ecdec5 79
e8482f24 80 m_hostname = hostname;
b7ecdec5 81
e8482f24
GL
82 // Set the default audio format
83 SetSoundFormat(pcm_default);
b7ecdec5 84
e8482f24
GL
85 // Initialize some variable
86 m_snderror = wxSOUND_NOERROR;
dea7e44a
WS
87 m_esd_stop = true;
88 m_q_filled = true;
89 m_esd_ok = true;
e8482f24
GL
90 m_fd_output= -1;
91 m_fd_input = -1;
a7b1654d 92#endif // defined HAVE_ESD_H
e8482f24
GL
93}
94
95wxSoundStreamESD::~wxSoundStreamESD()
96{
a7b1654d 97#ifdef HAVE_ESD_H
e8482f24
GL
98 if (!m_esd_stop)
99 StopProduction();
a7b1654d 100#endif // defined HAVE_ESD_H
e8482f24
GL
101}
102
103// --------------------------------------------------------------------------
104// Read several samples
105// --------------------------------------------------------------------------
106
107wxSoundStream& wxSoundStreamESD::Read(void *buffer, wxUint32 len)
108{
a7b1654d
MB
109#ifndef HAVE_ESD_H
110 m_snderror = wxSOUND_INVDEV;
111 return *this;
112#else
e8482f24 113 int ret;
b7ecdec5 114
e8482f24
GL
115 if (m_esd_stop) {
116 m_snderror = wxSOUND_NOTSTARTED;
117 return *this;
118 }
b7ecdec5
WS
119
120 ret = read(m_fd_input, buffer, len);
121 m_lastcount = (wxUint32)ret;
122
e8482f24
GL
123 if (ret < 0)
124 m_snderror = wxSOUND_IOERROR;
125 else
126 m_snderror = wxSOUND_NOERROR;
b7ecdec5 127
e8482f24 128 return *this;
a7b1654d 129#endif // defined HAVE_ESD_H
e8482f24
GL
130}
131
132// --------------------------------------------------------------------------
133// Write several samples
134// --------------------------------------------------------------------------
135wxSoundStream& wxSoundStreamESD::Write(const void *buffer, wxUint32 len)
136{
a7b1654d
MB
137#ifndef HAVE_ESD_H
138 m_snderror = wxSOUND_INVDEV;
139 return *this;
140#else
e8482f24
GL
141 int ret;
142
143 if (m_esd_stop) {
144 m_lastcount = 0;
145 m_snderror = wxSOUND_NOTSTARTED;
146 return *this;
147 }
b7ecdec5
WS
148
149 ret = write(m_fd_output, buffer, len);
150 m_lastcount = (wxUint32)ret;
151
e8482f24
GL
152 if (ret < 0)
153 m_snderror = wxSOUND_IOERROR;
154 else
155 m_snderror = wxSOUND_NOERROR;
b7ecdec5 156
dea7e44a 157 m_q_filled = true;
b7ecdec5 158
e8482f24 159 return *this;
a7b1654d 160#endif // defined HAVE_ESD_H
e8482f24
GL
161}
162
163// --------------------------------------------------------------------------
164// SetSoundFormat(): this function specifies which format we want and which
165// format is available
166// --------------------------------------------------------------------------
167bool wxSoundStreamESD::SetSoundFormat(const wxSoundFormatBase& format)
168{
a7b1654d
MB
169#ifndef HAVE_ESD_H
170 m_snderror = wxSOUND_INVDEV;
dea7e44a 171 return false;
a7b1654d 172#else
e8482f24 173 wxSoundFormatPcm *pcm_format;
b7ecdec5 174
e8482f24
GL
175 if (format.GetType() != wxSOUND_PCM) {
176 m_snderror = wxSOUND_INVFRMT;
dea7e44a 177 return false;
e8482f24
GL
178 }
179
180 if (!m_esd_ok) {
181 m_snderror = wxSOUND_INVDEV;
dea7e44a 182 return false;
e8482f24 183 }
b7ecdec5 184
e8482f24
GL
185 if (m_sndformat)
186 delete m_sndformat;
b7ecdec5 187
e8482f24
GL
188 m_sndformat = format.Clone();
189 if (!m_sndformat) {
190 m_snderror = wxSOUND_MEMERROR;
dea7e44a 191 return false;
e8482f24
GL
192 }
193 pcm_format = (wxSoundFormatPcm *)m_sndformat;
b7ecdec5 194
e8482f24
GL
195 // Detect the best format
196 DetectBest(pcm_format);
b7ecdec5 197
e8482f24
GL
198 m_snderror = wxSOUND_NOERROR;
199 if (*pcm_format != format) {
200 m_snderror = wxSOUND_NOEXACT;
dea7e44a 201 return false;
e8482f24 202 }
dea7e44a 203 return true;
a7b1654d 204#endif // defined HAVE_ESD_H
e8482f24
GL
205}
206
207// --------------------------------------------------------------------------
208// _wxSound_OSS_CBack (internal): it is called when the driver (ESD) is
209// ready for a next buffer.
210// --------------------------------------------------------------------------
a7b1654d 211#if defined(__WXGTK__) && defined(HAVE_ESD_H)
e8482f24
GL
212static void _wxSound_OSS_CBack(gpointer data, int source,
213 GdkInputCondition condition)
214{
215 wxSoundStreamESD *esd = (wxSoundStreamESD *)data;
b7ecdec5 216
e8482f24
GL
217 switch (condition) {
218 case GDK_INPUT_READ:
219 esd->WakeUpEvt(wxSOUND_INPUT);
220 break;
221 case GDK_INPUT_WRITE:
222 esd->WakeUpEvt(wxSOUND_OUTPUT);
223 break;
224 default:
225 break;
226 }
227}
228#endif
229
230
231// --------------------------------------------------------------------------
232// WakeUpEvt() (internal): it is called by _wxSound_OSS_CBack to bypass the
233// C++ protection
234// --------------------------------------------------------------------------
235void wxSoundStreamESD::WakeUpEvt(int evt)
236{
dea7e44a 237 m_q_filled = false;
e8482f24
GL
238 OnSoundEvent(evt);
239}
240
241// --------------------------------------------------------------------------
242// StartProduction(): see wxSoundStream
243// --------------------------------------------------------------------------
244bool wxSoundStreamESD::StartProduction(int evt)
245{
a7b1654d
MB
246#ifndef HAVE_ESD_H
247 m_snderror = wxSOUND_INVDEV;
dea7e44a 248 return false;
a7b1654d 249#else
e8482f24
GL
250 wxSoundFormatPcm *pcm;
251 int flag = 0;
252
253 if (!m_esd_ok) {
254 m_snderror = wxSOUND_INVDEV;
dea7e44a 255 return false;
e8482f24 256 }
b7ecdec5 257
e8482f24
GL
258 if (!m_esd_stop)
259 StopProduction();
b7ecdec5 260
e8482f24 261 pcm = (wxSoundFormatPcm *)m_sndformat;
b7ecdec5 262
e8482f24
GL
263 flag |= (pcm->GetBPS() == 16) ? ESD_BITS16 : ESD_BITS8;
264 flag |= (pcm->GetChannels() == 2) ? ESD_STEREO : ESD_MONO;
b7ecdec5 265
e8482f24
GL
266 if ((evt & wxSOUND_OUTPUT) != 0) {
267 flag |= ESD_PLAY | ESD_STREAM;
268 m_fd_output = esd_play_stream(flag, pcm->GetSampleRate(), NULL,
269 MY_ESD_NAME);
b7ecdec5
WS
270 }
271
e8482f24
GL
272 if ((evt & wxSOUND_INPUT) != 0) {
273 flag |= ESD_RECORD | ESD_STREAM;
274 m_fd_input = esd_record_stream(flag, pcm->GetSampleRate(), NULL,
275 MY_ESD_NAME);
276 }
b7ecdec5 277
e8482f24
GL
278#ifdef __WXGTK__
279 if ((evt & wxSOUND_OUTPUT) != 0) {
280 m_tag_output = gdk_input_add(m_fd_output, GDK_INPUT_WRITE,
281 _wxSound_OSS_CBack, (gpointer)this);
282 }
283 if ((evt & wxSOUND_INPUT) != 0) {
284 m_tag_input = gdk_input_add(m_fd_input, GDK_INPUT_READ,
285 _wxSound_OSS_CBack, (gpointer)this);
286 }
287#endif
b7ecdec5 288
dea7e44a
WS
289 m_esd_stop = false;
290 m_q_filled = false;
b7ecdec5 291
dea7e44a 292 return true;
a7b1654d 293#endif // defined HAVE_ESD_H
e8482f24
GL
294}
295
296// --------------------------------------------------------------------------
297// StopProduction(): see wxSoundStream
298// --------------------------------------------------------------------------
299bool wxSoundStreamESD::StopProduction()
300{
a7b1654d
MB
301#ifndef HAVE_ESD_H
302 m_snderror = wxSOUND_INVDEV;
dea7e44a 303 return false;
a7b1654d 304#else
e8482f24 305 if (m_esd_stop)
dea7e44a 306 return false;
b7ecdec5 307
e8482f24
GL
308 if (m_fd_input != -1) {
309 esd_close(m_fd_input);
310#ifdef __WXGTK__
311 gdk_input_remove(m_tag_input);
312#endif
313 }
314 if (m_fd_output != -1) {
315 esd_close(m_fd_output);
316#ifdef __WXGTK__
317 gdk_input_remove(m_tag_output);
318#endif
319 }
b7ecdec5 320
e8482f24
GL
321 m_fd_input = -1;
322 m_fd_output= -1;
dea7e44a
WS
323 m_esd_stop = true;
324 m_q_filled = true;
325 return true;
a7b1654d 326#endif // defined HAVE_ESD_H
e8482f24
GL
327}
328
329//
330// Detect the closest format (The best).
331//
332void wxSoundStreamESD::DetectBest(wxSoundFormatPcm *pcm)
333{
a7b1654d
MB
334#ifndef HAVE_ESD_H
335 m_snderror = wxSOUND_INVDEV;
336 return;
337#else
e8482f24
GL
338 wxSoundFormatPcm best_pcm;
339
340 // We change neither the number of channels nor the sample rate
341 // because ESD is clever.
b7ecdec5 342
e8482f24
GL
343 best_pcm.SetSampleRate(pcm->GetSampleRate());
344 best_pcm.SetChannels(pcm->GetChannels());
b7ecdec5 345
e8482f24
GL
346 // It supports 16 bits
347 if (pcm->GetBPS() >= 16)
348 best_pcm.SetBPS(16);
349 else
350 best_pcm.SetBPS(8);
351
352 best_pcm.SetOrder(wxLITTLE_ENDIAN);
dea7e44a 353 best_pcm.Signed(true);
b7ecdec5 354
e8482f24
GL
355 // Finally recopy the new format
356 *pcm = best_pcm;
a7b1654d 357#endif // defined HAVE_ESD_H
e8482f24 358}
15e8daec 359