Add capture support to the oss backend.

git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1360 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Pierre Ossman 2007-01-02 16:37:54 +00:00
parent 5300f18275
commit b05c6e25d1

View File

@ -3,6 +3,7 @@
Sound Channel Process Functions - Open Sound System Sound Channel Process Functions - Open Sound System
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 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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
@ -44,8 +45,16 @@
#define MAX_LEN 512 #define MAX_LEN 512
static int dsp_fd = -1; static int dsp_fd = -1;
static BOOL dsp_busy; static int dsp_mode;
static int dsp_refs;
static BOOL dsp_configured;
static BOOL dsp_out;
static BOOL dsp_in;
static int stereo;
static int format;
static int snd_rate; static int snd_rate;
static short samplewidth; static short samplewidth;
static char *dsp_dev; static char *dsp_dev;
@ -55,6 +64,7 @@ static BOOL in_esddsp;
static struct audio_driver oss_driver; static struct audio_driver oss_driver;
void oss_play(void); void oss_play(void);
void oss_record(void);
void void
oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv) oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
@ -62,10 +72,10 @@ oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
if (dsp_fd == -1) if (dsp_fd == -1)
return; return;
if (rdpsnd_queue_empty()) if (dsp_out && !rdpsnd_queue_empty())
return; FD_SET(dsp_fd, wfds);
if (dsp_in)
FD_SET(dsp_fd, wfds); FD_SET(dsp_fd, rfds);
if (dsp_fd > *n) if (dsp_fd > *n)
*n = dsp_fd; *n = dsp_fd;
} }
@ -75,6 +85,8 @@ oss_check_fds(fd_set * rfds, fd_set * wfds)
{ {
if (FD_ISSET(dsp_fd, wfds)) if (FD_ISSET(dsp_fd, wfds))
oss_play(); oss_play();
if (FD_ISSET(dsp_fd, rfds))
oss_record();
} }
static BOOL static BOOL
@ -100,14 +112,53 @@ detect_esddsp(void)
} }
BOOL BOOL
oss_open(void) oss_open(int fallback)
{ {
if ((dsp_fd = open(dsp_dev, O_WRONLY)) == -1) int caps;
if (dsp_fd != -1)
{ {
perror(dsp_dev); dsp_refs++;
if (dsp_mode == O_RDWR)
return True;
if (dsp_mode == fallback)
return True;
dsp_refs--;
return False; return False;
} }
dsp_configured = False;
dsp_mode = O_RDWR;
dsp_fd = open(dsp_dev, O_RDWR | O_NONBLOCK);
if (dsp_fd != -1)
{
ioctl(dsp_fd, SNDCTL_DSP_SETDUPLEX, 0);
if ((ioctl(dsp_fd, SNDCTL_DSP_GETCAPS, &caps) < 0) || !(caps & DSP_CAP_DUPLEX))
{
close(dsp_fd);
dsp_fd = -1;
}
}
if (dsp_fd == -1)
{
dsp_mode = fallback;
dsp_fd = open(dsp_dev, dsp_mode | O_NONBLOCK);
if (dsp_fd == -1)
{
perror(dsp_dev);
return False;
}
}
dsp_refs++;
in_esddsp = detect_esddsp(); in_esddsp = detect_esddsp();
return True; return True;
@ -116,9 +167,55 @@ oss_open(void)
void void
oss_close(void) oss_close(void)
{ {
dsp_refs--;
if (dsp_refs != 0)
return;
close(dsp_fd); close(dsp_fd);
dsp_fd = -1; dsp_fd = -1;
dsp_busy = False; }
BOOL
oss_open_out(void)
{
if (!oss_open(O_WRONLY))
return False;
dsp_out = True;
return True;
}
void
oss_close_out(void)
{
oss_close();
/* Ack all remaining packets */
while (!rdpsnd_queue_empty())
rdpsnd_queue_next(0);
dsp_out = False;
}
BOOL
oss_open_in(void)
{
if (!oss_open(O_RDONLY))
return False;
dsp_in = True;
return True;
}
void
oss_close_in(void)
{
oss_close();
dsp_in = False;
} }
BOOL BOOL
@ -137,9 +234,25 @@ oss_format_supported(WAVEFORMATEX * pwfx)
BOOL BOOL
oss_set_format(WAVEFORMATEX * pwfx) oss_set_format(WAVEFORMATEX * pwfx)
{ {
int stereo, format, fragments; int fragments;
static BOOL driver_broken = False; static BOOL driver_broken = False;
if (dsp_configured)
{
if ((pwfx->wBitsPerSample == 8) && (format != AFMT_U8))
return False;
if ((pwfx->wBitsPerSample == 16) && (format != AFMT_S16_LE))
return False;
if ((pwfx->nChannels == 2) != !!stereo)
return False;
if (pwfx->nSamplesPerSec != snd_rate)
return False;
return True;
}
ioctl(dsp_fd, SNDCTL_DSP_RESET, NULL); ioctl(dsp_fd, SNDCTL_DSP_RESET, NULL);
ioctl(dsp_fd, SNDCTL_DSP_SYNC, NULL); ioctl(dsp_fd, SNDCTL_DSP_SYNC, NULL);
@ -234,6 +347,8 @@ oss_set_format(WAVEFORMATEX * pwfx)
} }
} }
dsp_configured = True;
return True; return True;
} }
@ -316,6 +431,23 @@ oss_play(void)
} }
} }
void
oss_record(void)
{
char buffer[32768];
int len;
len = read(dsp_fd, buffer, sizeof(buffer));
if (len == -1)
{
if (errno != EWOULDBLOCK)
perror("read audio");
return;
}
rdpsnd_record(buffer, len);
}
struct audio_driver * struct audio_driver *
oss_register(char *options) oss_register(char *options)
{ {
@ -328,12 +460,18 @@ oss_register(char *options)
oss_driver.add_fds = oss_add_fds; oss_driver.add_fds = oss_add_fds;
oss_driver.check_fds = oss_check_fds; oss_driver.check_fds = oss_check_fds;
oss_driver.wave_out_open = oss_open; oss_driver.wave_out_open = oss_open_out;
oss_driver.wave_out_close = oss_close; oss_driver.wave_out_close = oss_close_out;
oss_driver.wave_out_format_supported = oss_format_supported; oss_driver.wave_out_format_supported = oss_format_supported;
oss_driver.wave_out_set_format = oss_set_format; oss_driver.wave_out_set_format = oss_set_format;
oss_driver.wave_out_volume = oss_volume; oss_driver.wave_out_volume = oss_volume;
oss_driver.wave_in_open = oss_open_in;
oss_driver.wave_in_close = oss_close_in;
oss_driver.wave_in_format_supported = oss_format_supported;
oss_driver.wave_in_set_format = oss_set_format;
oss_driver.wave_in_volume = NULL; /* FIXME */
oss_driver.need_byteswap_on_be = 0; oss_driver.need_byteswap_on_be = 0;
oss_driver.need_resampling = 0; oss_driver.need_resampling = 0;