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:
parent
139e42d9ef
commit
c6712a8945
1
proto.h
1
proto.h
@ -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
104
rdpsnd.c
@ -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 *
|
||||
|
10
rdpsnd.h
10
rdpsnd.h
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
74
rdpsnd_oss.c
74
rdpsnd_oss.c
@ -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,
|
||||
|
26
rdpsnd_sgi.c
26
rdpsnd_sgi.c
@ -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,
|
||||
|
58
rdpsnd_sun.c
58
rdpsnd_sun.c
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user