/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
Sound Channel Process Functions - Open Sound System
Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
Copyright (C) GuoJunBo <guojunbo@ict.ac.cn> 2003
Copyright 2006-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
Copyright 2005-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*/
/*
* Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
* other than GPL or LGPL is available it will apply instead, Oracle elects to use only
* the General Public License version 2 (GPLv2) at this time for any software where
* a choice of GPL license versions is made available with the language indicating
* that GPLv2 or any later version may be used, or where a choice of which version
* of the GPL is applied is otherwise unspecified.
*/
/*
This is a workaround for Esound bug 312665.
FIXME: Remove this when Esound is fixed.
*/
#ifdef _FILE_OFFSET_BITS
#endif
#include <assert.h>
#include "rdesktop.h"
#include "rdpsnd.h"
#include "rdpsnd_dsp.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/soundcard.h>
static int dsp_mode;
static int stereo;
static int format;
static short samplewidth;
static char *dsp_dev;
/* This is a just a forward declaration */
static void oss_play(void);
static void oss_record(void);
static void
{
if (dsp_fd == -1)
return;
if (dsp_fd > *n)
*n = dsp_fd;
}
static void
{
oss_play();
oss_record();
}
static RD_BOOL
detect_esddsp(void)
{
struct stat s;
char *preload;
return False;
return False;
return False;
return False;
return True;
}
static void
{
switch (format)
{
case AFMT_U8:
break;
case AFMT_S16_LE:
break;
default:
wfx.wBitsPerSample = 0;
}
}
static RD_BOOL
{
if (dsp_fd != -1)
{
{
/* should probably not happen */
return True;
}
else
{
/* device open but not our mode. Before
reopening O_RDWR, verify that the device is
duplex capable */
int caps;
|| !(caps & DSP_CAP_DUPLEX))
{
warning("This device is not capable of full duplex operation.\n");
return False;
}
}
}
else
{
}
dsp_broken = False;
if (dsp_fd == -1)
{
return False;
}
in_esddsp = detect_esddsp();
return True;
}
static void
oss_close(void)
{
dsp_fd = -1;
}
static RD_BOOL
oss_open_out(void)
{
return False;
return True;
}
static void
oss_close_out(void)
{
oss_close();
{
}
/* Ack all remaining packets */
while (!rdpsnd_queue_empty())
}
static RD_BOOL
oss_open_in(void)
{
return False;
return True;
}
static void
oss_close_in(void)
{
oss_close();
{
}
}
static RD_BOOL
{
return False;
return False;
return False;
return True;
}
static RD_BOOL
{
int fragments;
if (dsp_configured)
{
return False;
return False;
return False;
return False;
return True;
}
{
perror("SNDCTL_DSP_SETFMT");
oss_close();
return False;
}
{
stereo = 1;
samplewidth *= 2;
}
else
{
stereo = 0;
}
{
perror("SNDCTL_DSP_CHANNELS");
oss_close();
return False;
}
{
while (*prates != 0)
{
{
{
error("rdpsnd_dsp_resample_set failed");
oss_close();
return False;
}
break;
}
prates++;
}
if (*prates == 0)
{
perror("SNDCTL_DSP_SPEED");
oss_close();
return False;
}
}
/* try to get 12 fragments of 2^12 bytes size */
if (!driver_broken)
{
{
perror("SNDCTL_DSP_GETOSPACE");
oss_close();
return False;
}
{
"Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
}
}
return True;
}
static void
{
{
warning("hardware volume control unavailable, falling back to software volume control!\n");
return;
}
}
static void
oss_play(void)
{
/* We shouldn't be called if the queue is empty, but still */
if (rdpsnd_queue_empty())
return;
if (len == -1)
{
if (errno != EWOULDBLOCK)
{
if (!dsp_broken)
perror("RDPSND: write()");
dsp_broken = True;
}
return;
}
dsp_broken = False;
{
int delay_bytes;
unsigned long delay_us;
if (in_esddsp)
{
/* EsounD has no way of querying buffer status, so we have to
* go with a fixed size. */
}
else
{
#ifdef SNDCTL_DSP_GETODELAY
delay_bytes = 0;
delay_bytes = -1;
#else
delay_bytes = -1;
#endif
if (delay_bytes == -1)
{
else
}
}
}
}
static void
oss_record(void)
{
int len;
if (len == -1)
{
if (errno != EWOULDBLOCK)
{
if (!dsp_broken)
perror("RDPSND: read()");
dsp_broken = True;
}
return;
}
dsp_broken = False;
}
struct audio_driver *
{
if (options)
{
}
else
{
{
}
}
return &oss_driver;
}