mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-23 19:54:17 +00:00
gsmopen: begin cleaning from alsa
This commit is contained in:
1 parent
6623420e01
commit
49a4d2126b
2 files changed
+1
-466
No files matched your search
@@ -2444,357 +2444,6 @@ int gsmopen_hangup(private_t *tech_pvt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef GSMOPEN_ALSA
|
||||
/*! \brief ALSA pcm format, according to endianess */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
snd_pcm_format_t gsmopen_format = SND_PCM_FORMAT_S16_LE;
|
||||
#else
|
||||
snd_pcm_format_t gsmopen_format = SND_PCM_FORMAT_S16_BE;
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Initialize the ALSA soundcard channels (capture AND playback) used by one interface (a multichannel soundcard can be used by multiple interfaces)
|
||||
* \param p the gsmopen_pvt of the interface
|
||||
*
|
||||
* This function call alsa_open_dev to initialize the ALSA soundcard for each channel (capture AND playback) used by one interface (a multichannel soundcard can be used by multiple interfaces). Called by sound_init
|
||||
*
|
||||
* \return zero on success, -1 on error.
|
||||
*/
|
||||
int alsa_init(private_t *tech_pvt)
|
||||
{
|
||||
tech_pvt->alsac = alsa_open_dev(tech_pvt, SND_PCM_STREAM_CAPTURE);
|
||||
if (!tech_pvt->alsac) {
|
||||
ERRORA("Failed opening ALSA capture device: %s\n", GSMOPEN_P_LOG, tech_pvt->alsacname);
|
||||
if (alsa_shutdown(tech_pvt)) {
|
||||
ERRORA("alsa_shutdown failed\n", GSMOPEN_P_LOG);
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
tech_pvt->alsap = alsa_open_dev(tech_pvt, SND_PCM_STREAM_PLAYBACK);
|
||||
if (!tech_pvt->alsap) {
|
||||
ERRORA("Failed opening ALSA playback device: %s\n", GSMOPEN_P_LOG, tech_pvt->alsapname);
|
||||
if (alsa_shutdown(tech_pvt)) {
|
||||
ERRORA("alsa_shutdown failed\n", GSMOPEN_P_LOG);
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* make valgrind very happy */
|
||||
snd_config_update_free_global();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Shutdown the ALSA soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces)
|
||||
* \param p the gsmopen_pvt of the interface
|
||||
*
|
||||
* This function shutdown the ALSA soundcard channels (input and output) used by one interface (a multichannel soundcard can be used by multiple interfaces). Called by sound_init
|
||||
*
|
||||
* \return zero on success, -1 on error.
|
||||
*/
|
||||
|
||||
int alsa_shutdown(private_t *tech_pvt)
|
||||
{
|
||||
|
||||
int err;
|
||||
|
||||
if (tech_pvt->alsap) {
|
||||
err = snd_pcm_drop(tech_pvt->alsap);
|
||||
if (err < 0) {
|
||||
ERRORA("device [%s], snd_pcm_drop failed with error '%s'\n", GSMOPEN_P_LOG, tech_pvt->alsapname, snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_close(tech_pvt->alsap);
|
||||
if (err < 0) {
|
||||
ERRORA("device [%s], snd_pcm_close failed with error '%s'\n", GSMOPEN_P_LOG, tech_pvt->alsapname, snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
tech_pvt->alsap = NULL;
|
||||
}
|
||||
if (tech_pvt->alsac) {
|
||||
err = snd_pcm_drop(tech_pvt->alsac);
|
||||
if (err < 0) {
|
||||
ERRORA("device [%s], snd_pcm_drop failed with error '%s'\n", GSMOPEN_P_LOG, tech_pvt->alsacname, snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
err = snd_pcm_close(tech_pvt->alsac);
|
||||
if (err < 0) {
|
||||
ERRORA("device [%s], snd_pcm_close failed with error '%s'\n", GSMOPEN_P_LOG, tech_pvt->alsacname, snd_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
tech_pvt->alsac = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Setup and open the ALSA device (capture OR playback)
|
||||
* \param p the gsmopen_pvt of the interface
|
||||
* \param stream the ALSA capture/playback definition
|
||||
*
|
||||
* This function setup and open the ALSA device (capture OR playback). Called by alsa_init
|
||||
*
|
||||
* \return zero on success, -1 on error.
|
||||
*/
|
||||
snd_pcm_t *alsa_open_dev(private_t *tech_pvt, snd_pcm_stream_t stream)
|
||||
{
|
||||
|
||||
snd_pcm_t *handle = NULL;
|
||||
snd_pcm_hw_params_t *params;
|
||||
snd_pcm_sw_params_t *swparams;
|
||||
snd_pcm_uframes_t buffer_size;
|
||||
int err;
|
||||
size_t n;
|
||||
//snd_pcm_uframes_t xfer_align;
|
||||
unsigned int rate;
|
||||
snd_pcm_uframes_t start_threshold, stop_threshold;
|
||||
snd_pcm_uframes_t period_size = 0;
|
||||
snd_pcm_uframes_t chunk_size = 0;
|
||||
int start_delay = 0;
|
||||
int stop_delay = 0;
|
||||
snd_pcm_state_t state;
|
||||
snd_pcm_info_t *info;
|
||||
unsigned int chan_num;
|
||||
|
||||
period_size = tech_pvt->alsa_period_size;
|
||||
|
||||
snd_pcm_hw_params_alloca(¶ms);
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
|
||||
if (stream == SND_PCM_STREAM_CAPTURE) {
|
||||
err = snd_pcm_open(&handle, tech_pvt->alsacname, stream, 0 | SND_PCM_NONBLOCK);
|
||||
} else {
|
||||
err = snd_pcm_open(&handle, tech_pvt->alsapname, stream, 0 | SND_PCM_NONBLOCK);
|
||||
}
|
||||
if (err < 0) {
|
||||
ERRORA
|
||||
("snd_pcm_open failed with error '%s' on device '%s', if you are using a plughw:n device please change it to be a default:n device (so to allow it to be shared with other concurrent programs), or maybe you are using an ALSA voicemodem and slmodemd"
|
||||
" is running?\n", GSMOPEN_P_LOG, snd_strerror(err), stream == SND_PCM_STREAM_CAPTURE ? tech_pvt->alsacname : tech_pvt->alsapname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snd_pcm_info_alloca(&info);
|
||||
|
||||
if ((err = snd_pcm_info(handle, info)) < 0) {
|
||||
ERRORA("info error: %s", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = snd_pcm_nonblock(handle, 1);
|
||||
if (err < 0) {
|
||||
ERRORA("nonblock setting error: %s", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_any(handle, params);
|
||||
if (err < 0) {
|
||||
ERRORA("Broken configuration for this PCM, no configurations available: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (err < 0) {
|
||||
ERRORA("Access type not available: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_format(handle, params, gsmopen_format);
|
||||
if (err < 0) {
|
||||
ERRORA("Sample format non available: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
err = snd_pcm_hw_params_set_channels(handle, params, 1);
|
||||
if (err < 0) {
|
||||
DEBUGA_GSMOPEN("Channels count set failed: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
}
|
||||
#if 1
|
||||
err = snd_pcm_hw_params_get_channels(params, &chan_num);
|
||||
if (err < 0) {
|
||||
ERRORA("Channels count non available: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
if (chan_num < 1 || chan_num > 2) {
|
||||
ERRORA("Channels count MUST BE 1 or 2, it is: %d\n", GSMOPEN_P_LOG, chan_num);
|
||||
ERRORA("Channels count MUST BE 1 or 2, it is: %d on %s %s\n", GSMOPEN_P_LOG, chan_num, tech_pvt->alsapname, tech_pvt->alsacname);
|
||||
return NULL;
|
||||
} else {
|
||||
if (chan_num == 1) {
|
||||
if (stream == SND_PCM_STREAM_CAPTURE)
|
||||
tech_pvt->alsa_capture_is_mono = 1;
|
||||
else
|
||||
tech_pvt->alsa_play_is_mono = 1;
|
||||
} else {
|
||||
if (stream == SND_PCM_STREAM_CAPTURE)
|
||||
tech_pvt->alsa_capture_is_mono = 0;
|
||||
else
|
||||
tech_pvt->alsa_play_is_mono = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
tech_pvt->alsa_capture_is_mono = 1;
|
||||
tech_pvt->alsa_play_is_mono = 1;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
rate = tech_pvt->gsmopen_sound_rate;
|
||||
err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0);
|
||||
if ((float) tech_pvt->gsmopen_sound_rate * 1.05 < rate || (float) tech_pvt->gsmopen_sound_rate * 0.95 > rate) {
|
||||
WARNINGA("Rate is not accurate (requested = %iHz, got = %iHz)\n", GSMOPEN_P_LOG, tech_pvt->gsmopen_sound_rate, rate);
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
ERRORA("Error setting rate: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
tech_pvt->gsmopen_sound_rate = rate;
|
||||
|
||||
err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, 0);
|
||||
|
||||
if (err < 0) {
|
||||
ERRORA("Error setting period_size: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tech_pvt->alsa_period_size = period_size;
|
||||
|
||||
tech_pvt->alsa_buffer_size = tech_pvt->alsa_period_size * tech_pvt->alsa_periods_in_buffer;
|
||||
|
||||
err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &tech_pvt->alsa_buffer_size);
|
||||
|
||||
if (err < 0) {
|
||||
ERRORA("Error setting buffer_size: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = snd_pcm_hw_params(handle, params);
|
||||
if (err < 0) {
|
||||
ERRORA("Unable to install hw params: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
|
||||
snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
|
||||
if (chunk_size == buffer_size) {
|
||||
ERRORA("Can't use period equal to buffer size (%lu == %lu)\n", GSMOPEN_P_LOG, chunk_size, buffer_size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snd_pcm_sw_params_current(handle, swparams);
|
||||
|
||||
/*
|
||||
if (sleep_min)
|
||||
xfer_align = 1;
|
||||
err = snd_pcm_sw_params_set_sleep_min(handle, swparams,
|
||||
0);
|
||||
|
||||
if (err < 0) {
|
||||
ERRORA("Error setting slep_min: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
}
|
||||
*/
|
||||
n = chunk_size;
|
||||
err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);
|
||||
if (err < 0) {
|
||||
ERRORA("Error setting avail_min: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
}
|
||||
if (stream == SND_PCM_STREAM_CAPTURE) {
|
||||
start_delay = 1;
|
||||
}
|
||||
if (start_delay <= 0) {
|
||||
start_threshold = n + (snd_pcm_uframes_t) rate *start_delay / 1000000;
|
||||
} else {
|
||||
start_threshold = (snd_pcm_uframes_t) rate *start_delay / 1000000;
|
||||
}
|
||||
if (start_threshold < 1)
|
||||
start_threshold = 1;
|
||||
if (start_threshold > n)
|
||||
start_threshold = n;
|
||||
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
|
||||
if (err < 0) {
|
||||
ERRORA("Error setting start_threshold: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
}
|
||||
|
||||
if (stop_delay <= 0)
|
||||
stop_threshold = buffer_size + (snd_pcm_uframes_t) rate *stop_delay / 1000000;
|
||||
else
|
||||
stop_threshold = (snd_pcm_uframes_t) rate *stop_delay / 1000000;
|
||||
|
||||
if (stream == SND_PCM_STREAM_CAPTURE) {
|
||||
stop_threshold = -1;
|
||||
}
|
||||
|
||||
err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
|
||||
|
||||
if (err < 0) {
|
||||
ERRORA("Error setting stop_threshold: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
}
|
||||
|
||||
if (snd_pcm_sw_params(handle, swparams) < 0) {
|
||||
ERRORA("Error installing software parameters: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
}
|
||||
|
||||
err = snd_pcm_poll_descriptors_count(handle);
|
||||
if (err <= 0) {
|
||||
ERRORA("Unable to get a poll descriptors count, error is %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (err != 1) { //number of poll descriptors
|
||||
DEBUGA_GSMOPEN("Can't handle more than one device\n", GSMOPEN_P_LOG);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = snd_pcm_poll_descriptors(handle, &tech_pvt->pfd, err);
|
||||
if (err != 1) {
|
||||
ERRORA("snd_pcm_poll_descriptors failed, %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
DEBUGA_GSMOPEN("Acquired fd %d from the poll descriptor\n", GSMOPEN_P_LOG, tech_pvt->pfd.fd);
|
||||
|
||||
if (stream == SND_PCM_STREAM_CAPTURE) {
|
||||
tech_pvt->gsmopen_sound_capt_fd = tech_pvt->pfd.fd;
|
||||
}
|
||||
|
||||
state = snd_pcm_state(handle);
|
||||
|
||||
if (state != SND_PCM_STATE_RUNNING) {
|
||||
if (state != SND_PCM_STATE_PREPARED) {
|
||||
err = snd_pcm_prepare(handle);
|
||||
if (err) {
|
||||
ERRORA("snd_pcm_prepare failed, %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
DEBUGA_GSMOPEN("prepared!\n", GSMOPEN_P_LOG);
|
||||
}
|
||||
if (stream == SND_PCM_STREAM_CAPTURE) {
|
||||
err = snd_pcm_start(handle);
|
||||
if (err) {
|
||||
ERRORA("snd_pcm_start failed, %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
DEBUGA_GSMOPEN("started!\n", GSMOPEN_P_LOG);
|
||||
}
|
||||
}
|
||||
if (option_debug > 1) {
|
||||
snd_output_t *output = NULL;
|
||||
err = snd_output_stdio_attach(&output, stdout, 0);
|
||||
if (err < 0) {
|
||||
ERRORA("snd_output_stdio_attach failed: %s\n", GSMOPEN_P_LOG, snd_strerror(err));
|
||||
}
|
||||
snd_pcm_dump(handle, output);
|
||||
|
||||
}
|
||||
if (option_debug > 1)
|
||||
DEBUGA_GSMOPEN("ALSA handle = %ld\n", GSMOPEN_P_LOG, (long int) handle);
|
||||
return handle;
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Write audio frames to interface */
|
||||
#endif /* GSMOPEN_ALSA */
|
||||
|
||||
int gsmopen_call(private_t *tech_pvt, char *rdest, int timeout)
|
||||
{
|
||||
|
||||
|
||||
Reference in new issue
Block a user