/[rdesktop]/sourceforge.net/trunk/rdesktop/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 /sourceforge.net/trunk/rdesktop/rdpsnd_libao.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1346 - (show annotations)
Thu Dec 7 15:23:45 2006 UTC (17 years, 5 months ago) by ossman_
File MIME type: text/plain
File size: 4463 byte(s)
Abstract select() handling in rdpsnd so that backends can do their thing
more correctly.

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

  ViewVC Help
Powered by ViewVC 1.1.26