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