questzdoom/Projects/Android/jni/SupportLibs/timidity/sox/src/pulseaudio.c

170 lines
3.7 KiB
C
Raw Normal View History

2021-04-20 20:09:02 +00:00
/* Pulse Audio sound handler
*
* Copyright 2008 Chris Bagwell And Sundry Contributors
*/
#include "sox_i.h"
#include <pulse/simple.h>
#include <pulse/error.h>
typedef struct {
pa_simple *pasp;
} priv_t;
static int setup(sox_format_t *ft, int is_input)
{
priv_t *pa = (priv_t *)ft->priv;
char *server;
pa_stream_direction_t dir;
char *app_str;
char *dev;
pa_sample_spec spec;
int error;
/* TODO: If user specified device of type "server:dev" then
* break up and override server.
*/
server = NULL;
if (is_input)
{
dir = PA_STREAM_RECORD;
app_str = "record";
}
else
{
dir = PA_STREAM_PLAYBACK;
app_str = "playback";
}
if (strncmp(ft->filename, "default", (size_t)7) == 0)
dev = NULL;
else
dev = ft->filename;
/* If user doesn't specify, default to some reasonable values.
* Since this is mainly for recording case, default to typical
* 16-bit values to prevent saving larger files then average user
* wants. Power users can override to 32-bit if they wish.
*/
if (ft->signal.channels == 0)
ft->signal.channels = 2;
if (ft->signal.rate == 0)
ft->signal.rate = 44100;
if (ft->encoding.bits_per_sample == 0)
{
ft->encoding.bits_per_sample = 16;
ft->encoding.encoding = SOX_ENCODING_SIGN2;
}
spec.format = PA_SAMPLE_S32NE;
spec.rate = ft->signal.rate;
spec.channels = ft->signal.channels;
pa->pasp = pa_simple_new(server, "SoX", dir, dev, app_str, &spec,
NULL, NULL, &error);
if (pa->pasp == NULL)
{
lsx_fail_errno(ft, SOX_EPERM, "can not open audio device: %s", pa_strerror(error));
return SOX_EOF;
}
/* TODO: Is it better to convert format/rates in SoX or in
* always let Pulse Audio do it? Since we don't know what
* hardware prefers, assume it knows best and give it
* what user specifies.
*/
return SOX_SUCCESS;
}
static int startread(sox_format_t *ft)
{
return setup(ft, 1);
}
static int stopread(sox_format_t * ft)
{
priv_t *pa = (priv_t *)ft->priv;
pa_simple_free(pa->pasp);
return SOX_SUCCESS;
}
static size_t read_samples(sox_format_t *ft, sox_sample_t *buf, size_t nsamp)
{
priv_t *pa = (priv_t *)ft->priv;
size_t len;
int rc, error;
/* Pulse Audio buffer lengths are true buffer lengths and not
* count of samples. */
len = nsamp * sizeof(sox_sample_t);
rc = pa_simple_read(pa->pasp, buf, len, &error);
if (rc < 0)
{
lsx_fail_errno(ft, SOX_EPERM, "error reading from pulse audio device: %s", pa_strerror(error));
return SOX_EOF;
}
else
return nsamp;
}
static int startwrite(sox_format_t * ft)
{
return setup(ft, 0);
}
static size_t write_samples(sox_format_t *ft, const sox_sample_t *buf, size_t nsamp)
{
priv_t *pa = (priv_t *)ft->priv;
size_t len;
int rc, error;
/* Pulse Audio buffer lengths are true buffer lengths and not
* count of samples. */
len = nsamp * sizeof(sox_sample_t);
rc = pa_simple_write(pa->pasp, buf, len, &error);
if (rc < 0)
{
lsx_fail_errno(ft, SOX_EPERM, "error writing to pulse audio device: %s", pa_strerror(error));
return SOX_EOF;
}
return nsamp;
}
static int stopwrite(sox_format_t * ft)
{
priv_t *pa = (priv_t *)ft->priv;
int error;
pa_simple_drain(pa->pasp, &error);
pa_simple_free(pa->pasp);
return SOX_SUCCESS;
}
LSX_FORMAT_HANDLER(pulseaudio)
{
static char const *const names[] = { "pulseaudio", NULL };
static unsigned const write_encodings[] = {
SOX_ENCODING_SIGN2, 32, 0,
0};
static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
"Pulse Audio client",
names, SOX_FILE_DEVICE | SOX_FILE_NOSTDIO,
startread, read_samples, stopread,
startwrite, write_samples, stopwrite,
NULL, write_encodings, NULL, sizeof(priv_t)
};
return &handler;
}