--- sourceforge.net/trunk/rdesktop/rdpsnd_sun.c 2005/08/04 12:50:15 974 +++ sourceforge.net/trunk/rdesktop/rdpsnd_sun.c 2006/09/17 11:42:22 1256 @@ -3,7 +3,7 @@ Sound Channel Process Functions - Sun Copyright (C) Matthew Chapman 2003 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003 - Copyright (C) Michael Gernoth mike@zerfleddert.de 2003 + Copyright (C) Michael Gernoth mike@zerfleddert.de 2003-2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ */ #include "rdesktop.h" +#include "rdpsnd.h" #include #include #include @@ -31,32 +32,16 @@ #include #endif -#define MAX_QUEUE 10 +#define DEFAULTDEVICE "/dev/audio" -int g_dsp_fd; -BOOL g_dsp_busy = False; static BOOL g_reopened; static BOOL g_swapaudio; static short g_samplewidth; - -static struct audio_packet -{ - struct stream s; - uint16 tick; - uint8 index; -} packet_queue[MAX_QUEUE]; -static unsigned int queue_hi, queue_lo; +static char *dsp_dev; BOOL -wave_out_open(void) +sun_open(void) { - char *dsp_dev = getenv("AUDIODEV"); - - if (dsp_dev == NULL) - { - dsp_dev = xstrdup("/dev/audio"); - } - if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1) { perror(dsp_dev); @@ -66,21 +51,21 @@ /* Non-blocking so that user interface is responsive */ fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK); - queue_lo = queue_hi = 0; + rdpsnd_queue_init(); g_reopened = True; return True; } void -wave_out_close(void) +sun_close(void) { /* Ack all remaining packets */ - while (queue_lo != queue_hi) + while (!rdpsnd_queue_empty()) { - rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index); - free(packet_queue[queue_lo].s.data); - queue_lo = (queue_lo + 1) % MAX_QUEUE; + rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick, + rdpsnd_queue_current_packet()->index); + rdpsnd_queue_next(); } #if defined I_FLUSH && defined FLUSHW @@ -94,7 +79,7 @@ } BOOL -wave_out_format_supported(WAVEFORMATEX * pwfx) +sun_format_supported(WAVEFORMATEX * pwfx) { if (pwfx->wFormatTag != WAVE_FORMAT_PCM) return False; @@ -107,7 +92,7 @@ } BOOL -wave_out_set_format(WAVEFORMATEX * pwfx) +sun_set_format(WAVEFORMATEX * pwfx) { audio_info_t info; @@ -161,7 +146,7 @@ } void -wave_out_volume(uint16 left, uint16 right) +sun_volume(uint16 left, uint16 right) { audio_info_t info; uint balance; @@ -193,33 +178,7 @@ } 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 = malloc(s->size); - - if (!g_dsp_busy) - wave_out_play(); -} - -void -wave_out_play(void) +sun_play(void) { struct audio_packet *packet; audio_info_t info; @@ -243,13 +202,13 @@ g_reopened = False; } - if (queue_lo == queue_hi) + if (rdpsnd_queue_empty()) { g_dsp_busy = 0; return; } - packet = &packet_queue[queue_lo]; + packet = rdpsnd_queue_current_packet(); out = &packet->s; /* Swap the current packet, but only once */ @@ -297,9 +256,10 @@ if (info.play.samples >= samplecnt + ((numsamples * 7) / 10)) { samplecnt += numsamples; - rdpsnd_send_completion(packet->tick, packet->index); - free(out->data); - queue_lo = (queue_lo + 1) % MAX_QUEUE; + /* We need to add 50 to tell windows that time has passed while + * playing this packet */ + rdpsnd_send_completion(packet->tick + 50, packet->index); + rdpsnd_queue_next(); swapped = False; sentcompletion = True; } @@ -311,3 +271,37 @@ } } } + +struct audio_driver * +sun_register(char *options) +{ + static struct audio_driver sun_driver; + + sun_driver.wave_out_write = rdpsnd_queue_write; + sun_driver.wave_out_open = sun_open; + sun_driver.wave_out_close = sun_close; + sun_driver.wave_out_format_supported = sun_format_supported; + sun_driver.wave_out_set_format = sun_set_format; + sun_driver.wave_out_volume = sun_volume; + sun_driver.wave_out_play = sun_play; + sun_driver.name = xstrdup("sun"); + sun_driver.description = + xstrdup("SUN/BSD output driver, default device: " DEFAULTDEVICE " or $AUDIODEV"); + sun_driver.next = NULL; + + if (options) + { + dsp_dev = xstrdup(options); + } + else + { + dsp_dev = getenv("AUDIODEV"); + + if (dsp_dev == NULL) + { + dsp_dev = xstrdup(DEFAULTDEVICE); + } + } + + return &sun_driver; +}