278 lines
7.5 KiB
C
278 lines
7.5 KiB
C
/*
|
|
* iaxclient: a cross-platform IAX softphone library
|
|
*
|
|
* Copyrights:
|
|
* Copyright (C) 2006 Panfilov Dmitry
|
|
*
|
|
* Contributors:
|
|
* Panfilov Dmitry
|
|
*
|
|
* This program is free software, distributed under the terms of
|
|
* the GNU Lesser (Library) General Public License.
|
|
*
|
|
*/
|
|
|
|
#include "iaxclient_lib.h"
|
|
#include <alsa/asoundlib.h>
|
|
|
|
static snd_pcm_t *stream_out;
|
|
static snd_pcm_t *stream_in;
|
|
|
|
#define FRAMES_PER_BUFFER 80 /* 80 frames == 10ms */
|
|
|
|
|
|
static int alsa_play_sound(struct iaxc_sound *inSound, int ring) {
|
|
return 0;
|
|
}
|
|
|
|
int alsa_stop_sound(int soundID) {
|
|
return 0;
|
|
}
|
|
|
|
|
|
int alsa_start (struct iaxc_audio_driver *d ) {
|
|
return 0;
|
|
}
|
|
|
|
int alsa_stop (struct iaxc_audio_driver *d ) {
|
|
return 0;
|
|
}
|
|
|
|
void alsa_shutdown_audio()
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
int alsa_input(struct iaxc_audio_driver *d, void *samples, int *nSamples) {
|
|
|
|
/* we don't return partial buffers */
|
|
long r;
|
|
long byteread=*nSamples;
|
|
static int h;
|
|
*nSamples=0;
|
|
snd_pcm_start(stream_in);
|
|
if(h==1) { h=0; return 0;}
|
|
do{
|
|
r = snd_pcm_readi(stream_in, samples, byteread);
|
|
if (r == -EAGAIN){
|
|
continue;
|
|
}
|
|
if (r == - EPIPE) {
|
|
snd_pcm_prepare(stream_in);
|
|
continue;
|
|
}
|
|
samples += (r * 2);
|
|
byteread -= r;
|
|
*nSamples += r;
|
|
}while(r >=0 && byteread >0);
|
|
h=1;
|
|
return 0;
|
|
}
|
|
|
|
int alsa_output(struct iaxc_audio_driver *d, void *samples, int nSamples) {
|
|
|
|
long r;
|
|
snd_pcm_start(stream_out);
|
|
while (nSamples > 0) {
|
|
r = snd_pcm_writei(stream_out, samples, nSamples);
|
|
if (r == -EAGAIN){
|
|
continue;
|
|
}
|
|
if (r == - EPIPE) {
|
|
snd_pcm_prepare(stream_out);
|
|
continue;
|
|
}
|
|
if (r < 0) {
|
|
fprintf(stderr, "r=%d\n",r);
|
|
}
|
|
samples += r * 2;
|
|
nSamples -= r;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int alsa_select_devices (struct iaxc_audio_driver *d, int input, int output, int ring) {
|
|
return 0;
|
|
}
|
|
|
|
int alsa_selected_devices (struct iaxc_audio_driver *d, int *input, int *output, int *ring) {
|
|
*input = 0;
|
|
*output = 0;
|
|
*ring = 0;
|
|
return 0;
|
|
}
|
|
|
|
int alsa_destroy (struct iaxc_audio_driver *d )
|
|
{
|
|
/* TODO: something should happen here */
|
|
return 0;
|
|
}
|
|
|
|
double alsa_input_level_get(struct iaxc_audio_driver *d){
|
|
return -1;
|
|
}
|
|
|
|
double alsa_output_level_get(struct iaxc_audio_driver *d){
|
|
return -1;
|
|
}
|
|
|
|
int alsa_input_level_set(struct iaxc_audio_driver *d, double level){
|
|
return -1;
|
|
}
|
|
|
|
int alsa_output_level_set(struct iaxc_audio_driver *d, double level){
|
|
return -1;
|
|
}
|
|
|
|
|
|
/* initialize audio driver */
|
|
int alsa_initialize (struct iaxc_audio_driver *d ,int sample_rate) {
|
|
int i;
|
|
int err;
|
|
short buf[128];
|
|
snd_pcm_hw_params_t *hw_params;
|
|
snd_pcm_sw_params_t *sw_params;
|
|
|
|
if ((err = snd_pcm_open (&stream_out, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
|
fprintf (stderr, "cannot open audio device default (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
|
|
fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_any (stream_out, hw_params)) < 0) {
|
|
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_access (stream_out, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
|
fprintf (stderr, "cannot set access type (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_format (stream_out, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
|
|
fprintf (stderr, "cannot set sample format (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_rate (stream_out, hw_params, sample_rate, 0)) < 0) {
|
|
fprintf (stderr, "cannot set sample rate (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_channels (stream_out, hw_params, 1)) < 0) {
|
|
fprintf (stderr, "cannot set channel count (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params (stream_out, hw_params)) < 0) {
|
|
fprintf (stderr, "cannot set parameters (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
|
|
snd_pcm_sw_params_malloc(&sw_params);
|
|
|
|
err = snd_pcm_sw_params_current(stream_out, sw_params);
|
|
if (err < 0) {
|
|
printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
|
|
return err;
|
|
}
|
|
err = snd_pcm_sw_params_set_start_threshold(stream_out, sw_params, 80);
|
|
if (err < 0) {
|
|
fprintf(stderr, "Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
|
|
return err;
|
|
}
|
|
err = snd_pcm_sw_params(stream_out, sw_params);
|
|
if (err < 0) {
|
|
fprintf(stderr, "Unable to set sw params for playback: %s\n", snd_strerror(err));
|
|
return err;
|
|
}
|
|
|
|
if ((err = snd_pcm_open (&stream_in, "default", SND_PCM_STREAM_CAPTURE, 0)) < 0) {
|
|
fprintf (stderr, "cannot open audio device default (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_any (stream_in, hw_params)) < 0) {
|
|
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_access (stream_in, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
|
fprintf (stderr, "cannot set access type (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_format (stream_in, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
|
|
fprintf (stderr, "cannot set sample format (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_rate (stream_in, hw_params, sample_rate, 0)) < 0) {
|
|
fprintf (stderr, "cannot set sample rate (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_channels (stream_in, hw_params, 1)) < 0) {
|
|
fprintf (stderr, "cannot set channel count (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params (stream_in, hw_params)) < 0) {
|
|
fprintf (stderr, "cannot set parameters (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
|
|
err = snd_pcm_sw_params_current(stream_in, sw_params);
|
|
if (err < 0) {
|
|
printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err));
|
|
return err;
|
|
}
|
|
err = snd_pcm_sw_params_set_start_threshold(stream_in, sw_params, 80);
|
|
if (err < 0) {
|
|
fprintf(stderr, "Unable to set start threshold mode for playback: %s\n", snd_strerror(err));
|
|
return err;
|
|
}
|
|
err = snd_pcm_sw_params(stream_in, sw_params);
|
|
if (err < 0) {
|
|
fprintf(stderr, "Unable to set sw params for playback: %s\n", snd_strerror(err));
|
|
return err;
|
|
}
|
|
|
|
|
|
if ((err = snd_pcm_prepare (stream_in)) < 0) {
|
|
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
|
|
if ((err = snd_pcm_prepare (stream_out)) < 0) {
|
|
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
|
|
d->initialize = alsa_initialize;
|
|
d->destroy = alsa_destroy;
|
|
d->select_devices = alsa_select_devices;
|
|
d->selected_devices = alsa_selected_devices;
|
|
d->start = alsa_start;
|
|
d->stop = alsa_stop;
|
|
d->output = alsa_output;
|
|
d->input = alsa_input;
|
|
d->input_level_get = alsa_input_level_get;
|
|
d->input_level_set = alsa_input_level_set;
|
|
d->output_level_get = alsa_output_level_get;
|
|
d->output_level_set = alsa_output_level_set;
|
|
d->play_sound = alsa_play_sound;
|
|
d->stop_sound = alsa_stop_sound;
|
|
|
|
return 0;
|
|
}
|