openbsd-ports/devel/pwlib/files/sound_libsndio.cxx
ajacoutot 4e67ad9d4c - s/LIBSNDIO/SNDIO for consistency
discussed with naddy@

"sure" jakemsr@
2009-01-19 09:42:21 +00:00

508 lines
9.5 KiB
C++

/*
* sound_libsndio.cxx
*
* Sound driver implementation.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* $Log: sound_libsndio.cxx,v $
* Revision 1.2 2009/01/19 09:42:21 ajacoutot
* - s/LIBSNDIO/SNDIO for consistency
* discussed with naddy@
*
* "sure" jakemsr@
*
* Revision 1.1 2009/01/17 12:30:08 jakemsr
* - add sndio backend
* - remove OSS and esd support
* ok ajacoutot@ (MAINTAINER)
*
*/
#pragma implementation "sound_libsndio.h"
#include "sound_libsndio.h"
#include <sys/poll.h>
PCREATE_SOUND_PLUGIN(SNDIO, PSoundChannelLIBSNDIO);
PSoundChannelLIBSNDIO::PSoundChannelLIBSNDIO()
{
PSoundChannelLIBSNDIO::Construct();
}
PSoundChannelLIBSNDIO::PSoundChannelLIBSNDIO(const PString & device,
Directions dir,
unsigned numChannels,
unsigned sampleRate,
unsigned bitsPerSample)
{
Construct();
Open(device, dir, numChannels, sampleRate, bitsPerSample);
}
void PSoundChannelLIBSNDIO::Construct()
{
os_handle = -1;
hdl = NULL;
}
PSoundChannelLIBSNDIO::~PSoundChannelLIBSNDIO()
{
Close();
}
PStringArray PSoundChannelLIBSNDIO::GetDeviceNames(Directions)
{
static const char * const devices[] = {
"default",
"/tmp/aucat.sock",
"/dev/audio0",
"/dev/audio1",
"/dev/audio2"
};
return PStringArray(PARRAYSIZE(devices), devices);
}
PString PSoundChannelLIBSNDIO::GetDefaultDevice(Directions dir)
{
return "default";
}
BOOL PSoundChannelLIBSNDIO::Open(const PString & device,
Directions dir,
unsigned numChannels,
unsigned sampleRate,
unsigned bitsPerSample)
{
uint mode;
char sio_device[32];
Close();
if (dir == Recorder)
mode = SIO_REC;
else
mode = SIO_PLAY;
snprintf(sio_device, 32, "%s", (const char *)device);
if (strncmp(sio_device, "default", 7) == 0)
hdl = sio_open(NULL, mode, 0);
else
hdl = sio_open(sio_device, mode, 0);
if (hdl == NULL) {
printf("sio_open failed\n");
return FALSE;
}
mDirection = dir;
mDevice = device;
mSampleRate = sampleRate;
mNumChannels = numChannels;
mBitsPerSample = bitsPerSample;
mBytesPerFrame = (bitsPerSample / 8) * numChannels;
isInitialised = FALSE;
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::Setup()
{
if (!hdl) {
PTRACE(6, "LIBSNDIO\tSkipping setup of " << mDevice << " as not open");
return FALSE;
}
if (isInitialised) {
PTRACE(6, "LIBSNDIO\tSkipping setup of " << mDevice << " as instance already initialised");
return TRUE;
}
PTRACE(6, "LIBSNDIO\tInitialising " << mDevice);
sio_initpar(&par);
int framesPerFrag = mFragSize / mBytesPerFrame;
par.bufsz = mFragCount * framesPerFrag;
par.round = framesPerFrag;
par.bits = mBitsPerSample;
par.sig = 1;
#if PBYTE_ORDER == PLITTLE_ENDIAN
par.le = 1;
#else
par.le = 0;
#endif
if (mDirection == Recorder)
par.rchan = mNumChannels;
else
par.pchan = mNumChannels;
par.rate = mSampleRate;
if (!sio_setpar(hdl, &par)) {
printf("sio_setpar failed\n");
return FALSE;
}
if (!sio_getpar(hdl, &par)) {
printf("sio_getpar failed\n");
return FALSE;
}
mFragSize = par.round * mBytesPerFrame;
mFragCount = par.bufsz / par.round;
if (!sio_start(hdl)) {
printf("sio_start failed\n");
return FALSE;
}
isInitialised = TRUE;
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::Close()
{
if (!hdl)
return TRUE;
sio_close(hdl);
hdl = NULL;
return PChannel::Close();
}
BOOL PSoundChannelLIBSNDIO::IsOpen() const
{
return (hdl != NULL);
}
BOOL PSoundChannelLIBSNDIO::Write(const void * buf, PINDEX len)
{
lastWriteCount = 0;
if (!Setup() || !hdl)
return FALSE;
int did, tot = 0;
while (len > 0) {
did = sio_write(hdl, (void *)buf, len);
if (did == 0) {
printf("sio_write failed\n");
return FALSE;
}
len -= did;
(char *)buf += did;
tot += did;
}
lastWriteCount += tot;
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::Read(void * buf, PINDEX len)
{
lastReadCount = 0;
if (!Setup() || !hdl)
return FALSE;
int did, tot = 0;
while (len > 0) {
did = sio_read(hdl, buf, len);
if (did == 0) {
printf("sio_read failed\n");
return FALSE;
}
len -= did;
(char *)buf += did;
tot += did;
}
lastReadCount += tot;
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::SetFormat(unsigned numChannels,
unsigned sampleRate,
unsigned bitsPerSample)
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
PAssert((bitsPerSample == 8) || (bitsPerSample == 16), PInvalidParameter);
PAssert(numChannels >= 1 && numChannels <= 2, PInvalidParameter);
if (isInitialised) {
if ((numChannels != mNumChannels) ||
(sampleRate != mSampleRate) ||
(bitsPerSample != mBitsPerSample)) {
PTRACE(6, "LIBSNDIO\tTried to change read/write format without stopping");
return FALSE;
}
return TRUE;
}
mNumChannels = numChannels;
mSampleRate = sampleRate;
mBitsPerSample = bitsPerSample;
isInitialised = FALSE;
return TRUE;
}
unsigned PSoundChannelLIBSNDIO::GetChannels() const
{
return mNumChannels;
}
unsigned PSoundChannelLIBSNDIO::GetSampleRate() const
{
return mSampleRate;
}
unsigned PSoundChannelLIBSNDIO::GetSampleSize() const
{
return mBitsPerSample;
}
BOOL PSoundChannelLIBSNDIO::SetBuffers(PINDEX size, PINDEX count)
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
PAssert(size > 0 && count > 0 && count < 65536, PInvalidParameter);
if (isInitialised) {
if (mFragSize != (unsigned)size || mFragCount != (unsigned)count) {
PTRACE(6, "LIBSNDIO\tTried to change buffers without stopping");
return FALSE;
}
return TRUE;
}
mFragSize = size;
mFragCount = count;
isInitialised = FALSE;
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::GetBuffers(PINDEX & size, PINDEX & count)
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
count = mFragCount;
size = mFragSize;
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::PlaySound(const PSound & sound, BOOL wait)
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
if (!Write((const BYTE *)sound, sound.GetSize()))
return FALSE;
if (wait)
return WaitForPlayCompletion();
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::PlayFile(const PFilePath & filename, BOOL wait)
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
PFile file(filename, PFile::ReadOnly);
if (!file.IsOpen())
return FALSE;
for (;;) {
BYTE buffer[256];
if (!file.Read(buffer, 256))
break;
PINDEX len = file.GetLastReadCount();
if (len == 0)
break;
if (!Write(buffer, len))
break;
}
file.Close();
if (wait)
return WaitForPlayCompletion();
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::HasPlayCompleted()
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::WaitForPlayCompletion()
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::RecordSound(PSound & sound)
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
return FALSE;
}
BOOL PSoundChannelLIBSNDIO::RecordFile(const PFilePath & filename)
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
return FALSE;
}
BOOL PSoundChannelLIBSNDIO::StartRecording()
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::IsRecordBufferFull()
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
struct pollfd pfd;
int events = POLLIN;
sio_pollfd(hdl, &pfd, events);
return ConvertOSError(::poll(&pfd, 1, 0));
}
BOOL PSoundChannelLIBSNDIO::AreAllRecordBuffersFull()
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
struct pollfd pfd;
int events = POLLIN;
sio_pollfd(hdl, &pfd, events);
return ConvertOSError(::poll(&pfd, 1, 0));
}
BOOL PSoundChannelLIBSNDIO::WaitForRecordBufferFull()
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
// return PXSetIOBlock(PXReadBlock, readTimeout);
struct pollfd pfd;
int events = POLLIN;
sio_pollfd(hdl, &pfd, events);
return ConvertOSError(::poll(&pfd, 1, 1000));
}
BOOL PSoundChannelLIBSNDIO::WaitForAllRecordBuffersFull()
{
if (!hdl)
return SetErrorValues(NotOpen, EBADF);
struct pollfd pfd;
int events = POLLIN;
sio_pollfd(hdl, &pfd, events);
return ConvertOSError(::poll(&pfd, 1, 1000));
}
BOOL PSoundChannelLIBSNDIO::Abort()
{
return TRUE;
}
BOOL PSoundChannelLIBSNDIO::SetVolume(unsigned newVal)
{
if (!hdl)
return FALSE;
return FALSE;
}
BOOL PSoundChannelLIBSNDIO::GetVolume(unsigned &devVol)
{
if (!hdl)
return FALSE;
devVol = 0;
return FALSE;
}
// End of file