openbsd-ports/audio/esound/files/audio_sun.c
fgsch ef9c978b30 set number of channels with the encoding, otherwise AUDIO_SETINFO will
fail with EINVAL. this gives esound a chance to work.
wcobb@, brad@ (maintainer), naddy@ ok.
2004-01-25 22:07:28 +00:00

162 lines
4.5 KiB
C

/* $OpenBSD: audio_sun.c,v 1.3 2004/01/25 22:07:28 fgsch Exp $ */
/*
* Copyright (c) 2002 CubeSoft Communications, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistribution of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Neither the name of CubeSoft Communications, nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <sys/audioio.h>
static void sun_panic(int fd, char *s)
{
perror(s);
close(fd);
esd_audio_fd = -1;
}
#define ARCH_esd_audio_devices
const char *esd_audio_devices()
{
return "/dev/audio";
}
#define ARCH_esd_audio_open
int esd_audio_open()
{
const char *device;
int afd = -1;
int fmt = 0, channels = 0;
int mode = O_WRONLY;
audio_encoding_t enc;
audio_info_t info;
AUDIO_INITINFO(&info);
/* set the appropriate mode */
if((esd_audio_format & ESD_MASK_FUNC) == ESD_RECORD) {
mode = O_RDWR;
info.mode = AUMODE_PLAY | AUMODE_RECORD;
} else {
info.mode = AUMODE_PLAY;
}
mode |= O_NONBLOCK;
/* open the sound device */
device = esd_audio_device ? esd_audio_device : "/dev/audio";
if ((afd = open(device, mode, 0)) == -1) {
perror(device);
return( -2 );
}
mode = fcntl(afd, F_GETFL);
mode &= ~O_NONBLOCK;
fcntl(afd, F_SETFL, mode);
/* set the requested mode */
if(ioctl(afd, AUDIO_SETINFO, &info) < 0) {
sun_panic(afd, "AUDIO_SETINFO");
return(-1);
}
/* set full-duplex mode if we are recording */
if ( (esd_audio_format & ESD_MASK_FUNC) == ESD_RECORD ) {
if (ioctl(afd, AUDIO_SETFD, 1) == -1) {
sun_panic(afd, "AUDIO_SETFD");
return(-1);
}
}
/* pick a supported encoding */
#if defined(WORDS_BIGENDIAN)
fmt = ( (esd_audio_format & ESD_MASK_BITS) == ESD_BITS16 )
? /* 16 bit */ AUDIO_ENCODING_SLINEAR_BE
: /* 8 bit */ AUDIO_ENCODING_PCM8;
#else
fmt = ( (esd_audio_format & ESD_MASK_BITS) == ESD_BITS16 )
? /* 16 bit */ AUDIO_ENCODING_SLINEAR_LE
: /* 8 bit */ AUDIO_ENCODING_PCM8;
#endif
enc.index = 0;
while(!ioctl(afd, AUDIO_GETENC, &enc) && enc.encoding != fmt) {
enc.index++;
}
/* number of channels */
channels = (((esd_audio_format & ESD_MASK_CHAN) == ESD_STEREO)
? /* stereo */ 2
: /* mono */ 1);
info.play.channels = channels;
if((esd_audio_format & ESD_MASK_FUNC) == ESD_RECORD) {
info.record.channels = channels;
}
info.play.encoding = fmt;
info.play.precision = enc.precision;
if(ioctl(afd, AUDIO_SETINFO, &info) == -1) {
fprintf(stderr, "Unsupported encoding: %i-bit \"%s\" (0x%x)\n",
enc.precision, enc.name, fmt);
sun_panic(afd, "SETINFO");
return(-1);
}
/* finally, set the sample rate */
info.play.sample_rate = esd_audio_rate;
if(ioctl(afd, AUDIO_SETINFO, &info) < 0 ||
fabs(info.play.sample_rate - esd_audio_rate) > esd_audio_rate * 0.05) {
fprintf(stderr, "Unsupported rate: %i Hz\n", esd_audio_rate);
sun_panic(afd, "SETINFO");
return(-1);
}
return(esd_audio_fd = afd);
}
#define ARCH_esd_audio_pause
void esd_audio_pause()
{
audio_info_t info;
int afd = esd_audio_fd;
AUDIO_INITINFO(&info);
if(ioctl(afd, AUDIO_GETINFO, &info) < 0) {
sun_panic(afd, "AUDIO_GETINFO");
return;
}
if((info.mode & AUMODE_PLAY) == AUMODE_PLAY)
info.play.pause = !info.play.pause;
if((info.mode & AUMODE_RECORD) == AUMODE_RECORD)
info.record.pause = !info.record.pause;
return;
}