/[rdesktop]/jpeg/rdesktop/trunk/rdpsnd_libao.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /jpeg/rdesktop/trunk/rdpsnd_libao.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1364 - (show annotations)
Thu Jan 4 04:55:56 2007 UTC (17 years, 5 months ago) by jsorg71
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd_libao.c
File MIME type: text/plain
File size: 4785 byte(s)
RD_ prefix and win32 compatibility for core files

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
5 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6 Copyright (C) Michael Gernoth mike@zerfleddert.de 2005-2006
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 #include "rdesktop.h"
24 #include "rdpsnd.h"
25 #include "rdpsnd_dsp.h"
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <errno.h>
29 #include <ao/ao.h>
30 #include <sys/time.h>
31
32 #define WAVEOUTLEN 16
33
34 static ao_device *o_device = NULL;
35 static int default_driver;
36 static BOOL reopened;
37 static char *libao_device = NULL;
38
39 void libao_play(void);
40
41 void
42 libao_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
43 {
44 /* We need to be called rather often... */
45 FD_SET(0, wfds);
46 }
47
48 void
49 libao_check_fds(fd_set * rfds, fd_set * wfds)
50 {
51 if (o_device == NULL)
52 return;
53
54 if (!rdpsnd_queue_empty())
55 libao_play();
56 }
57
58 BOOL
59 libao_open(void)
60 {
61 ao_sample_format format;
62
63 ao_initialize();
64
65 if (libao_device)
66 {
67 default_driver = ao_driver_id(libao_device);
68 }
69 else
70 {
71 default_driver = ao_default_driver_id();
72 }
73
74 format.bits = 16;
75 format.channels = 2;
76 format.rate = 44100;
77 format.byte_format = AO_FMT_NATIVE;
78
79
80 o_device = ao_open_live(default_driver, &format, NULL);
81 if (o_device == NULL)
82 {
83 return False;
84 }
85
86 reopened = True;
87
88 return True;
89 }
90
91 void
92 libao_close(void)
93 {
94 /* Ack all remaining packets */
95 while (!rdpsnd_queue_empty())
96 {
97 rdpsnd_queue_next(0);
98 }
99
100 if (o_device != NULL)
101 ao_close(o_device);
102
103 o_device = NULL;
104
105 ao_shutdown();
106 }
107
108 BOOL
109 libao_set_format(RD_WAVEFORMATEX * pwfx)
110 {
111 ao_sample_format format;
112
113 format.bits = pwfx->wBitsPerSample;
114 format.channels = pwfx->nChannels;
115 format.rate = 44100;
116 format.byte_format = AO_FMT_NATIVE;
117
118 if (o_device != NULL)
119 ao_close(o_device);
120
121 o_device = ao_open_live(default_driver, &format, NULL);
122 if (o_device == NULL)
123 {
124 return False;
125 }
126
127 if (rdpsnd_dsp_resample_set(44100, pwfx->wBitsPerSample, pwfx->nChannels) == False)
128 {
129 return False;
130 }
131
132 reopened = True;
133
134 return True;
135 }
136
137 void
138 libao_play(void)
139 {
140 struct audio_packet *packet;
141 STREAM out;
142 int len;
143 static long prev_s, prev_us;
144 unsigned int duration;
145 struct timeval tv;
146 int next_tick;
147
148 if (reopened)
149 {
150 reopened = False;
151 gettimeofday(&tv, NULL);
152 prev_s = tv.tv_sec;
153 prev_us = tv.tv_usec;
154 }
155
156 /* We shouldn't be called if the queue is empty, but still */
157 if (rdpsnd_queue_empty())
158 return;
159
160 packet = rdpsnd_queue_current_packet();
161 out = &packet->s;
162
163 next_tick = rdpsnd_queue_next_tick();
164
165 len = (WAVEOUTLEN > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTLEN;
166 ao_play(o_device, (char *) out->p, len);
167 out->p += len;
168
169 gettimeofday(&tv, NULL);
170
171 duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000;
172
173 if (packet->tick > next_tick)
174 next_tick += 65536;
175
176 if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
177 {
178 unsigned int delay_us;
179
180 prev_s = tv.tv_sec;
181 prev_us = tv.tv_usec;
182
183 if (abs((next_tick - packet->tick) - duration) > 20)
184 {
185 DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick));
186 DEBUG(("last: %d, is: %d, should: %d\n", packet->tick,
187 (packet->tick + duration) % 65536, next_tick % 65536));
188 }
189
190 delay_us = ((out->size / 4) * (1000000 / 44100));
191
192 rdpsnd_queue_next(delay_us);
193 }
194 }
195
196 struct audio_driver *
197 libao_register(char *options)
198 {
199 static struct audio_driver libao_driver;
200
201 memset(&libao_driver, 0, sizeof(libao_driver));
202
203 libao_driver.name = "libao";
204 libao_driver.description = "libao output driver, default device: system dependent";
205
206 libao_driver.add_fds = libao_add_fds;
207 libao_driver.check_fds = libao_check_fds;
208
209 libao_driver.wave_out_open = libao_open;
210 libao_driver.wave_out_close = libao_close;
211 libao_driver.wave_out_format_supported = rdpsnd_dsp_resample_supported;
212 libao_driver.wave_out_set_format = libao_set_format;
213 libao_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
214
215 libao_driver.need_byteswap_on_be = 1;
216 libao_driver.need_resampling = 1;
217
218 if (options)
219 {
220 libao_device = xstrdup(options);
221 }
222
223 return &libao_driver;
224 }

  ViewVC Help
Powered by ViewVC 1.1.26