26 #include <jack/statistics.h> 27 #include <jack/jack.h> 28 #include <jack/thread.h> 32 #ifdef HAVE_JACK_SESSION 43 static const char *jack_amp_postfix =
"_amp";
44 static const char *jack_fx_postfix =
"_fx";
47 static const char *default_jack_instancename =
"gx_head";
48 return default_jack_instancename;
56 static unsigned int rt_watchdog_counter;
59 #define SCHED_IDLE SCHED_OTHER // non-linux systems 62 static void *rt_watchdog_run(
void *p) {
63 struct sched_param spar;
64 spar.sched_priority = 0;
65 pthread_setschedparam(pthread_self(),
SCHED_IDLE, &spar);
73 static int rt_watchdog_limit = 0;
75 static void rt_watchdog_start() {
76 if (rt_watchdog_limit > 0) {
78 pthread_attr_init(&attr);
80 if (pthread_create(&pthr, &attr, rt_watchdog_run, 0)) {
83 pthread_attr_destroy(&attr);
87 static inline bool rt_watchdog_check_alive(
unsigned int bs,
unsigned int sr) {
88 if (rt_watchdog_limit > 0) {
107 bypass_insert(false),
108 #ifdef HAVE_JACK_SESSION
110 session_event_ins(0),
111 session_callback_seen(0),
114 connection_changed(),
124 xrun_msg_blocked(false),
134 for(
int i = 0;i<5;i++) mmessage.
send_cc[i] =
false;
135 connection_queue.
new_data.connect(sigc::mem_fun(*
this, &GxJack::fetch_connection_data));
136 client_change_rt.connect(client_change);
138 sigc::mem_fun(*
this, &GxJack::cleanup_slot));
139 xrun.connect(sigc::mem_fun(
this, &GxJack::report_xrun));
147 rt_watchdog_limit = limit;
194 void GxJack::write_jack_port_connections(
199 const char** pl = jack_port_get_connections(pc.
port);
201 for (
const char **p = pl; *p; p++) {
203 w.
write(make_clientvar(*p));
211 for (list<string>::const_iterator i = pc.
conn.begin(); i != pc.
conn.end(); ++i) {
220 write_jack_port_connections(w,
"input",
ports.
input);
221 write_jack_port_connections(w,
"output1",
ports.
output1);
222 write_jack_port_connections(w,
"output2",
ports.
output2);
226 write_jack_port_connections(w,
"insert_in",
ports.
insert_in,
true);
234 int GxJack::is_power_of_two (
unsigned int x)
236 return ((x != 0) && ((x & (~x + 1)) == x));
242 int jackopt = (startserver ? JackNullOption : JackNoStartServer);
244 if (client_instance.empty()) {
247 jackopt |= JackUseExactName;
260 jack_status_t jackstat;
261 #ifdef HAVE_JACK_SESSION 264 client = jack_client_open(
265 client_name.c_str(), JackOptions(jackopt | JackSessionID),
268 if (ServerName.empty()) {
271 client = jack_client_open(
client_name.c_str(), JackOptions(jackopt | JackServerName),
272 &jackstat, ServerName.c_str());
276 if (ServerName.empty()) {
279 client = jack_client_open(
client_name.c_str(), JackOptions(jackopt | JackServerName),
280 &jackstat, ServerName.c_str());
288 std::string name = jack_get_client_name(
client);
289 std::string generated_suffix = name.substr(
client_name.size());
290 std::string base = name.substr(0,
client_name.size()-strlen(jack_amp_postfix));
291 client_instance = base + generated_suffix;
294 #ifdef HAVE_JACK_SESSION 298 JackOptions(jackopt | JackSessionID | JackUseExactName),
301 if (ServerName.empty()) {
304 JackOptions(jackopt | JackUseExactName ), &jackstat);
308 JackOptions(jackopt | JackUseExactName | JackServerName),
309 &jackstat, ServerName.c_str());
313 if (ServerName.empty()) {
316 JackOptions(jackopt | JackUseExactName), &jackstat);
320 JackOptions(jackopt | JackUseExactName | JackServerName),
321 &jackstat, ServerName.c_str());
325 jack_client_close(
client);
331 if (!(jackstat & JackServerFailed)) {
332 if ((jackstat & JackServerError) && (jackopt & JackUseExactName)) {
335 boost::format(_(
"can't get requested jack instance name '%1%'"))
340 _(
"unknown jack server communication error"));
349 if (wait_after_connect) {
350 usleep(wait_after_connect);
352 jack_sr = jack_get_sample_rate(
client);
355 boost::format(_(
"The jack sample rate is %1%/sec")) % jack_sr);
357 jack_bs = jack_get_buffer_size(
client);
358 if (!is_power_of_two(jack_bs)) {
361 boost::format(_(
"The jack buffer size is %1%/frames is not power of two, Convolver wont run"))
366 boost::format(_(
"The jack buffer size is %1%/frames ... "))
371 insert_buffer =
new float[jack_bs];
377 gx_jack_init_port_connection(opt);
384 void GxJack::cleanup_slot(
bool otherthread) {
396 jack_client_close(
client);
408 void GxJack::gx_jack_cleanup() {
421 #if defined(USE_MIDI_OUT) || defined(USE_MIDI_CC_OUT) 427 jack_client_close(
client);
431 delete[] insert_buffer;
432 insert_buffer = NULL;
442 if (!gx_jack_init(startserver, wait_after_connect, opt)) {
463 std::string GxJack::make_clientvar(
const std::string& s) {
464 std::size_t n = s.find(
':');
469 return "%A" + s.substr(n);
472 return "%F" + s.substr(n);
477 std::string GxJack::replace_clientvar(
const std::string& s) {
478 if (s.compare(0, 3,
"%A:") == 0) {
481 if (s.compare(0, 3,
"%F:") == 0) {
495 for (list<string>::iterator i = l.begin(); i != l.end(); ++i) {
506 for (list<string>::iterator i = l.begin(); i != l.end(); ++i) {
514 for (list<string>::iterator i = l1.begin(); i != l1.end(); ++i) {
518 for (list<string>::iterator i = l2.begin(); i != l2.end(); ++i) {
534 #if defined(USE_MIDI_OUT) || defined(USE_MIDI_CC_OUT) 537 for (list<string>::iterator i = lmo.begin(); i != lmo.end(); ++i) {
545 bool ifound =
false, ofound =
false;
546 for (list<string>::iterator i = lins_in.begin(); i != lins_in.end(); ++i) {
547 int rc = jack_connect(
client_insert, replace_clientvar(*i).c_str(),
549 if (rc == 0 || rc == EEXIST) {
554 for (list<string>::iterator i = lins_out.begin(); i != lins_out.end(); ++i) {
555 std::string port = replace_clientvar(*i);
556 if (!jack_port_connected_to(port_a, port.c_str())) {
559 if (rc == 0 || rc == EEXIST) {
566 if (!ifound || !ofound) {
578 void GxJack::gx_jack_callbacks() {
580 jack_set_xrun_callback(
client, gx_jack_xrun_callback,
this);
581 jack_set_sample_rate_callback(
client, gx_jack_srate_callback,
this);
582 jack_on_shutdown(
client, shutdown_callback_client,
this);
583 jack_on_shutdown(
client_insert, shutdown_callback_client_insert,
this);
584 jack_set_buffer_size_callback(
client, gx_jack_buffersize_callback,
this);
585 jack_set_port_registration_callback(
client, gx_jack_portreg_callback,
this);
586 jack_set_port_connect_callback(
client, gx_jack_portconn_callback,
this);
587 #ifdef HAVE_JACK_SESSION 588 if (jack_set_session_callback_fp) {
589 jack_set_session_callback_fp(
client, gx_jack_session_callback,
this);
590 jack_set_session_callback_fp(
client_insert, gx_jack_session_callback_ins,
this);
596 client,
"in_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
598 client,
"midi_in_1", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
600 client,
"out_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
601 #if defined(USE_MIDI_OUT) || defined(USE_MIDI_CC_OUT) 603 client,
"midi_out_1", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
610 client_insert,
"in_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
612 client_insert,
"out_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
614 client_insert,
"out_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
616 engine.
init(jack_sr, jack_bs, SCHED_FIFO,
617 jack_client_real_time_priority(
client));
618 jack_set_process_callback(
client, gx_jack_process,
this);
619 jack_set_process_callback(
client_insert, gx_jack_insert_process,
this);
620 if (jack_activate(
client) != 0) {
622 _(
"Jack Activation"),
623 string(_(
"Can't activate JACK gx_amp client")));
627 string(_(
"Can't activate JACK gx_amp_fx client")));
638 for(
int i = 0;i<5;i++) {
640 unsigned char* midi_send = jack_midi_event_reserve(buf, i, mmessage.
me_num[i]);
643 if (mmessage.
me_num[i] == 2) {
645 midi_send[1] = mmessage.
pg_num[i];
647 midi_send[0] = mmessage.
cc_num[i] | 0;
648 }
else if (mmessage.
me_num[i] == 3) {
649 midi_send[2] = mmessage.
bg_num[i];
651 midi_send[1] = mmessage.
pg_num[i];
653 midi_send[0] = mmessage.
cc_num[i] | 0;
668 jack_midi_clear_buffer(midi_port_buf);
670 return midi_port_buf;
673 static inline float *get_float_buf(jack_port_t *port, jack_nframes_t nframes) {
674 return static_cast<float *
>(jack_port_get_buffer(port, nframes));
677 inline void GxJack::check_overload() {
678 if (!rt_watchdog_check_alive(jack_bs, jack_sr)) {
685 int __rt_func GxJack::gx_jack_process(jack_nframes_t nframes,
void *arg) {
690 self.check_overload();
692 self.transport_state = jack_transport_query (
self.
client, &
self.
current);
695 self.engine.mono_chain.process(
700 if (
self.bypass_insert) {
701 memcpy(
self.insert_buffer, obuf, nframes*
sizeof(
float));
705 self.engine.controller_map.compute_midi_in(
711 self.old_transport_state =
self.transport_state;
715 void *buf =
self.get_midi_buffer(nframes);
716 self.process_midi_cc(buf, nframes);
719 self.engine.mono_chain.post_rt_finished();
725 int __rt_func GxJack::gx_jack_insert_process(jack_nframes_t nframes,
void *arg) {
730 self.check_overload();
734 if (!
self.bypass_insert) {
737 ibuf =
self.insert_buffer;
739 self.engine.stereo_chain.process(
745 self.engine.stereo_chain.post_rt_finished();
755 : ring(jack_ringbuffer_create(20*sizeof(
PortConnData))),
762 _(
"Jack init"), _(
"can't get memory for ringbuffer"));
764 jack_ringbuffer_mlock(ring);
768 jack_ringbuffer_free(ring);
777 size_t sz = jack_ringbuffer_write(ring, reinterpret_cast<const char*>(&p),
sizeof(p));
778 if (sz !=
sizeof(p)) {
781 jack_ringbuffer_write_advance(ring, sz);
789 jack_ringbuffer_reset(ring);
794 size_t sz = jack_ringbuffer_read(ring, reinterpret_cast<char*>(p),
sizeof(*p));
798 assert(sz ==
sizeof(*p));
799 jack_ringbuffer_read_advance(ring, sz);
803 void GxJack::fetch_connection_data() {
806 const char** port = jack_port_get_connections(ports.input.port);
816 bool fetched = connection_queue.pop(&p);
828 void GxJack::gx_jack_portconn_callback(jack_port_id_t a, jack_port_id_t b,
int connect,
void* arg) {
833 jack_port_t* port_a = jack_port_by_id(
self.client, a);
834 jack_port_t* port_b = jack_port_by_id(
self.client, b);
835 if (!port_a || !port_b) {
838 self.connection_queue.push(jack_port_name(port_a), jack_port_name(port_b), connect);
847 for(
int i = 0;i<5;i++) {
848 if (!mmessage.send_cc[i]) {
849 mmessage.send_cc[i] =
true;
850 mmessage.cc_num[i] = _cc;
851 mmessage.pg_num[i] = _pg;
852 mmessage.bg_num[i] = _bgn;
853 mmessage.me_num[i] = _num;
862 void GxJack::gx_jack_portreg_callback(jack_port_id_t pid,
int reg,
void* arg) {
867 jack_port_t* port = jack_port_by_id(
self.client, pid);
868 if (!port || jack_port_is_mine(
self.client, port)) {
871 self.connection_queue.portchange();
877 int GxJack::gx_jack_srate_callback(jack_nframes_t samplerate,
void* arg) {
879 if (
self.jack_sr == samplerate) {
883 self.jack_sr = samplerate;
884 self.engine.set_samplerate(samplerate);
891 int GxJack::gx_jack_buffersize_callback(jack_nframes_t nframes,
void* arg) {
893 if (
self.jack_bs == nframes) {
897 self.jack_bs = nframes;
898 self.engine.set_buffersize(nframes);
900 self.buffersize_change();
902 delete[]
self.insert_buffer;
903 self.insert_buffer = NULL;
904 self.insert_buffer =
new float[
self.jack_bs];
909 void GxJack::gx_jack_shutdown_callback() {
915 void GxJack::shutdown_callback_client(
void *arg) {
919 self.client_change_rt();
921 if (
self.client_insert) {
922 jack_client_close(
self.client_insert);
923 self.client_insert = 0;
925 self.gx_jack_shutdown_callback();
928 void GxJack::shutdown_callback_client_insert(
void *arg) {
932 jack_client_close(
self.client);
934 self.client_change_rt();
936 self.gx_jack_shutdown_callback();
939 void GxJack::report_xrun_clear() {
940 xrun_msg_blocked =
false;
943 void GxJack::report_xrun() {
944 if (xrun_msg_blocked) {
947 xrun_msg_blocked =
true;
948 Glib::signal_timeout().connect_once(
949 sigc::mem_fun(
this, &GxJack::report_xrun_clear), 100);
952 (boost::format(_(
" delay of at least %1% microsecs")) % last_xrun).str());
956 int GxJack::gx_jack_xrun_callback(
void* arg) {
961 self.last_xrun = jack_get_xrun_delayed_usecs(
self.client);
962 if (!
self.engine.mono_chain.is_stopped()) {
973 #ifdef HAVE_JACK_SESSION 974 jack_set_session_callback_type GxJack::jack_set_session_callback_fp =
975 reinterpret_cast<jack_set_session_callback_type
>(
976 dlsym(RTLD_DEFAULT,
"jack_set_session_callback"));
977 jack_get_uuid_for_client_name_type GxJack::jack_get_uuid_for_client_name_fp =
978 reinterpret_cast<jack_get_uuid_for_client_name_type
>(
979 dlsym(RTLD_DEFAULT,
"jack_get_uuid_for_client_name"));
980 jack_client_get_uuid_type GxJack::jack_client_get_uuid_fp =
981 reinterpret_cast<jack_client_get_uuid_type
>(
982 dlsym(RTLD_DEFAULT,
"jack_client_get_uuid"));
984 int GxJack::return_last_session_event() {
985 jack_session_event_t *
event = get_last_session_event();
987 session_callback_seen += 1;
988 jack_session_reply(client, event);
989 jack_session_event_free(event);
992 return session_callback_seen;
995 int GxJack::return_last_session_event_ins() {
996 jack_session_event_t *
event = get_last_session_event_ins();
998 session_callback_seen -= 1;
999 jack_session_reply(client_insert, event);
1000 jack_session_event_free(event);
1003 return session_callback_seen;
1006 string GxJack::get_uuid_insert() {
1009 if (jack_client_get_uuid_fp) {
1010 uuid = jack_client_get_uuid_fp(client_insert);
1011 }
else if (jack_get_uuid_for_client_name_fp) {
1012 uuid = jack_get_uuid_for_client_name_fp(
1013 client_insert, client_insert_name.c_str());
1024 void GxJack::gx_jack_session_callback(jack_session_event_t *event,
void *arg) {
1026 jack_session_event_t *np = 0;
1034 void GxJack::gx_jack_session_callback_ins(jack_session_event_t *event,
void *arg) {
1036 jack_session_event_t *np = 0;
void gx_print_info(const char *, const std::string &)
void set_jack_down(bool v)
void begin_array(bool nl=false)
StereoModuleChain stereo_chain
void end_array(bool nl=false)
virtual void wait_ramp_down_finished()
const Glib::ustring & get_jack_instancename() const
void read_connections(gx_system::JsonParser &jp)
void push(const char *a, const char *b, bool conn)
MonoModuleChain mono_chain
void process_midi_cc(void *buf, jack_nframes_t nframes)
void init(unsigned int samplerate, unsigned int buffersize, int policy, int priority)
static void rt_watchdog_set_limit(int limit)
PortConnection midi_output
GxJack(gx_engine::GxEngine &engine_)
PortConnection insert_out
Glib::Dispatcher connection
void write_key(const char *p, bool nl=false)
const Glib::ustring & get_jack_servername() const
int atomic_get(volatile int &p)
void gx_print_fatal(const char *, const std::string &)
Glib::Dispatcher new_data
void gx_print_error(const char *, const std::string &)
static string get_default_instancename()
void * get_midi_buffer(jack_nframes_t nframes)
void set_jack_exit(bool v)
void send_midi_cc(int cc_num, int pgm_num, int bgn, int num)
virtual void overload(OverloadType tp, const char *reason)
const Glib::ustring & get_jack_input() const
void write_connections(gx_system::JsonWriter &w)
void begin_object(bool nl=false)
static GxExit & get_instance()
Glib::ustring get_jack_output(unsigned int n) const
virtual void set_rack_changed()
bool get_jack_noconnect() const
jack_transport_state_t transport_state
jack_client_t * client_insert
const Glib::ustring & get_jack_uuid2() const
const Glib::ustring & get_jack_midi() const
PortConnection midi_input
void atomic_inc(volatile int *p)
void gx_print_warning(const char *, const std::string &)
virtual void start_ramp_down()
sigc::signal< void, bool > & signal_exit()
void atomic_set(volatile int *p, int v)
Glib::Dispatcher shutdown
string current_value() const
const Glib::ustring & get_jack_uuid() const
Glib::Dispatcher portchange
void set_stateflag(StateFlag flag)
bool atomic_compare_and_exchange(volatile int *p, int oldv, int newv)
bool gx_jack_connection(bool connect, bool startserver, int wait_after_connect, const gx_system::CmdlineOptions &opt)
void clear_stateflag(StateFlag flag)
Glib::Dispatcher session_ins
token next(token expect=no_token)
void write(float v, bool nl=false)
jack_transport_state_t old_transport_state
string client_insert_name
void end_object(bool nl=false)