/* PipeWire */ /* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */ /* SPDX-License-Identifier: MIT */ #ifndef PIPEWIRE_WEAK_JACK_H #define PIPEWIRE_WEAK_JACK_H #include "config.h" #include #include #include #include #ifdef __cplusplus extern "C" { #endif struct weakjack { jack_nframes_t (*cycle_wait) (jack_client_t* client); void (*cycle_signal) (jack_client_t* client, int status); jack_time_t (*get_time) (void); jack_nframes_t (*frame_time) (const jack_client_t *); int (*get_cycle_times) (const jack_client_t *client, jack_nframes_t *current_frames, jack_time_t *current_usecs, jack_time_t *next_usecs, float *period_usecs); jack_transport_state_t (*transport_query) (const jack_client_t *client, jack_position_t *pos); jack_client_t * (*client_open) (const char *client_name, jack_options_t options, jack_status_t *status, ...); int (*client_close) (jack_client_t *client); int (*activate) (jack_client_t *client); int (*deactivate) (jack_client_t *client); jack_nframes_t (*get_sample_rate) (jack_client_t *); int (*recompute_total_latencies) (jack_client_t *client); jack_port_t * (*port_register) (jack_client_t *client, const char *port_name, const char *port_type, unsigned long flags, unsigned long buffer_size); int (*port_unregister) (jack_client_t *client, jack_port_t *port); void * (*port_get_buffer) (jack_port_t *port, jack_nframes_t); const char * (*port_name) (const jack_port_t *port); void (*port_get_latency_range) (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range); void (*port_set_latency_range) (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range); int (*connect) (jack_client_t *client, const char *source_port, const char *destination_port); int (*disconnect) (jack_client_t *client, const char *source_port, const char *destination_port); const char ** (*get_ports) (jack_client_t *client, const char *port_name_pattern, const char *type_name_pattern, unsigned long flags); void (*free) (void* ptr); int (*set_process_thread) (jack_client_t* client, JackThreadCallback thread_callback, void *arg); int (*set_xrun_callback) (jack_client_t *client, JackXRunCallback xrun_callback, void *arg); void (*on_info_shutdown) (jack_client_t *client, JackInfoShutdownCallback shutdown_callback, void *arg); int (*set_latency_callback) (jack_client_t *client, JackLatencyCallback latency_callback, void *arg); void (*midi_clear_buffer) (void *port_buffer); int (*midi_event_write) (void *port_buffer, jack_nframes_t time, const jack_midi_data_t *data, size_t data_size); uint32_t (*midi_get_event_count) (void* port_buffer); int (*midi_event_get) (jack_midi_event_t *event, void *port_buffer, uint32_t event_index); }; static inline int weakjack_load_by_path(struct weakjack *jack, const char *path) { void *hnd; hnd = dlopen(path, RTLD_NOW); if (hnd == NULL) return -ENOENT; pw_log_info("opened libjack: %s", path); #define LOAD_SYM(name) ({ \ if ((jack->name = dlsym(hnd, "jack_"#name )) == NULL) \ return -ENOSYS; \ }) spa_zero(*jack); LOAD_SYM(cycle_wait); LOAD_SYM(cycle_signal); LOAD_SYM(get_time); LOAD_SYM(frame_time); LOAD_SYM(get_cycle_times); LOAD_SYM(transport_query); LOAD_SYM(client_open); LOAD_SYM(client_close); LOAD_SYM(activate); LOAD_SYM(deactivate); LOAD_SYM(get_sample_rate); LOAD_SYM(recompute_total_latencies); LOAD_SYM(port_register); LOAD_SYM(port_unregister); LOAD_SYM(port_get_buffer); LOAD_SYM(port_name); LOAD_SYM(port_get_latency_range); LOAD_SYM(port_set_latency_range); LOAD_SYM(connect); LOAD_SYM(disconnect); LOAD_SYM(get_ports); LOAD_SYM(free); LOAD_SYM(set_process_thread); LOAD_SYM(set_xrun_callback); LOAD_SYM(on_info_shutdown); LOAD_SYM(set_latency_callback); LOAD_SYM(midi_clear_buffer); LOAD_SYM(midi_event_write); LOAD_SYM(midi_get_event_count); LOAD_SYM(midi_event_get); #undef LOAD_SYM return 0; } static inline int weakjack_load(struct weakjack *jack, const char *lib) { int res = -ENOENT; const char *search_dirs, *p, *state = NULL; char path[PATH_MAX]; size_t len; while ((p = strstr(lib, "../")) != NULL) lib = p + 3; search_dirs = getenv("LIBJACK_PATH"); if (!search_dirs) search_dirs = PREFIX "/lib64/:" PREFIX "/lib/:" "/usr/lib64/:/usr/lib/:" LIBDIR; res = -ENAMETOOLONG; while ((p = pw_split_walk(search_dirs, ":", &len, &state))) { int pathlen; if (len >= sizeof(path)) continue; if (strncmp(lib, p, len) == 0) pathlen = snprintf(path, sizeof(path), "%s", lib); else pathlen = snprintf(path, sizeof(path), "%.*s/%s", (int) len, p, lib); if (pathlen < 0 || (size_t) pathlen >= sizeof(path)) continue; if ((res = weakjack_load_by_path(jack, path)) == 0) break; } return res; } #ifdef __cplusplus } #endif #endif /* PIPEWIRE_WEAK_JACK_H */