21 |
*/ |
*/ |
22 |
|
|
23 |
#include "rdesktop.h" |
#include "rdesktop.h" |
24 |
|
#include "rdpsnd.h" |
25 |
#include <unistd.h> |
#include <unistd.h> |
26 |
#include <fcntl.h> |
#include <fcntl.h> |
27 |
#include <errno.h> |
#include <errno.h> |
29 |
#include <sys/time.h> |
#include <sys/time.h> |
30 |
|
|
31 |
#define DEFAULTDEVICE "default" |
#define DEFAULTDEVICE "default" |
|
#define MAX_QUEUE 10 |
|
32 |
#define MAX_FRAMES 32 |
#define MAX_FRAMES 32 |
33 |
|
|
|
int g_dsp_fd; |
|
|
BOOL g_dsp_busy = False; |
|
34 |
static snd_pcm_t *pcm_handle = NULL; |
static snd_pcm_t *pcm_handle = NULL; |
35 |
static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; |
static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; |
36 |
static BOOL reopened; |
static BOOL reopened; |
37 |
static short samplewidth; |
static short samplewidth; |
38 |
static int audiochannels; |
static int audiochannels; |
39 |
|
|
|
static struct audio_packet |
|
|
{ |
|
|
struct stream s; |
|
|
uint16 tick; |
|
|
uint8 index; |
|
|
} packet_queue[MAX_QUEUE]; |
|
|
static unsigned int queue_hi, queue_lo; |
|
|
|
|
40 |
BOOL |
BOOL |
41 |
wave_out_open(void) |
wave_out_open(void) |
42 |
{ |
{ |
52 |
} |
} |
53 |
|
|
54 |
g_dsp_fd = 0; |
g_dsp_fd = 0; |
55 |
queue_lo = queue_hi = 0; |
rdpsnd_queue_init(); |
56 |
|
|
57 |
reopened = True; |
reopened = True; |
58 |
|
|
63 |
wave_out_close(void) |
wave_out_close(void) |
64 |
{ |
{ |
65 |
/* Ack all remaining packets */ |
/* Ack all remaining packets */ |
66 |
while (queue_lo != queue_hi) |
while (!rdpsnd_queue_empty()) |
67 |
{ |
{ |
68 |
rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index); |
rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick, |
69 |
free(packet_queue[queue_lo].s.data); |
rdpsnd_queue_current_packet()->index); |
70 |
queue_lo = (queue_lo + 1) % MAX_QUEUE; |
rdpsnd_queue_next(); |
71 |
} |
} |
72 |
|
|
73 |
|
|
74 |
if (pcm_handle) |
if (pcm_handle) |
75 |
{ |
{ |
76 |
snd_pcm_drop(pcm_handle); |
snd_pcm_drop(pcm_handle); |
222 |
} |
} |
223 |
|
|
224 |
void |
void |
|
wave_out_write(STREAM s, uint16 tick, uint8 index) |
|
|
{ |
|
|
struct audio_packet *packet = &packet_queue[queue_hi]; |
|
|
unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE; |
|
|
|
|
|
if (next_hi == queue_lo) |
|
|
{ |
|
|
error("No space to queue audio packet\n"); |
|
|
return; |
|
|
} |
|
|
|
|
|
queue_hi = next_hi; |
|
|
|
|
|
packet->s = *s; |
|
|
packet->tick = tick; |
|
|
packet->index = index; |
|
|
packet->s.p += 4; |
|
|
|
|
|
/* we steal the data buffer from s, give it a new one */ |
|
|
s->data = (uint8 *) malloc(s->size); |
|
|
|
|
|
if (!g_dsp_busy) |
|
|
wave_out_play(); |
|
|
} |
|
|
|
|
|
void |
|
225 |
wave_out_play(void) |
wave_out_play(void) |
226 |
{ |
{ |
227 |
struct audio_packet *packet; |
struct audio_packet *packet; |
240 |
prev_us = tv.tv_usec; |
prev_us = tv.tv_usec; |
241 |
} |
} |
242 |
|
|
243 |
if (queue_lo == queue_hi) |
if (rdpsnd_queue_empty()) |
244 |
{ |
{ |
245 |
g_dsp_busy = 0; |
g_dsp_busy = 0; |
246 |
return; |
return; |
247 |
} |
} |
248 |
|
|
249 |
packet = &packet_queue[queue_lo]; |
packet = rdpsnd_queue_current_packet(); |
250 |
out = &packet->s; |
out = &packet->s; |
251 |
|
|
252 |
if (((queue_lo + 1) % MAX_QUEUE) != queue_hi) |
next_tick = rdpsnd_queue_next_tick(); |
|
{ |
|
|
next_tick = packet_queue[(queue_lo + 1) % MAX_QUEUE].tick; |
|
|
} |
|
|
else |
|
|
{ |
|
|
next_tick = (packet->tick + 65535) % 65536; |
|
|
} |
|
253 |
|
|
254 |
len = (out->end - out->p) / (samplewidth * audiochannels); |
len = (out->end - out->p) / (samplewidth * audiochannels); |
255 |
if ((len = snd_pcm_writei(pcm_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0) |
if ((len = snd_pcm_writei(pcm_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0) |
278 |
(packet->tick + duration) % 65536, next_tick % 65536)); |
(packet->tick + duration) % 65536, next_tick % 65536)); |
279 |
} |
} |
280 |
|
|
281 |
/* Until all drivers are using the windows sound-ticks, we need to |
rdpsnd_send_completion(((packet->tick + duration) % 65536), packet->index); |
282 |
substract the 50 ticks added later by rdpsnd.c */ |
rdpsnd_queue_next(); |
|
rdpsnd_send_completion(((packet->tick + duration) % 65536) - 50, packet->index); |
|
|
free(out->data); |
|
|
queue_lo = (queue_lo + 1) % MAX_QUEUE; |
|
283 |
} |
} |
284 |
|
|
285 |
g_dsp_busy = 1; |
g_dsp_busy = 1; |