UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
jack.c File Reference
#include <jack/jack.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "audio/audio_playback.h"
#include "audio/types.h"
#include "audio/utils.h"
#include "debug.h"
#include "host.h"
#include "jack_common.h"
#include "lib_common.h"
#include "utils/audio_buffer.h"
#include "utils/macros.h"
#include "utils/ring_buffer.h"
Include dependency graph for jack.c:

Go to the source code of this file.

Classes

struct  state_jack_playback
 

Macros

#define MOD_NAME   "[JACK playback] "
 

Enumerations

enum  { DEFAULT_AUDIO_BUF_LEN_MS = 50 , MAX_LEN_MS = 1000 , MAX_PORTS = 64 }
 

Functions

static bool audio_play_jack_ctl (void *state, int request, void *data, size_t *len)
 
static void audio_play_jack_done (void *state)
 
static void audio_play_jack_help (const char *client_name)
 
static void * audio_play_jack_init (const char *cfg)
 
static void audio_play_jack_probe (struct device_info **available_devices, int *count, void(**deleter)(void *))
 
static void audio_play_jack_put_frame (void *state, const struct audio_frame *frame)
 
static bool audio_play_jack_query_format (struct state_jack_playback *s, void *data, size_t *len)
 
static bool audio_play_jack_reconfigure (void *state, struct audio_desc desc)
 
static int jack_process_callback (jack_nframes_t nframes, void *arg)
 
static int jack_samplerate_changed_callback (jack_nframes_t nframes, void *arg)
 
 REGISTER_MODULE (jack, &aplay_jack_info, LIBRARY_CLASS_AUDIO_PLAYBACK, AUDIO_PLAYBACK_ABI_VERSION)
 

Variables

static const struct audio_playback_info aplay_jack_info
 

Detailed Description

Author
Martin Pulec pulec.nosp@m.@ces.nosp@m.net.c.nosp@m.z

Definition in file jack.c.

Macro Definition Documentation

◆ MOD_NAME

#define MOD_NAME   "[JACK playback] "

Definition at line 54 of file jack.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
DEFAULT_AUDIO_BUF_LEN_MS 
MAX_LEN_MS 
MAX_PORTS 

Definition at line 56 of file jack.c.

56 {
58 MAX_LEN_MS = 1000,
59 MAX_PORTS = 64,
60};
@ MAX_PORTS
Definition jack.c:57
@ MAX_LEN_MS
Definition jack.c:58
@ DEFAULT_AUDIO_BUF_LEN_MS
Definition jack.c:57

Function Documentation

◆ audio_play_jack_ctl()

static bool audio_play_jack_ctl ( void * state,
int request,
void * data,
size_t * len )
static

Definition at line 282 of file jack.c.

283{
284 struct state_jack_playback *s = (struct state_jack_playback *) state;
285
286 switch (request) {
289 default:
290 return false;
291 }
292}
void ** state
int void size_t * len
#define AUDIO_PLAYBACK_CTL_QUERY_FORMAT
static bool audio_play_jack_query_format(struct state_jack_playback *s, void *data, size_t *len)
Definition jack.c:261

References audio_play_jack_query_format(), AUDIO_PLAYBACK_CTL_QUERY_FORMAT, state_jack_playback::data, len, and state.

Here is the call graph for this function:

◆ audio_play_jack_done()

static void audio_play_jack_done ( void * state)
static

Definition at line 385 of file jack.c.

386{
387 struct state_jack_playback *s = (struct state_jack_playback *) state;
388
390 free(s->tmp);
391 free(s->converted);
392 free(s->jack_ports_pattern);
393 if (s->buffer_fns) {
394 s->buffer_fns->destroy(s->data);
395 }
396
398
399 free(s);
400}
static void close_libjack(struct libjack_connection *s)
void(* destroy)(void *buf)
jack_client_close_t client_close
struct audio_buffer_api * buffer_fns
Definition jack.c:75
jack_client_t * client
Definition jack.c:67
struct libjack_connection * libjack
Definition jack.c:63
char * tmp
temporary buffer used to demux data
Definition jack.c:76
float * converted
temporery buffer for int2float (put_frame)
Definition jack.c:71
char * jack_ports_pattern
Definition jack.c:65

References state_jack_playback::buffer_fns, state_jack_playback::client, libjack_connection::client_close, close_libjack(), state_jack_playback::converted, state_jack_playback::data, audio_buffer_api::destroy, state_jack_playback::jack_ports_pattern, state_jack_playback::libjack, state, and state_jack_playback::tmp.

Here is the call graph for this function:

◆ audio_play_jack_help()

static void audio_play_jack_help ( const char * client_name)
static

Definition at line 132 of file jack.c.

133{
134 int count = 0;
135 int i = 0;
136 struct device_info *available_devices = audio_jack_probe(client_name, JackPortIsInput, &count);
137 if(!available_devices)
138 return;
139
140 printf("Usage:\n");
141 printf("\t-r jack[:first_channel=<f>][:name=<n>][:<device>]\n");
142 printf("\twhere\n");
143 printf("\t\t<f> - index of first channel to capture (default: 0)\n");
144 printf("\t\t<n> - name of the JACK client (default: %s)\n", PACKAGE_NAME);
145 printf("\n");
146
147 printf("Available devices:\n");
148 for(i = 0; i < count; i++){
149 printf("\t%s\n", available_devices[i].name);
150 }
151 free(available_devices);
152}
int count
Definition hd-rum.c:44
static struct device_info * audio_jack_probe(const char *client_name, unsigned long port_flags, int *count)
const char * name
Definition settings.cpp:193

References audio_jack_probe(), count, and name.

Referenced by audio_play_jack_init().

Here is the call graph for this function:

◆ audio_play_jack_init()

static void * audio_play_jack_init ( const char * cfg)
static

Definition at line 154 of file jack.c.

155{
156 struct state_jack_playback *s;
157 const char **ports;
158 jack_status_t status;
159 char *client_name;
160 const char *source_name = "";
161
162 client_name = alloca(MAX(strlen(PACKAGE_NAME), strlen(cfg)) + 1);
163 strcpy(client_name, PACKAGE_NAME);
164
165 s = calloc(1, sizeof(struct state_jack_playback));
166 if(!s) {
167 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to allocate memory.\n");
168 return NULL;
169 }
170
171 s->libjack = open_libjack();
172 if (s->libjack == NULL) {
173 free(s);
174 return NULL;
175 }
176
177 char *dup = strdup(cfg);
178 assert(dup != NULL);
179 char *tmp = dup, *item, *save_ptr;
180 while ((item = strtok_r(tmp, ":", &save_ptr)) != NULL) {
181 if (strcmp(item, "help") == 0) {
182 audio_play_jack_help(client_name);
183 free(s);
184 free(dup);
185 return INIT_NOERR;
186 } else if (strstr(item, "first_channel=") == item) {
187 char *endptr;
188 char *val = item + strlen("first_channel=");
189 errno = 0;
190 s->first_channel = strtol(val, &endptr, 0);
191 if (errno == ERANGE || *endptr != '\0' || s->first_channel < 0) {
192 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Wrong value '%s'.\n", val);
193 goto error;
194 }
195 } else if (strstr(item, "name=") == item) {
196 strcpy(client_name, item + strlen("name="));
197 } else { // the rest is the device name
198 source_name = cfg + (item - dup);
199 break;
200 }
201 tmp = NULL;
202 }
203 free(dup);
204 dup = NULL;
205
206 s->jack_ports_pattern = strdup(source_name);
207
208 s->client = s->libjack->client_open(client_name, JackNullOption, &status);
209 if(status & JackFailure) {
210 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Opening JACK client failed.\n");
211 goto error;
212 }
213
215 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Registering callback problem.\n");
216 goto release_client;
217 }
218
219
220 if (s->libjack->set_process_callback(s->client, jack_process_callback, (void *) s) != 0) {
221 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Process callback registration problem.\n");
222 goto release_client;
223 }
224
225 s->jack_sample_rate = s->libjack->get_sample_rate (s->client);
226 log_msg(LOG_LEVEL_INFO, "JACK sample rate: %d\n", s->jack_sample_rate);
227
228
229 ports = s->libjack->get_ports(s->client, s->jack_ports_pattern, NULL, JackPortIsInput);
230 if(ports == NULL) {
231 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to input ports matching %s.\n", s->jack_ports_pattern);
232 goto release_client;
233 }
234
235 s->jack_ports_count = 0;
236 while(ports[s->jack_ports_count]) s->jack_ports_count++;
237 free(ports);
238
239 {
240 char name[30];
241 int i;
242
243 for(i = 0; i < MAX_PORTS; ++i) {
244 snprintf(name, 30, "playback_%02u", i);
245 s->output_port[i] = s->libjack->port_register (s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
246 }
247 }
248
249
250 return s;
251
252release_client:
253 s->libjack->client_close(s->client);
254error:
255 close_libjack(s->libjack);
256 free(dup);
257 free(s);
258 return NULL;
259}
int void * val
static int jack_process_callback(jack_nframes_t nframes, void *arg)
Definition jack.c:89
static int jack_samplerate_changed_callback(jack_nframes_t nframes, void *arg)
Definition jack.c:80
#define MOD_NAME
Definition jack.c:54
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define INIT_NOERR
Definition host.h:73
static struct libjack_connection * open_libjack(void)
#define MAX(a, b)
Definition macros.h:65
static void audio_play_jack_help(const char *client_name)
Definition jack.c:132
Definition hd-rum.c:27
jack_set_sample_rate_callback_t set_sample_rate_callback
jack_client_open_t client_open
long int first_channel
Definition jack.c:78

References audio_play_jack_help(), state_jack_playback::client, libjack_connection::client_close, libjack_connection::client_open, close_libjack(), state_jack_playback::first_channel, libjack_connection::get_ports, libjack_connection::get_sample_rate, INIT_NOERR, state_jack_playback::jack_ports_count, state_jack_playback::jack_ports_pattern, jack_process_callback(), state_jack_playback::jack_sample_rate, jack_samplerate_changed_callback(), state_jack_playback::libjack, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, log_msg(), MAX, MAX_PORTS, MOD_NAME, name, open_libjack(), state_jack_playback::output_port, libjack_connection::port_register, libjack_connection::set_process_callback, libjack_connection::set_sample_rate_callback, state_jack_playback::tmp, and val.

Here is the call graph for this function:

◆ audio_play_jack_probe()

static void audio_play_jack_probe ( struct device_info ** available_devices,
int * count,
void(** deleter )(void *) )
static

Definition at line 126 of file jack.c.

127{
128 *deleter = free;
129 *available_devices = audio_jack_probe(PACKAGE_STRING, JackPortIsInput, count);
130}
int void(** deleter)(void *))

References audio_jack_probe(), count, and deleter.

Here is the call graph for this function:

◆ audio_play_jack_put_frame()

static void audio_play_jack_put_frame ( void * state,
const struct audio_frame * frame )
static

Definition at line 370 of file jack.c.

371{
372 struct state_jack_playback *s = (struct state_jack_playback *) state;
373 assert(frame->bps == 4);
374 int len = frame->data_len;
375
376 if (len >= s->max_channel_len * frame->ch_count) {
377 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Long frame: %d!\n", frame->data_len);
378 len = s->max_channel_len * frame->ch_count;
379 }
380
381 int2float((char *) s->converted, frame->data, len);
382 s->buffer_fns->write(s->data, (char *) s->converted, len);
383}
struct video_frame * frame
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
void(* write)(void *buf, const char *in, int len)
int max_channel_len
maximal length of channel data that is processed at once
Definition jack.c:70
void int2float(char *out, const char *in, int len)
Definition utils.cpp:496

References state_jack_playback::buffer_fns, state_jack_playback::converted, state_jack_playback::data, frame, int2float(), len, LOG_LEVEL_WARNING, log_msg(), state_jack_playback::max_channel_len, MOD_NAME, state, and audio_buffer_api::write.

Here is the call graph for this function:

◆ audio_play_jack_query_format()

static bool audio_play_jack_query_format ( struct state_jack_playback * s,
void * data,
size_t * len )
static

Definition at line 261 of file jack.c.

262{
263 struct audio_desc desc;
264 if (*len < sizeof desc) {
265 return false;
266 } else {
267 memcpy(&desc, data, sizeof desc);
268 }
269
270 if (s->jack_sample_rate <= 0) {
271 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Wrong JACK sample rate detected: %d!",
273 return false;
274 }
275 desc = (struct audio_desc){4, s->jack_sample_rate, MIN(s->jack_ports_count, desc.ch_count), AC_PCM};
276
277 memcpy(data, &desc, sizeof desc);
278 *len = sizeof desc;
279 return true;
280}
struct video_desc desc
@ AC_PCM
Definition types.h:53
#define MIN(a, b)
Definition macros.h:63
int jack_ports_count
Definition jack.c:73
int jack_sample_rate
Definition jack.c:66

References AC_PCM, desc, state_jack_playback::jack_ports_count, state_jack_playback::jack_sample_rate, len, LOG_LEVEL_ERROR, log_msg(), MIN, and MOD_NAME.

Referenced by audio_play_jack_ctl().

Here is the call graph for this function:

◆ audio_play_jack_reconfigure()

static bool audio_play_jack_reconfigure ( void * state,
struct audio_desc desc )
static

Definition at line 294 of file jack.c.

295{
296 struct state_jack_playback *s = (struct state_jack_playback *) state;
297 const char **ports;
298 int i;
299
300 assert(desc.bps == 4 && desc.sample_rate == s->jack_sample_rate && desc.codec == AC_PCM);
301
302 s->libjack->deactivate(s->client);
303
304 ports = s->libjack->get_ports(s->client, s->jack_ports_pattern, NULL, JackPortIsInput);
305 if(ports == NULL) {
306 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to input ports matching %s.\n", s->jack_ports_pattern);
307 return false;
308 }
309
310 if(desc.ch_count > s->jack_ports_count) {
311 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Warning: received %d audio channels, JACK can process only %d.", desc.ch_count, s->jack_ports_count);
312 }
313
314 if (s->buffer_fns) {
315 s->buffer_fns->destroy(s->data);
316 s->buffer_fns = NULL;
317 s->data = NULL;
318 }
319
320 {
321 int buf_len_ms = DEFAULT_AUDIO_BUF_LEN_MS;
322 if (get_commandline_param("low-latency-audio")) {
323 buf_len_ms = 5;
324 }
325 if (get_commandline_param("audio-buffer-len")) {
326 buf_len_ms = atoi(get_commandline_param("audio-buffer-len"));
327 assert(buf_len_ms > 0 && buf_len_ms < MAX_LEN_MS);
328 }
329 if (get_commandline_param("audio-disable-adaptive-buffer")) {
330 int buf_len = desc.bps * desc.ch_count * (desc.sample_rate * buf_len_ms / 1000);
331 s->data = ring_buffer_init(buf_len);
333 } else {
334 s->data = audio_buffer_init(desc.sample_rate, desc.bps, desc.ch_count, buf_len_ms);
336 }
337 }
338
339 /* for all channels previously connected */
340 for(i = 0; i < desc.ch_count; ++i) {
341 s->libjack->disconnect(s->client, s->libjack->port_name (s->output_port[i]), ports[i]);
342 log_msg(LOG_LEVEL_INFO, MOD_NAME "Port %d: %s\n", i, ports[i]);
343 }
344 free(s->tmp);
345 free(s->converted);
346 s->desc.bps = desc.bps;
347 s->desc.ch_count = desc.ch_count;
348 s->desc.sample_rate = desc.sample_rate;
349
350 s->max_channel_len = (desc.sample_rate / 1000) * MAX_LEN_MS * sizeof(float);
351 s->tmp = malloc(s->max_channel_len);
352 s->converted = malloc(desc.ch_count * s->max_channel_len);
353
354 if (s->libjack->activate(s->client)) {
355 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot activate client.\n");
356 return false;
357 }
358
359 for(i = 0; i < desc.ch_count; ++i) {
360 if (s->libjack->connect (s->client, s->libjack->port_name (s->output_port[i]), ports[i])) {
361 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot connect output port: %d.\n", i);
362 return false;
363 }
364 }
365 free(ports);
366
367 return true;
368}
struct audio_buffer_api audio_buffer_fns
struct audio_buffer * audio_buffer_init(int sample_rate, int bps, int ch_count, int suggested_latency_ms)
const char * get_commandline_param(const char *key)
Definition host.cpp:894
struct audio_buffer_api ring_buffer_fns
struct ring_buffer * ring_buffer_init(int size)
int sample_rate
Definition types.h:78
int ch_count
Definition types.h:79
int bps
Definition types.h:77
jack_connect_t connect
jack_port_name_t port_name
jack_deactivate_t deactivate
jack_activate_t activate
jack_get_ports_t get_ports
jack_disconnect_t disconnect
jack_port_t * output_port[MAX_PORTS]
Definition jack.c:68
struct audio_desc desc
Definition jack.c:69

References AC_PCM, libjack_connection::activate, audio_buffer_fns, audio_buffer_init(), audio_desc::bps, state_jack_playback::buffer_fns, audio_desc::ch_count, state_jack_playback::client, libjack_connection::connect, state_jack_playback::converted, state_jack_playback::data, libjack_connection::deactivate, DEFAULT_AUDIO_BUF_LEN_MS, desc, state_jack_playback::desc, audio_buffer_api::destroy, libjack_connection::disconnect, get_commandline_param(), libjack_connection::get_ports, state_jack_playback::jack_ports_count, state_jack_playback::jack_ports_pattern, state_jack_playback::jack_sample_rate, state_jack_playback::libjack, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, log_msg(), state_jack_playback::max_channel_len, MAX_LEN_MS, MOD_NAME, state_jack_playback::output_port, libjack_connection::port_name, ring_buffer_fns, ring_buffer_init(), audio_desc::sample_rate, state, and state_jack_playback::tmp.

Here is the call graph for this function:

◆ jack_process_callback()

static int jack_process_callback ( jack_nframes_t nframes,
void * arg )
static

Definition at line 103 of file jack.c.

104{
105 struct state_jack_playback *s = (struct state_jack_playback *) arg;
106 int len;
107 int req_len = s->desc.ch_count * nframes * sizeof(float);
108 int nframes_available = nframes;
109
110 len = s->buffer_fns->read(s->data, s->tmp, req_len);
111 if (len != req_len) {
112 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Buffer underflow detected.\n");
113 nframes_available = len / s->desc.ch_count / sizeof(float);
114 }
115
116 for (int i = 0; i < s->desc.ch_count; ++i) {
117 jack_default_audio_sample_t *out =
118 s->libjack->port_get_buffer (s->output_port[i], nframes_available);
119 assert(out != NULL);
120 demux_channel((char *) out, s->tmp, sizeof(float), len, s->desc.ch_count, i);
121 }
122
123 return 0;
124}
int(* read)(void *buf, char *out, int max_len)
jack_port_get_buffer_t port_get_buffer
void demux_channel(char *out, char *in, int bps, int in_len, int in_stream_channels, int pos_in_stream)
Definition utils.cpp:334

References state_jack_playback::buffer_fns, audio_desc::ch_count, state_jack_playback::data, demux_channel(), state_jack_playback::desc, len, state_jack_playback::libjack, LOG_LEVEL_WARNING, log_msg(), MOD_NAME, state_jack_playback::output_port, libjack_connection::port_get_buffer, audio_buffer_api::read, and state_jack_playback::tmp.

Here is the call graph for this function:

◆ jack_samplerate_changed_callback()

static int jack_samplerate_changed_callback ( jack_nframes_t nframes,
void * arg )
static

Definition at line 84 of file jack.c.

85{
86 struct state_jack_playback *s = (struct state_jack_playback *) arg;
87
88 if (s->jack_sample_rate != 0) {
89 bug_msg(LOG_LEVEL_WARNING, "JACK sample rate changed from %d to %d. "
90 "Runtime change is not supported in UG and will likely "
91 "cause malfunctioning. ",
92 s->jack_sample_rate, nframes);
93 } else {
94 log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Sample rate changed to: %d\n",
95 nframes);
96 }
97
98 s->jack_sample_rate = nframes;
99
100 return 0;
101}
void bug_msg(int level, const char *format,...)
prints the error with the advice to report the bug
Definition debug.cpp:379
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61

References bug_msg(), state_jack_playback::jack_sample_rate, LOG_LEVEL_NOTICE, LOG_LEVEL_WARNING, log_msg(), and MOD_NAME.

Here is the call graph for this function:

◆ REGISTER_MODULE()

REGISTER_MODULE ( jack ,
& aplay_jack_info,
LIBRARY_CLASS_AUDIO_PLAYBACK ,
AUDIO_PLAYBACK_ABI_VERSION  )

Variable Documentation

◆ aplay_jack_info

const struct audio_playback_info aplay_jack_info
static
Initial value:
= {
}
static bool audio_play_jack_ctl(void *state, int request, void *data, size_t *len)
Definition jack.c:282
static void audio_play_jack_done(void *state)
Definition jack.c:385
static void audio_play_jack_probe(struct device_info **available_devices, int *count, void(**deleter)(void *))
Definition jack.c:126
static bool audio_play_jack_reconfigure(void *state, struct audio_desc desc)
Definition jack.c:294
static void * audio_play_jack_init(const char *cfg)
Definition jack.c:154
static void audio_play_jack_put_frame(void *state, const struct audio_frame *frame)
Definition jack.c:370

Definition at line 402 of file jack.c.