diff options
Diffstat (limited to 'media/libcubeb/src/cubeb_jack.cpp')
-rw-r--r-- | media/libcubeb/src/cubeb_jack.cpp | 693 |
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; } |