CVS: rdesktop rdpsnd_alsa.c,1.14,1.15
Pierre Ossman <[email protected]> Tue, 02 Jan 2007 08:36:53 -0800
| Newsgroups | gmane.network.rdesktop.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/rdesktop/rdesktop
In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv17211
Modified Files:
rdpsnd_alsa.c
Log Message:
Add capture support to the alsa backend.
Index: rdpsnd_alsa.c
===================================================================
RCS file: /cvsroot/rdesktop/rdesktop/rdpsnd_alsa.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -d -r1.14 -r1.15
*** rdpsnd_alsa.c 2 Jan 2007 11:39:56 -0000 1.14
--- rdpsnd_alsa.c 2 Jan 2007 16:36:51 -0000 1.15
***************
*** 5,8 ****
--- 5,9 ----
Copyright (C) GuoJunBo [email protected] 2003
Copyright (C) Michael Gernoth [email protected] 2006
+ Copyright 2006 Pierre Ossman <[email protected]> for Cendio AB
This program is free software; you can redistribute it and/or modify
***************
*** 33,48 ****
#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;
! static short samplewidth;
! static int audiochannels;
! static unsigned int rate;
static char *pcm_name;
void alsa_play(void);
void
--- 34,60 ----
#define MAX_FRAMES 32
! static struct pollfd pfds_out[32];
! static int num_fds_out;
!
! static struct pollfd pfds_in[32];
! static int num_fds_in;
!
! static snd_pcm_t *out_handle = NULL;
! static snd_pcm_t *in_handle = NULL;
static BOOL reopened;
!
! static short samplewidth_out;
! static int audiochannels_out;
! static unsigned int rate_out;
!
! static short samplewidth_in;
! static int audiochannels_in;
! static unsigned int rate_in;
!
static char *pcm_name;
void alsa_play(void);
+ void alsa_record(void);
void
***************
*** 52,78 ****
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;
}
}
--- 64,109 ----
struct pollfd *f;
! if (out_handle && !rdpsnd_queue_empty())
! {
! num_fds_out = snd_pcm_poll_descriptors_count(out_handle);
! if (num_fds_out > sizeof(pfds_out) / sizeof(*pfds_out))
! return;
! err = snd_pcm_poll_descriptors(out_handle, pfds_out, num_fds_out);
! if (err < 0)
! return;
! for (f = pfds_out; f < &pfds_out[num_fds_out]; 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;
! }
! }
! if (in_handle)
{
! num_fds_in = snd_pcm_poll_descriptors_count(in_handle);
!
! if (num_fds_in > sizeof(pfds_in) / sizeof(*pfds_in))
! return;
!
! err = snd_pcm_poll_descriptors(in_handle, pfds_in, num_fds_in);
! if (err < 0)
! return;
!
! for (f = pfds_in; f < &pfds_in[num_fds_in]; 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;
! }
}
}
***************
*** 85,181 ****
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)
! {
! int err;
! if ((err = snd_pcm_open(&pcm_handle, pcm_name, stream, 0)) < 0)
! {
! error("snd_pcm_open: %s\n", snd_strerror(err));
! return False;
}
- reopened = True;
-
- return True;
- }
-
- void
- alsa_close(void)
- {
- /* Ack all remaining packets */
- while (!rdpsnd_queue_empty())
- rdpsnd_queue_next(0);
! if (pcm_handle)
{
! snd_pcm_close(pcm_handle);
! pcm_handle = NULL;
! }
! }
!
! BOOL
! alsa_format_supported(WAVEFORMATEX * pwfx)
! {
! #if 0
! int err;
! snd_pcm_hw_params_t *hwparams = NULL;
! if ((err = snd_pcm_hw_params_malloc(&hwparams)) < 0)
! {
! error("snd_pcm_hw_params_malloc: %s\n", snd_strerror(err));
! return False;
! }
! if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0)
! {
! error("snd_pcm_hw_params_malloc: %s\n", snd_strerror(err));
! return False;
}
- snd_pcm_hw_params_free(hwparams);
- #endif
-
- if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
- return False;
- if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
- return False;
- if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
- return False;
- if ((pwfx->nSamplesPerSec != 44100) && (pwfx->nSamplesPerSec != 22050))
- return False;
-
- return True;
}
! BOOL
! alsa_set_format(WAVEFORMATEX * pwfx)
{
snd_pcm_hw_params_t *hwparams = NULL;
int err;
unsigned int buffertime;
samplewidth = pwfx->wBitsPerSample / 8;
--- 116,176 ----
unsigned short revents;
! if (out_handle && !rdpsnd_queue_empty())
{
! for (f = pfds_out; f < &pfds_out[num_fds_out]; 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(out_handle, pfds_out, num_fds_out, &revents);
! if (err < 0)
! return;
! if (revents & POLLOUT)
! alsa_play();
}
! if (in_handle)
{
! for (f = pfds_in; f < &pfds_in[num_fds_in]; 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(in_handle, pfds_in, num_fds_in, &revents);
! if (err < 0)
! return;
! if (revents & POLLIN)
! alsa_record();
}
}
! static BOOL
! alsa_set_format(snd_pcm_t * pcm, WAVEFORMATEX * pwfx)
{
snd_pcm_hw_params_t *hwparams = NULL;
int err;
unsigned int buffertime;
+ short samplewidth;
+ int audiochannels;
+ unsigned int rate;
samplewidth = pwfx->wBitsPerSample / 8;
***************
*** 187,191 ****
}
! if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0)
{
error("snd_pcm_hw_params_any: %s\n", snd_strerror(err));
--- 182,186 ----
}
! if ((err = snd_pcm_hw_params_any(pcm, hwparams)) < 0)
{
error("snd_pcm_hw_params_any: %s\n", snd_strerror(err));
***************
*** 193,198 ****
}
! if ((err =
! snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
error("snd_pcm_hw_params_set_access: %s\n", snd_strerror(err));
--- 188,192 ----
}
! if ((err = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
error("snd_pcm_hw_params_set_access: %s\n", snd_strerror(err));
***************
*** 202,207 ****
if (pwfx->wBitsPerSample == 16)
{
! if ((err =
! snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE)) < 0)
{
error("snd_pcm_hw_params_set_format: %s\n", snd_strerror(err));
--- 196,200 ----
if (pwfx->wBitsPerSample == 16)
{
! if ((err = snd_pcm_hw_params_set_format(pcm, hwparams, SND_PCM_FORMAT_S16_LE)) < 0)
{
error("snd_pcm_hw_params_set_format: %s\n", snd_strerror(err));
***************
*** 211,216 ****
else
{
! if ((err =
! snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S8)) < 0)
{
error("snd_pcm_hw_params_set_format: %s\n", snd_strerror(err));
--- 204,208 ----
else
{
! if ((err = snd_pcm_hw_params_set_format(pcm, hwparams, SND_PCM_FORMAT_S8)) < 0)
{
error("snd_pcm_hw_params_set_format: %s\n", snd_strerror(err));
***************
*** 220,224 ****
#if 0
! if ((err = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 1)) < 0)
{
error("snd_pcm_hw_params_set_rate_resample: %s\n", snd_strerror(err));
--- 212,216 ----
#if 0
! if ((err = snd_pcm_hw_params_set_rate_resample(pcm, hwparams, 1)) < 0)
{
error("snd_pcm_hw_params_set_rate_resample: %s\n", snd_strerror(err));
***************
*** 228,232 ****
rate = pwfx->nSamplesPerSec;
! if ((err = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0)) < 0)
{
error("snd_pcm_hw_params_set_rate_near: %s\n", snd_strerror(err));
--- 220,224 ----
rate = pwfx->nSamplesPerSec;
! if ((err = snd_pcm_hw_params_set_rate_near(pcm, hwparams, &rate, 0)) < 0)
{
error("snd_pcm_hw_params_set_rate_near: %s\n", snd_strerror(err));
***************
*** 235,239 ****
audiochannels = pwfx->nChannels;
! if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, pwfx->nChannels)) < 0)
{
error("snd_pcm_hw_params_set_channels: %s\n", snd_strerror(err));
--- 227,231 ----
audiochannels = pwfx->nChannels;
! if ((err = snd_pcm_hw_params_set_channels(pcm, hwparams, pwfx->nChannels)) < 0)
{
error("snd_pcm_hw_params_set_channels: %s\n", snd_strerror(err));
***************
*** 243,248 ****
buffertime = 500000; /* microseconds */
! if ((err =
! snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hwparams, &buffertime, 0)) < 0)
{
error("snd_pcm_hw_params_set_buffer_time_near: %s\n", snd_strerror(err));
--- 235,239 ----
buffertime = 500000; /* microseconds */
! if ((err = snd_pcm_hw_params_set_buffer_time_near(pcm, hwparams, &buffertime, 0)) < 0)
{
error("snd_pcm_hw_params_set_buffer_time_near: %s\n", snd_strerror(err));
***************
*** 250,254 ****
}
! if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
{
error("snd_pcm_hw_params: %s\n", snd_strerror(err));
--- 241,245 ----
}
! if ((err = snd_pcm_hw_params(pcm, hwparams)) < 0)
{
error("snd_pcm_hw_params: %s\n", snd_strerror(err));
***************
*** 258,262 ****
snd_pcm_hw_params_free(hwparams);
! if ((err = snd_pcm_prepare(pcm_handle)) < 0)
{
error("snd_pcm_prepare: %s\n", snd_strerror(err));
--- 249,253 ----
snd_pcm_hw_params_free(hwparams);
! if ((err = snd_pcm_prepare(pcm)) < 0)
{
error("snd_pcm_prepare: %s\n", snd_strerror(err));
***************
*** 269,272 ****
--- 260,339 ----
}
+ BOOL
+ alsa_open_out(void)
+ {
+ int err;
+
+ if ((err = snd_pcm_open(&out_handle, pcm_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
+ {
+ error("snd_pcm_open: %s\n", snd_strerror(err));
+ return False;
+ }
+
+ reopened = True;
+
+ return True;
+ }
+
+ void
+ alsa_close_out(void)
+ {
+ /* Ack all remaining packets */
+ while (!rdpsnd_queue_empty())
+ rdpsnd_queue_next(0);
+
+ if (out_handle)
+ {
+ snd_pcm_close(out_handle);
+ out_handle = NULL;
+ }
+ }
+
+ BOOL
+ alsa_format_supported(WAVEFORMATEX * pwfx)
+ {
+ #if 0
+ int err;
+ snd_pcm_hw_params_t *hwparams = NULL;
+
+ if ((err = snd_pcm_hw_params_malloc(&hwparams)) < 0)
+ {
+ error("snd_pcm_hw_params_malloc: %s\n", snd_strerror(err));
+ return False;
+ }
+
+ if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0)
+ {
+ error("snd_pcm_hw_params_malloc: %s\n", snd_strerror(err));
+ return False;
+ }
+ snd_pcm_hw_params_free(hwparams);
+ #endif
+
+ if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
+ return False;
+ if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
+ return False;
+ if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
+ return False;
+ if ((pwfx->nSamplesPerSec != 44100) && (pwfx->nSamplesPerSec != 22050))
+ return False;
+
+ return True;
+ }
+
+ BOOL
+ alsa_set_format_out(WAVEFORMATEX * pwfx)
+ {
+ if (!alsa_set_format(out_handle, pwfx))
+ return False;
+
+ samplewidth_out = pwfx->wBitsPerSample / 8;
+ audiochannels_out = pwfx->nChannels;
+ rate_out = pwfx->nSamplesPerSec;
+
+ return True;
+ }
+
void
alsa_play(void)
***************
*** 297,307 ****
next_tick = rdpsnd_queue_next_tick();
! len = (out->end - out->p) / (samplewidth * audiochannels);
! if ((len = snd_pcm_writei(pcm_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0)
{
! snd_pcm_prepare(pcm_handle);
len = 0;
}
! out->p += (len * samplewidth * audiochannels);
gettimeofday(&tv, NULL);
--- 364,375 ----
next_tick = rdpsnd_queue_next_tick();
! len = (out->end - out->p) / (samplewidth_out * audiochannels_out);
! if ((len = snd_pcm_writei(out_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0)
{
! printf("Fooo!\n");
! snd_pcm_prepare(out_handle);
len = 0;
}
! out->p += (len * samplewidth_out * audiochannels_out);
gettimeofday(&tv, NULL);
***************
*** 327,336 ****
}
! if (snd_pcm_delay(pcm_handle, &delay_frames) < 0)
! delay_frames = out->size / (samplewidth * audiochannels);
if (delay_frames < 0)
delay_frames = 0;
! delay_us = delay_frames * (1000000 / rate);
rdpsnd_queue_next(delay_us);
--- 395,404 ----
}
! if (snd_pcm_delay(out_handle, &delay_frames) < 0)
! delay_frames = out->size / (samplewidth_out * audiochannels_out);
if (delay_frames < 0)
delay_frames = 0;
! delay_us = delay_frames * (1000000 / rate_out);
rdpsnd_queue_next(delay_us);
***************
*** 338,341 ****
--- 406,472 ----
}
+ BOOL
+ alsa_open_in(void)
+ {
+ int err;
+
+ if ((err =
+ snd_pcm_open(&in_handle, pcm_name, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0)
+ {
+ error("snd_pcm_open: %s\n", snd_strerror(err));
+ return False;
+ }
+
+ return True;
+ }
+
+ void
+ alsa_close_in(void)
+ {
+ if (in_handle)
+ {
+ snd_pcm_close(in_handle);
+ in_handle = NULL;
+ }
+ }
+
+ BOOL
+ alsa_set_format_in(WAVEFORMATEX * pwfx)
+ {
+ int err;
+
+ if (!alsa_set_format(in_handle, pwfx))
+ return False;
+
+ if ((err = snd_pcm_start(in_handle)) < 0)
+ {
+ error("snd_pcm_start: %s\n", snd_strerror(err));
+ return False;
+ }
+
+ samplewidth_in = pwfx->wBitsPerSample / 8;
+ audiochannels_in = pwfx->nChannels;
+ rate_in = pwfx->nSamplesPerSec;
+
+ return True;
+ }
+
+ void
+ alsa_record(void)
+ {
+ int len;
+ char buffer[32768];
+
+ len = snd_pcm_readi(in_handle, buffer,
+ sizeof(buffer) / (samplewidth_in * audiochannels_in));
+ if (len < 0)
+ {
+ snd_pcm_prepare(in_handle);
+ len = 0;
+ }
+
+ rdpsnd_record(buffer, len * samplewidth_in * audiochannels_in);
+ }
+
struct audio_driver *
alsa_register(char *options)
***************
*** 351,360 ****
alsa_driver.check_fds = alsa_check_fds;
! alsa_driver.wave_out_open = alsa_open;
! alsa_driver.wave_out_close = alsa_close;
alsa_driver.wave_out_format_supported = alsa_format_supported;
! alsa_driver.wave_out_set_format = alsa_set_format;
alsa_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
alsa_driver.need_byteswap_on_be = 0;
alsa_driver.need_resampling = 0;
--- 482,497 ----
alsa_driver.check_fds = alsa_check_fds;
! alsa_driver.wave_out_open = alsa_open_out;
! alsa_driver.wave_out_close = alsa_close_out;
alsa_driver.wave_out_format_supported = alsa_format_supported;
! alsa_driver.wave_out_set_format = alsa_set_format_out;
alsa_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
+ alsa_driver.wave_in_open = alsa_open_in;
+ alsa_driver.wave_in_close = alsa_close_in;
+ alsa_driver.wave_in_format_supported = alsa_format_supported;
+ alsa_driver.wave_in_set_format = alsa_set_format_in;
+ alsa_driver.wave_in_volume = NULL; /* FIXME */
+
alsa_driver.need_byteswap_on_be = 0;
alsa_driver.need_resampling = 0;
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV