unify queue-handling in rdpsnd.c (remove private copies from all

drivers)


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1253 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Michael Gernoth 2006-09-17 10:32:18 +00:00
parent f4dce045b5
commit ec4862937f
7 changed files with 183 additions and 273 deletions

View File

@ -20,6 +20,7 @@
*/ */
#include "rdesktop.h" #include "rdesktop.h"
#include "rdpsnd.h"
#define RDPSND_CLOSE 1 #define RDPSND_CLOSE 1
#define RDPSND_WRITE 2 #define RDPSND_WRITE 2
@ -30,6 +31,10 @@
#define RDPSND_NEGOTIATE 7 #define RDPSND_NEGOTIATE 7
#define MAX_FORMATS 10 #define MAX_FORMATS 10
#define MAX_QUEUE 10
BOOL g_dsp_busy = False;
int g_dsp_fd;
static VCHANNEL *rdpsnd_channel; static VCHANNEL *rdpsnd_channel;
@ -37,6 +42,8 @@ static BOOL device_open;
static WAVEFORMATEX formats[MAX_FORMATS]; static WAVEFORMATEX formats[MAX_FORMATS];
static unsigned int format_count; static unsigned int format_count;
static unsigned int current_format; static unsigned int current_format;
static unsigned int queue_hi, queue_lo;
static struct audio_packet packet_queue[MAX_QUEUE];
static STREAM static STREAM
rdpsnd_init_packet(uint16 type, uint16 size) rdpsnd_init_packet(uint16 type, uint16 size)
@ -66,7 +73,7 @@ rdpsnd_send_completion(uint16 tick, uint8 packet_index)
STREAM s; STREAM s;
s = rdpsnd_init_packet(RDPSND_COMPLETION, 4); 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, packet_index);
out_uint8(s, 0); out_uint8(s, 0);
s_mark_end(s); s_mark_end(s);
@ -214,7 +221,7 @@ rdpsnd_process(STREAM s)
current_format = format; current_format = format;
} }
wave_out_write(s, tick, packet_index); rdpsnd_queue_write(s, tick, packet_index);
awaiting_data_packet = False; awaiting_data_packet = False;
return; return;
} }
@ -260,5 +267,70 @@ rdpsnd_init(void)
rdpsnd_channel = rdpsnd_channel =
channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
rdpsnd_process); rdpsnd_process);
return (rdpsnd_channel != NULL); 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;
}
}

36
rdpsnd.h Normal file
View File

@ -0,0 +1,36 @@
/*
rdesktop: A Remote Desktop Protocol client.
Sound infrastructure
Copyright (C) Michael Gernoth 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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
struct audio_packet
{
struct stream s;
uint16 tick;
uint8 index;
};
extern BOOL g_dsp_busy;
extern int g_dsp_fd;
void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
inline struct audio_packet *rdpsnd_queue_current_packet(void);
inline BOOL rdpsnd_queue_empty(void);
inline void rdpsnd_queue_init(void);
inline void rdpsnd_queue_next(void);
inline int rdpsnd_queue_next_tick(void);

View File

@ -21,6 +21,7 @@
*/ */
#include "rdesktop.h" #include "rdesktop.h"
#include "rdpsnd.h"
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
@ -28,25 +29,14 @@
#include <sys/time.h> #include <sys/time.h>
#define DEFAULTDEVICE "default" #define DEFAULTDEVICE "default"
#define MAX_QUEUE 10
#define MAX_FRAMES 32 #define MAX_FRAMES 32
int g_dsp_fd;
BOOL g_dsp_busy = False;
static snd_pcm_t *pcm_handle = NULL; static snd_pcm_t *pcm_handle = NULL;
static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK; static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
static BOOL reopened; static BOOL reopened;
static short samplewidth; static short samplewidth;
static int audiochannels; static int audiochannels;
static struct audio_packet
{
struct stream s;
uint16 tick;
uint8 index;
} packet_queue[MAX_QUEUE];
static unsigned int queue_hi, queue_lo;
BOOL BOOL
wave_out_open(void) wave_out_open(void)
{ {
@ -62,7 +52,7 @@ wave_out_open(void)
} }
g_dsp_fd = 0; g_dsp_fd = 0;
queue_lo = queue_hi = 0; rdpsnd_queue_init();
reopened = True; reopened = True;
@ -73,13 +63,14 @@ void
wave_out_close(void) wave_out_close(void)
{ {
/* Ack all remaining packets */ /* 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); rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick,
free(packet_queue[queue_lo].s.data); rdpsnd_queue_current_packet()->index);
queue_lo = (queue_lo + 1) % MAX_QUEUE; rdpsnd_queue_next();
} }
if (pcm_handle) if (pcm_handle)
{ {
snd_pcm_drop(pcm_handle); snd_pcm_drop(pcm_handle);
@ -230,32 +221,6 @@ wave_out_volume(uint16 left, uint16 right)
} }
} }
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 void
wave_out_play(void) wave_out_play(void)
{ {
@ -275,23 +240,16 @@ wave_out_play(void)
prev_us = tv.tv_usec; prev_us = tv.tv_usec;
} }
if (queue_lo == queue_hi) if (rdpsnd_queue_empty())
{ {
g_dsp_busy = 0; g_dsp_busy = 0;
return; return;
} }
packet = &packet_queue[queue_lo]; packet = rdpsnd_queue_current_packet();
out = &packet->s; out = &packet->s;
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;
}
len = (out->end - out->p) / (samplewidth * audiochannels); len = (out->end - out->p) / (samplewidth * audiochannels);
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)
@ -320,11 +278,8 @@ wave_out_play(void)
(packet->tick + duration) % 65536, next_tick % 65536)); (packet->tick + duration) % 65536, next_tick % 65536));
} }
/* Until all drivers are using the windows sound-ticks, we need to rdpsnd_send_completion(((packet->tick + duration) % 65536), packet->index);
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;
} }
g_dsp_busy = 1; g_dsp_busy = 1;

View File

@ -3,7 +3,7 @@
Sound Channel Process Functions - libao-driver Sound Channel Process Functions - libao-driver
Copyright (C) Matthew Chapman 2003 Copyright (C) Matthew Chapman 2003
Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
Copyright (C) Michael Gernoth mike@zerfleddert.de 2005 Copyright (C) Michael Gernoth mike@zerfleddert.de 2005-2006
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -21,17 +21,15 @@
*/ */
#include "rdesktop.h" #include "rdesktop.h"
#include "rdpsnd.h"
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <ao/ao.h> #include <ao/ao.h>
#include <sys/time.h> #include <sys/time.h>
#define MAX_QUEUE 10
#define WAVEOUTBUF 16 #define WAVEOUTBUF 16
int g_dsp_fd;
BOOL g_dsp_busy = False;
static ao_device *o_device = NULL; static ao_device *o_device = NULL;
static int default_driver; static int default_driver;
static int samplerate; static int samplerate;
@ -39,14 +37,6 @@ static int audiochannels;
static BOOL reopened; static BOOL reopened;
static short samplewidth; static short samplewidth;
static struct audio_packet
{
struct stream s;
uint16 tick;
uint8 index;
} packet_queue[MAX_QUEUE];
static unsigned int queue_hi, queue_lo;
BOOL BOOL
wave_out_open(void) wave_out_open(void)
{ {
@ -69,7 +59,7 @@ wave_out_open(void)
} }
g_dsp_fd = 0; g_dsp_fd = 0;
queue_lo = queue_hi = 0; rdpsnd_queue_init();
reopened = True; reopened = True;
@ -80,11 +70,11 @@ void
wave_out_close(void) wave_out_close(void)
{ {
/* Ack all remaining packets */ /* 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); rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick,
free(packet_queue[queue_lo].s.data); rdpsnd_queue_current_packet()->index);
queue_lo = (queue_lo + 1) % MAX_QUEUE; rdpsnd_queue_next();
} }
if (o_device != NULL) if (o_device != NULL)
@ -144,32 +134,6 @@ wave_out_volume(uint16 left, uint16 right)
warning("volume changes not supported with libao-output\n"); warning("volume changes not supported with libao-output\n");
} }
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 void
wave_out_play(void) wave_out_play(void)
{ {
@ -190,23 +154,16 @@ wave_out_play(void)
prev_us = tv.tv_usec; prev_us = tv.tv_usec;
} }
if (queue_lo == queue_hi) if (rdpsnd_queue_empty())
{ {
g_dsp_busy = 0; g_dsp_busy = 0;
return; return;
} }
packet = &packet_queue[queue_lo]; packet = rdpsnd_queue_current_packet();
out = &packet->s; out = &packet->s;
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;
}
len = 0; len = 0;
@ -261,11 +218,8 @@ wave_out_play(void)
(packet->tick + duration) % 65536, next_tick % 65536)); (packet->tick + duration) % 65536, next_tick % 65536));
} }
/* Until all drivers are using the windows sound-ticks, we need to rdpsnd_send_completion(((packet->tick + duration) % 65536), packet->index);
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;
} }
g_dsp_busy = 1; g_dsp_busy = 1;

View File

@ -28,6 +28,7 @@
#endif #endif
#include "rdesktop.h" #include "rdesktop.h"
#include "rdpsnd.h"
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
@ -35,22 +36,12 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/soundcard.h> #include <sys/soundcard.h>
#define DEFAULTDEVICE "/dev/dsp"
#define MAX_LEN 512 #define MAX_LEN 512
#define MAX_QUEUE 10
int g_dsp_fd;
BOOL g_dsp_busy = False;
static int snd_rate; static int snd_rate;
static short samplewidth; static short samplewidth;
static struct audio_packet
{
struct stream s;
uint16 tick;
uint8 index;
} packet_queue[MAX_QUEUE];
static unsigned int queue_hi, queue_lo;
BOOL BOOL
wave_out_open(void) wave_out_open(void)
{ {
@ -58,7 +49,7 @@ wave_out_open(void)
if (dsp_dev == NULL) if (dsp_dev == NULL)
{ {
dsp_dev = xstrdup("/dev/dsp"); dsp_dev = xstrdup(DEFAULTDEVICE);
} }
if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1) if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
@ -200,32 +191,6 @@ wave_out_volume(uint16 left, uint16 right)
} }
} }
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 void
wave_out_play(void) wave_out_play(void)
{ {
@ -237,13 +202,13 @@ wave_out_play(void)
static BOOL started = False; static BOOL started = False;
struct timeval tv; struct timeval tv;
if (queue_lo == queue_hi) if (rdpsnd_queue_empty())
{ {
g_dsp_busy = 0; g_dsp_busy = 0;
return; return;
} }
packet = &packet_queue[queue_lo]; packet = rdpsnd_queue_current_packet();
out = &packet->s; out = &packet->s;
if (!started) if (!started)
@ -277,9 +242,10 @@ wave_out_play(void)
if (elapsed >= (duration * 85) / 100) if (elapsed >= (duration * 85) / 100)
{ {
rdpsnd_send_completion(packet->tick, packet->index); /* We need to add 50 to tell windows that time has passed while
free(out->data); * playing this packet */
queue_lo = (queue_lo + 1) % MAX_QUEUE; rdpsnd_send_completion(packet->tick + 50, packet->index);
rdpsnd_queue_next();
started = False; started = False;
} }
else else

View File

@ -28,13 +28,9 @@
#define IRIX_MAX_VOL 65535 #define IRIX_MAX_VOL 65535
#define MAX_QUEUE 10
int g_dsp_fd;
ALconfig audioconfig; ALconfig audioconfig;
ALport output_port; ALport output_port;
BOOL g_dsp_busy = False;
static BOOL g_swapaudio; static BOOL g_swapaudio;
static int g_snd_rate; static int g_snd_rate;
static BOOL g_swapaudio; static BOOL g_swapaudio;
@ -44,56 +40,46 @@ double min_volume, max_volume, volume_range;
int resource, maxFillable; int resource, maxFillable;
int combinedFrameSize; int combinedFrameSize;
static struct audio_packet
{
struct stream s;
uint16 tick;
uint8 index;
} packet_queue[MAX_QUEUE];
static unsigned int queue_hi, queue_lo;
BOOL BOOL
wave_out_open(void) wave_out_open(void)
{ {
ALparamInfo pinfo; ALparamInfo pinfo;
#if (defined(IRIX_DEBUG)) #if (defined(IRIX_DEBUG))
fprintf(stderr, "wave_out_open: begin\n"); fprintf(stderr, "sgi_open: begin\n");
#endif #endif
if (alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo) < 0) if (alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo) < 0)
{ {
fprintf(stderr, "wave_out_open: alGetParamInfo failed: %s\n", fprintf(stderr, "sgi_open: alGetParamInfo failed: %s\n",
alGetErrorString(oserror())); alGetErrorString(oserror()));
} }
min_volume = alFixedToDouble(pinfo.min.ll); min_volume = alFixedToDouble(pinfo.min.ll);
max_volume = alFixedToDouble(pinfo.max.ll); max_volume = alFixedToDouble(pinfo.max.ll);
volume_range = (max_volume - min_volume); volume_range = (max_volume - min_volume);
#if (defined(IRIX_DEBUG)) #if (defined(IRIX_DEBUG))
fprintf(stderr, "wave_out_open: minvol = %lf, maxvol= %lf, range = %lf.\n", fprintf(stderr, "sgi_open: minvol = %lf, maxvol= %lf, range = %lf.\n",
min_volume, max_volume, volume_range); min_volume, max_volume, volume_range);
#endif #endif
queue_lo = queue_hi = 0; rdpsnd_queue_init();
audioconfig = alNewConfig(); audioconfig = alNewConfig();
if (audioconfig == (ALconfig) 0) if (audioconfig == (ALconfig) 0)
{ {
fprintf(stderr, "wave_out_open: alNewConfig failed: %s\n", fprintf(stderr, "sgi_open: alNewConfig failed: %s\n", alGetErrorString(oserror()));
alGetErrorString(oserror()));
return False; return False;
} }
output_port = alOpenPort("rdpsnd", "w", 0); output_port = alOpenPort("rdpsnd", "w", 0);
if (output_port == (ALport) 0) if (output_port == (ALport) 0)
{ {
fprintf(stderr, "wave_out_open: alOpenPort failed: %s\n", fprintf(stderr, "sgi_open: alOpenPort failed: %s\n", alGetErrorString(oserror()));
alGetErrorString(oserror()));
return False; return False;
} }
#if (defined(IRIX_DEBUG)) #if (defined(IRIX_DEBUG))
fprintf(stderr, "wave_out_open: returning\n"); fprintf(stderr, "sgi_open: returning\n");
#endif #endif
return True; return True;
} }
@ -103,21 +89,23 @@ wave_out_close(void)
{ {
/* Ack all remaining packets */ /* Ack all remaining packets */
#if (defined(IRIX_DEBUG)) #if (defined(IRIX_DEBUG))
fprintf(stderr, "wave_out_close: begin\n"); fprintf(stderr, "sgi_close: begin\n");
#endif #endif
while (queue_lo != queue_hi) while (!rdpsnd_queue_empty())
{ {
rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index); /* We need to add 50 to tell windows that time has passed while
free(packet_queue[queue_lo].s.data); * playing this packet */
queue_lo = (queue_lo + 1) % MAX_QUEUE; rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick + 50,
rdpsnd_queue_current_packet()->index);
rdpsnd_queue_next();
} }
alDiscardFrames(output_port, 0); alDiscardFrames(output_port, 0);
alClosePort(output_port); alClosePort(output_port);
alFreeConfig(audioconfig); alFreeConfig(audioconfig);
#if (defined(IRIX_DEBUG)) #if (defined(IRIX_DEBUG))
fprintf(stderr, "wave_out_close: returning\n"); fprintf(stderr, "sgi_close: returning\n");
#endif #endif
} }
@ -142,7 +130,7 @@ wave_out_set_format(WAVEFORMATEX * pwfx)
ALpv params; ALpv params;
#if (defined(IRIX_DEBUG)) #if (defined(IRIX_DEBUG))
fprintf(stderr, "wave_out_set_format: init...\n"); fprintf(stderr, "sgi_set_format: init...\n");
#endif #endif
g_swapaudio = False; g_swapaudio = False;
@ -178,7 +166,7 @@ wave_out_set_format(WAVEFORMATEX * pwfx)
if (output_port == (ALport) 0) if (output_port == (ALport) 0)
{ {
fprintf(stderr, "wave_out_set_format: alOpenPort failed: %s\n", fprintf(stderr, "sgi_set_format: alOpenPort failed: %s\n",
alGetErrorString(oserror())); alGetErrorString(oserror()));
return False; return False;
} }
@ -192,7 +180,7 @@ wave_out_set_format(WAVEFORMATEX * pwfx)
if (frameSize == 0 || channelCount == 0) if (frameSize == 0 || channelCount == 0)
{ {
fprintf(stderr, "wave_out_set_format: bad frameSize or channelCount\n"); fprintf(stderr, "sgi_set_format: bad frameSize or channelCount\n");
return False; return False;
} }
combinedFrameSize = frameSize * channelCount; combinedFrameSize = frameSize * channelCount;
@ -213,7 +201,7 @@ wave_out_set_format(WAVEFORMATEX * pwfx)
} }
#if (defined(IRIX_DEBUG)) #if (defined(IRIX_DEBUG))
fprintf(stderr, "wave_out_set_format: returning...\n"); fprintf(stderr, "sgi_set_format: returning...\n");
#endif #endif
return True; return True;
} }
@ -226,7 +214,7 @@ wave_out_volume(uint16 left, uint16 right)
ALfixed gain[8]; ALfixed gain[8];
#if (defined(IRIX_DEBUG)) #if (defined(IRIX_DEBUG))
fprintf(stderr, "wave_out_volume: begin\n"); fprintf(stderr, "sgi_volume: begin\n");
fprintf(stderr, "left='%d', right='%d'\n", left, right); fprintf(stderr, "left='%d', right='%d'\n", left, right);
#endif #endif
@ -241,42 +229,16 @@ wave_out_volume(uint16 left, uint16 right)
pv[0].sizeIn = 8; pv[0].sizeIn = 8;
if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0) if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0)
{ {
fprintf(stderr, "wave_out_volume: alSetParams failed: %s\n", fprintf(stderr, "sgi_volume: alSetParams failed: %s\n",
alGetErrorString(oserror())); alGetErrorString(oserror()));
return; return;
} }
#if (defined(IRIX_DEBUG)) #if (defined(IRIX_DEBUG))
fprintf(stderr, "wave_out_volume: returning\n"); fprintf(stderr, "sgi_volume: returning\n");
#endif #endif
} }
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)
{
fprintf(stderr, "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 void
wave_out_play(void) wave_out_play(void)
{ {
@ -290,13 +252,13 @@ wave_out_play(void)
while (1) while (1)
{ {
if (queue_lo == queue_hi) if (rdpsnd_queue_empty())
{ {
g_dsp_busy = False; g_dsp_busy = False;
return; return;
} }
packet = &packet_queue[queue_lo]; packet = rdpsnd_queue_current_packet();
out = &packet->s; out = &packet->s;
/* Swap the current packet, but only once */ /* Swap the current packet, but only once */
@ -322,8 +284,7 @@ wave_out_play(void)
if (gf < (4 * maxFillable / 10)) if (gf < (4 * maxFillable / 10))
{ {
rdpsnd_send_completion(packet->tick, packet->index); rdpsnd_send_completion(packet->tick, packet->index);
free(out->data); rdpsnd_queue_next();
queue_lo = (queue_lo + 1) % MAX_QUEUE;
swapped = False; swapped = False;
} }
else else

View File

@ -3,7 +3,7 @@
Sound Channel Process Functions - Sun Sound Channel Process Functions - Sun
Copyright (C) Matthew Chapman 2003 Copyright (C) Matthew Chapman 2003
Copyright (C) GuoJunBo guojunbo@ict.ac.cn 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 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 it under the terms of the GNU General Public License as published by
@ -21,6 +21,7 @@
*/ */
#include "rdesktop.h" #include "rdesktop.h"
#include "rdpsnd.h"
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
@ -31,22 +32,12 @@
#include <stropts.h> #include <stropts.h>
#endif #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_reopened;
static BOOL g_swapaudio; static BOOL g_swapaudio;
static short g_samplewidth; 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;
BOOL BOOL
wave_out_open(void) wave_out_open(void)
{ {
@ -54,7 +45,7 @@ wave_out_open(void)
if (dsp_dev == NULL) if (dsp_dev == NULL)
{ {
dsp_dev = xstrdup("/dev/audio"); dsp_dev = xstrdup(DEFAULTDEVICE);
} }
if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1) if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
@ -66,7 +57,7 @@ wave_out_open(void)
/* Non-blocking so that user interface is responsive */ /* Non-blocking so that user interface is responsive */
fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK); 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; g_reopened = True;
return True; return True;
@ -76,11 +67,11 @@ void
wave_out_close(void) wave_out_close(void)
{ {
/* Ack all remaining packets */ /* 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); rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick,
free(packet_queue[queue_lo].s.data); rdpsnd_queue_current_packet()->index);
queue_lo = (queue_lo + 1) % MAX_QUEUE; rdpsnd_queue_next();
} }
#if defined I_FLUSH && defined FLUSHW #if defined I_FLUSH && defined FLUSHW
@ -192,32 +183,6 @@ wave_out_volume(uint16 left, uint16 right)
} }
} }
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 void
wave_out_play(void) wave_out_play(void)
{ {
@ -243,13 +208,13 @@ wave_out_play(void)
g_reopened = False; g_reopened = False;
} }
if (queue_lo == queue_hi) if (rdpsnd_queue_empty())
{ {
g_dsp_busy = 0; g_dsp_busy = 0;
return; return;
} }
packet = &packet_queue[queue_lo]; packet = rdpsnd_queue_current_packet();
out = &packet->s; out = &packet->s;
/* Swap the current packet, but only once */ /* Swap the current packet, but only once */
@ -297,9 +262,10 @@ wave_out_play(void)
if (info.play.samples >= samplecnt + ((numsamples * 7) / 10)) if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
{ {
samplecnt += numsamples; samplecnt += numsamples;
rdpsnd_send_completion(packet->tick, packet->index); /* We need to add 50 to tell windows that time has passed while
free(out->data); * playing this packet */
queue_lo = (queue_lo + 1) % MAX_QUEUE; rdpsnd_send_completion(packet->tick + 50, packet->index);
rdpsnd_queue_next();
swapped = False; swapped = False;
sentcompletion = True; sentcompletion = True;
} }