1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions - Sun
4 Copyright (C) Matthew Chapman 2003
5 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6 Copyright (C) Michael Gernoth mike@zerfleddert.de 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include <sys/ioctl.h>
28 #include <sys/audioio.h>
30 #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
37 BOOL This
->dsp_bu
= False
;
38 static BOOL g_reopened
;
39 static BOOL g_swapaudio
;
40 static short g_samplewidth
;
42 static struct audio_packet
47 } packet_queue
[MAX_QUEUE
];
48 static unsigned int queue_hi
, queue_lo
;
53 char *dsp_dev
= getenv("AUDIODEV");
57 dsp_dev
= xstrdup("/dev/audio");
60 if ((This
->dsp_
= open(dsp_dev
, O_WRONLY
| O_NONBLOCK
)) == -1)
66 /* Non-blocking so that user interface is responsive */
67 fcntl(This
->dsp_
, F_SETFL
, fcntl(This
->dsp_
, F_GETFL
) | O_NONBLOCK
);
69 queue_lo
= queue_hi
= 0;
78 /* Ack all remaining packets */
79 while (queue_lo
!= queue_hi
)
81 rdpsnd_send_completion(packet_queue
[queue_lo
].tick
, packet_queue
[queue_lo
].index
);
82 free(packet_queue
[queue_lo
].s
.data
);
83 queue_lo
= (queue_lo
+ 1) % MAX_QUEUE
;
86 #if defined I_FLUSH && defined FLUSHW
87 /* Flush the audiobuffer */
88 ioctl(This
->dsp_
, I_FLUSH
, FLUSHW
);
90 #if defined AUDIO_FLUSH
91 ioctl(This
->dsp_
, AUDIO_FLUSH
, NULL
);
97 wave_out_format_supported(WAVEFORMATEX
* pwfx
)
99 if (pwfx
->wFormatTag
!= WAVE_FORMAT_PCM
)
101 if ((pwfx
->nChannels
!= 1) && (pwfx
->nChannels
!= 2))
103 if ((pwfx
->wBitsPerSample
!= 8) && (pwfx
->wBitsPerSample
!= 16))
110 wave_out_set_format(WAVEFORMATEX
* pwfx
)
114 ioctl(This
->dsp_
, AUDIO_DRAIN
, 0);
116 AUDIO_INITINFO(&info
);
119 if (pwfx
->wBitsPerSample
== 8)
121 info
.play
.encoding
= AUDIO_ENCODING_LINEAR8
;
123 else if (pwfx
->wBitsPerSample
== 16)
125 info
.play
.encoding
= AUDIO_ENCODING_LINEAR
;
126 /* Do we need to swap the 16bit values? (Are we BigEndian) */
134 g_samplewidth
= pwfx
->wBitsPerSample
/ 8;
136 if (pwfx
->nChannels
== 1)
138 info
.play
.channels
= 1;
140 else if (pwfx
->nChannels
== 2)
142 info
.play
.channels
= 2;
146 info
.play
.sample_rate
= pwfx
->nSamplesPerSec
;
147 info
.play
.precision
= pwfx
->wBitsPerSample
;
148 info
.play
.samples
= 0;
153 if (ioctl(This
->dsp_
, AUDIO_SETINFO
, &info
) == -1)
155 perror("AUDIO_SETINFO");
164 wave_out_volume(uint16 left
, uint16 right
)
170 AUDIO_INITINFO(&info
);
172 volume
= (left
> right
) ? left
: right
;
174 if (volume
/ AUDIO_MID_BALANCE
!= 0)
177 AUDIO_MID_BALANCE
- (left
/ (volume
/ AUDIO_MID_BALANCE
)) +
178 (right
/ (volume
/ AUDIO_MID_BALANCE
));
182 balance
= AUDIO_MID_BALANCE
;
185 info
.play
.gain
= volume
/ (65536 / AUDIO_MAX_GAIN
);
186 info
.play
.balance
= balance
;
188 if (ioctl(This
->dsp_
, AUDIO_SETINFO
, &info
) == -1)
190 perror("AUDIO_SETINFO");
196 wave_out_write(STREAM s
, uint16 tick
, uint8 index
)
198 struct audio_packet
*packet
= &packet_queue
[queue_hi
];
199 unsigned int next_hi
= (queue_hi
+ 1) % MAX_QUEUE
;
201 if (next_hi
== queue_lo
)
203 error("No space to queue audio packet\n");
211 packet
->index
= index
;
214 /* we steal the data buffer from s, give it a new one */
215 s
->data
= malloc(s
->size
);
224 struct audio_packet
*packet
;
230 static BOOL swapped
= False
;
231 static BOOL sentcompletion
= True
;
232 static uint32 samplecnt
= 0;
233 static uint32 numsamples
;
239 /* Device was just (re)openend */
242 sentcompletion
= True
;
246 if (queue_lo
== queue_hi
)
252 packet
= &packet_queue
[queue_lo
];
255 /* Swap the current packet, but only once */
256 if (g_swapaudio
&& !swapped
)
258 for (i
= 0; i
< out
->end
- out
->p
; i
+= 2)
260 swap
= *(out
->p
+ i
);
261 *(out
->p
+ i
) = *(out
->p
+ i
+ 1);
262 *(out
->p
+ i
+ 1) = swap
;
269 sentcompletion
= False
;
270 numsamples
= (out
->end
- out
->p
) / g_samplewidth
;
275 if (out
->end
!= out
->p
)
277 len
= write(This
->dsp_
, out
->p
, out
->end
- out
->p
);
280 if (errno
!= EWOULDBLOCK
)
281 perror("write audio");
288 if (out
->p
== out
->end
)
290 if (ioctl(This
->dsp_
, AUDIO_GETINFO
, &info
) == -1)
292 perror("AUDIO_GETINFO");
296 /* Ack the packet, if we have played at least 70% */
297 if (info
.play
.samples
>= samplecnt
+ ((numsamples
* 7) / 10))
299 samplecnt
+= numsamples
;
300 rdpsnd_send_completion(packet
->tick
, packet
->index
);
302 queue_lo
= (queue_lo
+ 1) % MAX_QUEUE
;
304 sentcompletion
= True
;