VirtualBox

source: vbox/trunk/src/VBox/RDP/client/rdpsnd_libao.c@ 13795

最後變更 在這個檔案從13795是 11982,由 vboxsync 提交於 16 年 前

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 5.2 KB
 
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions - libao-driver
4 Copyright (C) Matthew Chapman 2003-2007
5 Copyright (C) GuoJunBo [email protected] 2003
6 Copyright (C) Michael Gernoth [email protected] 2005-2007
7
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.
12
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.
17
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.
21*/
22
23/*
24 * Sun 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, Sun 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 format.bits = 16;
85 format.channels = 2;
86 format.rate = 44100;
87 format.byte_format = AO_FMT_NATIVE;
88
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 format.bits = pwfx->wBitsPerSample;
124 format.channels = pwfx->nChannels;
125 format.rate = 44100;
126 format.byte_format = AO_FMT_NATIVE;
127
128 if (o_device != NULL)
129 ao_close(o_device);
130
131 o_device = ao_open_live(default_driver, &format, NULL);
132 if (o_device == NULL)
133 {
134 return False;
135 }
136
137 if (rdpsnd_dsp_resample_set(44100, pwfx->wBitsPerSample, pwfx->nChannels) == False)
138 {
139 return False;
140 }
141
142 reopened = True;
143
144 return True;
145}
146
147void
148libao_play(void)
149{
150 struct audio_packet *packet;
151 STREAM out;
152 int len;
153 static long prev_s, prev_us;
154 unsigned int duration;
155 struct timeval tv;
156 int next_tick;
157
158 if (reopened)
159 {
160 reopened = False;
161 gettimeofday(&tv, NULL);
162 prev_s = tv.tv_sec;
163 prev_us = tv.tv_usec;
164 }
165
166 /* We shouldn't be called if the queue is empty, but still */
167 if (rdpsnd_queue_empty())
168 return;
169
170 packet = rdpsnd_queue_current_packet();
171 out = &packet->s;
172
173 next_tick = rdpsnd_queue_next_tick();
174
175 len = (WAVEOUTLEN > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTLEN;
176 ao_play(o_device, (char *) out->p, len);
177 out->p += len;
178
179 gettimeofday(&tv, NULL);
180
181 duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000;
182
183 if (packet->tick > next_tick)
184 next_tick += 65536;
185
186 if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
187 {
188 unsigned int delay_us;
189
190 prev_s = tv.tv_sec;
191 prev_us = tv.tv_usec;
192
193 if (abs((next_tick - packet->tick) - duration) > 20)
194 {
195 DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick));
196 DEBUG(("last: %d, is: %d, should: %d\n", packet->tick,
197 (packet->tick + duration) % 65536, next_tick % 65536));
198 }
199
200 delay_us = ((out->size / 4) * (1000000 / 44100));
201
202 rdpsnd_queue_next(delay_us);
203 }
204}
205
206struct audio_driver *
207libao_register(char *options)
208{
209 static struct audio_driver libao_driver;
210
211 memset(&libao_driver, 0, sizeof(libao_driver));
212
213 libao_driver.name = "libao";
214 libao_driver.description = "libao output driver, default device: system dependent";
215
216 libao_driver.add_fds = libao_add_fds;
217 libao_driver.check_fds = libao_check_fds;
218
219 libao_driver.wave_out_open = libao_open;
220 libao_driver.wave_out_close = libao_close;
221 libao_driver.wave_out_format_supported = rdpsnd_dsp_resample_supported;
222 libao_driver.wave_out_set_format = libao_set_format;
223 libao_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
224
225 libao_driver.need_byteswap_on_be = 1;
226 libao_driver.need_resampling = 1;
227
228 if (options)
229 {
230 libao_device = xstrdup(options);
231 }
232
233 return &libao_driver;
234}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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