dep/cubeb: Update to dc511c6
This commit is contained in:
@ -8,53 +8,59 @@
|
||||
*/
|
||||
#define _DEFAULT_SOURCE
|
||||
#define _BSD_SOURCE
|
||||
#if !defined(__FreeBSD__) && !defined(__APPLE__)
|
||||
#ifndef __FreeBSD__
|
||||
#define _POSIX_SOURCE
|
||||
#endif
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "cubeb-internal.h"
|
||||
#include "cubeb/cubeb.h"
|
||||
#include "cubeb_resampler.h"
|
||||
#include "cubeb_utils.h"
|
||||
#include <dlfcn.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <jack/jack.h>
|
||||
#include <jack/statistics.h>
|
||||
|
||||
#define JACK_API_VISIT(X) \
|
||||
X(jack_activate) \
|
||||
X(jack_client_close) \
|
||||
X(jack_client_open) \
|
||||
X(jack_connect) \
|
||||
X(jack_free) \
|
||||
X(jack_get_ports) \
|
||||
X(jack_get_sample_rate) \
|
||||
X(jack_get_xrun_delayed_usecs) \
|
||||
X(jack_get_buffer_size) \
|
||||
X(jack_port_get_buffer) \
|
||||
X(jack_port_name) \
|
||||
X(jack_port_register) \
|
||||
X(jack_port_unregister) \
|
||||
X(jack_port_get_latency_range) \
|
||||
X(jack_set_process_callback) \
|
||||
X(jack_set_xrun_callback) \
|
||||
X(jack_set_graph_order_callback) \
|
||||
X(jack_set_error_function) \
|
||||
#ifdef DISABLE_LIBJACK_DLOPEN
|
||||
#define WRAP(x) x
|
||||
#else
|
||||
#define WRAP(x) (*api_##x)
|
||||
#define JACK_API_VISIT(X) \
|
||||
X(jack_activate) \
|
||||
X(jack_client_close) \
|
||||
X(jack_client_open) \
|
||||
X(jack_connect) \
|
||||
X(jack_free) \
|
||||
X(jack_get_ports) \
|
||||
X(jack_get_sample_rate) \
|
||||
X(jack_get_xrun_delayed_usecs) \
|
||||
X(jack_get_buffer_size) \
|
||||
X(jack_port_get_buffer) \
|
||||
X(jack_port_name) \
|
||||
X(jack_port_register) \
|
||||
X(jack_port_unregister) \
|
||||
X(jack_port_get_latency_range) \
|
||||
X(jack_set_process_callback) \
|
||||
X(jack_set_xrun_callback) \
|
||||
X(jack_set_graph_order_callback) \
|
||||
X(jack_set_error_function) \
|
||||
X(jack_set_info_function)
|
||||
|
||||
#define IMPORT_FUNC(x) static decltype(x) * api_##x;
|
||||
JACK_API_VISIT(IMPORT_FUNC);
|
||||
#undef IMPORT_FUNC
|
||||
#endif
|
||||
|
||||
#define JACK_DEFAULT_IN "JACK capture"
|
||||
#define JACK_DEFAULT_OUT "JACK playback"
|
||||
|
||||
static const int MAX_STREAMS = 16;
|
||||
static const int MAX_CHANNELS = 8;
|
||||
static const int MAX_CHANNELS = 8;
|
||||
static const int FIFO_SIZE = 4096 * sizeof(float);
|
||||
|
||||
enum devstream {
|
||||
@ -64,6 +70,12 @@ enum devstream {
|
||||
DUPLEX,
|
||||
};
|
||||
|
||||
enum cbjack_connect_ports_options {
|
||||
CBJACK_CP_OPTIONS_NONE = 0x0,
|
||||
CBJACK_CP_OPTIONS_SKIP_OUTPUT = 0x1,
|
||||
CBJACK_CP_OPTIONS_SKIP_INPUT = 0x2,
|
||||
};
|
||||
|
||||
static void
|
||||
s16ne_to_float(float * dst, const int16_t * src, size_t n)
|
||||
{
|
||||
@ -75,71 +87,95 @@ static void
|
||||
float_to_s16ne(int16_t * dst, float * src, size_t n)
|
||||
{
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (*src > 1.f) *src = 1.f;
|
||||
if (*src < -1.f) *src = -1.f;
|
||||
if (*src > 1.f)
|
||||
*src = 1.f;
|
||||
if (*src < -1.f)
|
||||
*src = -1.f;
|
||||
*(dst++) = (int16_t)((int16_t)(*(src++) * 32767));
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
/*static*/ int jack_init (cubeb ** context, char const * context_name);
|
||||
extern "C" {
|
||||
/*static*/ int
|
||||
jack_init(cubeb ** context, char const * context_name);
|
||||
}
|
||||
static char const * cbjack_get_backend_id(cubeb * context);
|
||||
static int cbjack_get_max_channel_count(cubeb * ctx, uint32_t * max_channels);
|
||||
static int cbjack_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_frames);
|
||||
static int cbjack_get_latency(cubeb_stream * stm, unsigned int * latency_frames);
|
||||
static int cbjack_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate);
|
||||
static void cbjack_destroy(cubeb * context);
|
||||
static void cbjack_interleave_capture(cubeb_stream * stream, float **in, jack_nframes_t nframes, bool format_mismatch);
|
||||
static void cbjack_deinterleave_playback_refill_s16ne(cubeb_stream * stream, short **bufs_in, float **bufs_out, jack_nframes_t nframes);
|
||||
static void cbjack_deinterleave_playback_refill_float(cubeb_stream * stream, float **bufs_in, float **bufs_out, jack_nframes_t nframes);
|
||||
static int cbjack_stream_device_destroy(cubeb_stream * stream,
|
||||
cubeb_device * device);
|
||||
static int cbjack_stream_get_current_device(cubeb_stream * stm, cubeb_device ** const device);
|
||||
static int cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
cubeb_device_collection * collection);
|
||||
static int cbjack_device_collection_destroy(cubeb * context,
|
||||
cubeb_device_collection * collection);
|
||||
static int cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name,
|
||||
cubeb_devid input_device,
|
||||
cubeb_stream_params * input_stream_params,
|
||||
cubeb_devid output_device,
|
||||
cubeb_stream_params * output_stream_params,
|
||||
unsigned int latency_frames,
|
||||
cubeb_data_callback data_callback,
|
||||
cubeb_state_callback state_callback,
|
||||
void * user_ptr);
|
||||
static void cbjack_stream_destroy(cubeb_stream * stream);
|
||||
static int cbjack_stream_start(cubeb_stream * stream);
|
||||
static int cbjack_stream_stop(cubeb_stream * stream);
|
||||
static int cbjack_stream_get_position(cubeb_stream * stream, uint64_t * position);
|
||||
static int cbjack_stream_set_volume(cubeb_stream * stm, float volume);
|
||||
static char const *
|
||||
cbjack_get_backend_id(cubeb * context);
|
||||
static int
|
||||
cbjack_get_max_channel_count(cubeb * ctx, uint32_t * max_channels);
|
||||
static int
|
||||
cbjack_get_min_latency(cubeb * ctx, cubeb_stream_params params,
|
||||
uint32_t * latency_frames);
|
||||
static int
|
||||
cbjack_get_latency(cubeb_stream * stm, unsigned int * latency_frames);
|
||||
static int
|
||||
cbjack_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate);
|
||||
static void
|
||||
cbjack_destroy(cubeb * context);
|
||||
static void
|
||||
cbjack_interleave_capture(cubeb_stream * stream, float ** in,
|
||||
jack_nframes_t nframes, bool format_mismatch);
|
||||
static void
|
||||
cbjack_deinterleave_playback_refill_s16ne(cubeb_stream * stream,
|
||||
short ** bufs_in, float ** bufs_out,
|
||||
jack_nframes_t nframes);
|
||||
static void
|
||||
cbjack_deinterleave_playback_refill_float(cubeb_stream * stream,
|
||||
float ** bufs_in, float ** bufs_out,
|
||||
jack_nframes_t nframes);
|
||||
static int
|
||||
cbjack_stream_device_destroy(cubeb_stream * stream, cubeb_device * device);
|
||||
static int
|
||||
cbjack_stream_get_current_device(cubeb_stream * stm,
|
||||
cubeb_device ** const device);
|
||||
static int
|
||||
cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
cubeb_device_collection * collection);
|
||||
static int
|
||||
cbjack_device_collection_destroy(cubeb * context,
|
||||
cubeb_device_collection * collection);
|
||||
static int
|
||||
cbjack_stream_init(cubeb * context, cubeb_stream ** stream,
|
||||
char const * stream_name, cubeb_devid input_device,
|
||||
cubeb_stream_params * input_stream_params,
|
||||
cubeb_devid output_device,
|
||||
cubeb_stream_params * output_stream_params,
|
||||
unsigned int latency_frames,
|
||||
cubeb_data_callback data_callback,
|
||||
cubeb_state_callback state_callback, void * user_ptr);
|
||||
static void
|
||||
cbjack_stream_destroy(cubeb_stream * stream);
|
||||
static int
|
||||
cbjack_stream_start(cubeb_stream * stream);
|
||||
static int
|
||||
cbjack_stream_stop(cubeb_stream * stream);
|
||||
static int
|
||||
cbjack_stream_get_position(cubeb_stream * stream, uint64_t * position);
|
||||
static int
|
||||
cbjack_stream_set_volume(cubeb_stream * stm, float volume);
|
||||
|
||||
static struct cubeb_ops const cbjack_ops = {
|
||||
.init = jack_init,
|
||||
.get_backend_id = cbjack_get_backend_id,
|
||||
.get_max_channel_count = cbjack_get_max_channel_count,
|
||||
.get_min_latency = cbjack_get_min_latency,
|
||||
.get_preferred_sample_rate = cbjack_get_preferred_sample_rate,
|
||||
.enumerate_devices = cbjack_enumerate_devices,
|
||||
.device_collection_destroy = cbjack_device_collection_destroy,
|
||||
.destroy = cbjack_destroy,
|
||||
.stream_init = cbjack_stream_init,
|
||||
.stream_destroy = cbjack_stream_destroy,
|
||||
.stream_start = cbjack_stream_start,
|
||||
.stream_stop = cbjack_stream_stop,
|
||||
.stream_reset_default_device = NULL,
|
||||
.stream_get_position = cbjack_stream_get_position,
|
||||
.stream_get_latency = cbjack_get_latency,
|
||||
.stream_get_input_latency = NULL,
|
||||
.stream_set_volume = cbjack_stream_set_volume,
|
||||
.stream_set_name = NULL,
|
||||
.stream_get_current_device = cbjack_stream_get_current_device,
|
||||
.stream_device_destroy = cbjack_stream_device_destroy,
|
||||
.stream_register_device_changed_callback = NULL,
|
||||
.register_device_collection_changed = NULL
|
||||
};
|
||||
.init = jack_init,
|
||||
.get_backend_id = cbjack_get_backend_id,
|
||||
.get_max_channel_count = cbjack_get_max_channel_count,
|
||||
.get_min_latency = cbjack_get_min_latency,
|
||||
.get_preferred_sample_rate = cbjack_get_preferred_sample_rate,
|
||||
.enumerate_devices = cbjack_enumerate_devices,
|
||||
.device_collection_destroy = cbjack_device_collection_destroy,
|
||||
.destroy = cbjack_destroy,
|
||||
.stream_init = cbjack_stream_init,
|
||||
.stream_destroy = cbjack_stream_destroy,
|
||||
.stream_start = cbjack_stream_start,
|
||||
.stream_stop = cbjack_stream_stop,
|
||||
.stream_get_position = cbjack_stream_get_position,
|
||||
.stream_get_latency = cbjack_get_latency,
|
||||
.stream_get_input_latency = NULL,
|
||||
.stream_set_volume = cbjack_stream_set_volume,
|
||||
.stream_set_name = NULL,
|
||||
.stream_get_current_device = cbjack_stream_get_current_device,
|
||||
.stream_device_destroy = cbjack_stream_device_destroy,
|
||||
.stream_register_device_changed_callback = NULL,
|
||||
.register_device_collection_changed = NULL};
|
||||
|
||||
struct cubeb_stream {
|
||||
/* Note: Must match cubeb_stream layout in cubeb.c. */
|
||||
@ -150,7 +186,7 @@ struct cubeb_stream {
|
||||
/**< Mutex for each stream */
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
bool in_use; /**< Set to false iff the stream is free */
|
||||
bool in_use; /**< Set to false iff the stream is free */
|
||||
bool ports_ready; /**< Set to true iff the JACK ports are ready */
|
||||
|
||||
cubeb_data_callback data_callback;
|
||||
@ -205,15 +241,16 @@ struct cubeb {
|
||||
static int
|
||||
load_jack_lib(cubeb * context)
|
||||
{
|
||||
#ifndef DISABLE_LIBJACK_DLOPEN
|
||||
#ifdef __APPLE__
|
||||
context->libjack = dlopen("libjack.0.dylib", RTLD_LAZY);
|
||||
context->libjack = dlopen("/usr/local/lib/libjack.0.dylib", RTLD_LAZY);
|
||||
#elif defined(__WIN32__)
|
||||
# ifdef _WIN64
|
||||
context->libjack = LoadLibrary("libjack64.dll");
|
||||
# else
|
||||
context->libjack = LoadLibrary("libjack.dll");
|
||||
# endif
|
||||
#ifdef _WIN64
|
||||
context->libjack = LoadLibrary("libjack64.dll");
|
||||
#else
|
||||
context->libjack = LoadLibrary("libjack.dll");
|
||||
#endif
|
||||
#else
|
||||
context->libjack = dlopen("libjack.so.0", RTLD_LAZY);
|
||||
if (!context->libjack) {
|
||||
@ -224,56 +261,59 @@ load_jack_lib(cubeb * context)
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
#define LOAD(x) \
|
||||
{ \
|
||||
api_##x = (decltype(x)*)dlsym(context->libjack, #x); \
|
||||
if (!api_##x) { \
|
||||
dlclose(context->libjack); \
|
||||
return CUBEB_ERROR; \
|
||||
} \
|
||||
#define LOAD(x) \
|
||||
{ \
|
||||
api_##x = (decltype(x) *)dlsym(context->libjack, #x); \
|
||||
if (!api_##x) { \
|
||||
dlclose(context->libjack); \
|
||||
return CUBEB_ERROR; \
|
||||
} \
|
||||
}
|
||||
|
||||
JACK_API_VISIT(LOAD);
|
||||
#undef LOAD
|
||||
|
||||
#endif
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
cbjack_connect_port_out (cubeb_stream * stream, const size_t out_port, const char * const phys_in_port)
|
||||
cbjack_connect_port_out(cubeb_stream * stream, const size_t out_port,
|
||||
const char * const phys_in_port)
|
||||
{
|
||||
const char *src_port = api_jack_port_name (stream->output_ports[out_port]);
|
||||
const char * src_port = WRAP(jack_port_name)(stream->output_ports[out_port]);
|
||||
|
||||
api_jack_connect (stream->context->jack_client, src_port, phys_in_port);
|
||||
WRAP(jack_connect)(stream->context->jack_client, src_port, phys_in_port);
|
||||
}
|
||||
|
||||
static void
|
||||
cbjack_connect_port_in (cubeb_stream * stream, const char * const phys_out_port, size_t in_port)
|
||||
cbjack_connect_port_in(cubeb_stream * stream, const char * const phys_out_port,
|
||||
size_t in_port)
|
||||
{
|
||||
const char *src_port = api_jack_port_name (stream->input_ports[in_port]);
|
||||
const char * src_port = WRAP(jack_port_name)(stream->input_ports[in_port]);
|
||||
|
||||
api_jack_connect (stream->context->jack_client, phys_out_port, src_port);
|
||||
WRAP(jack_connect)(stream->context->jack_client, phys_out_port, src_port);
|
||||
}
|
||||
|
||||
static int
|
||||
cbjack_connect_ports (cubeb_stream * stream)
|
||||
cbjack_connect_ports(cubeb_stream * stream,
|
||||
enum cbjack_connect_ports_options options)
|
||||
{
|
||||
int r = CUBEB_ERROR;
|
||||
const char ** phys_in_ports = api_jack_get_ports (stream->context->jack_client,
|
||||
NULL, NULL,
|
||||
JackPortIsInput
|
||||
| JackPortIsPhysical);
|
||||
const char ** phys_out_ports = api_jack_get_ports (stream->context->jack_client,
|
||||
NULL, NULL,
|
||||
JackPortIsOutput
|
||||
| JackPortIsPhysical);
|
||||
const char ** phys_in_ports =
|
||||
WRAP(jack_get_ports)(stream->context->jack_client, NULL, NULL,
|
||||
JackPortIsInput | JackPortIsPhysical);
|
||||
const char ** phys_out_ports =
|
||||
WRAP(jack_get_ports)(stream->context->jack_client, NULL, NULL,
|
||||
JackPortIsOutput | JackPortIsPhysical);
|
||||
|
||||
if (phys_in_ports == NULL || *phys_in_ports == NULL) {
|
||||
if (phys_in_ports == NULL || *phys_in_ports == NULL ||
|
||||
options & CBJACK_CP_OPTIONS_SKIP_OUTPUT) {
|
||||
goto skipplayback;
|
||||
}
|
||||
|
||||
// Connect outputs to playback
|
||||
for (unsigned int c = 0; c < stream->out_params.channels && phys_in_ports[c] != NULL; c++) {
|
||||
for (unsigned int c = 0;
|
||||
c < stream->out_params.channels && phys_in_ports[c] != NULL; c++) {
|
||||
cbjack_connect_port_out(stream, c, phys_in_ports[c]);
|
||||
}
|
||||
|
||||
@ -285,20 +325,22 @@ cbjack_connect_ports (cubeb_stream * stream)
|
||||
r = CUBEB_OK;
|
||||
|
||||
skipplayback:
|
||||
if (phys_out_ports == NULL || *phys_out_ports == NULL) {
|
||||
if (phys_out_ports == NULL || *phys_out_ports == NULL ||
|
||||
options & CBJACK_CP_OPTIONS_SKIP_INPUT) {
|
||||
goto end;
|
||||
}
|
||||
// Connect inputs to capture
|
||||
for (unsigned int c = 0; c < stream->in_params.channels && phys_out_ports[c] != NULL; c++) {
|
||||
for (unsigned int c = 0;
|
||||
c < stream->in_params.channels && phys_out_ports[c] != NULL; c++) {
|
||||
cbjack_connect_port_in(stream, phys_out_ports[c], c);
|
||||
}
|
||||
r = CUBEB_OK;
|
||||
end:
|
||||
if (phys_out_ports) {
|
||||
api_jack_free(phys_out_ports);
|
||||
WRAP(jack_free)(phys_out_ports);
|
||||
}
|
||||
if (phys_in_ports) {
|
||||
api_jack_free(phys_in_ports);
|
||||
WRAP(jack_free)(phys_in_ports);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@ -308,8 +350,9 @@ cbjack_xrun_callback(void * arg)
|
||||
{
|
||||
cubeb * ctx = (cubeb *)arg;
|
||||
|
||||
float delay = api_jack_get_xrun_delayed_usecs(ctx->jack_client);
|
||||
float fragments = ceilf(((delay / 1000000.0) * ctx->jack_sample_rate) / ctx->jack_buffer_size);
|
||||
float delay = WRAP(jack_get_xrun_delayed_usecs)(ctx->jack_client);
|
||||
float fragments = ceilf(((delay / 1000000.0) * ctx->jack_sample_rate) /
|
||||
ctx->jack_buffer_size);
|
||||
|
||||
ctx->jack_xruns += (unsigned int)fragments;
|
||||
return 0;
|
||||
@ -324,7 +367,7 @@ cbjack_graph_order_callback(void * arg)
|
||||
jack_nframes_t port_latency, max_latency = 0;
|
||||
|
||||
for (int j = 0; j < MAX_STREAMS; j++) {
|
||||
cubeb_stream *stm = &ctx->streams[j];
|
||||
cubeb_stream * stm = &ctx->streams[j];
|
||||
|
||||
if (!stm->in_use)
|
||||
continue;
|
||||
@ -332,10 +375,11 @@ cbjack_graph_order_callback(void * arg)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < (int)stm->out_params.channels; ++i) {
|
||||
api_jack_port_get_latency_range(stm->output_ports[i], JackPlaybackLatency, &latency_range);
|
||||
WRAP(jack_port_get_latency_range)
|
||||
(stm->output_ports[i], JackPlaybackLatency, &latency_range);
|
||||
port_latency = latency_range.max;
|
||||
if (port_latency > max_latency)
|
||||
max_latency = port_latency;
|
||||
max_latency = port_latency;
|
||||
}
|
||||
/* Cap minimum latency to 128 frames */
|
||||
if (max_latency < 128)
|
||||
@ -357,9 +401,9 @@ cbjack_process(jack_nframes_t nframes, void * arg)
|
||||
ctx->jack_xruns = 0;
|
||||
|
||||
for (int j = 0; j < MAX_STREAMS; j++) {
|
||||
cubeb_stream *stm = &ctx->streams[j];
|
||||
float *bufs_out[stm->out_params.channels];
|
||||
float *bufs_in[stm->in_params.channels];
|
||||
cubeb_stream * stm = &ctx->streams[j];
|
||||
float * bufs_out[stm->out_params.channels];
|
||||
float * bufs_in[stm->in_params.channels];
|
||||
|
||||
if (!stm->in_use)
|
||||
continue;
|
||||
@ -373,18 +417,20 @@ cbjack_process(jack_nframes_t nframes, void * arg)
|
||||
if (stm->devs & OUT_ONLY) {
|
||||
// get jack output buffers
|
||||
for (i = 0; i < (int)stm->out_params.channels; i++)
|
||||
bufs_out[i] = (float*)api_jack_port_get_buffer(stm->output_ports[i], nframes);
|
||||
bufs_out[i] =
|
||||
(float *)WRAP(jack_port_get_buffer)(stm->output_ports[i], nframes);
|
||||
}
|
||||
if (stm->devs & IN_ONLY) {
|
||||
// get jack input buffers
|
||||
for (i = 0; i < (int)stm->in_params.channels; i++)
|
||||
bufs_in[i] = (float*)api_jack_port_get_buffer(stm->input_ports[i], nframes);
|
||||
bufs_in[i] =
|
||||
(float *)WRAP(jack_port_get_buffer)(stm->input_ports[i], nframes);
|
||||
}
|
||||
if (stm->pause) {
|
||||
// paused, play silence on output
|
||||
if (stm->devs & OUT_ONLY) {
|
||||
for (unsigned int c = 0; c < stm->out_params.channels; c++) {
|
||||
float* buffer_out = bufs_out[c];
|
||||
float * buffer_out = bufs_out[c];
|
||||
for (long f = 0; f < nframes; f++) {
|
||||
buffer_out[f] = 0.f;
|
||||
}
|
||||
@ -393,7 +439,7 @@ cbjack_process(jack_nframes_t nframes, void * arg)
|
||||
if (stm->devs & IN_ONLY) {
|
||||
// paused, capture silence
|
||||
for (unsigned int c = 0; c < stm->in_params.channels; c++) {
|
||||
float* buffer_in = bufs_in[c];
|
||||
float * buffer_in = bufs_in[c];
|
||||
for (long f = 0; f < nframes; f++) {
|
||||
buffer_in[f] = 0.f;
|
||||
}
|
||||
@ -404,31 +450,38 @@ cbjack_process(jack_nframes_t nframes, void * arg)
|
||||
// try to lock stream mutex
|
||||
if (pthread_mutex_trylock(&stm->mutex) == 0) {
|
||||
|
||||
int16_t *in_s16ne = stm->context->in_resampled_interleaved_buffer_s16ne;
|
||||
float *in_float = stm->context->in_resampled_interleaved_buffer_float;
|
||||
int16_t * in_s16ne =
|
||||
stm->context->in_resampled_interleaved_buffer_s16ne;
|
||||
float * in_float = stm->context->in_resampled_interleaved_buffer_float;
|
||||
|
||||
// unpaused, play audio
|
||||
if (stm->devs == DUPLEX) {
|
||||
if (stm->out_params.format == CUBEB_SAMPLE_S16NE) {
|
||||
cbjack_interleave_capture(stm, bufs_in, nframes, true);
|
||||
cbjack_deinterleave_playback_refill_s16ne(stm, &in_s16ne, bufs_out, nframes);
|
||||
cbjack_deinterleave_playback_refill_s16ne(stm, &in_s16ne, bufs_out,
|
||||
nframes);
|
||||
} else if (stm->out_params.format == CUBEB_SAMPLE_FLOAT32NE) {
|
||||
cbjack_interleave_capture(stm, bufs_in, nframes, false);
|
||||
cbjack_deinterleave_playback_refill_float(stm, &in_float, bufs_out, nframes);
|
||||
cbjack_deinterleave_playback_refill_float(stm, &in_float, bufs_out,
|
||||
nframes);
|
||||
}
|
||||
} else if (stm->devs == IN_ONLY) {
|
||||
if (stm->in_params.format == CUBEB_SAMPLE_S16NE) {
|
||||
cbjack_interleave_capture(stm, bufs_in, nframes, true);
|
||||
cbjack_deinterleave_playback_refill_s16ne(stm, &in_s16ne, nullptr, nframes);
|
||||
cbjack_deinterleave_playback_refill_s16ne(stm, &in_s16ne, nullptr,
|
||||
nframes);
|
||||
} else if (stm->in_params.format == CUBEB_SAMPLE_FLOAT32NE) {
|
||||
cbjack_interleave_capture(stm, bufs_in, nframes, false);
|
||||
cbjack_deinterleave_playback_refill_float(stm, &in_float, nullptr, nframes);
|
||||
cbjack_deinterleave_playback_refill_float(stm, &in_float, nullptr,
|
||||
nframes);
|
||||
}
|
||||
} else if (stm->devs == OUT_ONLY) {
|
||||
if (stm->out_params.format == CUBEB_SAMPLE_S16NE) {
|
||||
cbjack_deinterleave_playback_refill_s16ne(stm, nullptr, bufs_out, nframes);
|
||||
cbjack_deinterleave_playback_refill_s16ne(stm, nullptr, bufs_out,
|
||||
nframes);
|
||||
} else if (stm->out_params.format == CUBEB_SAMPLE_FLOAT32NE) {
|
||||
cbjack_deinterleave_playback_refill_float(stm, nullptr, bufs_out, nframes);
|
||||
cbjack_deinterleave_playback_refill_float(stm, nullptr, bufs_out,
|
||||
nframes);
|
||||
}
|
||||
}
|
||||
// unlock stream mutex
|
||||
@ -439,7 +492,7 @@ cbjack_process(jack_nframes_t nframes, void * arg)
|
||||
// output silence
|
||||
if (stm->devs & OUT_ONLY) {
|
||||
for (unsigned int c = 0; c < stm->out_params.channels; c++) {
|
||||
float* buffer_out = bufs_out[c];
|
||||
float * buffer_out = bufs_out[c];
|
||||
for (long f = 0; f < nframes; f++) {
|
||||
buffer_out[f] = 0.f;
|
||||
}
|
||||
@ -448,7 +501,7 @@ cbjack_process(jack_nframes_t nframes, void * arg)
|
||||
if (stm->devs & IN_ONLY) {
|
||||
// capture silence
|
||||
for (unsigned int c = 0; c < stm->in_params.channels; c++) {
|
||||
float* buffer_in = bufs_in[c];
|
||||
float * buffer_in = bufs_in[c];
|
||||
for (long f = 0; f < nframes; f++) {
|
||||
buffer_in[f] = 0.f;
|
||||
}
|
||||
@ -461,7 +514,9 @@ cbjack_process(jack_nframes_t nframes, void * arg)
|
||||
}
|
||||
|
||||
static void
|
||||
cbjack_deinterleave_playback_refill_float(cubeb_stream * stream, float ** in, float ** bufs_out, jack_nframes_t nframes)
|
||||
cbjack_deinterleave_playback_refill_float(cubeb_stream * stream, float ** in,
|
||||
float ** bufs_out,
|
||||
jack_nframes_t nframes)
|
||||
{
|
||||
float * out_interleaved_buffer = nullptr;
|
||||
|
||||
@ -472,20 +527,24 @@ cbjack_deinterleave_playback_refill_float(cubeb_stream * stream, float ** in, fl
|
||||
long done_frames = 0;
|
||||
long input_frames_count = (in != NULL) ? nframes : 0;
|
||||
|
||||
done_frames = cubeb_resampler_fill(stream->resampler,
|
||||
inptr,
|
||||
&input_frames_count,
|
||||
(bufs_out != NULL) ? stream->context->out_resampled_interleaved_buffer_float : NULL,
|
||||
needed_frames);
|
||||
done_frames = cubeb_resampler_fill(
|
||||
stream->resampler, inptr, &input_frames_count,
|
||||
(bufs_out != NULL)
|
||||
? stream->context->out_resampled_interleaved_buffer_float
|
||||
: NULL,
|
||||
needed_frames);
|
||||
|
||||
out_interleaved_buffer = stream->context->out_resampled_interleaved_buffer_float;
|
||||
out_interleaved_buffer =
|
||||
stream->context->out_resampled_interleaved_buffer_float;
|
||||
|
||||
if (outptr) {
|
||||
// convert interleaved output buffers to contiguous buffers
|
||||
for (unsigned int c = 0; c < stream->out_params.channels; c++) {
|
||||
float* buffer = bufs_out[c];
|
||||
float * buffer = bufs_out[c];
|
||||
for (long f = 0; f < done_frames; f++) {
|
||||
buffer[f] = out_interleaved_buffer[(f * stream->out_params.channels) + c] * stream->volume;
|
||||
buffer[f] =
|
||||
out_interleaved_buffer[(f * stream->out_params.channels) + c] *
|
||||
stream->volume;
|
||||
}
|
||||
if (done_frames < needed_frames) {
|
||||
// draining
|
||||
@ -519,7 +578,9 @@ cbjack_deinterleave_playback_refill_float(cubeb_stream * stream, float ** in, fl
|
||||
}
|
||||
|
||||
static void
|
||||
cbjack_deinterleave_playback_refill_s16ne(cubeb_stream * stream, short ** in, float ** bufs_out, jack_nframes_t nframes)
|
||||
cbjack_deinterleave_playback_refill_s16ne(cubeb_stream * stream, short ** in,
|
||||
float ** bufs_out,
|
||||
jack_nframes_t nframes)
|
||||
{
|
||||
float * out_interleaved_buffer = nullptr;
|
||||
|
||||
@ -530,22 +591,28 @@ cbjack_deinterleave_playback_refill_s16ne(cubeb_stream * stream, short ** in, fl
|
||||
long done_frames = 0;
|
||||
long input_frames_count = (in != NULL) ? nframes : 0;
|
||||
|
||||
done_frames = cubeb_resampler_fill(stream->resampler,
|
||||
inptr,
|
||||
&input_frames_count,
|
||||
(bufs_out != NULL) ? stream->context->out_resampled_interleaved_buffer_s16ne : NULL,
|
||||
needed_frames);
|
||||
done_frames = cubeb_resampler_fill(
|
||||
stream->resampler, inptr, &input_frames_count,
|
||||
(bufs_out != NULL)
|
||||
? stream->context->out_resampled_interleaved_buffer_s16ne
|
||||
: NULL,
|
||||
needed_frames);
|
||||
|
||||
s16ne_to_float(stream->context->out_resampled_interleaved_buffer_float, stream->context->out_resampled_interleaved_buffer_s16ne, done_frames * stream->out_params.channels);
|
||||
s16ne_to_float(stream->context->out_resampled_interleaved_buffer_float,
|
||||
stream->context->out_resampled_interleaved_buffer_s16ne,
|
||||
done_frames * stream->out_params.channels);
|
||||
|
||||
out_interleaved_buffer = stream->context->out_resampled_interleaved_buffer_float;
|
||||
out_interleaved_buffer =
|
||||
stream->context->out_resampled_interleaved_buffer_float;
|
||||
|
||||
if (outptr) {
|
||||
// convert interleaved output buffers to contiguous buffers
|
||||
for (unsigned int c = 0; c < stream->out_params.channels; c++) {
|
||||
float* buffer = bufs_out[c];
|
||||
float * buffer = bufs_out[c];
|
||||
for (long f = 0; f < done_frames; f++) {
|
||||
buffer[f] = out_interleaved_buffer[(f * stream->out_params.channels) + c] * stream->volume;
|
||||
buffer[f] =
|
||||
out_interleaved_buffer[(f * stream->out_params.channels) + c] *
|
||||
stream->volume;
|
||||
}
|
||||
if (done_frames < needed_frames) {
|
||||
// draining
|
||||
@ -579,20 +646,25 @@ cbjack_deinterleave_playback_refill_s16ne(cubeb_stream * stream, short ** in, fl
|
||||
}
|
||||
|
||||
static void
|
||||
cbjack_interleave_capture(cubeb_stream * stream, float **in, jack_nframes_t nframes, bool format_mismatch)
|
||||
cbjack_interleave_capture(cubeb_stream * stream, float ** in,
|
||||
jack_nframes_t nframes, bool format_mismatch)
|
||||
{
|
||||
float *in_buffer = stream->context->in_float_interleaved_buffer;
|
||||
float * in_buffer = stream->context->in_float_interleaved_buffer;
|
||||
|
||||
for (unsigned int c = 0; c < stream->in_params.channels; c++) {
|
||||
for (long f = 0; f < nframes; f++) {
|
||||
in_buffer[(f * stream->in_params.channels) + c] = in[c][f] * stream->volume;
|
||||
in_buffer[(f * stream->in_params.channels) + c] =
|
||||
in[c][f] * stream->volume;
|
||||
}
|
||||
}
|
||||
if (format_mismatch) {
|
||||
float_to_s16ne(stream->context->in_resampled_interleaved_buffer_s16ne, in_buffer, nframes * stream->in_params.channels);
|
||||
float_to_s16ne(stream->context->in_resampled_interleaved_buffer_s16ne,
|
||||
in_buffer, nframes * stream->in_params.channels);
|
||||
} else {
|
||||
memset(stream->context->in_resampled_interleaved_buffer_float, 0, (FIFO_SIZE * MAX_CHANNELS * 3) * sizeof(float));
|
||||
memcpy(stream->context->in_resampled_interleaved_buffer_float, in_buffer, (FIFO_SIZE * MAX_CHANNELS * 2) * sizeof(float));
|
||||
memset(stream->context->in_resampled_interleaved_buffer_float, 0,
|
||||
(FIFO_SIZE * MAX_CHANNELS * 3) * sizeof(float));
|
||||
memcpy(stream->context->in_resampled_interleaved_buffer_float, in_buffer,
|
||||
(FIFO_SIZE * MAX_CHANNELS * 2) * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,7 +674,7 @@ silent_jack_error_callback(char const * /*msg*/)
|
||||
}
|
||||
|
||||
/*static*/ int
|
||||
jack_init (cubeb ** context, char const * context_name)
|
||||
jack_init(cubeb ** context, char const * context_name)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -619,8 +691,8 @@ jack_init (cubeb ** context, char const * context_name)
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
api_jack_set_error_function(silent_jack_error_callback);
|
||||
api_jack_set_info_function(silent_jack_error_callback);
|
||||
WRAP(jack_set_error_function)(silent_jack_error_callback);
|
||||
WRAP(jack_set_info_function)(silent_jack_error_callback);
|
||||
|
||||
ctx->ops = &cbjack_ops;
|
||||
|
||||
@ -633,9 +705,8 @@ jack_init (cubeb ** context, char const * context_name)
|
||||
if (context_name)
|
||||
jack_client_name = context_name;
|
||||
|
||||
ctx->jack_client = api_jack_client_open(jack_client_name,
|
||||
JackNoStartServer,
|
||||
NULL);
|
||||
ctx->jack_client =
|
||||
WRAP(jack_client_open)(jack_client_name, JackNoStartServer, NULL);
|
||||
|
||||
if (ctx->jack_client == NULL) {
|
||||
cbjack_destroy(ctx);
|
||||
@ -644,16 +715,17 @@ jack_init (cubeb ** context, char const * context_name)
|
||||
|
||||
ctx->jack_xruns = 0;
|
||||
|
||||
api_jack_set_process_callback (ctx->jack_client, cbjack_process, ctx);
|
||||
api_jack_set_xrun_callback (ctx->jack_client, cbjack_xrun_callback, ctx);
|
||||
api_jack_set_graph_order_callback (ctx->jack_client, cbjack_graph_order_callback, ctx);
|
||||
WRAP(jack_set_process_callback)(ctx->jack_client, cbjack_process, ctx);
|
||||
WRAP(jack_set_xrun_callback)(ctx->jack_client, cbjack_xrun_callback, ctx);
|
||||
WRAP(jack_set_graph_order_callback)
|
||||
(ctx->jack_client, cbjack_graph_order_callback, ctx);
|
||||
|
||||
if (api_jack_activate (ctx->jack_client)) {
|
||||
if (WRAP(jack_activate)(ctx->jack_client)) {
|
||||
cbjack_destroy(ctx);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
ctx->jack_sample_rate = api_jack_get_sample_rate(ctx->jack_client);
|
||||
ctx->jack_sample_rate = WRAP(jack_get_sample_rate)(ctx->jack_client);
|
||||
ctx->jack_latency = 128 * 1000 / ctx->jack_sample_rate;
|
||||
|
||||
ctx->active = true;
|
||||
@ -683,7 +755,8 @@ cbjack_get_latency(cubeb_stream * stm, unsigned int * latency_ms)
|
||||
}
|
||||
|
||||
static int
|
||||
cbjack_get_min_latency(cubeb * ctx, cubeb_stream_params /*params*/, uint32_t * latency_ms)
|
||||
cbjack_get_min_latency(cubeb * ctx, cubeb_stream_params /*params*/,
|
||||
uint32_t * latency_ms)
|
||||
{
|
||||
*latency_ms = ctx->jack_latency;
|
||||
return CUBEB_OK;
|
||||
@ -693,18 +766,17 @@ static int
|
||||
cbjack_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
|
||||
{
|
||||
if (!ctx->jack_client) {
|
||||
jack_client_t * testclient = api_jack_client_open("test-samplerate",
|
||||
JackNoStartServer,
|
||||
NULL);
|
||||
jack_client_t * testclient =
|
||||
WRAP(jack_client_open)("test-samplerate", JackNoStartServer, NULL);
|
||||
if (!testclient) {
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
*rate = api_jack_get_sample_rate(testclient);
|
||||
api_jack_client_close(testclient);
|
||||
*rate = WRAP(jack_get_sample_rate)(testclient);
|
||||
WRAP(jack_client_close)(testclient);
|
||||
|
||||
} else {
|
||||
*rate = api_jack_get_sample_rate(ctx->jack_client);
|
||||
*rate = WRAP(jack_get_sample_rate)(ctx->jack_client);
|
||||
}
|
||||
return CUBEB_OK;
|
||||
}
|
||||
@ -715,7 +787,7 @@ cbjack_destroy(cubeb * context)
|
||||
context->active = false;
|
||||
|
||||
if (context->jack_client != NULL)
|
||||
api_jack_client_close (context->jack_client);
|
||||
WRAP(jack_client_close)(context->jack_client);
|
||||
|
||||
if (context->libjack)
|
||||
dlclose(context->libjack);
|
||||
@ -738,30 +810,27 @@ context_alloc_stream(cubeb * context, char const * stream_name)
|
||||
}
|
||||
|
||||
static int
|
||||
cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_name,
|
||||
cubeb_devid input_device,
|
||||
cbjack_stream_init(cubeb * context, cubeb_stream ** stream,
|
||||
char const * stream_name, cubeb_devid input_device,
|
||||
cubeb_stream_params * input_stream_params,
|
||||
cubeb_devid output_device,
|
||||
cubeb_stream_params * output_stream_params,
|
||||
unsigned int /*latency_frames*/,
|
||||
cubeb_data_callback data_callback,
|
||||
cubeb_state_callback state_callback,
|
||||
void * user_ptr)
|
||||
cubeb_state_callback state_callback, void * user_ptr)
|
||||
{
|
||||
int stream_actual_rate = 0;
|
||||
int jack_rate = api_jack_get_sample_rate(context->jack_client);
|
||||
int jack_rate = WRAP(jack_get_sample_rate)(context->jack_client);
|
||||
|
||||
if (output_stream_params
|
||||
&& (output_stream_params->format != CUBEB_SAMPLE_FLOAT32NE &&
|
||||
output_stream_params->format != CUBEB_SAMPLE_S16NE)
|
||||
) {
|
||||
if (output_stream_params &&
|
||||
(output_stream_params->format != CUBEB_SAMPLE_FLOAT32NE &&
|
||||
output_stream_params->format != CUBEB_SAMPLE_S16NE)) {
|
||||
return CUBEB_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
if (input_stream_params
|
||||
&& (input_stream_params->format != CUBEB_SAMPLE_FLOAT32NE &&
|
||||
input_stream_params->format != CUBEB_SAMPLE_S16NE)
|
||||
) {
|
||||
if (input_stream_params &&
|
||||
(input_stream_params->format != CUBEB_SAMPLE_FLOAT32NE &&
|
||||
input_stream_params->format != CUBEB_SAMPLE_S16NE)) {
|
||||
return CUBEB_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
@ -771,8 +840,10 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_
|
||||
}
|
||||
|
||||
// Loopback is unsupported
|
||||
if ((input_stream_params && (input_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK)) ||
|
||||
(output_stream_params && (output_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK))) {
|
||||
if ((input_stream_params &&
|
||||
(input_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK)) ||
|
||||
(output_stream_params &&
|
||||
(output_stream_params->prefs & CUBEB_STREAM_PREF_LOOPBACK))) {
|
||||
return CUBEB_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@ -841,7 +912,7 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_
|
||||
stm->state_callback = state_callback;
|
||||
stm->position = 0;
|
||||
stm->volume = 1.0f;
|
||||
context->jack_buffer_size = api_jack_get_buffer_size(context->jack_client);
|
||||
context->jack_buffer_size = WRAP(jack_get_buffer_size)(context->jack_client);
|
||||
context->fragment_size = context->jack_buffer_size;
|
||||
|
||||
if (stm->devs == NONE) {
|
||||
@ -852,29 +923,20 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_
|
||||
stm->resampler = NULL;
|
||||
|
||||
if (stm->devs == DUPLEX) {
|
||||
stm->resampler = cubeb_resampler_create(stm,
|
||||
&stm->in_params,
|
||||
&stm->out_params,
|
||||
stream_actual_rate,
|
||||
stm->data_callback,
|
||||
stm->user_ptr,
|
||||
CUBEB_RESAMPLER_QUALITY_DESKTOP);
|
||||
stm->resampler = cubeb_resampler_create(
|
||||
stm, &stm->in_params, &stm->out_params, stream_actual_rate,
|
||||
stm->data_callback, stm->user_ptr, CUBEB_RESAMPLER_QUALITY_DESKTOP,
|
||||
CUBEB_RESAMPLER_RECLOCK_NONE);
|
||||
} else if (stm->devs == IN_ONLY) {
|
||||
stm->resampler = cubeb_resampler_create(stm,
|
||||
&stm->in_params,
|
||||
nullptr,
|
||||
stream_actual_rate,
|
||||
stm->data_callback,
|
||||
stm->user_ptr,
|
||||
CUBEB_RESAMPLER_QUALITY_DESKTOP);
|
||||
stm->resampler = cubeb_resampler_create(
|
||||
stm, &stm->in_params, nullptr, stream_actual_rate, stm->data_callback,
|
||||
stm->user_ptr, CUBEB_RESAMPLER_QUALITY_DESKTOP,
|
||||
CUBEB_RESAMPLER_RECLOCK_NONE);
|
||||
} else if (stm->devs == OUT_ONLY) {
|
||||
stm->resampler = cubeb_resampler_create(stm,
|
||||
nullptr,
|
||||
&stm->out_params,
|
||||
stream_actual_rate,
|
||||
stm->data_callback,
|
||||
stm->user_ptr,
|
||||
CUBEB_RESAMPLER_QUALITY_DESKTOP);
|
||||
stm->resampler = cubeb_resampler_create(
|
||||
stm, nullptr, &stm->out_params, stream_actual_rate, stm->data_callback,
|
||||
stm->user_ptr, CUBEB_RESAMPLER_QUALITY_DESKTOP,
|
||||
CUBEB_RESAMPLER_RECLOCK_NONE);
|
||||
}
|
||||
|
||||
if (!stm->resampler) {
|
||||
@ -887,11 +949,18 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_
|
||||
for (unsigned int c = 0; c < stm->out_params.channels; c++) {
|
||||
char portname[256];
|
||||
snprintf(portname, 255, "%s_out_%d", stm->stream_name, c);
|
||||
stm->output_ports[c] = api_jack_port_register(stm->context->jack_client,
|
||||
portname,
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput,
|
||||
0);
|
||||
stm->output_ports[c] = WRAP(jack_port_register)(
|
||||
stm->context->jack_client, portname, JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsOutput, 0);
|
||||
if (!(output_stream_params->prefs &
|
||||
CUBEB_STREAM_PREF_JACK_NO_AUTO_CONNECT)) {
|
||||
if (cbjack_connect_ports(stm, CBJACK_CP_OPTIONS_SKIP_INPUT) !=
|
||||
CUBEB_OK) {
|
||||
pthread_mutex_unlock(&stm->mutex);
|
||||
cbjack_stream_destroy(stm);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -899,19 +968,18 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream, char const * stream_
|
||||
for (unsigned int c = 0; c < stm->in_params.channels; c++) {
|
||||
char portname[256];
|
||||
snprintf(portname, 255, "%s_in_%d", stm->stream_name, c);
|
||||
stm->input_ports[c] = api_jack_port_register(stm->context->jack_client,
|
||||
portname,
|
||||
JACK_DEFAULT_AUDIO_TYPE,
|
||||
JackPortIsInput,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!input_stream_params->prefs & CUBEB_STREAM_PREF_JACK_NO_AUTO_CONNECT) {
|
||||
if (cbjack_connect_ports(stm) != CUBEB_OK) {
|
||||
pthread_mutex_unlock(&stm->mutex);
|
||||
cbjack_stream_destroy(stm);
|
||||
return CUBEB_ERROR;
|
||||
stm->input_ports[c] =
|
||||
WRAP(jack_port_register)(stm->context->jack_client, portname,
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
|
||||
if (!(input_stream_params->prefs &
|
||||
CUBEB_STREAM_PREF_JACK_NO_AUTO_CONNECT)) {
|
||||
if (cbjack_connect_ports(stm, CBJACK_CP_OPTIONS_SKIP_OUTPUT) !=
|
||||
CUBEB_OK) {
|
||||
pthread_mutex_unlock(&stm->mutex);
|
||||
cbjack_stream_destroy(stm);
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -933,7 +1001,8 @@ cbjack_stream_destroy(cubeb_stream * stream)
|
||||
if (stream->devs == DUPLEX || stream->devs == OUT_ONLY) {
|
||||
for (unsigned int c = 0; c < stream->out_params.channels; c++) {
|
||||
if (stream->output_ports[c]) {
|
||||
api_jack_port_unregister (stream->context->jack_client, stream->output_ports[c]);
|
||||
WRAP(jack_port_unregister)
|
||||
(stream->context->jack_client, stream->output_ports[c]);
|
||||
stream->output_ports[c] = NULL;
|
||||
}
|
||||
}
|
||||
@ -942,7 +1011,8 @@ cbjack_stream_destroy(cubeb_stream * stream)
|
||||
if (stream->devs == DUPLEX || stream->devs == IN_ONLY) {
|
||||
for (unsigned int c = 0; c < stream->in_params.channels; c++) {
|
||||
if (stream->input_ports[c]) {
|
||||
api_jack_port_unregister (stream->context->jack_client, stream->input_ports[c]);
|
||||
WRAP(jack_port_unregister)
|
||||
(stream->context->jack_client, stream->input_ports[c]);
|
||||
stream->input_ports[c] = NULL;
|
||||
}
|
||||
}
|
||||
@ -987,7 +1057,8 @@ cbjack_stream_set_volume(cubeb_stream * stm, float volume)
|
||||
}
|
||||
|
||||
static int
|
||||
cbjack_stream_get_current_device(cubeb_stream * stm, cubeb_device ** const device)
|
||||
cbjack_stream_get_current_device(cubeb_stream * stm,
|
||||
cubeb_device ** const device)
|
||||
{
|
||||
*device = (cubeb_device *)calloc(1, sizeof(cubeb_device));
|
||||
if (*device == NULL)
|
||||
@ -1012,8 +1083,7 @@ cbjack_stream_get_current_device(cubeb_stream * stm, cubeb_device ** const devic
|
||||
}
|
||||
|
||||
static int
|
||||
cbjack_stream_device_destroy(cubeb_stream * /*stream*/,
|
||||
cubeb_device * device)
|
||||
cbjack_stream_device_destroy(cubeb_stream * /*stream*/, cubeb_device * device)
|
||||
{
|
||||
if (device->input_name)
|
||||
free(device->input_name);
|
||||
@ -1042,7 +1112,7 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
if (type & CUBEB_DEVICE_TYPE_OUTPUT) {
|
||||
cubeb_device_info * cur = &devices[collection->count];
|
||||
cur->device_id = JACK_DEFAULT_OUT;
|
||||
cur->devid = (cubeb_devid) cur->device_id;
|
||||
cur->devid = (cubeb_devid)cur->device_id;
|
||||
cur->friendly_name = JACK_DEFAULT_OUT;
|
||||
cur->group_id = JACK_DEFAULT_OUT;
|
||||
cur->vendor_name = JACK_DEFAULT_OUT;
|
||||
@ -1057,13 +1127,13 @@ cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
|
||||
cur->default_rate = rate;
|
||||
cur->latency_lo = 0;
|
||||
cur->latency_hi = 0;
|
||||
collection->count +=1 ;
|
||||
collection->count += 1;
|
||||
}
|
||||
|
||||
if (type & CUBEB_DEVICE_TYPE_INPUT) {
|
||||
cubeb_device_info * cur = &devices[collection->count];
|
||||
cur->device_id = JACK_DEFAULT_IN;
|
||||
cur->devid = (cubeb_devid) cur->device_id;
|
||||
cur->devid = (cubeb_devid)cur->device_id;
|
||||
cur->friendly_name = JACK_DEFAULT_IN;
|
||||
cur->group_id = JACK_DEFAULT_IN;
|
||||
cur->vendor_name = JACK_DEFAULT_IN;
|
||||
@ -1091,6 +1161,6 @@ cbjack_device_collection_destroy(cubeb * /*ctx*/,
|
||||
cubeb_device_collection * collection)
|
||||
{
|
||||
XASSERT(collection);
|
||||
delete [] collection->device;
|
||||
delete[] collection->device;
|
||||
return CUBEB_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user