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_capture.h"
#include "audio/types.h"
#include "audio/utils.h"
#include "compat/platform_semaphore.h"
#include "debug.h"
#include "host.h"
#include "jack_common.h"
#include "lib_common.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_capture
 

Macros

#define MOD_NAME   "[JACK capture] "
 

Enumerations

enum  { MAX_PORTS = 64 }
 

Functions

static void audio_cap_jack_done (void *state)
 
static void audio_cap_jack_help (const char *client_name)
 
static void * audio_cap_jack_init (struct module *parent, const char *cfg)
 
static void audio_cap_jack_probe (struct device_info **available_devices, int *count, void(**deleter)(void *))
 
static struct audio_frame * audio_cap_jack_read (void *state)
 
static void audio_cap_jack_should_exit (void *state)
 
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, &acap_jack_info, LIBRARY_CLASS_AUDIO_CAPTURE, AUDIO_CAPTURE_ABI_VERSION)
 

Variables

static const struct audio_capture_info acap_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

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
MAX_PORTS 

Definition at line 56 of file jack.c.

56 {
57 MAX_PORTS = 64,
58};
@ MAX_PORTS
Definition jack.c:57

Function Documentation

◆ audio_cap_jack_done()

static void audio_cap_jack_done ( void * state)
static

Definition at line 304 of file jack.c.

305{
306 struct state_jack_capture *s = (struct state_jack_capture *) state;
307
309 s);
310
312 free(s->tmp);
314 free(s->frame.data);
317 free(s);
318}
void ** state
static void audio_cap_jack_should_exit(void *state)
Definition jack.c:139
void unregister_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
Definition host.cpp:1158
static void close_libjack(struct libjack_connection *s)
void platform_sem_destroy(void *semStructure)
void ring_buffer_destroy(struct ring_buffer *ring)
char * data
Definition types.h:102
jack_client_close_t client_close
struct module * parent
Definition jack.c:64
jack_client_t * client
Definition jack.c:68
struct audio_frame frame
Definition jack.c:67
struct ring_buffer * data
Definition jack.c:73
struct libjack_connection * libjack
Definition jack.c:65
sem_t data_sem
Definition jack.c:72

References audio_cap_jack_should_exit(), state_jack_capture::client, libjack_connection::client_close, close_libjack(), audio_frame::data, state_jack_capture::data, state_jack_capture::data_sem, state_jack_capture::frame, state_jack_capture::libjack, state_jack_capture::parent, platform_sem_destroy(), ring_buffer_destroy(), state, state_jack_capture::tmp, and unregister_should_exit_callback().

Here is the call graph for this function:

◆ audio_cap_jack_help()

static void audio_cap_jack_help ( const char * client_name)
static

Definition at line 116 of file jack.c.

117{
118 int count = 0;
119 int i = 0;
120 struct device_info *available_devices = audio_jack_probe(client_name, JackPortIsOutput, &count);
121
122 printf("Usage:\n");
123 printf("\t-s jack[:first_channel=<f>][:name=<n>][:<device>]\n");
124 printf("\twhere\n");
125 printf("\t\t<f> - index of first channel to capture (default: 0)\n");
126 printf("\t\t<n> - name of the JACK client (default: %s)\n", PACKAGE_NAME);
127 printf("\n");
128
129 if(!available_devices)
130 return;
131
132 printf("Available devices:\n");
133 for(i = 0; i < count; i++){
134 printf("\t%s\n", available_devices[i].name);
135 }
136 free(available_devices);
137}
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_cap_jack_init().

Here is the call graph for this function:

◆ audio_cap_jack_init()

static void * audio_cap_jack_init ( struct module * parent,
const char * cfg )
static

Definition at line 146 of file jack.c.

147{
148 jack_status_t status;
149 const char **ports;
150 int i;
151 char *client_name;
152 const char *source_name = NULL;
153
154 client_name = alloca(MAX(strlen(PACKAGE_NAME), strlen(cfg)) + 1);
155 strcpy(client_name, PACKAGE_NAME);
156
157 struct state_jack_capture *s = (struct state_jack_capture *) calloc(1, sizeof(struct state_jack_capture));
158 if(!s) {
159 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to allocate memory.\n");
160 return NULL;
161 }
162 s->parent = parent;
163 s->libjack = open_libjack();
164 if (s->libjack == NULL) {
165 free(s);
166 return NULL;
167 }
168
169 char *dup = strdup(cfg);
170 assert(dup != NULL);
171 char *tmp = dup, *item, *save_ptr;
172 while ((item = strtok_r(tmp, ":", &save_ptr)) != NULL) {
173 if (strcmp(item, "help") == 0) {
174 audio_cap_jack_help(client_name);
175 free(dup);
176 free(s);
177 return INIT_NOERR;
178 } else if (strstr(item, "first_channel=") == item) {
179 char *endptr;
180 char *val = item + strlen("first_channel=");
181 errno = 0;
182 s->first_channel = strtol(val, &endptr, 0);
183 if (errno == ERANGE || *endptr != '\0' || s->first_channel < 0) {
184 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Wrong value '%s'.\n", val);
185 goto error;
186 }
187 } else if (strstr(item, "name=") == item) {
188 strcpy(client_name, item + strlen("name="));
189 } else { // this is the device name
190 source_name = cfg + (item - dup);
191 break;
192 }
193
194 tmp = NULL;
195 }
196 free(dup);
197 dup = NULL;
198
199 s->client = s->libjack->client_open(client_name, JackNullOption, &status);
200 if(status & JackFailure) {
201 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Opening JACK client failed.\n");
202 goto error;
203 }
204
205 ports = s->libjack->get_ports(s->client, source_name, NULL, JackPortIsOutput);
206 if(ports == NULL) {
207 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to output ports matching \"%s\".\n", source_name);
208 goto release_client;
209 }
210
211 i = 0;
212 while(ports[i]) i++;
213
215 if (i < s->frame.ch_count) {
216 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Requested channel count %d not found (matching pattern %s).\n",
217 s->frame.ch_count, cfg);
218 goto release_client;
219
220 }
221
222 s->frame.bps = 4;
224 log_msg(LOG_LEVEL_WARNING, "[JACK capture] Ignoring user specified sample rate!\n");
225 }
228 s->frame.data = malloc(s->frame.max_size);
229
230 platform_sem_init(&s->data_sem, 0, 0);
231
232 s->tmp = malloc(s->frame.max_size);
233
235
237 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Registring callback problem.\n");
238 goto release_client;
239 }
240
241 if (s->libjack->set_process_callback(s->client, jack_process_callback, (void *) s) != 0) {
242 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Process callback registration problem.\n");
243 goto release_client;
244 }
245
246 if (s->libjack->activate(s->client)) {
247 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot activate client.\n");
248 goto release_client;
249 }
250
251 {
252 int port;
253 char name[32];
254
255 for(port = 0; port < s->frame.ch_count; port++) {
256 snprintf(name, 32, "capture_%02u", port);
257 s->input_ports[port] = s->libjack->port_register(s->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
258 /* attach ports */
259 if (s->libjack->connect(s->client, ports[port], s->libjack->port_name(s->input_ports[port]))) {
260 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot connect input ports.\n");
261 }
262 }
263 }
264
265 free(ports);
267
268 s->can_process = true;
269
270 return s;
271
272release_client:
273 s->libjack->client_close(s->client);
274error:
275 close_libjack(s->libjack);
276 free(dup);
277 free(s);
278 return NULL;
279}
int void * val
struct video_frame * frame
static void audio_cap_jack_help(const char *client_name)
Definition jack.c:116
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_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
void register_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
Definition host.cpp:1144
unsigned int audio_capture_sample_rate
Definition host.cpp:165
unsigned int audio_capture_channels
Definition host.cpp:163
#define DEFAULT_AUDIO_CAPTURE_CHANNELS
Definition host.h:89
#define INIT_NOERR
Definition host.h:73
static struct libjack_connection * open_libjack(void)
#define MAX(a, b)
Definition macros.h:65
void platform_sem_init(void *semStructure, int pshared, int initialValue)
struct ring_buffer * ring_buffer_init(int size)
const char * parent
Definition settings.cpp:198
int sample_rate
Definition types.h:101
int ch_count
Definition types.h:104
int bps
Definition types.h:100
int max_size
Definition types.h:105
Definition hd-rum.c:27
jack_set_sample_rate_callback_t set_sample_rate_callback
jack_get_sample_rate_t get_sample_rate
jack_client_open_t client_open
jack_get_ports_t get_ports
long int first_channel
Definition jack.c:77

References libjack_connection::activate, audio_cap_jack_help(), audio_cap_jack_should_exit(), audio_capture_channels, audio_capture_sample_rate, audio_frame::bps, state_jack_capture::can_process, audio_frame::ch_count, state_jack_capture::client, libjack_connection::client_close, libjack_connection::client_open, close_libjack(), libjack_connection::connect, audio_frame::data, state_jack_capture::data, state_jack_capture::data_sem, DEFAULT_AUDIO_CAPTURE_CHANNELS, state_jack_capture::first_channel, frame, state_jack_capture::frame, libjack_connection::get_ports, libjack_connection::get_sample_rate, INIT_NOERR, state_jack_capture::input_ports, jack_process_callback(), jack_samplerate_changed_callback(), state_jack_capture::libjack, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, log_msg(), MAX, audio_frame::max_size, MOD_NAME, name, open_libjack(), parent, state_jack_capture::parent, platform_sem_init(), libjack_connection::port_name, libjack_connection::port_register, register_should_exit_callback(), ring_buffer_init(), audio_frame::sample_rate, libjack_connection::set_process_callback, libjack_connection::set_sample_rate_callback, state_jack_capture::tmp, and val.

Here is the call graph for this function:

◆ audio_cap_jack_probe()

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

Definition at line 110 of file jack.c.

111{
112 *deleter = free;
113 *available_devices = audio_jack_probe(PACKAGE_STRING, JackPortIsOutput, count);
114}
int void(** deleter)(void *))

References audio_jack_probe(), count, and deleter.

Here is the call graph for this function:

◆ audio_cap_jack_read()

static struct audio_frame * audio_cap_jack_read ( void * state)
static

Definition at line 281 of file jack.c.

282{
283 struct state_jack_capture *s = (struct state_jack_capture *) state;
284
286
287 int read_avail = ring_get_current_size(s->data);
289 if(read_avail > s->frame.data_len){
290 /* We didn't read all available data in ring buffer, so we
291 * increment the semaphore back up, so we don't wait needlessly
292 * on the next call */
294 }
295
296 float2int((char *) s->frame.data, (char *) s->frame.data, s->frame.max_size);
297
298 if(!s->frame.data_len)
299 return NULL;
300
301 return &s->frame;
302}
void platform_sem_post(void *semStructure)
void platform_sem_wait(void *semStructure)
int ring_get_current_size(struct ring_buffer *ring)
int ring_buffer_read(struct ring_buffer *ring, char *out, int max_len)
int data_len
Definition types.h:103
void float2int(char *out, const char *in, int len)
Definition utils.cpp:482

References audio_frame::data, state_jack_capture::data, audio_frame::data_len, state_jack_capture::data_sem, float2int(), state_jack_capture::frame, audio_frame::max_size, platform_sem_post(), platform_sem_wait(), ring_buffer_read(), ring_get_current_size(), and state.

Here is the call graph for this function:

◆ audio_cap_jack_should_exit()

static void audio_cap_jack_should_exit ( void * state)
static

Definition at line 139 of file jack.c.

140{
141 struct state_jack_capture *s = state;
142 s->should_exit = true;
144}
bool should_exit
Definition jack.c:75

References state_jack_capture::data_sem, platform_sem_post(), state_jack_capture::should_exit, and state.

Referenced by audio_cap_jack_done(), and audio_cap_jack_init().

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 89 of file jack.c.

90{
91 struct state_jack_capture *s = (struct state_jack_capture *) arg;
92 int i;
93 int channel_size = nframes * sizeof(int32_t);
94
95 if (!s->can_process) {
96 return 0;
97 }
98
99 for (i = 0; i < s->frame.ch_count; ++i) {
100 jack_default_audio_sample_t *in = s->libjack->port_get_buffer(s->input_ports[i], nframes);
101 mux_channel(s->tmp, (char *) in, sizeof(int32_t), channel_size, s->frame.ch_count, i, 1.0);
102 }
103
104 ring_buffer_write(s->data, s->tmp, channel_size * s->frame.ch_count);
106
107 return 0;
108}
void ring_buffer_write(struct ring_buffer *ring, const char *in, int len)
jack_port_get_buffer_t port_get_buffer
jack_port_t * input_ports[MAX_PORTS]
Definition jack.c:69
bool can_process
Definition jack.c:74
void mux_channel(char *out, const char *in, int bps, int in_len, int out_stream_channels, int pos_in_stream, double scale)
Definition utils.cpp:371

References state_jack_capture::can_process, audio_frame::ch_count, state_jack_capture::data, state_jack_capture::data_sem, state_jack_capture::frame, state_jack_capture::input_ports, state_jack_capture::libjack, mux_channel(), platform_sem_post(), libjack_connection::port_get_buffer, ring_buffer_write(), and state_jack_capture::tmp.

Referenced by audio_cap_jack_init(), audio_play_jack_init(), and jack_start().

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 80 of file jack.c.

81{
82 struct state_jack_capture *s = (struct state_jack_capture *) arg;
83
84 s->frame.sample_rate = nframes;
85
86 return 0;
87}

References state_jack_capture::frame, and audio_frame::sample_rate.

Referenced by audio_cap_jack_init(), audio_play_jack_init(), and jack_start().

◆ REGISTER_MODULE()

REGISTER_MODULE ( jack ,
& acap_jack_info,
LIBRARY_CLASS_AUDIO_CAPTURE ,
AUDIO_CAPTURE_ABI_VERSION  )

Variable Documentation

◆ acap_jack_info

const struct audio_capture_info acap_jack_info
static
Initial value:
= {
}
static void audio_cap_jack_probe(struct device_info **available_devices, int *count, void(**deleter)(void *))
Definition jack.c:110
static void * audio_cap_jack_init(struct module *parent, const char *cfg)
Definition jack.c:146
static struct audio_frame * audio_cap_jack_read(void *state)
Definition jack.c:281
static void audio_cap_jack_done(void *state)
Definition jack.c:304

Definition at line 320 of file jack.c.