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.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
23 #include <sys/ioctl.h>
24 #include <sys/types.h>
39 #include <sys/audioio.h>
42 static const ALCchar solaris_device
[] = "Solaris Default";
44 static const char *solaris_driver
= "/dev/audio";
57 static int SolarisProc(void *ptr
)
59 ALCdevice
*Device
= (ALCdevice
*)ptr
;
60 solaris_data
*data
= (solaris_data
*)Device
->ExtraData
;
65 althrd_setname(althrd_current(), MIXER_THREAD_NAME
);
67 frameSize
= FrameSizeFromDevFmt(Device
->FmtChans
, Device
->FmtType
);
69 while(!data
->killNow
&& Device
->Connected
)
71 ALint len
= data
->data_size
;
72 ALubyte
*WritePtr
= data
->mix_data
;
74 aluMixData(Device
, WritePtr
, len
/frameSize
);
75 while(len
> 0 && !data
->killNow
)
77 wrote
= write(data
->fd
, WritePtr
, len
);
80 if(errno
!= EAGAIN
&& errno
!= EWOULDBLOCK
&& errno
!= EINTR
)
82 ERR("write failed: %s\n", strerror(errno
));
83 ALCdevice_Lock(Device
);
84 aluHandleDisconnect(Device
);
85 ALCdevice_Unlock(Device
);
102 static ALCenum
solaris_open_playback(ALCdevice
*device
, const ALCchar
*deviceName
)
107 deviceName
= solaris_device
;
108 else if(strcmp(deviceName
, solaris_device
) != 0)
109 return ALC_INVALID_VALUE
;
111 data
= (solaris_data
*)calloc(1, sizeof(solaris_data
));
114 data
->fd
= open(solaris_driver
, O_WRONLY
);
118 ERR("Could not open %s: %s\n", solaris_driver
, strerror(errno
));
119 return ALC_INVALID_VALUE
;
122 al_string_copy_cstr(&device
->DeviceName
, deviceName
);
123 device
->ExtraData
= data
;
127 static void solaris_close_playback(ALCdevice
*device
)
129 solaris_data
*data
= (solaris_data
*)device
->ExtraData
;
133 device
->ExtraData
= NULL
;
136 static ALCboolean
solaris_reset_playback(ALCdevice
*device
)
138 solaris_data
*data
= (solaris_data
*)device
->ExtraData
;
143 AUDIO_INITINFO(&info
);
145 info
.play
.sample_rate
= device
->Frequency
;
147 if(device
->FmtChans
!= DevFmtMono
)
148 device
->FmtChans
= DevFmtStereo
;
149 numChannels
= ChannelsFromDevFmt(device
->FmtChans
);
150 info
.play
.channels
= numChannels
;
152 switch(device
->FmtType
)
155 info
.play
.precision
= 8;
156 info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
159 info
.play
.precision
= 8;
160 info
.play
.encoding
= AUDIO_ENCODING_LINEAR8
;
166 device
->FmtType
= DevFmtShort
;
169 info
.play
.precision
= 16;
170 info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
174 frameSize
= numChannels
* BytesFromDevFmt(device
->FmtType
);
175 info
.play
.buffer_size
= device
->UpdateSize
*device
->NumUpdates
* frameSize
;
177 if(ioctl(data
->fd
, AUDIO_SETINFO
, &info
) < 0)
179 ERR("ioctl failed: %s\n", strerror(errno
));
183 if(ChannelsFromDevFmt(device
->FmtChans
) != info
.play
.channels
)
185 ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device
->FmtChans
), info
.play
.channels
);
189 if(!((info
.play
.precision
== 8 && info
.play
.encoding
== AUDIO_ENCODING_LINEAR8
&& device
->FmtType
== DevFmtUByte
) ||
190 (info
.play
.precision
== 8 && info
.play
.encoding
== AUDIO_ENCODING_LINEAR
&& device
->FmtType
== DevFmtByte
) ||
191 (info
.play
.precision
== 16 && info
.play
.encoding
== AUDIO_ENCODING_LINEAR
&& device
->FmtType
== DevFmtShort
) ||
192 (info
.play
.precision
== 32 && info
.play
.encoding
== AUDIO_ENCODING_LINEAR
&& device
->FmtType
== DevFmtInt
)))
194 ERR("Could not set %s samples, got %d (0x%x)\n", DevFmtTypeString(device
->FmtType
),
195 info
.play
.precision
, info
.play
.encoding
);
199 device
->Frequency
= info
.play
.sample_rate
;
200 device
->UpdateSize
= (info
.play
.buffer_size
/device
->NumUpdates
) + 1;
202 SetDefaultChannelOrder(device
);
207 static ALCboolean
solaris_start_playback(ALCdevice
*device
)
209 solaris_data
*data
= (solaris_data
*)device
->ExtraData
;
211 data
->data_size
= device
->UpdateSize
* FrameSizeFromDevFmt(device
->FmtChans
, device
->FmtType
);
212 data
->mix_data
= calloc(1, data
->data_size
);
215 if(althrd_create(&data
->thread
, SolarisProc
, device
) != althrd_success
)
217 free(data
->mix_data
);
218 data
->mix_data
= NULL
;
225 static void solaris_stop_playback(ALCdevice
*device
)
227 solaris_data
*data
= (solaris_data
*)device
->ExtraData
;
234 althrd_join(data
->thread
, &res
);
236 if(ioctl(data
->fd
, AUDIO_DRAIN
) < 0)
237 ERR("Error draining device: %s\n", strerror(errno
));
239 free(data
->mix_data
);
240 data
->mix_data
= NULL
;
244 static const BackendFuncs solaris_funcs
= {
245 solaris_open_playback
,
246 solaris_close_playback
,
247 solaris_reset_playback
,
248 solaris_start_playback
,
249 solaris_stop_playback
,
256 ALCdevice_GetLatencyDefault
259 ALCboolean
alc_solaris_init(BackendFuncs
*func_list
)
261 ConfigValueStr("solaris", "device", &solaris_driver
);
263 *func_list
= solaris_funcs
;
267 void alc_solaris_deinit(void)
271 void alc_solaris_probe(enum DevProbe type
)
275 case ALL_DEVICE_PROBE
:
279 if(stat(solaris_driver
, &buf
) == 0)
281 AppendAllDevicesList(solaris_device
);
285 case CAPTURE_DEVICE_PROBE
: