Mercurial > audio-send
diff Alc/backends/solaris.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Alc/backends/solaris.c Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,282 @@ 1.4 +/** 1.5 + * OpenAL cross platform audio library 1.6 + * Copyright (C) 1999-2007 by authors. 1.7 + * This library is free software; you can redistribute it and/or 1.8 + * modify it under the terms of the GNU Library General Public 1.9 + * License as published by the Free Software Foundation; either 1.10 + * version 2 of the License, or (at your option) any later version. 1.11 + * 1.12 + * This library is distributed in the hope that it will be useful, 1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.15 + * Library General Public License for more details. 1.16 + * 1.17 + * You should have received a copy of the GNU Library General Public 1.18 + * License along with this library; if not, write to the 1.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 1.20 + * Boston, MA 02111-1307, USA. 1.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 1.22 + */ 1.23 + 1.24 +#include "config.h" 1.25 + 1.26 +#include <sys/ioctl.h> 1.27 +#include <sys/types.h> 1.28 +#include <sys/stat.h> 1.29 +#include <fcntl.h> 1.30 +#include <stdlib.h> 1.31 +#include <stdio.h> 1.32 +#include <memory.h> 1.33 +#include <unistd.h> 1.34 +#include <errno.h> 1.35 +#include <math.h> 1.36 +#include "alMain.h" 1.37 +#include "AL/al.h" 1.38 +#include "AL/alc.h" 1.39 + 1.40 +#include <sys/audioio.h> 1.41 + 1.42 + 1.43 +static const ALCchar solaris_device[] = "Solaris Default"; 1.44 + 1.45 +typedef struct { 1.46 + int fd; 1.47 + volatile int killNow; 1.48 + ALvoid *thread; 1.49 + 1.50 + ALubyte *mix_data; 1.51 + int data_size; 1.52 +} solaris_data; 1.53 + 1.54 + 1.55 +static ALuint SolarisProc(ALvoid *ptr) 1.56 +{ 1.57 + ALCdevice *pDevice = (ALCdevice*)ptr; 1.58 + solaris_data *data = (solaris_data*)pDevice->ExtraData; 1.59 + ALint frameSize; 1.60 + int wrote; 1.61 + 1.62 + SetRTPriority(); 1.63 + 1.64 + frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 1.65 + 1.66 + while(!data->killNow && pDevice->Connected) 1.67 + { 1.68 + ALint len = data->data_size; 1.69 + ALubyte *WritePtr = data->mix_data; 1.70 + 1.71 + aluMixData(pDevice, WritePtr, len/frameSize); 1.72 + while(len > 0 && !data->killNow) 1.73 + { 1.74 + wrote = write(data->fd, WritePtr, len); 1.75 + if(wrote < 0) 1.76 + { 1.77 + if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) 1.78 + { 1.79 + ERR("write failed: %s\n", strerror(errno)); 1.80 + aluHandleDisconnect(pDevice); 1.81 + break; 1.82 + } 1.83 + 1.84 + Sleep(1); 1.85 + continue; 1.86 + } 1.87 + 1.88 + len -= wrote; 1.89 + WritePtr += wrote; 1.90 + } 1.91 + } 1.92 + 1.93 + return 0; 1.94 +} 1.95 + 1.96 + 1.97 +static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *deviceName) 1.98 +{ 1.99 + char driver[64]; 1.100 + solaris_data *data; 1.101 + 1.102 + strncpy(driver, GetConfigValue("solaris", "device", "/dev/audio"), sizeof(driver)-1); 1.103 + driver[sizeof(driver)-1] = 0; 1.104 + 1.105 + if(!deviceName) 1.106 + deviceName = solaris_device; 1.107 + else if(strcmp(deviceName, solaris_device) != 0) 1.108 + return ALC_FALSE; 1.109 + 1.110 + data = (solaris_data*)calloc(1, sizeof(solaris_data)); 1.111 + data->killNow = 0; 1.112 + 1.113 + data->fd = open(driver, O_WRONLY); 1.114 + if(data->fd == -1) 1.115 + { 1.116 + free(data); 1.117 + ERR("Could not open %s: %s\n", driver, strerror(errno)); 1.118 + return ALC_FALSE; 1.119 + } 1.120 + 1.121 + device->szDeviceName = strdup(deviceName); 1.122 + device->ExtraData = data; 1.123 + return ALC_TRUE; 1.124 +} 1.125 + 1.126 +static void solaris_close_playback(ALCdevice *device) 1.127 +{ 1.128 + solaris_data *data = (solaris_data*)device->ExtraData; 1.129 + 1.130 + close(data->fd); 1.131 + free(data); 1.132 + device->ExtraData = NULL; 1.133 +} 1.134 + 1.135 +static ALCboolean solaris_reset_playback(ALCdevice *device) 1.136 +{ 1.137 + solaris_data *data = (solaris_data*)device->ExtraData; 1.138 + audio_info_t info; 1.139 + ALuint frameSize; 1.140 + int numChannels; 1.141 + 1.142 + AUDIO_INITINFO(&info); 1.143 + 1.144 + info.play.sample_rate = device->Frequency; 1.145 + 1.146 + if(device->FmtChans != DevFmtMono) 1.147 + device->FmtChans = DevFmtStereo; 1.148 + numChannels = ChannelsFromDevFmt(device->FmtChans); 1.149 + info.play.channels = numChannels; 1.150 + 1.151 + switch(device->FmtType) 1.152 + { 1.153 + case DevFmtByte: 1.154 + info.play.precision = 8; 1.155 + info.play.encoding = AUDIO_ENCODING_LINEAR; 1.156 + break; 1.157 + case DevFmtUByte: 1.158 + info.play.precision = 8; 1.159 + info.play.encoding = AUDIO_ENCODING_LINEAR8; 1.160 + break; 1.161 + case DevFmtUShort: 1.162 + case DevFmtFloat: 1.163 + device->FmtType = DevFmtShort; 1.164 + /* fall-through */ 1.165 + case DevFmtShort: 1.166 + info.play.precision = 16; 1.167 + info.play.encoding = AUDIO_ENCODING_LINEAR; 1.168 + break; 1.169 + } 1.170 + 1.171 + frameSize = numChannels * BytesFromDevFmt(device->FmtType); 1.172 + info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize; 1.173 + 1.174 + if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0) 1.175 + { 1.176 + ERR("ioctl failed: %s\n", strerror(errno)); 1.177 + return ALC_FALSE; 1.178 + } 1.179 + 1.180 + if(ChannelsFromDevFmt(device->FmtChans) != info.play.channels) 1.181 + { 1.182 + ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels); 1.183 + return ALC_FALSE; 1.184 + } 1.185 + 1.186 + if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && 1.187 + device->FmtType == DevFmtByte) || 1.188 + (info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && 1.189 + device->FmtType == DevFmtUByte) || 1.190 + (info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && 1.191 + device->FmtType == DevFmtShort))) 1.192 + { 1.193 + ERR("Could not set %#x sample type, got %d (%#x)\n", 1.194 + device->FmtType, info.play.precision, info.play.encoding); 1.195 + return ALC_FALSE; 1.196 + } 1.197 + 1.198 + if(device->Frequency != info.play.sample_rate) 1.199 + { 1.200 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 1.201 + ERR("Failed to set requested frequency %dhz, got %dhz instead\n", device->Frequency, info.play.sample_rate); 1.202 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 1.203 + device->Frequency = info.play.sample_rate; 1.204 + } 1.205 + device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1; 1.206 + 1.207 + data->data_size = device->UpdateSize * frameSize; 1.208 + data->mix_data = calloc(1, data->data_size); 1.209 + 1.210 + SetDefaultChannelOrder(device); 1.211 + 1.212 + data->thread = StartThread(SolarisProc, device); 1.213 + if(data->thread == NULL) 1.214 + { 1.215 + free(data->mix_data); 1.216 + data->mix_data = NULL; 1.217 + return ALC_FALSE; 1.218 + } 1.219 + 1.220 + return ALC_TRUE; 1.221 +} 1.222 + 1.223 +static void solaris_stop_playback(ALCdevice *device) 1.224 +{ 1.225 + solaris_data *data = (solaris_data*)device->ExtraData; 1.226 + 1.227 + if(!data->thread) 1.228 + return; 1.229 + 1.230 + data->killNow = 1; 1.231 + StopThread(data->thread); 1.232 + data->thread = NULL; 1.233 + 1.234 + data->killNow = 0; 1.235 + if(ioctl(data->fd, AUDIO_DRAIN) < 0) 1.236 + ERR("Error draining device: %s\n", strerror(errno)); 1.237 + 1.238 + free(data->mix_data); 1.239 + data->mix_data = NULL; 1.240 +} 1.241 + 1.242 + 1.243 +static const BackendFuncs solaris_funcs = { 1.244 + solaris_open_playback, 1.245 + solaris_close_playback, 1.246 + solaris_reset_playback, 1.247 + solaris_stop_playback, 1.248 + NULL, 1.249 + NULL, 1.250 + NULL, 1.251 + NULL, 1.252 + NULL, 1.253 + NULL 1.254 +}; 1.255 + 1.256 +ALCboolean alc_solaris_init(BackendFuncs *func_list) 1.257 +{ 1.258 + *func_list = solaris_funcs; 1.259 + return ALC_TRUE; 1.260 +} 1.261 + 1.262 +void alc_solaris_deinit(void) 1.263 +{ 1.264 +} 1.265 + 1.266 +void alc_solaris_probe(enum DevProbe type) 1.267 +{ 1.268 +#ifdef HAVE_STAT 1.269 + struct stat buf; 1.270 + if(stat(GetConfigValue("solaris", "device", "/dev/audio"), &buf) != 0) 1.271 + return; 1.272 +#endif 1.273 + 1.274 + switch(type) 1.275 + { 1.276 + case DEVICE_PROBE: 1.277 + AppendDeviceList(solaris_device); 1.278 + break; 1.279 + case ALL_DEVICE_PROBE: 1.280 + AppendAllDeviceList(solaris_device); 1.281 + break; 1.282 + case CAPTURE_DEVICE_PROBE: 1.283 + break; 1.284 + } 1.285 +}