Reworked device opening, only open the device with the access that we

currently needs. Avoids transmitting recording data on playback with padsp.


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1480 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Peter Åstrand 2008-10-02 18:21:58 +00:00
parent edbae085f1
commit d87e27483f

View File

@ -28,6 +28,8 @@
#undef _FILE_OFFSET_BITS #undef _FILE_OFFSET_BITS
#endif #endif
#include <assert.h>
#include "rdesktop.h" #include "rdesktop.h"
#include "rdpsnd.h" #include "rdpsnd.h"
#include "rdpsnd_dsp.h" #include "rdpsnd_dsp.h"
@ -46,14 +48,10 @@
static int dsp_fd = -1; static int dsp_fd = -1;
static int dsp_mode; static int dsp_mode;
static int dsp_refs;
static RD_BOOL dsp_configured; static RD_BOOL dsp_configured;
static RD_BOOL dsp_broken; static RD_BOOL dsp_broken;
static RD_BOOL dsp_out;
static RD_BOOL dsp_in;
static int stereo; static int stereo;
static int format; static int format;
static uint32 snd_rate; static uint32 snd_rate;
@ -66,6 +64,7 @@ static struct audio_driver oss_driver;
static void oss_play(void); static void oss_play(void);
static void oss_record(void); static void oss_record(void);
static RD_BOOL oss_set_format(RD_WAVEFORMATEX * pwfx);
static void static 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)
@ -73,9 +72,9 @@ 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 (dsp_out && !rdpsnd_queue_empty()) if ((dsp_mode == O_WRONLY || dsp_mode == O_RDWR) && !rdpsnd_queue_empty())
FD_SET(dsp_fd, wfds); FD_SET(dsp_fd, wfds);
if (dsp_in) if (dsp_mode == O_RDONLY || dsp_mode == O_RDWR)
FD_SET(dsp_fd, rfds); FD_SET(dsp_fd, rfds);
if (dsp_fd > *n) if (dsp_fd > *n)
*n = dsp_fd; *n = dsp_fd;
@ -112,55 +111,72 @@ detect_esddsp(void)
return True; return True;
} }
static RD_BOOL
oss_open(int fallback)
{
int caps;
static void
oss_restore_format()
{
RD_WAVEFORMATEX wfx;
memset(&wfx, 0, sizeof(RD_WAVEFORMATEX));
switch (format)
{
case AFMT_U8:
wfx.wBitsPerSample = 8;
break;
case AFMT_S16_LE:
wfx.wBitsPerSample = 16;
break;
default:
wfx.wBitsPerSample = 0;
}
wfx.nChannels = stereo ? 2 : 1;
wfx.nSamplesPerSec = snd_rate;
oss_set_format(&wfx);
}
static RD_BOOL
oss_open(int wanted)
{
if (dsp_fd != -1) if (dsp_fd != -1)
{ {
dsp_refs++; if (wanted == dsp_mode)
{
if (dsp_mode == O_RDWR) /* should probably not happen */
return True; return True;
}
if (dsp_mode == fallback) else
return True; {
/* device open but not our mode. Before
dsp_refs--; reopening O_RDWR, verify that the device is
return False; duplex capable */
int caps;
ioctl(dsp_fd, SNDCTL_DSP_SETDUPLEX, 0);
if ((ioctl(dsp_fd, SNDCTL_DSP_GETCAPS, &caps) < 0)
|| !(caps & DSP_CAP_DUPLEX))
{
warning("This device is not capable of full duplex operation.\n");
return False;
}
close(dsp_fd);
dsp_mode = O_RDWR;
}
}
else
{
dsp_mode = wanted;
} }
dsp_configured = False; dsp_configured = False;
dsp_broken = False; dsp_broken = False;
dsp_mode = O_RDWR; dsp_fd = open(dsp_dev, dsp_mode | O_NONBLOCK);
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) if (dsp_fd == -1)
{ {
dsp_mode = fallback; perror(dsp_dev);
return False;
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;
@ -169,11 +185,6 @@ oss_open(int fallback)
static void static 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;
} }
@ -184,8 +195,6 @@ oss_open_out(void)
if (!oss_open(O_WRONLY)) if (!oss_open(O_WRONLY))
return False; return False;
dsp_out = True;
return True; return True;
} }
@ -193,12 +202,15 @@ static void
oss_close_out(void) oss_close_out(void)
{ {
oss_close(); oss_close();
if (dsp_mode == O_RDWR)
{
if (oss_open(O_RDONLY))
oss_restore_format();
}
/* Ack all remaining packets */ /* Ack all remaining packets */
while (!rdpsnd_queue_empty()) while (!rdpsnd_queue_empty())
rdpsnd_queue_next(0); rdpsnd_queue_next(0);
dsp_out = False;
} }
static RD_BOOL static RD_BOOL
@ -207,8 +219,6 @@ oss_open_in(void)
if (!oss_open(O_RDONLY)) if (!oss_open(O_RDONLY))
return False; return False;
dsp_in = True;
return True; return True;
} }
@ -216,8 +226,11 @@ static void
oss_close_in(void) oss_close_in(void)
{ {
oss_close(); oss_close();
if (dsp_mode == O_RDWR)
dsp_in = False; {
if (oss_open(O_WRONLY))
oss_restore_format();
}
} }
static RD_BOOL static RD_BOOL
@ -239,6 +252,8 @@ oss_set_format(RD_WAVEFORMATEX * pwfx)
int fragments; int fragments;
static RD_BOOL driver_broken = False; static RD_BOOL driver_broken = False;
assert(dsp_fd != -1);
if (dsp_configured) if (dsp_configured)
{ {
if ((pwfx->wBitsPerSample == 8) && (format != AFMT_U8)) if ((pwfx->wBitsPerSample == 8) && (format != AFMT_U8))
@ -378,6 +393,8 @@ oss_play(void)
ssize_t len; ssize_t len;
STREAM out; STREAM out;
assert(dsp_fd != -1);
/* We shouldn't be called if the queue is empty, but still */ /* We shouldn't be called if the queue is empty, but still */
if (rdpsnd_queue_empty()) if (rdpsnd_queue_empty())
return; return;
@ -446,6 +463,8 @@ oss_record(void)
char buffer[32768]; char buffer[32768];
int len; int len;
assert(dsp_fd != -1);
len = read(dsp_fd, buffer, sizeof(buffer)); len = read(dsp_fd, buffer, sizeof(buffer));
if (len == -1) if (len == -1)
{ {