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