]> git.saurik.com Git - wxWidgets.git/blame_incremental - contrib/src/mmedia/sndesd.cpp
The last commit was too hasty.
[wxWidgets.git] / contrib / src / mmedia / sndesd.cpp
... / ...
CommitLineData
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
54wxSoundStreamESD::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
90wxSoundStreamESD::~wxSoundStreamESD()
91{
92 if (!m_esd_stop)
93 StopProduction();
94}
95
96// --------------------------------------------------------------------------
97// Read several samples
98// --------------------------------------------------------------------------
99
100wxSoundStream& 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// --------------------------------------------------------------------------
122wxSoundStream& 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// --------------------------------------------------------------------------
148bool 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__
188static 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// --------------------------------------------------------------------------
211void wxSoundStreamESD::WakeUpEvt(int evt)
212{
213 m_q_filled = FALSE;
214 OnSoundEvent(evt);
215}
216
217// --------------------------------------------------------------------------
218// StartProduction(): see wxSoundStream
219// --------------------------------------------------------------------------
220bool 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// --------------------------------------------------------------------------
270bool 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//
298void 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}