2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
23 #include <sys/ioctl.h>
24 #include <sys/types.h>
37 #include <sys/audioio.h>
40 static const ALCchar solaris_device
[] = "Solaris Default";
52 static ALuint
SolarisProc(ALvoid
*ptr
)
54 ALCdevice
*pDevice
= (ALCdevice
*)ptr
;
55 solaris_data
*data
= (solaris_data
*)pDevice
->ExtraData
;
61 frameSize
= FrameSizeFromDevFmt(pDevice
->FmtChans
, pDevice
->FmtType
);
63 while(!data
->killNow
&& pDevice
->Connected
)
65 ALint len
= data
->data_size
;
66 ALubyte
*WritePtr
= data
->mix_data
;
68 aluMixData(pDevice
, WritePtr
, len
/frameSize
);
69 while(len
> 0 && !data
->killNow
)
71 wrote
= write(data
->fd
, WritePtr
, len
);
74 if(errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
&& errno
!= EINTR
)
76 ERR("write failed: %s\n", strerror(errno
));
77 aluHandleDisconnect(pDevice
);
94 static ALCenum
solaris_open_playback(ALCdevice
*device
, const ALCchar
*deviceName
)
99 strncpy(driver
, GetConfigValue("solaris", "device", "/dev/audio"), sizeof(driver
)-1);
100 driver
[sizeof(driver
)-1] = 0;
103 deviceName
= solaris_device
;
104 else if(strcmp(deviceName
, solaris_device
) != 0)
105 return ALC_INVALID_VALUE
;
107 data
= (solaris_data
*)calloc(1, sizeof(solaris_data
));
110 data
->fd
= open(driver
, O_WRONLY
);
114 ERR("Could not open %s: %s\n", driver
, strerror(errno
));
115 return ALC_INVALID_VALUE
;
118 device
->szDeviceName
= strdup(deviceName
);
119 device
->ExtraData
= data
;
123 static void solaris_close_playback(ALCdevice
*device
)
125 solaris_data
*data
= (solaris_data
*)device
->ExtraData
;
129 device
->ExtraData
= NULL
;
132 static ALCboolean
solaris_reset_playback(ALCdevice
*device
)
134 solaris_data
*data
= (solaris_data
*)device
->ExtraData
;
139 AUDIO_INITINFO(&info
);
141 info
.play
.sample_rate
= device
->Frequency
;
143 if(device
->FmtChans
!= DevFmtMono
)
144 device
->FmtChans
= DevFmtStereo
;
145 numChannels
= ChannelsFromDevFmt(device
->FmtChans
);
146 info
.play
.channels
= numChannels
;
148 switch(device
->FmtType
)
151 info
.play
.precision
= 8;
152 info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
155 info
.play
.precision
= 8;
156 info
.play
.encoding
= AUDIO_ENCODING_LINEAR8
;
160 device
->FmtType
= DevFmtShort
;
163 info
.play
.precision
= 16;
164 info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
168 frameSize
= numChannels
* BytesFromDevFmt(device
->FmtType
);
169 info
.play
.buffer_size
= device
->UpdateSize
*device
->NumUpdates
* frameSize
;
171 if(ioctl(data
->fd
, AUDIO_SETINFO
, &info
) < 0)
173 ERR("ioctl failed: %s\n", strerror(errno
));
177 if(ChannelsFromDevFmt(device
->FmtChans
) != info
.play
.channels
)
179 ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device
->FmtChans
), info
.play
.channels
);
183 if(!((info
.play
.precision
== 8 && info
.play
.encoding
== AUDIO_ENCODING_LINEAR
&&
184 device
->FmtType
== DevFmtByte
) ||
185 (info
.play
.precision
== 8 && info
.play
.encoding
== AUDIO_ENCODING_LINEAR8
&&
186 device
->FmtType
== DevFmtUByte
) ||
187 (info
.play
.precision
== 16 && info
.play
.encoding
== AUDIO_ENCODING_LINEAR
&&
188 device
->FmtType
== DevFmtShort
)))
190 ERR("Could not set %#x sample type, got %d (%#x)\n",
191 device
->FmtType
, info
.play
.precision
, info
.play
.encoding
);
195 if(device
->Frequency
!= info
.play
.sample_rate
)
197 if((device
->Flags
&DEVICE_FREQUENCY_REQUEST
))
198 ERR("Failed to set requested frequency %dhz, got %dhz instead\n", device
->Frequency
, info
.play
.sample_rate
);
199 device
->Flags
&= ~DEVICE_FREQUENCY_REQUEST
;
200 device
->Frequency
= info
.play
.sample_rate
;
202 device
->UpdateSize
= (info
.play
.buffer_size
/device
->NumUpdates
) + 1;
204 data
->data_size
= device
->UpdateSize
* frameSize
;
205 data
->mix_data
= calloc(1, data
->data_size
);
207 SetDefaultChannelOrder(device
);
209 data
->thread
= StartThread(SolarisProc
, device
);
210 if(data
->thread
== NULL
)
212 free(data
->mix_data
);
213 data
->mix_data
= NULL
;
220 static void solaris_stop_playback(ALCdevice
*device
)
222 solaris_data
*data
= (solaris_data
*)device
->ExtraData
;
228 StopThread(data
->thread
);
232 if(ioctl(data
->fd
, AUDIO_DRAIN
) < 0)
233 ERR("Error draining device: %s\n", strerror(errno
));
235 free(data
->mix_data
);
236 data
->mix_data
= NULL
;
240 static const BackendFuncs solaris_funcs
= {
241 solaris_open_playback
,
242 solaris_close_playback
,
243 solaris_reset_playback
,
244 solaris_stop_playback
,
253 ALCboolean
alc_solaris_init(BackendFuncs
*func_list
)
255 *func_list
= solaris_funcs
;
259 void alc_solaris_deinit(void)
263 void alc_solaris_probe(enum DevProbe type
)
267 if(stat(GetConfigValue("solaris", "device", "/dev/audio"), &buf
) != 0)
274 AppendDeviceList(solaris_device
);
276 case ALL_DEVICE_PROBE
:
277 AppendAllDeviceList(solaris_device
);
279 case CAPTURE_DEVICE_PROBE
: