--- sourceforge.net/trunk/rdesktop/rdpsnd.c 2003/10/15 14:01:32 499 +++ sourceforge.net/trunk/rdesktop/rdpsnd.c 2006/09/17 10:32:18 1254 @@ -1,4 +1,4 @@ -/* +/* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. Sound Channel Process Functions Copyright (C) Matthew Chapman 2003 @@ -20,16 +20,21 @@ */ #include "rdesktop.h" +#include "rdpsnd.h" #define RDPSND_CLOSE 1 #define RDPSND_WRITE 2 #define RDPSND_SET_VOLUME 3 #define RDPSND_UNKNOWN4 4 #define RDPSND_COMPLETION 5 -#define RDPSND_UNKNOWN6 6 +#define RDPSND_SERVERTICK 6 #define RDPSND_NEGOTIATE 7 #define MAX_FORMATS 10 +#define MAX_QUEUE 10 + +BOOL g_dsp_busy = False; +int g_dsp_fd; static VCHANNEL *rdpsnd_channel; @@ -37,8 +42,10 @@ static WAVEFORMATEX formats[MAX_FORMATS]; static unsigned int format_count; static unsigned int current_format; +static unsigned int queue_hi, queue_lo; +static struct audio_packet packet_queue[MAX_QUEUE]; -STREAM +static STREAM rdpsnd_init_packet(uint16 type, uint16 size) { STREAM s; @@ -49,7 +56,7 @@ return s; } -void +static void rdpsnd_send(STREAM s) { #ifdef RDPSND_DEBUG @@ -66,14 +73,14 @@ STREAM s; s = rdpsnd_init_packet(RDPSND_COMPLETION, 4); - out_uint16_le(s, tick + 50); + out_uint16_le(s, tick); out_uint8(s, packet_index); out_uint8(s, 0); s_mark_end(s); rdpsnd_send(s); } -void +static void rdpsnd_process_negotiate(STREAM in) { unsigned int in_format_count, i; @@ -156,24 +163,24 @@ rdpsnd_send(out); } -void -rdpsnd_process_unknown6(STREAM in) +static void +rdpsnd_process_servertick(STREAM in) { - uint16 unknown1, unknown2; + uint16 tick1, tick2; STREAM out; /* in_uint8s(in, 4); unknown */ - in_uint16_le(in, unknown1); - in_uint16_le(in, unknown2); + in_uint16_le(in, tick1); + in_uint16_le(in, tick2); - out = rdpsnd_init_packet(RDPSND_UNKNOWN6 | 0x2300, 4); - out_uint16_le(out, unknown1); - out_uint16_le(out, unknown2); + out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4); + out_uint16_le(out, tick1); + out_uint16_le(out, tick2); s_mark_end(out); rdpsnd_send(out); } -void +static void rdpsnd_process(STREAM s) { uint8 type; @@ -214,7 +221,7 @@ current_format = format; } - wave_out_write(s, tick, packet_index); + rdpsnd_queue_write(s, tick, packet_index); awaiting_data_packet = False; return; } @@ -238,8 +245,8 @@ case RDPSND_NEGOTIATE: rdpsnd_process_negotiate(s); break; - case RDPSND_UNKNOWN6: - rdpsnd_process_unknown6(s); + case RDPSND_SERVERTICK: + rdpsnd_process_servertick(s); break; case RDPSND_SET_VOLUME: in_uint32(s, volume); @@ -260,5 +267,70 @@ rdpsnd_channel = channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, rdpsnd_process); + return (rdpsnd_channel != NULL); } + +void +rdpsnd_queue_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 = malloc(s->size); + + if (!g_dsp_busy) + wave_out_play(); +} + +inline struct audio_packet * +rdpsnd_queue_current_packet(void) +{ + return &packet_queue[queue_lo]; +} + +inline BOOL +rdpsnd_queue_empty(void) +{ + return (queue_lo == queue_hi); +} + +inline void +rdpsnd_queue_init(void) +{ + queue_lo = queue_hi = 0; +} + +inline void +rdpsnd_queue_next(void) +{ + free(packet_queue[queue_lo].s.data); + queue_lo = (queue_lo + 1) % MAX_QUEUE; +} + +inline int +rdpsnd_queue_next_tick(void) +{ + if (((queue_lo + 1) % MAX_QUEUE) != queue_hi) + { + return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick; + } + else + { + return (packet_queue[queue_lo].tick + 65535) % 65536; + } +}