4 * Sound driver implementation.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
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/
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
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.8 2002/03/27 06:53:47 robertj
31 * iSome more implementation, thanks Raimo Ruokonen
33 * Revision 1.7 2002/02/09 00:52:01 robertj
34 * Slight adjustment to API and documentation for volume functions.
36 * Revision 1.6 2002/02/07 20:57:21 dereks
37 * add SetVolume and GetVolume methods to PSoundChannel
39 * Revision 1.5 2001/10/18 01:15:18 robertj
40 * Fixed compile error.
42 * Revision 1.4 1999/09/03 02:01:34 robertj
43 * Added missing functions so will at least link
45 * Revision 1.3 1999/06/28 09:28:02 robertj
46 * Portability issues, especially n BeOS (thanks Yuri!)
48 * Revision 1.2 1999/03/02 04:34:10 robertj
49 * Fixed header comments
53 #pragma implementation "sound.h"
57 #include <sys/audioio.h>
60 PSound::PSound(unsigned channels
,
61 unsigned samplesPerSecond
,
62 unsigned bitsPerSample
,
67 numChannels
= channels
;
68 sampleRate
= samplesPerSecond
;
69 sampleSize
= bitsPerSample
;
72 memcpy(GetPointer(), buffer
, bufferSize
);
76 PSound::PSound(const PFilePath
& filename
)
86 PSound
& PSound::operator=(const PBYTEArray
& data
)
88 PBYTEArray::operator=(data
);
93 void PSound::SetFormat(unsigned channels
,
94 unsigned samplesPerSecond
,
95 unsigned bitsPerSample
)
98 numChannels
= channels
;
99 sampleRate
= samplesPerSecond
;
100 sampleSize
= bitsPerSample
;
101 formatInfo
.SetSize(0);
105 BOOL
PSound::Load(const PFilePath
& /*filename*/)
111 BOOL
PSound::Save(const PFilePath
& /*filename*/)
117 ///////////////////////////////////////////////////////////////////////////////
119 PSoundChannel::PSoundChannel()
125 PSoundChannel::PSoundChannel(const PString
& device
,
127 unsigned numChannels
,
129 unsigned bitsPerSample
)
132 Open(device
, dir
, numChannels
, sampleRate
, bitsPerSample
);
136 void PSoundChannel::Construct()
141 PSoundChannel::~PSoundChannel()
147 PStringArray
PSoundChannel::GetDeviceNames(Directions
/*dir*/)
151 array
[0] = "/dev/audio";
152 array
[1] = "/dev/dsp";
158 PString
PSoundChannel::GetDefaultDevice(Directions
/*dir*/)
164 BOOL
PSoundChannel::Open(const PString
& device
,
166 unsigned numChannels
,
168 unsigned bitsPerSample
)
171 if (!ConvertOSError(os_handle
= ::open(device
, (dir
== Player
? O_WRONLY
: O_RDONLY
) ,0)))
176 int flag
= fcntl(os_handle
, F_GETFL
, 0)| O_NONBLOCK
| O_NDELAY
;
178 if (fcntl(os_handle
, F_SETFL
, flag
) < 0) {
179 PTRACE(1,"F_SETFL fcntl ERROR");
184 return SetFormat(numChannels
, sampleRate
, bitsPerSample
);
188 BOOL
PSoundChannel::Close()
190 return PChannel::Close();
194 BOOL
PSoundChannel::SetFormat(unsigned numChannels
,
196 unsigned bitsPerSample
){
197 PAssert(numChannels
>= 1 && numChannels
<= 2, PInvalidParameter
);
198 PAssert(bitsPerSample
== 8 || bitsPerSample
== 16, PInvalidParameter
);
200 audio_info_t audio_info
;
203 AUDIO_INITINFO(&audio_info
); // Change only the values needed below
204 if (direction
== Player
){
205 mSampleRate
= audio_info
.play
.sample_rate
= sampleRate
; // Output settings
206 mNumChannels
= audio_info
.play
.channels
= numChannels
;
207 mBitsPerSample
= audio_info
.play
.precision
= bitsPerSample
;
208 audio_info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
209 audio_info
.play
.port
&= AUDIO_HEADPHONE
;
210 audio_info
.play
.port
&= (~AUDIO_SPEAKER
); // No speaker output
212 mSampleRate
= audio_info
.record
.sample_rate
= sampleRate
; // Input settings
213 mNumChannels
= audio_info
.record
.channels
= numChannels
;
214 mBitsPerSample
= audio_info
.record
.precision
= bitsPerSample
;
215 audio_info
.record
.encoding
= AUDIO_ENCODING_LINEAR
;
216 audio_info
.record
.port
&= AUDIO_MICROPHONE
;
217 audio_info
.record
.port
&= (~AUDIO_LINE_IN
);
219 err
=::ioctl(os_handle
,AUDIO_SETINFO
,&audio_info
); // The actual setting of the parameters
220 if(err
==EINVAL
|| err
==EBUSY
)
223 err
= ::ioctl(os_handle
, AUDIO_GETINFO
, &audio_info
); // Let's recheck the configuration...
224 if (direction
== Player
){
225 actualSampleRate
= audio_info
.play
.sample_rate
;
226 // PAssert(actualSampleRate==sampleRate && audio_info.play.precision==bitsPerSample && audio_info.play.encoding==AUDIO_ENCODING_LINEAR, PInvalidParameter);
228 actualSampleRate
= audio_info
.record
.sample_rate
;
229 // PAssert(actualSampleRate==sampleRate && audio_info.record.precision==bitsPerSample && audio_info.record.encoding==AUDIO_ENCODING_LINEAR, PInvalidParameter);
235 BOOL
PSoundChannel::SetBuffers(PINDEX size
, PINDEX count
)
237 PAssert(size
> 0 && count
> 0 && count
< 65536, PInvalidParameter
);
239 audio_info_t audio_info
;
242 AUDIO_INITINFO(&audio_info
); // Change only the values needed below
243 if (direction
== Player
)
244 audio_info
.play
.buffer_size
= count
*size
; // man audio says there is no way to set the buffer count... This doesn't affect the actual buffer size on Solaris ?
246 audio_info
.record
.buffer_size
= count
*size
; // Recorder
248 err
= ioctl(os_handle
,AUDIO_SETINFO
,&audio_info
); // The actual setting of the parameters
249 if (err
== EINVAL
|| err
== EBUSY
)
256 BOOL
PSoundChannel::GetBuffers(PINDEX
& size
, PINDEX
& count
)
262 BOOL
PSoundChannel::Write(const void * buf
, PINDEX len
)
264 return PChannel::Write(buf
, len
);
266 /* Implementation based on OSS PSoundChannel::Write. This works, but no difference on sound when compared to the basic implementation...
267 while (!ConvertOSError(err=::write(os_handle, (void *)buf, len)))
268 if (GetErrorCode() != Interrupted){
276 BOOL
PSoundChannel::PlaySound(const PSound
& sound
, BOOL wait
)
280 if (!Write((const BYTE
*)sound
, sound
.GetSize()))
284 return WaitForPlayCompletion();
290 BOOL
PSoundChannel::PlayFile(const PFilePath
& filename
, BOOL wait
)
295 BOOL
PSoundChannel::HasPlayCompleted()
300 BOOL
PSoundChannel::WaitForPlayCompletion()
305 BOOL
PSoundChannel::Read(void * buffer
, PINDEX length
)
307 return PChannel::Read(buffer
, length
);
311 BOOL
PSoundChannel::RecordSound(PSound
& sound
)
316 BOOL
PSoundChannel::RecordFile(const PFilePath
& filename
)
321 BOOL
PSoundChannel::StartRecording()
326 BOOL
PSoundChannel::IsRecordBufferFull()
331 BOOL
PSoundChannel::AreAllRecordBuffersFull()
336 BOOL
PSoundChannel::WaitForRecordBufferFull()
339 return SetErrorValues(NotOpen
, EBADF
);
341 return PXSetIOBlock(PXReadBlock
, readTimeout
);
345 BOOL
PSoundChannel::WaitForAllRecordBuffersFull()
351 BOOL
PSoundChannel::Abort()
355 BOOL
PSoundChannel::SetVolume(unsigned newVolume
)
357 cerr
<< __FILE__
<< "PSoundChannel :: SetVolume called in error. Please fix"<<endl
;
361 BOOL
PSoundChannel::GetVolume(unsigned & volume
)
363 cerr
<< __FILE__
<< "PSoundChannel :: GetVolume called in error. Please fix"<<endl
;