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