VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.4/rdpsnd_libao.c@ 78352

Last change on this file since 78352 was 55123, checked in by vboxsync, 10 years ago

rdesktop 1.8.3 modified for VBox

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 5.3 KB
Line 
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions - libao-driver
4 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
5 Copyright (C) GuoJunBo <[email protected]> 2003
6 Copyright (C) Michael Gernoth <[email protected]> 2005-2008
7 Copyright (C) 2013 Henrik Andersson
8
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23/*
24 * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
25 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
26 * the General Public License version 2 (GPLv2) at this time for any software where
27 * a choice of GPL license versions is made available with the language indicating
28 * that GPLv2 or any later version may be used, or where a choice of which version
29 * of the GPL is applied is otherwise unspecified.
30 */
31
32#include "rdesktop.h"
33#include "rdpsnd.h"
34#include "rdpsnd_dsp.h"
35#include <unistd.h>
36#include <fcntl.h>
37#include <errno.h>
38#include <ao/ao.h>
39#include <sys/time.h>
40
41#define WAVEOUTLEN 16
42
43static ao_device *o_device = NULL;
44static int default_driver;
45static RD_BOOL reopened;
46static char *libao_device = NULL;
47
48void libao_play(void);
49
50void
51libao_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
52{
53 /* We need to be called rather often... */
54 if (o_device != NULL && !rdpsnd_queue_empty())
55 FD_SET(0, wfds);
56}
57
58void
59libao_check_fds(fd_set * rfds, fd_set * wfds)
60{
61 if (o_device == NULL)
62 return;
63
64 if (!rdpsnd_queue_empty())
65 libao_play();
66}
67
68RD_BOOL
69libao_open(void)
70{
71 ao_sample_format format;
72
73 ao_initialize();
74
75 if (libao_device)
76 {
77 default_driver = ao_driver_id(libao_device);
78 }
79 else
80 {
81 default_driver = ao_default_driver_id();
82 }
83
84 memset(&format, 0, sizeof(format));
85 format.bits = 16;
86 format.channels = 2;
87 format.rate = 44100;
88 format.byte_format = AO_FMT_NATIVE;
89
90 o_device = ao_open_live(default_driver, &format, NULL);
91 if (o_device == NULL)
92 {
93 return False;
94 }
95
96 reopened = True;
97
98 return True;
99}
100
101void
102libao_close(void)
103{
104 /* Ack all remaining packets */
105 while (!rdpsnd_queue_empty())
106 {
107 rdpsnd_queue_next(0);
108 }
109
110 if (o_device != NULL)
111 ao_close(o_device);
112
113 o_device = NULL;
114
115 ao_shutdown();
116}
117
118RD_BOOL
119libao_set_format(RD_WAVEFORMATEX * pwfx)
120{
121 ao_sample_format format;
122
123 memset(&format, 0, sizeof(format));
124 format.bits = pwfx->wBitsPerSample;
125 format.channels = pwfx->nChannels;
126 format.rate = 44100;
127 format.byte_format = AO_FMT_NATIVE;
128
129 if (o_device != NULL)
130 ao_close(o_device);
131
132 o_device = ao_open_live(default_driver, &format, NULL);
133 if (o_device == NULL)
134 {
135 return False;
136 }
137
138 if (rdpsnd_dsp_resample_set(44100, pwfx->wBitsPerSample, pwfx->nChannels) == False)
139 {
140 return False;
141 }
142
143 reopened = True;
144
145 return True;
146}
147
148void
149libao_play(void)
150{
151 struct audio_packet *packet;
152 STREAM out;
153 int len;
154 static long prev_s, prev_us;
155 unsigned int duration;
156 struct timeval tv;
157 int next_tick;
158
159 if (reopened)
160 {
161 reopened = False;
162 gettimeofday(&tv, NULL);
163 prev_s = tv.tv_sec;
164 prev_us = tv.tv_usec;
165 }
166
167 /* We shouldn't be called if the queue is empty, but still */
168 if (rdpsnd_queue_empty())
169 return;
170
171 packet = rdpsnd_queue_current_packet();
172 out = &packet->s;
173
174 next_tick = rdpsnd_queue_next_tick();
175
176 len = (WAVEOUTLEN > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTLEN;
177 ao_play(o_device, (char *) out->p, len);
178 out->p += len;
179
180 gettimeofday(&tv, NULL);
181
182 duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000;
183
184 if (packet->tick > next_tick)
185 next_tick += 65536;
186
187 if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
188 {
189 unsigned int delay_us;
190
191 prev_s = tv.tv_sec;
192 prev_us = tv.tv_usec;
193
194 if (abs((next_tick - packet->tick) - duration) > 20)
195 {
196 DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick));
197 DEBUG(("last: %d, is: %d, should: %d\n", packet->tick,
198 (packet->tick + duration) % 65536, next_tick % 65536));
199 }
200
201 delay_us = ((out->size / 4) * (1000000 / 44100));
202
203 rdpsnd_queue_next(delay_us);
204 }
205}
206
207struct audio_driver *
208libao_register(char *options)
209{
210 static struct audio_driver libao_driver;
211
212 memset(&libao_driver, 0, sizeof(libao_driver));
213
214 libao_driver.name = "libao";
215 libao_driver.description = "libao output driver, default device: system dependent";
216
217 libao_driver.add_fds = libao_add_fds;
218 libao_driver.check_fds = libao_check_fds;
219
220 libao_driver.wave_out_open = libao_open;
221 libao_driver.wave_out_close = libao_close;
222 libao_driver.wave_out_format_supported = rdpsnd_dsp_resample_supported;
223 libao_driver.wave_out_set_format = libao_set_format;
224 libao_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
225
226 libao_driver.need_byteswap_on_be = 1;
227 libao_driver.need_resampling = 1;
228
229 if (options)
230 {
231 libao_device = xstrdup(options);
232 }
233
234 return &libao_driver;
235}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette