summaryrefslogtreecommitdiff
path: root/media/libcubeb/src/cubeb_jack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libcubeb/src/cubeb_jack.cpp')
-rw-r--r--media/libcubeb/src/cubeb_jack.cpp693
1 files changed, 292 insertions, 401 deletions
diff --git a/media/libcubeb/src/cubeb_jack.cpp b/media/libcubeb/src/cubeb_jack.cpp
index 9dc5199e71..8f995da661 100644
--- a/media/libcubeb/src/cubeb_jack.cpp
+++ b/media/libcubeb/src/cubeb_jack.cpp
@@ -8,53 +8,53 @@
*/
#define _DEFAULT_SOURCE
#define _BSD_SOURCE
-#ifndef __FreeBSD__
#define _POSIX_SOURCE
-#endif
-#include "cubeb-internal.h"
-#include "cubeb/cubeb.h"
-#include "cubeb_resampler.h"
-#include "cubeb_utils.h"
+#include <algorithm>
#include <dlfcn.h>
-#include <limits.h>
-#include <math.h>
-#include <pthread.h>
+#include <limits>
#include <stdio.h>
-#include <stdlib.h>
+#include <sys/time.h>
+#include <assert.h>
#include <string.h>
+#include <limits.h>
+#include <poll.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <math.h>
+#include "cubeb/cubeb.h"
+#include "cubeb-internal.h"
+#include "cubeb_resampler.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) \
+#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);
-#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,12 +64,6 @@ 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)
{
@@ -81,110 +75,79 @@ 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_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_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,
+ .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_set_volume = cbjack_stream_set_volume,
+ .stream_set_panning = 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. */
cubeb * context;
- void * user_ptr;
- /**/
/**< 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;
cubeb_state_callback state_callback;
+ void * user_ptr;
cubeb_stream_params in_params;
cubeb_stream_params out_params;
@@ -220,6 +183,7 @@ struct cubeb {
cubeb_stream streams[MAX_STREAMS];
unsigned int active_streams;
+ cubeb_device_info * devinfo[2];
cubeb_device_collection_changed_callback collection_changed_callback;
bool active;
@@ -239,28 +203,25 @@ load_jack_lib(cubeb * context)
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) {
- context->libjack = dlopen("libjack.so", RTLD_LAZY);
- }
#endif
if (!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; \
- } \
+#define LOAD(x) \
+ { \
+ api_##x = (decltype(x)*)dlsym(context->libjack, #x); \
+ if (!api_##x) { \
+ dlclose(context->libjack); \
+ return CUBEB_ERROR; \
+ } \
}
JACK_API_VISIT(LOAD);
@@ -270,72 +231,41 @@ load_jack_lib(cubeb * context)
}
static void
-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]);
-
- api_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_ports (cubeb_stream * stream)
{
- const char * src_port = api_jack_port_name(stream->input_ports[in_port]);
-
- api_jack_connect(stream->context->jack_client, phys_out_port, src_port);
-}
-
-static int
-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);
-
- if (phys_in_ports == NULL || *phys_in_ports == NULL ||
- options & CBJACK_CP_OPTIONS_SKIP_OUTPUT) {
+ 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);
+
+ if (*phys_in_ports == NULL) {
goto skipplayback;
}
// Connect outputs to playback
- 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]);
- }
+ for (unsigned int c = 0; c < stream->out_params.channels && phys_in_ports[c] != NULL; c++) {
+ const char *src_port = api_jack_port_name (stream->output_ports[c]);
- // Special case playing mono source in stereo
- if (stream->out_params.channels == 1 && phys_in_ports[1] != NULL) {
- cbjack_connect_port_out(stream, 0, phys_in_ports[1]);
+ api_jack_connect (stream->context->jack_client, src_port, phys_in_ports[c]);
}
- r = CUBEB_OK;
-
skipplayback:
- if (phys_out_ports == NULL || *phys_out_ports == NULL ||
- options & CBJACK_CP_OPTIONS_SKIP_INPUT) {
+ if (*phys_out_ports == NULL) {
goto end;
}
// Connect inputs to capture
- 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);
+ for (unsigned int c = 0; c < stream->in_params.channels && phys_out_ports[c] != NULL; c++) {
+ const char *src_port = api_jack_port_name (stream->input_ports[c]);
+
+ api_jack_connect (stream->context->jack_client, phys_out_ports[c], src_port);
}
- r = CUBEB_OK;
end:
- if (phys_out_ports) {
- api_jack_free(phys_out_ports);
- }
- if (phys_in_ports) {
- api_jack_free(phys_in_ports);
- }
- return r;
+ api_jack_free(phys_out_ports);
+ api_jack_free(phys_in_ports);
}
static int
@@ -344,10 +274,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);
-
- ctx->jack_xruns += (unsigned int)fragments;
+ int fragments = (int)ceilf( ((delay / 1000000.0) * ctx->jack_sample_rate )
+ / (float)(ctx->jack_buffer_size) );
+ ctx->jack_xruns += fragments;
return 0;
}
@@ -360,7 +289,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;
@@ -368,11 +297,10 @@ 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);
+ api_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)
@@ -388,21 +316,22 @@ static int
cbjack_process(jack_nframes_t nframes, void * arg)
{
cubeb * ctx = (cubeb *)arg;
- unsigned int t_jack_xruns = ctx->jack_xruns;
+ int t_jack_xruns = ctx->jack_xruns;
int i;
- 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;
// handle xruns by skipping audio that should have been played
- stm->position += t_jack_xruns * ctx->fragment_size * stm->ratio;
+ for (i = 0; i < t_jack_xruns; i++) {
+ stm->position += ctx->fragment_size * stm->ratio;
+ }
+ ctx->jack_xruns -= t_jack_xruns;
if (!stm->ports_ready)
continue;
@@ -410,20 +339,18 @@ 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*)api_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*)api_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;
}
@@ -432,7 +359,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;
}
@@ -443,38 +370,31 @@ 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
@@ -485,7 +405,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;
}
@@ -494,7 +414,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;
}
@@ -506,10 +426,9 @@ cbjack_process(jack_nframes_t nframes, void * arg)
return 0;
}
+
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;
@@ -520,24 +439,21 @@ cbjack_deinterleave_playback_refill_float(cubeb_stream * stream, float ** in,
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);
- out_interleaved_buffer =
- stream->context->out_resampled_interleaved_buffer_float;
+ 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;
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
@@ -571,9 +487,7 @@ cbjack_deinterleave_playback_refill_float(cubeb_stream * stream, float ** in,
}
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;
@@ -584,28 +498,22 @@ cbjack_deinterleave_playback_refill_s16ne(cubeb_stream * stream, short ** in,
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
@@ -639,25 +547,20 @@ cbjack_deinterleave_playback_refill_s16ne(cubeb_stream * stream, short ** in,
}
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));
}
}
@@ -667,7 +570,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;
@@ -698,8 +601,9 @@ 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 = api_jack_client_open(jack_client_name,
+ JackNoStartServer,
+ NULL);
if (ctx->jack_client == NULL) {
cbjack_destroy(ctx);
@@ -708,12 +612,11 @@ 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);
+ 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);
- if (api_jack_activate(ctx->jack_client)) {
+ if (api_jack_activate (ctx->jack_client)) {
cbjack_destroy(ctx);
return CUBEB_ERROR;
}
@@ -748,8 +651,7 @@ 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;
@@ -759,8 +661,9 @@ 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 = api_jack_client_open("test-samplerate",
+ JackNoStartServer,
+ NULL);
if (!testclient) {
return CUBEB_ERROR;
}
@@ -780,7 +683,7 @@ cbjack_destroy(cubeb * context)
context->active = false;
if (context->jack_client != NULL)
- api_jack_client_close(context->jack_client);
+ api_jack_client_close (context->jack_client);
if (context->libjack)
dlclose(context->libjack);
@@ -803,42 +706,35 @@ 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);
- 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;
}
- if ((input_device && input_device != JACK_DEFAULT_IN) ||
- (output_device && output_device != JACK_DEFAULT_OUT)) {
+ if (input_device || output_device)
return CUBEB_ERROR_NOT_SUPPORTED;
- }
-
- // 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))) {
- return CUBEB_ERROR_NOT_SUPPORTED;
- }
*stream = NULL;
@@ -916,17 +812,29 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** 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);
} 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);
} 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);
}
if (!stm->resampler) {
@@ -939,18 +847,11 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** 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);
- 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;
- }
- }
+ stm->output_ports[c] = api_jack_port_register(stm->context->jack_client,
+ portname,
+ JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsOutput,
+ 0);
}
}
@@ -958,21 +859,16 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** 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, CBJACK_CP_OPTIONS_SKIP_OUTPUT) !=
- CUBEB_OK) {
- pthread_mutex_unlock(&stm->mutex);
- cbjack_stream_destroy(stm);
- return CUBEB_ERROR;
- }
- }
+ stm->input_ports[c] = api_jack_port_register(stm->context->jack_client,
+ portname,
+ JACK_DEFAULT_AUDIO_TYPE,
+ JackPortIsInput,
+ 0);
}
}
+ cbjack_connect_ports(stm);
+
*stream = stm;
stm->ports_ready = true;
@@ -991,8 +887,7 @@ 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]);
+ api_jack_port_unregister (stream->context->jack_client, stream->output_ports[c]);
stream->output_ports[c] = NULL;
}
}
@@ -1001,8 +896,7 @@ 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]);
+ api_jack_port_unregister (stream->context->jack_client, stream->input_ports[c]);
stream->input_ports[c] = NULL;
}
}
@@ -1046,16 +940,16 @@ cbjack_stream_set_volume(cubeb_stream * stm, float volume)
return CUBEB_OK;
}
+
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)
return CUBEB_ERROR;
- const char * j_in = JACK_DEFAULT_IN;
- const char * j_out = JACK_DEFAULT_OUT;
+ const char * j_in = "JACK capture";
+ const char * j_out = "JACK playback";
const char * empty = "";
if (stm->devs == DUPLEX) {
@@ -1073,7 +967,8 @@ cbjack_stream_get_current_device(cubeb_stream * stm,
}
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);
@@ -1085,72 +980,68 @@ cbjack_stream_device_destroy(cubeb_stream * /*stream*/, cubeb_device * device)
static int
cbjack_enumerate_devices(cubeb * context, cubeb_device_type type,
- cubeb_device_collection * collection)
+ cubeb_device_collection ** collection)
{
if (!context)
return CUBEB_ERROR;
uint32_t rate;
+ uint8_t i = 0;
+ uint8_t j;
cbjack_get_preferred_sample_rate(context, &rate);
-
- cubeb_device_info * devices = new cubeb_device_info[2];
- if (!devices)
- return CUBEB_ERROR;
- PodZero(devices, 2);
- collection->count = 0;
+ const char * j_in = "JACK capture";
+ const char * j_out = "JACK playback";
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->friendly_name = JACK_DEFAULT_OUT;
- cur->group_id = JACK_DEFAULT_OUT;
- cur->vendor_name = JACK_DEFAULT_OUT;
- cur->type = CUBEB_DEVICE_TYPE_OUTPUT;
- cur->state = CUBEB_DEVICE_STATE_ENABLED;
- cur->preferred = CUBEB_DEVICE_PREF_ALL;
- cur->format = CUBEB_DEVICE_FMT_F32NE;
- cur->default_format = CUBEB_DEVICE_FMT_F32NE;
- cur->max_channels = MAX_CHANNELS;
- cur->min_rate = rate;
- cur->max_rate = rate;
- cur->default_rate = rate;
- cur->latency_lo = 0;
- cur->latency_hi = 0;
- collection->count += 1;
+ context->devinfo[i] = (cubeb_device_info *)malloc(sizeof(cubeb_device_info));
+ context->devinfo[i]->device_id = strdup(j_out);
+ context->devinfo[i]->devid = context->devinfo[i]->device_id;
+ context->devinfo[i]->friendly_name = strdup(j_out);
+ context->devinfo[i]->group_id = strdup(j_out);
+ context->devinfo[i]->vendor_name = strdup(j_out);
+ context->devinfo[i]->type = CUBEB_DEVICE_TYPE_OUTPUT;
+ context->devinfo[i]->state = CUBEB_DEVICE_STATE_ENABLED;
+ context->devinfo[i]->preferred = CUBEB_DEVICE_PREF_ALL;
+ context->devinfo[i]->format = CUBEB_DEVICE_FMT_F32NE;
+ context->devinfo[i]->default_format = CUBEB_DEVICE_FMT_F32NE;
+ context->devinfo[i]->max_channels = MAX_CHANNELS;
+ context->devinfo[i]->min_rate = rate;
+ context->devinfo[i]->max_rate = rate;
+ context->devinfo[i]->default_rate = rate;
+ context->devinfo[i]->latency_lo = 0;
+ context->devinfo[i]->latency_hi = 0;
+ i++;
}
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->friendly_name = JACK_DEFAULT_IN;
- cur->group_id = JACK_DEFAULT_IN;
- cur->vendor_name = JACK_DEFAULT_IN;
- cur->type = CUBEB_DEVICE_TYPE_INPUT;
- cur->state = CUBEB_DEVICE_STATE_ENABLED;
- cur->preferred = CUBEB_DEVICE_PREF_ALL;
- cur->format = CUBEB_DEVICE_FMT_F32NE;
- cur->default_format = CUBEB_DEVICE_FMT_F32NE;
- cur->max_channels = MAX_CHANNELS;
- cur->min_rate = rate;
- cur->max_rate = rate;
- cur->default_rate = rate;
- cur->latency_lo = 0;
- cur->latency_hi = 0;
- collection->count += 1;
+ context->devinfo[i] = (cubeb_device_info *)malloc(sizeof(cubeb_device_info));
+ context->devinfo[i]->device_id = strdup(j_in);
+ context->devinfo[i]->devid = context->devinfo[i]->device_id;
+ context->devinfo[i]->friendly_name = strdup(j_in);
+ context->devinfo[i]->group_id = strdup(j_in);
+ context->devinfo[i]->vendor_name = strdup(j_in);
+ context->devinfo[i]->type = CUBEB_DEVICE_TYPE_INPUT;
+ context->devinfo[i]->state = CUBEB_DEVICE_STATE_ENABLED;
+ context->devinfo[i]->preferred = CUBEB_DEVICE_PREF_ALL;
+ context->devinfo[i]->format = CUBEB_DEVICE_FMT_F32NE;
+ context->devinfo[i]->default_format = CUBEB_DEVICE_FMT_F32NE;
+ context->devinfo[i]->max_channels = MAX_CHANNELS;
+ context->devinfo[i]->min_rate = rate;
+ context->devinfo[i]->max_rate = rate;
+ context->devinfo[i]->default_rate = rate;
+ context->devinfo[i]->latency_lo = 0;
+ context->devinfo[i]->latency_hi = 0;
+ i++;
}
- collection->device = devices;
+ *collection = (cubeb_device_collection *)
+ malloc(sizeof(cubeb_device_collection) +
+ i * sizeof(cubeb_device_info *));
- return CUBEB_OK;
-}
+ (*collection)->count = i;
-static int
-cbjack_device_collection_destroy(cubeb * /*ctx*/,
- cubeb_device_collection * collection)
-{
- XASSERT(collection);
- delete[] collection->device;
+ for (j = 0; j < i; j++) {
+ (*collection)->device[j] = context->devinfo[j];
+ }
return CUBEB_OK;
}