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