2019-09-01 21:47:54 +01:00

186 lines
4.8 KiB
C

/*
* $Id: be3drv.c 1.0 1998/10/12 00:33:08 chasan Exp $
*
* Intel BeOS Release 3 audio driver.
*
* Copyright (C) 1998-1999 Carlos Hasan
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include "BeOS/old_audio_driver.h"
#include "audio.h"
#include "drivers.h"
#define BUFFERSIZE (1 << 12)
/*
* BeOS driver configuration structure
*/
static struct {
int nHandle;
char szDeviceName[MAXNAMLEN];
BYTE aBuffer[sizeof(audio_buffer_header) + BUFFERSIZE];
LPFNAUDIOWAVE lpfnAudioWave;
} Audio;
/*
* BeOS driver API interface
*/
static UINT AIAPI GetAudioCaps(LPAUDIOCAPS lpCaps)
{
static AUDIOCAPS Caps =
{
AUDIO_PRODUCT_BEOSR3, "BeOS R3 Sound Driver",
AUDIO_FORMAT_1M08 | AUDIO_FORMAT_1S08 |
AUDIO_FORMAT_1M16 | AUDIO_FORMAT_1S16 |
AUDIO_FORMAT_2M08 | AUDIO_FORMAT_2S08 |
AUDIO_FORMAT_2M16 | AUDIO_FORMAT_2S16 |
AUDIO_FORMAT_4M08 | AUDIO_FORMAT_4S08 |
AUDIO_FORMAT_4M16 | AUDIO_FORMAT_4S16
};
memcpy(lpCaps, &Caps, sizeof(AUDIOCAPS));
return AUDIO_ERROR_NONE;
}
static UINT AIAPI PingAudio(VOID)
{
DIR *dir;
struct dirent *entry;
/* first try the default sound device */
strcpy(Audio.szDeviceName, "/dev/old/sound");
if (access(Audio.szDeviceName, W_OK) == 0)
return AUDIO_ERROR_NONE;
/* search an old audio device */
if ((dir = opendir("/dev/old")) != 0) {
while ((entry = readdir(dir)) != 0) {
if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) {
strcat(strcpy(Audio.szDeviceName, "/dev/old/"), entry->d_name);
if (access(Audio.szDeviceName, W_OK) == 0) {
closedir(dir);
return AUDIO_ERROR_NONE;
}
}
}
closedir(dir);
}
return AUDIO_ERROR_NODEVICE;
}
static UINT AIAPI OpenAudio(LPAUDIOINFO lpInfo)
{
static int sample_rates[] = {
5510, B_AUDIO_SAMPLE_RATE_5510,
6620, B_AUDIO_SAMPLE_RATE_6620,
8000, B_AUDIO_SAMPLE_RATE_8000,
9600, B_AUDIO_SAMPLE_RATE_9600,
11025, B_AUDIO_SAMPLE_RATE_11025,
16000, B_AUDIO_SAMPLE_RATE_16000,
18900, B_AUDIO_SAMPLE_RATE_18900,
22050, B_AUDIO_SAMPLE_RATE_22050,
27420, B_AUDIO_SAMPLE_RATE_27420,
32000, B_AUDIO_SAMPLE_RATE_32000,
33075, B_AUDIO_SAMPLE_RATE_33075,
37800, B_AUDIO_SAMPLE_RATE_37800,
44100, B_AUDIO_SAMPLE_RATE_44100,
48000, B_AUDIO_SAMPLE_RATE_48000 };
struct audio_params params;
int index;
memset(&Audio, 0, sizeof(Audio));
/* search an old audio device for playback */
if (PingAudio() != AUDIO_ERROR_NONE)
return AUDIO_ERROR_NODEVICE;
/* try to open audio device for playback */
if ((Audio.nHandle = open(Audio.szDeviceName, O_WRONLY)) < 0)
return AUDIO_ERROR_DEVICEBUSY;
/* setup audio playback encoding format and sampling frequency */
if (ioctl(Audio.nHandle, B_AUDIO_GET_PARAMS, &params) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_NODEVICE;
}
for (index = 0; index < 2*13; index += 2) {
if (sample_rates[index] >= lpInfo->nSampleRate)
break;
}
lpInfo->nSampleRate = sample_rates[index];
params.sample_rate = sample_rates[index+1];
lpInfo->wFormat |= AUDIO_FORMAT_STEREO | AUDIO_FORMAT_16BITS;
/* params.playback_format = B_AUDIO_FORMAT_16_BIT_STEREO; */
if (ioctl(Audio.nHandle, B_AUDIO_SET_PARAMS, &params) < 0) {
close(Audio.nHandle);
return AUDIO_ERROR_BADFORMAT;
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI CloseAudio(VOID)
{
/* close DSP audio device */
close(Audio.nHandle);
return AUDIO_ERROR_NONE;
}
static UINT AIAPI UpdateAudio(UINT nFrames)
{
audio_buffer_header *header = (audio_buffer_header *) Audio.aBuffer;
/* compute frame size */
nFrames <<= 2;
if (nFrames <= 0 || nFrames > BUFFERSIZE)
nFrames = BUFFERSIZE;
/* send PCM samples to the DSP audio device */
if (Audio.lpfnAudioWave != NULL) {
Audio.lpfnAudioWave(Audio.aBuffer + sizeof(*header), nFrames);
header->buffer_number = 0;
header->subscriber_count = 0;
header->reserved_1 = sizeof(*header) + nFrames;
ioctl(Audio.nHandle, B_AUDIO_WRITE_BUFFER, header);
}
return AUDIO_ERROR_NONE;
}
static UINT AIAPI SetAudioCallback(LPFNAUDIOWAVE lpfnAudioWave)
{
/* set up DSP audio device user's callback function */
Audio.lpfnAudioWave = lpfnAudioWave;
return AUDIO_ERROR_NONE;
}
/*
* BeOS driver public interface
*/
AUDIOWAVEDRIVER BeOSR3WaveDriver =
{
GetAudioCaps, PingAudio, OpenAudio, CloseAudio,
UpdateAudio, SetAudioCallback
};
AUDIODRIVER BeOSR3Driver =
{
&BeOSR3WaveDriver, NULL
};