1 /*
2 * esdaudio.cxx
3 *
4 * Sound driver implementation to use ESound.
5 *
6 * Portable Windows Library
7 *
8 * Copyright (c) 2001 Equivalence Pty. Ltd.
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is
23 * Shawn Pai-Hsiang Hsiao <shawn@eecs.harvard.edu>
24 *
25 * All Rights Reserved.
26 *
27 * Contributor(s): ______________________________________.
28 *
29 * $Revision: 20385 $
30 * $Author: rjongbloed $
31 * $Date: 2008-06-04 05:40:38 -0500 (Wed, 04 Jun 2008) $
32 */
33
34 #pragma implementation "sound.h"
35
36 #include <ptlib.h>
37 #include <esd.h>
38
39 #pragma implementation "sound_esd.h"
40
41 #include "sound_esd.h"
42
43 PCREATE_SOUND_PLUGIN(ESD, PSoundChannelESD);
44
45 ///////////////////////////////////////////////////////////////////////////////
46
PSoundChannelESD()47 PSoundChannelESD::PSoundChannelESD()
48 {
49 Construct();
50 }
51
52
PSoundChannelESD(const PString & device,Directions dir,unsigned numChannels,unsigned sampleRate,unsigned bitsPerSample)53 PSoundChannelESD::PSoundChannelESD(const PString & device,
54 Directions dir,
55 unsigned numChannels,
56 unsigned sampleRate,
57 unsigned bitsPerSample)
58 {
59 Construct();
60 Open(device, dir, numChannels, sampleRate, bitsPerSample);
61 }
62
63
Construct()64 void PSoundChannelESD::Construct()
65 {
66 }
67
68
~PSoundChannelESD()69 PSoundChannelESD::~PSoundChannelESD()
70 {
71 Close();
72 }
73
74
GetDeviceNames(Directions)75 PStringArray PSoundChannelESD::GetDeviceNames(Directions /*dir*/)
76 {
77 PStringArray array;
78
79 array[0] = "ESound";
80
81 return array;
82 }
83
84
GetDefaultDevice(Directions)85 PString PSoundChannelESD::GetDefaultDevice(Directions /*dir*/)
86 {
87 return "ESound";
88 }
89
Open(const PString & device,Directions dir,unsigned numChannels,unsigned sampleRate,unsigned bitsPerSample)90 PBoolean PSoundChannelESD::Open(const PString & device,
91 Directions dir,
92 unsigned numChannels,
93 unsigned sampleRate,
94 unsigned bitsPerSample)
95 {
96 int bits, channels, rate, mode, func;
97 esd_format_t format;
98 char *host = NULL, *name = NULL;
99
100 Close();
101
102 // make sure we have proper bits per sample
103 switch (bitsPerSample) {
104 case 16:
105 bits = ESD_BITS16;
106 break;
107 case 8:
108 bits = ESD_BITS8;
109 break;
110 default:
111 return (PFalse);
112 }
113
114 // make sure we have proper number of channels
115 switch (numChannels) {
116 case 2:
117 channels = ESD_STEREO;
118 break;
119 case 1:
120 channels = ESD_MONO;
121 break;
122 default:
123 return (PFalse);
124 }
125
126 rate = sampleRate;
127 mode = ESD_STREAM;
128
129 // a separate stream for Player and Recorder
130 switch (dir) {
131 case Recorder:
132 func = ESD_RECORD;
133 break;
134 case Player:
135 func = ESD_PLAY;
136 break;
137 default:
138 return (PFalse);
139 }
140
141 format = bits | channels | mode | func;
142 if (dir == Recorder)
143 os_handle = esd_record_stream_fallback( format, rate, host, name );
144 else
145 os_handle = esd_play_stream_fallback( format, rate, host, name );
146
147 if ( os_handle <= 0 )
148 return (PFalse);
149
150 return SetFormat(numChannels, sampleRate, bitsPerSample);
151 }
152
SetVolume(unsigned newVal)153 PBoolean PSoundChannelESD::SetVolume(unsigned newVal)
154 {
155 if (os_handle <= 0) //Cannot set volume in loop back mode.
156 return PFalse;
157
158 return PFalse;
159 }
160
GetVolume(unsigned & devVol)161 PBoolean PSoundChannelESD::GetVolume(unsigned &devVol)
162 {
163 if (os_handle <= 0) //Cannot get volume in loop back mode.
164 return PFalse;
165
166 devVol = 0;
167 return PFalse;
168 }
169
170
171
Close()172 PBoolean PSoundChannelESD::Close()
173 {
174 /* I think there is a bug here. We should be testing for loopback mode
175 * and NOT calling PChannel::Close() when we are in loopback mode.
176 * (otherwise we close file handle 0 which is stdin)
177 */
178
179 return PChannel::Close();
180 }
181
182
SetFormat(unsigned numChannels,unsigned sampleRate,unsigned bitsPerSample)183 PBoolean PSoundChannelESD::SetFormat(unsigned numChannels,
184 unsigned sampleRate,
185 unsigned bitsPerSample)
186 {
187 PAssert(numChannels >= 1 && numChannels <= 2, PInvalidParameter);
188 PAssert(bitsPerSample == 8 || bitsPerSample == 16, PInvalidParameter);
189
190 return PTrue;
191 }
192
193
SetBuffers(PINDEX size,PINDEX count)194 PBoolean PSoundChannelESD::SetBuffers(PINDEX size, PINDEX count)
195 {
196 Abort();
197
198 PAssert(size > 0 && count > 0 && count < 65536, PInvalidParameter);
199
200 return PTrue;
201 }
202
203
GetBuffers(PINDEX & size,PINDEX & count)204 PBoolean PSoundChannelESD::GetBuffers(PINDEX & size, PINDEX & count)
205 {
206 return PTrue;
207 }
208
209
Write(const void * buf,PINDEX len)210 PBoolean PSoundChannelESD::Write(const void * buf, PINDEX len)
211 {
212 int rval;
213
214 if (os_handle >= 0) {
215
216 // Sends data to esd.
217 rval = ::write(os_handle, buf, len);
218 if (rval > 0) {
219 #if defined(P_MACOSX)
220 // Mac OS X's esd has a big input buffer so we need to simulate
221 // writing data out at the correct rate.
222 writeDelay.Delay(len/16);
223 #endif
224 return (PTrue);
225 }
226 }
227
228 return PFalse;
229 }
230
231
PlaySound(const PSound & sound,PBoolean wait)232 PBoolean PSoundChannelESD::PlaySound(const PSound & sound, PBoolean wait)
233 {
234 Abort();
235
236 if (!Write((const BYTE *)sound, sound.GetSize()))
237 return PFalse;
238
239 if (wait)
240 return WaitForPlayCompletion();
241
242 return PTrue;
243 }
244
245
PlayFile(const PFilePath & filename,PBoolean wait)246 PBoolean PSoundChannelESD::PlayFile(const PFilePath & filename, PBoolean wait)
247 {
248 return PTrue;
249 }
250
251
HasPlayCompleted()252 PBoolean PSoundChannelESD::HasPlayCompleted()
253 {
254 return PFalse;
255 }
256
257
WaitForPlayCompletion()258 PBoolean PSoundChannelESD::WaitForPlayCompletion()
259 {
260 return PTrue;
261 }
262
263
Read(void * buf,PINDEX len)264 PBoolean PSoundChannelESD::Read(void * buf, PINDEX len)
265 {
266 if (os_handle < 0)
267 return PFalse;
268
269 lastReadCount = 0;
270 // keep looping until we have read 'len' bytes
271 while (lastReadCount < len) {
272 int retval = ::read(os_handle, ((char *)buf)+lastReadCount, len-lastReadCount);
273 if (retval <= 0) return PFalse;
274 lastReadCount += retval;
275 }
276 return (PTrue);
277 }
278
279
RecordSound(PSound & sound)280 PBoolean PSoundChannelESD::RecordSound(PSound & sound)
281 {
282 return PTrue;
283 }
284
285
RecordFile(const PFilePath & filename)286 PBoolean PSoundChannelESD::RecordFile(const PFilePath & filename)
287 {
288 return PTrue;
289 }
290
291
StartRecording()292 PBoolean PSoundChannelESD::StartRecording()
293 {
294 return (PTrue);
295 }
296
297
IsRecordBufferFull()298 PBoolean PSoundChannelESD::IsRecordBufferFull()
299 {
300 return (PTrue);
301 }
302
303
AreAllRecordBuffersFull()304 PBoolean PSoundChannelESD::AreAllRecordBuffersFull()
305 {
306 return PTrue;
307 }
308
309
WaitForRecordBufferFull()310 PBoolean PSoundChannelESD::WaitForRecordBufferFull()
311 {
312 if (os_handle < 0) {
313 return PFalse;
314 }
315
316 return PXSetIOBlock(PXReadBlock, readTimeout);
317 }
318
319
WaitForAllRecordBuffersFull()320 PBoolean PSoundChannelESD::WaitForAllRecordBuffersFull()
321 {
322 return PFalse;
323 }
324
325
Abort()326 PBoolean PSoundChannelESD::Abort()
327 {
328 return PTrue;
329 }
330
331
332 // End of file
333
334