Abstract select() handling in rdpsnd so that backends can do their thing

more correctly.


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1345 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Pierre Ossman 2006-12-07 15:23:45 +00:00
parent 139e42d9ef
commit c6712a8945
9 changed files with 257 additions and 131 deletions

View File

@ -168,7 +168,6 @@ BOOL rdpdr_abort_io(uint32 fd, uint32 major, NTSTATUS status);
/* rdpsnd.c */
BOOL rdpsnd_init(char *optarg);
void rdpsnd_show_help(void);
void rdpsnd_play(void);
void rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv);
void rdpsnd_check_fds(fd_set * rfds, fd_set * wfds);
struct audio_packet *rdpsnd_queue_current_packet(void);

104
rdpsnd.c
View File

@ -37,9 +37,6 @@
#define MAX_FORMATS 10
#define MAX_QUEUE 10
BOOL g_dsp_busy = False;
int g_dsp_fd;
static VCHANNEL *rdpsnd_channel;
static struct audio_driver *drivers = NULL;
struct audio_driver *current_driver = NULL;
@ -94,6 +91,34 @@ rdpsnd_send_completion(uint16 tick, uint8 packet_index)
(unsigned) tick, (unsigned) packet_index));
}
static BOOL
rdpsnd_auto_select(void)
{
static BOOL failed = False;
if (!failed)
{
current_driver = drivers;
while (current_driver != NULL)
{
DEBUG(("trying %s...\n", current_driver->name));
if (current_driver->wave_out_open())
{
DEBUG(("selected %s\n", current_driver->name));
return True;
}
current_driver = current_driver->next;
}
warning("no working audio-driver found\n");
failed = True;
current_driver = NULL;
}
return False;
}
static void
rdpsnd_process_negotiate(STREAM in)
{
@ -115,7 +140,10 @@ rdpsnd_process_negotiate(STREAM in)
DEBUG_SOUND(("RDPSND: RDPSND_NEGOTIATE(formats: %d, pad: 0x%02x, version: %x)\n",
(int) in_format_count, (unsigned) pad, (unsigned) version));
if (current_driver->wave_out_open())
if (!current_driver)
rdpsnd_auto_select();
if (current_driver && current_driver->wave_out_open())
{
current_driver->wave_out_close();
device_available = True;
@ -230,6 +258,16 @@ rdpsnd_process_packet(uint8 opcode, STREAM s)
if (!device_open || (format != current_format))
{
/*
* If we haven't selected a device by now, then either
* we've failed to find a working device, or the server
* is sending bogus RDPSND_WRITE.
*/
if (!current_driver)
{
rdpsnd_send_completion(tick, packet_index);
break;
}
if (!device_open && !current_driver->wave_out_open())
{
rdpsnd_send_completion(tick, packet_index);
@ -253,7 +291,8 @@ rdpsnd_process_packet(uint8 opcode, STREAM s)
break;
case RDPSND_CLOSE:
DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
current_driver->wave_out_close();
if (device_open)
current_driver->wave_out_close();
device_open = False;
break;
case RDPSND_NEGOTIATE:
@ -333,36 +372,6 @@ rdpsnd_process(STREAM s)
}
}
static BOOL
rdpsnd_auto_open(void)
{
static BOOL failed = False;
if (!failed)
{
struct audio_driver *auto_driver = current_driver;
current_driver = drivers;
while (current_driver != NULL)
{
DEBUG(("trying %s...\n", current_driver->name));
if (current_driver->wave_out_open())
{
DEBUG(("selected %s\n", current_driver->name));
return True;
}
g_dsp_fd = 0;
current_driver = current_driver->next;
}
warning("no working audio-driver found\n");
failed = True;
current_driver = auto_driver;
}
return False;
}
static void
rdpsnd_register_drivers(char *options)
{
@ -402,7 +411,6 @@ rdpsnd_register_drivers(char *options)
BOOL
rdpsnd_init(char *optarg)
{
static struct audio_driver auto_driver;
struct audio_driver *pos;
char *driver = NULL, *options = NULL;
@ -444,11 +452,7 @@ rdpsnd_init(char *optarg)
rdpsnd_register_drivers(options);
if (!driver)
{
auto_driver.wave_out_open = &rdpsnd_auto_open;
current_driver = &auto_driver;
return True;
}
pos = drivers;
while (pos != NULL)
@ -479,22 +483,13 @@ rdpsnd_show_help(void)
}
}
void
rdpsnd_play(void)
{
current_driver->wave_out_play();
}
void
rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
{
long next_pending;
if (g_dsp_busy)
{
FD_SET(g_dsp_fd, wfds);
*n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
}
if (device_open)
current_driver->add_fds(n, rfds, wfds, tv);
next_pending = rdpsnd_queue_next_completion();
if (next_pending >= 0)
@ -515,8 +510,8 @@ rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
{
rdpsnd_queue_complete_pending();
if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
rdpsnd_play();
if (device_open)
current_driver->check_fds(rfds, wfds);
}
static void
@ -538,9 +533,6 @@ rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
packet->index = index;
gettimeofday(&packet->arrive_tv, NULL);
if (!g_dsp_busy)
current_driver->wave_out_play();
}
struct audio_packet *

View File

@ -30,12 +30,15 @@ struct audio_packet
struct audio_driver
{
BOOL(*wave_out_open) (void);
void (*add_fds) (int *n, fd_set * rfds, fd_set * wfds, struct timeval * tv);
void (*check_fds) (fd_set * rfds, fd_set * wfds);
BOOL(*wave_out_open) (void);
void (*wave_out_close) (void);
BOOL(*wave_out_format_supported) (WAVEFORMATEX * pwfx);
BOOL(*wave_out_set_format) (WAVEFORMATEX * pwfx);
void (*wave_out_volume) (uint16 left, uint16 right);
void (*wave_out_play) (void);
char *name;
char *description;
int need_byteswap_on_be;
@ -43,9 +46,6 @@ struct audio_driver
struct audio_driver *next;
};
extern BOOL g_dsp_busy;
extern int g_dsp_fd;
/* Driver register functions */
struct audio_driver *alsa_register(char *options);
struct audio_driver *libao_register(char *options);

View File

@ -32,6 +32,9 @@
#define DEFAULTDEVICE "default"
#define MAX_FRAMES 32
static struct pollfd pfds[32];
static int num_fds;
static snd_pcm_t *pcm_handle = NULL;
static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
static BOOL reopened;
@ -40,6 +43,71 @@ static int audiochannels;
static unsigned int rate;
static char *pcm_name;
void alsa_play(void);
void
alsa_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
{
int err;
struct pollfd *f;
if (!pcm_handle)
return;
if (rdpsnd_queue_empty())
return;
num_fds = snd_pcm_poll_descriptors_count(pcm_handle);
if (num_fds > sizeof(pfds) / sizeof(*pfds))
return;
err = snd_pcm_poll_descriptors(pcm_handle, pfds, num_fds);
if (err < 0)
return;
for (f = pfds; f < &pfds[num_fds]; f++)
{
if (f->events & POLLIN)
FD_SET(f->fd, rfds);
if (f->events & POLLOUT)
FD_SET(f->fd, wfds);
if (f->fd > *n && (f->events & (POLLIN | POLLOUT)))
*n = f->fd;
}
}
void
alsa_check_fds(fd_set * rfds, fd_set * wfds)
{
struct pollfd *f;
int err;
unsigned short revents;
if (!pcm_handle)
return;
for (f = pfds; f < &pfds[num_fds]; f++)
{
f->revents = 0;
if (f->fd != -1)
{
/* Fixme: This doesn't properly deal with things like POLLHUP */
if (FD_ISSET(f->fd, rfds))
f->revents |= POLLIN;
if (FD_ISSET(f->fd, wfds))
f->revents |= POLLOUT;
}
}
err = snd_pcm_poll_descriptors_revents(pcm_handle, pfds, num_fds, &revents);
if (err < 0)
return;
if (revents & POLLOUT)
alsa_play();
}
BOOL
alsa_open(void)
{
@ -51,8 +119,6 @@ alsa_open(void)
return False;
}
g_dsp_fd = 0;
reopened = True;
return True;
@ -221,11 +287,9 @@ alsa_play(void)
prev_us = tv.tv_usec;
}
/* We shouldn't be called if the queue is empty, but still */
if (rdpsnd_queue_empty())
{
g_dsp_busy = 0;
return;
}
packet = rdpsnd_queue_current_packet();
out = &packet->s;
@ -271,21 +335,20 @@ alsa_play(void)
rdpsnd_queue_next(delay_us);
}
g_dsp_busy = 1;
return;
}
static struct audio_driver alsa_driver = {
.name = "alsa",
.description = "ALSA output driver, default device: " DEFAULTDEVICE,
.add_fds = alsa_add_fds,
.check_fds = alsa_check_fds,
.wave_out_open = alsa_open,
.wave_out_close = alsa_close,
.wave_out_format_supported = alsa_format_supported,
.wave_out_set_format = alsa_set_format,
.wave_out_volume = rdpsnd_dsp_softvol_set,
.wave_out_play = alsa_play,
.need_byteswap_on_be = 0,
.need_resampling = 0,

View File

@ -36,6 +36,23 @@ static int default_driver;
static BOOL reopened;
static char *libao_device = NULL;
void libao_play(void);
void
libao_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
{
}
void
libao_check_fds(fd_set * rfds, fd_set * wfds)
{
if (o_device == NULL)
return;
if (!rdpsnd_queue_empty())
libao_play();
}
BOOL
libao_open(void)
{
@ -64,8 +81,6 @@ libao_open(void)
return False;
}
g_dsp_fd = 0;
reopened = True;
return True;
@ -83,6 +98,8 @@ libao_close(void)
if (o_device != NULL)
ao_close(o_device);
o_device = NULL;
ao_shutdown();
}
@ -134,11 +151,9 @@ libao_play(void)
prev_us = tv.tv_usec;
}
/* We shouldn't be called if the queue is empty, but still */
if (rdpsnd_queue_empty())
{
g_dsp_busy = 0;
return;
}
packet = rdpsnd_queue_current_packet();
out = &packet->s;
@ -170,21 +185,20 @@ libao_play(void)
rdpsnd_queue_next(duration);
}
g_dsp_busy = 1;
return;
}
static struct audio_driver libao_driver = {
.name = "libao",
.description = "libao output driver, default device: system dependent",
.add_fds = libao_add_fds,
.check_fds = libao_check_fds,
.wave_out_open = libao_open,
.wave_out_close = libao_close,
.wave_out_format_supported = rdpsnd_dsp_resample_supported,
.wave_out_set_format = libao_set_format,
.wave_out_volume = rdpsnd_dsp_softvol_set,
.wave_out_play = libao_play,
.need_byteswap_on_be = 1,
.need_resampling = 1,

View File

@ -43,6 +43,9 @@
#define DEFAULTDEVICE "/dev/dsp"
#define MAX_LEN 512
static int dsp_fd = -1;
static BOOL dsp_busy;
static int snd_rate;
static short samplewidth;
static char *dsp_dev;
@ -51,13 +54,36 @@ static BOOL in_esddsp;
/* This is a just a forward declaration */
static struct audio_driver oss_driver;
void oss_play(void);
void
oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
{
if (dsp_fd == -1)
return;
if (rdpsnd_queue_empty())
return;
FD_SET(dsp_fd, wfds);
if (dsp_fd > *n)
*n = dsp_fd;
}
void
oss_check_fds(fd_set * rfds, fd_set * wfds)
{
if (FD_ISSET(dsp_fd, wfds))
oss_play();
}
static BOOL
detect_esddsp(void)
{
struct stat s;
char *preload;
if (fstat(g_dsp_fd, &s) == -1)
if (fstat(dsp_fd, &s) == -1)
return False;
if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
@ -76,7 +102,7 @@ detect_esddsp(void)
BOOL
oss_open(void)
{
if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
if ((dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
{
perror(dsp_dev);
return False;
@ -90,8 +116,9 @@ oss_open(void)
void
oss_close(void)
{
close(g_dsp_fd);
g_dsp_busy = 0;
close(dsp_fd);
dsp_fd = -1;
dsp_busy = False;
}
BOOL
@ -113,8 +140,8 @@ oss_set_format(WAVEFORMATEX * pwfx)
int stereo, format, fragments;
static BOOL driver_broken = False;
ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);
ioctl(dsp_fd, SNDCTL_DSP_RESET, NULL);
ioctl(dsp_fd, SNDCTL_DSP_SYNC, NULL);
if (pwfx->wBitsPerSample == 8)
format = AFMT_U8;
@ -123,7 +150,7 @@ oss_set_format(WAVEFORMATEX * pwfx)
samplewidth = pwfx->wBitsPerSample / 8;
if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
if (ioctl(dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
{
perror("SNDCTL_DSP_SETFMT");
oss_close();
@ -140,7 +167,7 @@ oss_set_format(WAVEFORMATEX * pwfx)
stereo = 0;
}
if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
if (ioctl(dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
{
perror("SNDCTL_DSP_CHANNELS");
oss_close();
@ -149,7 +176,7 @@ oss_set_format(WAVEFORMATEX * pwfx)
oss_driver.need_resampling = 0;
snd_rate = pwfx->nSamplesPerSec;
if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
if (ioctl(dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
{
int rates[] = { 44100, 48000, 0 };
int *prates = rates;
@ -157,7 +184,7 @@ oss_set_format(WAVEFORMATEX * pwfx)
while (*prates != 0)
{
if ((pwfx->nSamplesPerSec != *prates)
&& (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, prates) != -1))
&& (ioctl(dsp_fd, SNDCTL_DSP_SPEED, prates) != -1))
{
oss_driver.need_resampling = 1;
snd_rate = *prates;
@ -184,14 +211,14 @@ oss_set_format(WAVEFORMATEX * pwfx)
/* try to get 12 fragments of 2^12 bytes size */
fragments = (12 << 16) + 12;
ioctl(g_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
ioctl(dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
if (!driver_broken)
{
audio_buf_info info;
memset(&info, 0, sizeof(info));
if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
if (ioctl(dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
{
perror("SNDCTL_DSP_GETOSPACE");
oss_close();
@ -218,7 +245,7 @@ oss_volume(uint16 left, uint16 right)
volume = left / (65536 / 100);
volume |= right / (65536 / 100) << 8;
if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
if (ioctl(dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
{
warning("hardware volume control unavailable, falling back to software volume control!\n");
oss_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
@ -234,23 +261,20 @@ oss_play(void)
ssize_t len;
STREAM out;
/* We shouldn't be called if the queue is empty, but still */
if (rdpsnd_queue_empty())
{
g_dsp_busy = 0;
return;
}
packet = rdpsnd_queue_current_packet();
out = &packet->s;
len = out->end - out->p;
len = write(g_dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
if (len == -1)
{
if (errno != EWOULDBLOCK)
perror("write audio");
g_dsp_busy = 1;
return;
}
@ -272,7 +296,7 @@ oss_play(void)
{
#ifdef SNDCTL_DSP_GETODELAY
delay_bytes = 0;
if (ioctl(g_dsp_fd, SNDCTL_DSP_GETODELAY, &delay_bytes) == -1)
if (ioctl(dsp_fd, SNDCTL_DSP_GETODELAY, &delay_bytes) == -1)
delay_bytes = -1;
#else
delay_bytes = -1;
@ -280,7 +304,7 @@ oss_play(void)
if (delay_bytes == -1)
{
if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) != -1)
if (ioctl(dsp_fd, SNDCTL_DSP_GETOSPACE, &info) != -1)
delay_bytes = info.fragstotal * info.fragsize - info.bytes;
else
delay_bytes = out->size;
@ -290,24 +314,20 @@ oss_play(void)
delay_us = delay_bytes * (1000000 / (samplewidth * snd_rate));
rdpsnd_queue_next(delay_us);
}
else
{
g_dsp_busy = 1;
}
return;
}
static struct audio_driver oss_driver = {
.name = "oss",
.description = "OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV",
.add_fds = oss_add_fds,
.check_fds = oss_check_fds,
.wave_out_open = oss_open,
.wave_out_close = oss_close,
.wave_out_format_supported = oss_format_supported,
.wave_out_set_format = oss_set_format,
.wave_out_volume = oss_volume,
.wave_out_play = oss_play,
.need_byteswap_on_be = 0,
.need_resampling = 0,

View File

@ -39,6 +39,23 @@ double min_volume, max_volume, volume_range;
int resource, maxFillable;
int combinedFrameSize;
void sgi_play(void);
void
sgi_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
{
}
void
sgi_check_fds(fd_set * rfds, fd_set * wfds)
{
if (output_port == (ALport) 0)
return;
if (!rdpsnd_queue_empty())
sgi_play();
}
BOOL
sgi_open(void)
{
@ -101,6 +118,7 @@ sgi_close(void)
alDiscardFrames(output_port, 0);
alClosePort(output_port);
output_port = (ALport) 0;
alFreeConfig(audioconfig);
#if (defined(IRIX_DEBUG))
fprintf(stderr, "sgi_close: returning\n");
@ -240,10 +258,7 @@ sgi_play(void)
while (1)
{
if (rdpsnd_queue_empty())
{
g_dsp_busy = False;
return;
}
packet = rdpsnd_queue_current_packet();
out = &packet->s;
@ -265,7 +280,6 @@ sgi_play(void)
#if (defined(IRIX_DEBUG))
/* fprintf(stderr,"Busy playing...\n"); */
#endif
g_dsp_busy = True;
usleep(10);
return;
}
@ -277,12 +291,14 @@ static struct audio_driver sgi_driver = {
.name = "sgi",
.description = "SGI output driver",
.add_fds = sgi_add_fds,
.check_fds = sgi_check_fds,
.wave_out_open = sgi_open,
.wave_out_close = sgi_close,
.wave_out_format_supported = sgi_format_supported,
.wave_out_set_format = sgi_set_format,
.wave_out_volume = sgi_volume,
.wave_out_play = sgi_play,
.need_byteswap_on_be = 1,
.need_resampling = 0,

View File

@ -34,21 +34,47 @@
#define DEFAULTDEVICE "/dev/audio"
static int dsp_fd = -1;
static BOOL dsp_busy;
static BOOL g_reopened;
static short g_samplewidth;
static char *dsp_dev;
void oss_play(void);
void
sun_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
{
if (dsp_fd == -1)
return;
if (rdpsnd_queue_empty())
return;
FD_SET(dsp_fd, wfds);
if (dsp_fd > *n)
*n = dsp_fd;
}
void
sun_check_fds(fd_set * rfds, fd_set * wfds)
{
if (FD_ISSET(dsp_fd, wfds))
sun_play();
}
BOOL
sun_open(void)
{
if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
if ((dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
{
perror(dsp_dev);
return False;
}
/* Non-blocking so that user interface is responsive */
fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
fcntl(dsp_fd, F_SETFL, fcntl(dsp_fd, F_GETFL) | O_NONBLOCK);
g_reopened = True;
@ -64,12 +90,13 @@ sun_close(void)
#if defined I_FLUSH && defined FLUSHW
/* Flush the audiobuffer */
ioctl(g_dsp_fd, I_FLUSH, FLUSHW);
ioctl(dsp_fd, I_FLUSH, FLUSHW);
#endif
#if defined AUDIO_FLUSH
ioctl(g_dsp_fd, AUDIO_FLUSH, NULL);
ioctl(dsp_fd, AUDIO_FLUSH, NULL);
#endif
close(g_dsp_fd);
close(dsp_fd);
dsp_fd = -1;
}
BOOL
@ -90,7 +117,7 @@ sun_set_format(WAVEFORMATEX * pwfx)
{
audio_info_t info;
ioctl(g_dsp_fd, AUDIO_DRAIN, 0);
ioctl(dsp_fd, AUDIO_DRAIN, 0);
AUDIO_INITINFO(&info);
@ -122,10 +149,10 @@ sun_set_format(WAVEFORMATEX * pwfx)
info.play.error = 0;
g_reopened = True;
if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)
if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
{
perror("AUDIO_SETINFO");
close(g_dsp_fd);
sun_close();
return False;
}
@ -157,7 +184,7 @@ sun_volume(uint16 left, uint16 right)
info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
info.play.balance = balance;
if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)
if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
{
perror("AUDIO_SETINFO");
return;
@ -187,10 +214,7 @@ sun_play(void)
}
if (rdpsnd_queue_empty())
{
g_dsp_busy = 0;
return;
}
packet = rdpsnd_queue_current_packet();
out = &packet->s;
@ -205,12 +229,11 @@ sun_play(void)
if (out->end != out->p)
{
len = write(g_dsp_fd, out->p, out->end - out->p);
len = write(dsp_fd, out->p, out->end - out->p);
if (len == -1)
{
if (errno != EWOULDBLOCK)
perror("write audio");
g_dsp_busy = 1;
return;
}
}
@ -218,7 +241,7 @@ sun_play(void)
out->p += len;
if (out->p == out->end)
{
if (ioctl(g_dsp_fd, AUDIO_GETINFO, &info) == -1)
if (ioctl(dsp_fd, AUDIO_GETINFO, &info) == -1)
{
perror("AUDIO_GETINFO");
return;
@ -235,7 +258,6 @@ sun_play(void)
}
else
{
g_dsp_busy = 1;
return;
}
}
@ -246,12 +268,14 @@ static struct audio_driver sun_driver = {
.name = "sun",
.description = "SUN/BSD output driver, default device: " DEFAULTDEVICE " or $AUDIODEV",
.add_fds = sun_add_fds,
.check_fds = sun_check_fds,
.wave_out_open = sun_open,
.wave_out_close = sun_close,
.wave_out_format_supported = sun_format_supported,
.wave_out_set_format = sun_set_format,
.wave_out_volume = sun_volume,
.wave_out_play = sun_play,
.need_byteswap_on_be = 1,
.need_resampling = 0,

2
xwin.c
View File

@ -147,8 +147,6 @@ static int g_move_y_offset = 0;
static BOOL g_using_full_workarea = False;
#ifdef WITH_RDPSND
extern int g_dsp_fd;
extern BOOL g_dsp_busy;
extern BOOL g_rdpsnd;
#endif