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