diff options
-rw-r--r-- | Alc/ALc.c | 3 | ||||
-rw-r--r-- | Alc/solaris.c | 258 | ||||
-rw-r--r-- | CMakeLists.txt | 11 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 1 | ||||
-rw-r--r-- | alsoftrc.sample | 6 | ||||
-rw-r--r-- | config.h.in | 3 |
6 files changed, 281 insertions, 1 deletions
@@ -58,6 +58,9 @@ static struct { #ifdef HAVE_OSS { "oss", alc_oss_init, EmptyFuncs }, #endif +#ifdef HAVE_SOLARIS + { "solaris", alc_solaris_init, EmptyFuncs }, +#endif #ifdef HAVE_DSOUND { "dsound", alcDSoundInit, EmptyFuncs }, #endif diff --git a/Alc/solaris.c b/Alc/solaris.c new file mode 100644 index 00000000..66f41730 --- /dev/null +++ b/Alc/solaris.c @@ -0,0 +1,258 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2007 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <memory.h> +#include <unistd.h> +#include <errno.h> +#include <math.h> +#include "alMain.h" +#include "AL/al.h" +#include "AL/alc.h" + +#include <sys/audioio.h> + + +static char *solaris_device; + +typedef struct { + int fd; + volatile int killNow; + ALvoid *thread; + + ALubyte *mix_data; + int data_size; +} solaris_data; + + +static ALuint SolarisProc(ALvoid *ptr) +{ + ALCdevice *pDevice = (ALCdevice*)ptr; + solaris_data *data = (solaris_data*)pDevice->ExtraData; + int remaining = 0; + int wrote; + + while(!data->killNow) + { + int len = data->data_size - remaining; + + if(len > 0) + { + SuspendContext(NULL); + aluMixData(pDevice->Context, data->mix_data+remaining, len, pDevice->Format); + ProcessContext(NULL); + } + + remaining += len; + wrote = write(data->fd, data->mix_data, remaining); + if(wrote < 0) + { + AL_PRINT("write failed: %s\n", strerror(errno)); + remaining = 0; + } + else if(wrote > 0) + { + remaining -= wrote; + if(remaining > 0) + memmove(data->mix_data, data->mix_data+wrote, remaining); + } + else + Sleep(1); + } + + return 0; +} + + +static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *deviceName) +{ + audio_info_t info; + ALuint frameSize; + char driver[64]; + int numChannels; + solaris_data *data; + + strncpy(driver, GetConfigValue("solaris", "device", "/dev/audio"), sizeof(driver)-1); + driver[sizeof(driver)-1] = 0; + if(deviceName) + { + if(strcmp(deviceName, solaris_device)) + return ALC_FALSE; + device->szDeviceName = solaris_device; + } + else + device->szDeviceName = solaris_device; + + data = (solaris_data*)calloc(1, sizeof(solaris_data)); + data->killNow = 0; + + data->fd = open(driver, O_WRONLY); + if(data->fd == -1) + { + free(data); + AL_PRINT("Could not open %s: %s\n", driver, strerror(errno)); + return ALC_FALSE; + } + + numChannels = aluChannelsFromFormat(device->Format); + AUDIO_INITINFO(&info); + info.play.sample_rate = device->Frequency; + info.play.channels = numChannels; + + switch(aluBytesFromFormat(device->Format)) + { + case 1: + info.play.precision = 8; + info.play.encoding = AUDIO_ENCODING_LINEAR8; + break; + case 2: + info.play.precision = 16; + info.play.encoding = AUDIO_ENCODING_LINEAR; + break; + default: + AL_PRINT("Unknown format?! %x\n", device->Format); + } + + frameSize = numChannels * aluBytesFromFormat(device->Format); + info.play.buffer_size = device->UpdateSize * frameSize; + + if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0) + { + AL_PRINT("ioctl failed: %s\n", strerror(errno)); + close(data->fd); + free(data); + return ALC_FALSE; + } + + device->Frequency = info.play.sample_rate; + + if(aluChannelsFromFormat(device->Format) != info.play.channels) + { + AL_PRINT("Could not set %d channels, got %d instead\n", aluChannelsFromFormat(device->Format), info.play.channels); + close(data->fd); + free(data); + return ALC_FALSE; + } + + if(!((info.play.precision == 8 && aluBytesFromFormat(device->Format) == 1) || + (info.play.precision == 16 && aluBytesFromFormat(device->Format) == 2))) + { + AL_PRINT("Could not set %d-bit output, got %d\n", aluBytesFromFormat(device->Format)*8, info.play.precision); + close(data->fd); + free(data); + return ALC_FALSE; + } + + device->UpdateSize = info.play.buffer_size / 4; + + data->data_size = device->UpdateSize * frameSize; + data->mix_data = calloc(1, data->data_size); + + device->ExtraData = data; + data->thread = StartThread(SolarisProc, device); + if(data->thread == NULL) + { + device->ExtraData = NULL; + free(data->mix_data); + free(data); + return ALC_FALSE; + } + + return ALC_TRUE; +} + +static void solaris_close_playback(ALCdevice *device) +{ + solaris_data *data = (solaris_data*)device->ExtraData; + data->killNow = 1; + StopThread(data->thread); + + close(data->fd); + + free(data->mix_data); + free(data); + device->ExtraData = NULL; +} + + +static ALCboolean solaris_open_capture(ALCdevice *device, const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize) +{ + (void)device; + (void)deviceName; + (void)frequency; + (void)format; + (void)SampleSize; + return ALC_FALSE; +} + +static void solaris_close_capture(ALCdevice *device) +{ + (void)device; +} + +static void solaris_start_capture(ALCdevice *pDevice) +{ + (void)pDevice; +} + +static void solaris_stop_capture(ALCdevice *pDevice) +{ + (void)pDevice; +} + +static void solaris_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples) +{ + (void)pDevice; + (void)pBuffer; + (void)lSamples; +} + +static ALCuint solaris_available_samples(ALCdevice *pDevice) +{ + (void)pDevice; + return 0; +} + + +BackendFuncs solaris_funcs = { + solaris_open_playback, + solaris_close_playback, + solaris_open_capture, + solaris_close_capture, + solaris_start_capture, + solaris_stop_capture, + solaris_capture_samples, + solaris_available_samples +}; + +void alc_solaris_init(BackendFuncs *func_list) +{ + *func_list = solaris_funcs; + + solaris_device = AppendDeviceList("Solaris Software"); + AppendAllDeviceList(solaris_device); +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e22ad27..a2afea99 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE) OPTION(ALSA "Check for ALSA backend" ON) OPTION(OSS "Check for OSS backend" ON) +OPTION(SOLARIS "Check for Solaris backend" ON) OPTION(DSOUND "Check for DirectSound backend" ON) OPTION(WINMM "Check for Windows Multimedia backend" ON) @@ -264,6 +265,16 @@ IF(OSS) ENDIF() ENDIF() +# Check Solaris backend +IF(SOLARIS) + CHECK_INCLUDE_FILE(sys/audioio.h HAVE_SYS_AUDIOIO_H) + IF(HAVE_SYS_AUDIOIO_H) + SET(HAVE_SOLARIS 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/solaris.c) + SET(BACKENDS "${BACKENDS} Solaris,") + ENDIF() +ENDIF() + # Check DSound/MMSystem backend IF(HAVE_WINDOWS_H) IF(DSOUND) diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index aadb71ba..fb9cfb5e 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -144,6 +144,7 @@ typedef struct { void alc_alsa_init(BackendFuncs *func_list); void alc_oss_init(BackendFuncs *func_list); +void alc_solaris_init(BackendFuncs *func_list); void alcDSoundInit(BackendFuncs *func_list); void alcWinMMInit(BackendFuncs *FuncList); void alc_wave_init(BackendFuncs *func_list); diff --git a/alsoftrc.sample b/alsoftrc.sample index acc64b53..ab1faee0 100644 --- a/alsoftrc.sample +++ b/alsoftrc.sample @@ -57,7 +57,7 @@ drivers = # Sets the backend driver list order, comma-seperated. Unknown # backends and duplicated names are ignored, and unlisted backends # won't be considered for use. An empty list means the default. # Default is: - # alsa,oss,dsound,winmm,wave + # alsa,oss,solaris,dsound,winmm,wave [alsa] # ALSA backend stuff device = default # Sets the device name for the default playback device. @@ -82,6 +82,10 @@ periods = 4 # Sets the number of update buffers. Default is 4 capture = /dev/dsp # Sets the device name for OSS capture. Default is /dev/dsp +[solaris] # Solaris backend stuff +device = /dev/audio # Sets the device name for Solaris output. Default is + # /dev/audio + [dsound] # DirectSound backend stuff # Nothing yet... diff --git a/config.h.in b/config.h.in index 7b310f3b..733c348b 100644 --- a/config.h.in +++ b/config.h.in @@ -7,6 +7,9 @@ /* Define if we have the OSS backend */ #cmakedefine HAVE_OSS +/* Define if we have the Solaris backend */ +#cmakedefine HAVE_SOLARIS + /* Define if we have the DSound backend */ #cmakedefine HAVE_DSOUND |