1 /*
2  * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3  * Copyright (C) 2011 Pete Shorthose
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  * --------------------------------------------------------------------------
19  *
20  *  This is the gx_head interface to the jackd audio / midi server
21  *
22  * --------------------------------------------------------------------------
23  */
24 
25 #include <errno.h>              // NOLINT
26 #include <jack/statistics.h>    // NOLINT
27 #include <jack/jack.h>          // NOLINT
28 #include <jack/thread.h>        // NOLINT
29 
30 #include "engine.h"           // NOLINT
31 
32 #ifdef HAVE_JACK_SESSION
33 #include <dlfcn.h>
34 #endif
35 
36 
37 namespace gx_jack {
38 
39 /****************************************************************
40  ** class GxJack
41  ****************************************************************/
42 
43 static const char *jack_amp_postfix = "_amp";
44 static const char *jack_fx_postfix = "_fx";
45 
get_default_instancename()46 string GxJack::get_default_instancename() {
47     static const char *default_jack_instancename = "gx_head";
48     return default_jack_instancename;
49 }
50 
51 
52 /****************************************************************
53  ** rt_watchdog
54  */
55 
56 static unsigned int rt_watchdog_counter;
57 
58 #ifndef SCHED_IDLE
59 #define SCHED_IDLE SCHED_OTHER  // non-linux systems
60 #endif
61 
rt_watchdog_run(void * p)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);
66     while (true) {
67 	gx_system::atomic_set(&rt_watchdog_counter, 0);
68 	usleep(1000000);
69     }
70     return NULL;
71 }
72 
73 static int rt_watchdog_limit = 0;
74 
rt_watchdog_start()75 static void rt_watchdog_start() {
76     if (rt_watchdog_limit > 0) {
77 	pthread_attr_t      attr;
78 	pthread_attr_init(&attr);
79 	pthread_t pthr;
80 	if (pthread_create(&pthr, &attr, rt_watchdog_run, 0)) {
81 	    gx_print_error("watchdog", _("can't create thread"));
82 	}
83 	pthread_attr_destroy(&attr);
84     }
85 }
86 
rt_watchdog_check_alive(unsigned int bs,unsigned int sr)87 static inline bool rt_watchdog_check_alive(unsigned int bs, unsigned int sr) {
88     if (rt_watchdog_limit > 0) {
89 	if (gx_system::atomic_get(rt_watchdog_counter) > rt_watchdog_limit*(2*sr)/bs) {
90 	    return false;
91 	}
92 	gx_system::atomic_inc(&rt_watchdog_counter);
93     }
94     return true;
95 }
96 
97 
98 /****************************************************************
99  ** class MidiCC
100  */
101 
MidiCC(gx_engine::GxEngine & engine_)102 MidiCC::MidiCC(gx_engine::GxEngine& engine_)
103     : engine(engine_) {
104     for (int i = 0; i < max_midi_cc_cnt; i++) {
105         send_cc[i] = false;
106     }
107 }
108 
send_midi_cc(int _cc,int _pg,int _bgn,int _num)109 bool MidiCC::send_midi_cc(int _cc, int _pg, int _bgn, int _num) {
110     int c = engine.controller_map.get_midi_channel();
111     if (c) _cc |=c-1;
112     for(int i = 0; i < max_midi_cc_cnt; i++) {
113         if (send_cc[i].load(std::memory_order_acquire)) {
114             if (cc_num[i] == _cc && pg_num[i] == _pg &&
115                 bg_num[i] == _bgn && me_num[i] == _num)
116                 return true;
117         } else if (!send_cc[i].load(std::memory_order_acquire)) {
118             cc_num[i] = _cc;
119             pg_num[i] = _pg;
120             bg_num[i] = _bgn;
121             me_num[i] = _num;
122             send_cc[i].store(true, std::memory_order_release);
123             return true;
124         }
125     }
126 #ifndef NDEBUG
127     cerr << "Internal error: MidiCC overflow" << endl;
128     assert(false);
129 #endif
130     return false;
131 }
132 
133 /****************************************************************
134  ** GxJack ctor, dtor
135  */
136 
GxJack(gx_engine::GxEngine & engine_)137 GxJack::GxJack(gx_engine::GxEngine& engine_)
138     : sigc::trackable(),
139       engine(engine_),
140       jack_is_down(false),
141       jack_is_exit(true),
142       bypass_insert(false),
143       mmessage(engine_),
144 #ifdef HAVE_JACK_SESSION
145       session_event(0),
146       session_event_ins(0),
147       session_callback_seen(0),
148 #endif
149       connection_queue(),
150       connection_changed(),
151       buffersize_change(),
152       client_change_rt(),
153       client_change(),
154       client_instance(),
155       jack_sr(),
156       jack_bs(),
157       insert_buffer(NULL),
158       xrun(),
159       last_xrun(0),
160       xrun_msg_blocked(false),
161       ports(),
162       client(0),
163       client_insert(0),
164       client_name(),
165       client_insert_name(),
166       session(),
167       session_ins(),
168       shutdown(),
169       connection(),
170       single_client(false) {
171     connection_queue.new_data.connect(sigc::mem_fun(*this, &GxJack::fetch_connection_data));
172     client_change_rt.connect(client_change);
173     GxExit::get_instance().signal_exit().connect(
174 	sigc::mem_fun(*this, &GxJack::cleanup_slot));
175     xrun.connect(sigc::mem_fun(this, &GxJack::report_xrun));
176 }
177 
~GxJack()178 GxJack::~GxJack() {
179     gx_jack_cleanup();
180 }
181 
rt_watchdog_set_limit(int limit)182 void GxJack::rt_watchdog_set_limit(int limit) {
183     rt_watchdog_limit = limit;
184     if (limit > 0) {
185 	rt_watchdog_start();
186     }
187 }
188 
189 
190 /****************************************************************
191  ** load state, save state
192  */
193 
read_connections(gx_system::JsonParser & jp)194 void GxJack::read_connections(gx_system::JsonParser& jp) {
195     jp.next(gx_system::JsonParser::begin_object);
196     while (jp.peek() == gx_system::JsonParser::value_key) {
197         list<string> *i;
198         jp.next(gx_system::JsonParser::value_key);
199         if (jp.current_value() == "input") {
200             i = &ports.input.conn;
201         } else if (jp.current_value() == "output1") {
202             i = &ports.output1.conn;
203         } else if (jp.current_value() == "output2") {
204             i = &ports.output2.conn;
205         } else if (jp.current_value() == "midi_input") {
206             i = &ports.midi_input.conn;
207         } else if (jp.current_value() == "midi_output") {
208             i = &ports.midi_output.conn;
209         } else if (jp.current_value() == "insert_out") {
210             i = &ports.insert_out.conn;
211         } else if (jp.current_value() == "insert_in") {
212             i = &ports.insert_in.conn;
213         } else {
214 	    gx_print_warning(
215 		_("recall state"),
216 		_("unknown jack ports section: ") + jp.current_value());
217             jp.skip_object();
218             continue;
219         }
220 	i->clear();
221         jp.next(gx_system::JsonParser::begin_array);
222         while (jp.peek() == gx_system::JsonParser::value_string) {
223             jp.next();
224             i->push_back(jp.current_value());
225         }
226         jp.next(gx_system::JsonParser::end_array);
227     }
228     jp.next(gx_system::JsonParser::end_object);
229 }
230 
write_jack_port_connections(gx_system::JsonWriter & w,const char * key,const PortConnection & pc,bool replace)231 void GxJack::write_jack_port_connections(
232     gx_system::JsonWriter& w, const char *key, const PortConnection& pc, bool replace) {
233     w.write_key(key);
234     w.begin_array();
235     if (client && pc.port) {
236 	const char** pl = jack_port_get_connections(pc.port);
237 	if (pl) {
238 	    for (const char **p = pl; *p; p++) {
239 		if (replace) {
240 		    w.write(make_clientvar(*p));
241 		} else {
242 		    w.write(*p);
243 		}
244 	    }
245 	    free(pl);
246 	}
247     } else {
248 	for (list<string>::const_iterator i = pc.conn.begin(); i != pc.conn.end(); ++i) {
249 	    w.write(*i);
250 	}
251     }
252     w.end_array(true);
253 }
254 
write_connections(gx_system::JsonWriter & w)255 void GxJack::write_connections(gx_system::JsonWriter& w) {
256     w.begin_object(true);
257     write_jack_port_connections(w, "input", ports.input);
258     write_jack_port_connections(w, "output1", ports.output1);
259     write_jack_port_connections(w, "output2", ports.output2);
260     write_jack_port_connections(w, "midi_input", ports.midi_input);
261     write_jack_port_connections(w, "midi_output", ports.midi_output);
262     if (!single_client) {
263     write_jack_port_connections(w, "insert_out", ports.insert_out, true);
264     write_jack_port_connections(w, "insert_in", ports.insert_in, true);
265     }
266     w.end_object(true);
267 }
268 
269 
270 /****************************************************************
271  ** client connection init and cleanup
272  */
is_power_of_two(unsigned int x)273 int GxJack::is_power_of_two (unsigned int x)
274 {
275     return ((x != 0) && ((x & (~x + 1)) == x));
276 }
277 
278 // ----- pop up a dialog for starting jack
gx_jack_init(bool startserver,int wait_after_connect,const gx_system::CmdlineOptions & opt)279 bool GxJack::gx_jack_init(bool startserver, int wait_after_connect, const gx_system::CmdlineOptions& opt) {
280     AVOIDDENORMALS();
281     single_client = opt.get_jack_single();
282     int jackopt = (startserver ? JackNullOption : JackNoStartServer);
283     client_instance = opt.get_jack_instancename();
284     if (client_instance.empty()) {
285     if (!single_client) {
286         client_instance = get_default_instancename();
287     } else {
288         client_instance = "guitarix";
289     }
290     } else {
291 	jackopt |= JackUseExactName;
292     }
293 
294     std::string ServerName = opt.get_jack_servername();
295 
296     set_jack_down(false);
297     set_jack_exit(true);
298     engine.set_stateflag(gx_engine::GxEngine::SF_INITIALIZING);
299 
300     //ports = JackPorts(); //FIXME
301 
302     if (!single_client) {
303         client_name = client_instance + jack_amp_postfix;
304     } else {
305         client_name = client_instance;
306     }
307     client_insert_name = client_instance + jack_fx_postfix;
308     jack_status_t jackstat;
309 #ifdef HAVE_JACK_SESSION
310     // try to open jack gxjack.client
311     if (!opt.get_jack_uuid().empty()) {
312         client = jack_client_open(
313 	    client_name.c_str(), JackOptions(jackopt | JackSessionID),
314 	    &jackstat, opt.get_jack_uuid().c_str());
315     } else {
316         if (ServerName.empty()) {
317         client = jack_client_open(client_name.c_str(), JackOptions(jackopt), &jackstat);
318         } else {
319         client = jack_client_open(client_name.c_str(), JackOptions(jackopt | JackServerName),
320         &jackstat, ServerName.c_str());
321         }
322     }
323 #else
324     if (ServerName.empty()) {
325     client = jack_client_open(client_name.c_str(), JackOptions(jackopt), &jackstat);
326     } else {
327     client = jack_client_open(client_name.c_str(), JackOptions(jackopt | JackServerName),
328     &jackstat, ServerName.c_str());
329     }
330 #endif
331     // ----- only start the insert gxjack.client when the amp gxjack.client is true
332     if (client && !single_client) {
333 	// it is maybe not the 1st gx_head instance ?
334 	// session handler can change name without setting JackNameNotUnique in return status; jack bug??
335 	// this code depends on jackd only appending a suffix to make a client name unique
336 	std::string name = jack_get_client_name(client);
337 	std::string generated_suffix = name.substr(client_name.size());
338 	std::string base = name.substr(0, client_name.size()-strlen(jack_amp_postfix));
339 	client_instance = base + generated_suffix;
340 	client_name = name;
341 	client_insert_name = base + jack_fx_postfix + generated_suffix;
342 #ifdef HAVE_JACK_SESSION
343         if (!opt.get_jack_uuid2().empty()) {
344             client_insert = jack_client_open(
345 		client_insert_name.c_str(),
346 		JackOptions(jackopt | JackSessionID | JackUseExactName),
347 		&jackstat, opt.get_jack_uuid2().c_str());
348         } else {
349             if (ServerName.empty()) {
350             client_insert = jack_client_open(
351 		client_insert_name.c_str(),
352 		JackOptions(jackopt | JackUseExactName ), &jackstat);
353         } else {
354             client_insert = jack_client_open(
355 		client_insert_name.c_str(),
356 		JackOptions(jackopt | JackUseExactName | JackServerName),
357         &jackstat, ServerName.c_str());
358         }
359         }
360 #else
361         if (ServerName.empty()) {
362         client_insert = jack_client_open(
363 	    client_insert_name.c_str(),
364 	    JackOptions(jackopt | JackUseExactName), &jackstat);
365         } else {
366         client_insert = jack_client_open(
367 	    client_insert_name.c_str(),
368 	    JackOptions(jackopt | JackUseExactName | JackServerName),
369         &jackstat, ServerName.c_str());
370         }
371 #endif
372 	if (!client_insert) {
373 	    jack_client_close(client);
374 	    client = 0;
375 	}
376     }
377 
378     if (!client) {
379 	if (!(jackstat & JackServerFailed)) {
380 	    if ((jackstat & JackServerError) && (jackopt & JackUseExactName)) {
381 		gx_print_error(
382 		    _("Jack Init"),
383 		    boost::format(_("can't get requested jack instance name '%1%'"))
384 		    % client_instance);
385 	    } else {
386 		gx_print_error(
387 		    _("Jack Init"),
388 		    _("unknown jack server communication error"));
389 	    }
390 	}
391 	return false;
392     }
393 
394     // ----------------------------------
395     set_jack_down(false);
396 
397     if (wait_after_connect) {
398 	usleep(wait_after_connect);
399     }
400     jack_sr = jack_get_sample_rate(client); // jack sample rate
401     gx_print_info(
402 	_("Jack init"),
403 	boost::format(_("The jack sample rate is %1%/sec")) % jack_sr);
404 
405     jack_bs = jack_get_buffer_size(client); // jack buffer size
406 	if (!is_power_of_two(jack_bs)) {
407     gx_print_warning(
408 	_("Jack init"),
409 	boost::format(_("The jack buffer size is %1%/frames is not power of two, Convolver won't run"))
410 	% jack_bs);
411 	} else {
412     gx_print_info(
413 	_("Jack init"),
414 	boost::format(_("The jack buffer size is %1%/frames ... "))
415 	% jack_bs);
416 	}
417 
418 	// create buffer to bypass the insert ports
419     insert_buffer = new float[jack_bs];
420 
421     gx_jack_callbacks();
422     client_change(); // might load port connection definitions
423     if (opt.get_jack_uuid().empty() && !opt.get_jack_noconnect()) {
424 	// when not loaded by session manager
425 	gx_jack_init_port_connection(opt);
426     }
427     set_jack_exit(false);
428 	if (jack_sr > 96000) {
429     gx_print_fatal(
430 		    _("Jack Init"),
431 		    _("Sample rates above 96kHz ain't be supported"));
432 		return false;
433 	}
434     return true;
435 }
436 
cleanup_slot(bool otherthread)437 void GxJack::cleanup_slot(bool otherthread) {
438     if (!otherthread) {
439 	gx_jack_cleanup();
440     } else {
441 	// called from other thread. Since most cleanup functions are
442 	// not thread safe, just do minimal jack cleanup
443 	if (client) {
444 	    if (!is_jack_down()) {
445 		engine.start_ramp_down();
446 		engine.wait_ramp_down_finished();
447 	    }
448 	    jack_deactivate(client);
449 	    jack_client_close(client);
450 	    client = 0;
451 	}
452 	if (client_insert) {
453 	    jack_deactivate(client_insert);
454 	    jack_client_close(client_insert);
455 	    client_insert = 0;
456 	}
457     }
458 }
459 
460 // -----Function that cleans the jack stuff on shutdown
gx_jack_cleanup()461 void GxJack::gx_jack_cleanup() {
462     if (!client || is_jack_down()) {
463 	return;
464     }
465     engine.start_ramp_down();
466     engine.wait_ramp_down_finished();
467     set_jack_exit(true);
468     engine.set_stateflag(gx_engine::GxEngine::SF_INITIALIZING);
469     jack_deactivate(client);
470     if (!single_client) jack_deactivate(client_insert);
471     jack_port_unregister(client, ports.input.port);
472     jack_port_unregister(client, ports.midi_input.port);
473     if (!single_client) {
474         jack_port_unregister(client, ports.insert_out.port);
475     } else {
476         jack_port_unregister(client, ports.output1.port);
477         jack_port_unregister(client, ports.output2.port);
478     }
479 #if defined(USE_MIDI_OUT) || defined(USE_MIDI_CC_OUT)
480     jack_port_unregister(client, ports.midi_output.port);
481 #endif
482     if (!single_client) {
483         jack_port_unregister(client_insert, ports.insert_in.port);
484         jack_port_unregister(client_insert, ports.output1.port);
485         jack_port_unregister(client_insert, ports.output2.port);
486     }
487     jack_client_close(client);
488     client = 0;
489     if (!single_client) jack_client_close(client_insert);
490     client_insert = 0;
491     delete[] insert_buffer;
492     insert_buffer = NULL;
493     client_change();
494 }
495 
496 // ---- Jack server connection / disconnection
gx_jack_connection(bool connect,bool startserver,int wait_after_connect,const gx_system::CmdlineOptions & opt)497 bool GxJack::gx_jack_connection(bool connect, bool startserver, int wait_after_connect, const gx_system::CmdlineOptions& opt) {
498     if (connect) {
499 	if (client) {
500 	    return true;
501 	}
502 	if (!gx_jack_init(startserver, wait_after_connect, opt)) {
503 	    return false;
504 	}
505 	engine.set_rack_changed();
506 	engine.clear_stateflag(gx_engine::GxEngine::SF_INITIALIZING);
507     } else {
508 	if (!client) {
509 	    return true;
510 	}
511 	gx_jack_cleanup();
512     }
513     connection();
514     connection_queue.portchange();
515     return true;
516 }
517 
518 
519 /****************************************************************
520  ** port connections
521  */
522 
make_clientvar(const std::string & s)523 std::string GxJack::make_clientvar(const std::string& s) {
524     std::size_t n = s.find(':');
525     if (n == s.npos) {
526 	return s; // no ':' in jack port name??
527     }
528     if (s.compare(0, n, client_name) == 0) {
529 	return "%A" + s.substr(n);
530     }
531     if (s.compare(0, n, client_insert_name) == 0) {
532 	return "%F" + s.substr(n);
533     }
534     return s;
535 }
536 
replace_clientvar(const std::string & s)537 std::string GxJack::replace_clientvar(const std::string& s) {
538     if (s.compare(0, 3, "%A:") == 0) {
539 	return client_name + s.substr(2);
540     }
541     if (s.compare(0, 3, "%F:") == 0) {
542 	return client_insert_name + s.substr(2);
543     }
544     return s;
545 }
546 
547 // ----- connect ports if we know them
gx_jack_init_port_connection(const gx_system::CmdlineOptions & opt)548 void GxJack::gx_jack_init_port_connection(const gx_system::CmdlineOptions& opt) {
549     // set autoconnect capture to user capture port
550     if (!opt.get_jack_input().empty()) {
551         jack_connect(client, opt.get_jack_input().c_str(),
552                      jack_port_name(ports.input.port));
553     } else {
554         list<string>& l = ports.input.conn;
555         for (list<string>::iterator i = l.begin(); i != l.end(); ++i) {
556             jack_connect(client, i->c_str(), jack_port_name(ports.input.port));
557         }
558     }
559 
560     // set autoconnect midi to user midi port
561     if (ports.midi_input.port && !opt.get_jack_midi().empty()) {
562         jack_connect(client, opt.get_jack_midi().c_str(),
563                      jack_port_name(ports.midi_input.port));
564     } else {
565         list<string>& l = ports.midi_input.conn;
566         for (list<string>::iterator i = l.begin(); i != l.end(); ++i) {
567             jack_connect(client, i->c_str(), jack_port_name(ports.midi_input.port));
568         }
569     }
570 
571     if (!single_client) {
572     // set autoconnect to user playback ports
573     if (opt.get_jack_output(0).empty() && opt.get_jack_output(1).empty()) {
574         list<string>& l1 = ports.output1.conn;
575         for (list<string>::iterator i = l1.begin(); i != l1.end(); ++i) {
576             jack_connect(client_insert, jack_port_name(ports.output1.port), i->c_str());
577         }
578         list<string>& l2 = ports.output2.conn;
579         for (list<string>::iterator i = l2.begin(); i != l2.end(); ++i) {
580             jack_connect(client_insert, jack_port_name(ports.output2.port), i->c_str());
581         }
582     } else {
583 	if (!opt.get_jack_output(0).empty()) {
584 	    jack_connect(client_insert,
585 			 jack_port_name(ports.output1.port),
586 			 opt.get_jack_output(0).c_str());
587 	}
588 	if (!opt.get_jack_output(1).empty()) {
589 	    jack_connect(client_insert,
590 			 jack_port_name(ports.output2.port),
591 			 opt.get_jack_output(1).c_str());
592 	}
593     }
594 
595     } else {
596 // set autoconnect to user playback ports
597     if (opt.get_jack_output(0).empty() && opt.get_jack_output(1).empty()) {
598         list<string>& l1 = ports.output1.conn;
599         for (list<string>::iterator i = l1.begin(); i != l1.end(); ++i) {
600             jack_connect(client, jack_port_name(ports.output1.port), i->c_str());
601         }
602         list<string>& l2 = ports.output2.conn;
603         for (list<string>::iterator i = l2.begin(); i != l2.end(); ++i) {
604             jack_connect(client, jack_port_name(ports.output2.port), i->c_str());
605         }
606     } else {
607 	if (!opt.get_jack_output(0).empty()) {
608 	    jack_connect(client,
609 			 jack_port_name(ports.output1.port),
610 			 opt.get_jack_output(0).c_str());
611 	}
612 	if (!opt.get_jack_output(1).empty()) {
613 	    jack_connect(client,
614 			 jack_port_name(ports.output2.port),
615 			 opt.get_jack_output(1).c_str());
616 	}
617     }
618 
619     }
620 
621 #if defined(USE_MIDI_OUT) || defined(USE_MIDI_CC_OUT)
622     // autoconnect midi output port
623     list<string>& lmo = ports.midi_output.conn;
624     for (list<string>::iterator i = lmo.begin(); i != lmo.end(); ++i) {
625         jack_connect(client, jack_port_name(ports.midi_output.port), i->c_str());
626     }
627 #endif
628 
629     if (!single_client) {
630     // autoconnect to insert ports
631     list<string>& lins_in = ports.insert_in.conn;
632     list<string>& lins_out = ports.insert_out.conn;
633     bool ifound = false, ofound = false;
634     for (list<string>::iterator i = lins_in.begin(); i != lins_in.end(); ++i) {
635         int rc = jack_connect(client_insert, replace_clientvar(*i).c_str(),
636                               jack_port_name(ports.insert_in.port));
637         if (rc == 0 || rc == EEXIST) {
638             ifound = true;
639         }
640     }
641     jack_port_t* port_a = jack_port_by_name(client, jack_port_name(ports.insert_out.port));
642     for (list<string>::iterator i = lins_out.begin(); i != lins_out.end(); ++i) {
643 	std::string port = replace_clientvar(*i);
644 	if (!jack_port_connected_to(port_a, port.c_str())) {
645 	    int rc = jack_connect(client, jack_port_name(ports.insert_out.port),
646 				  port.c_str());
647 	    if (rc == 0 || rc == EEXIST) {
648 		ofound = true;
649 	    }
650 	} else {
651 	    ofound = true;
652 	}
653     }
654     if (!ifound || !ofound) {
655         jack_connect(client_insert, jack_port_name(ports.insert_out.port),
656 		     (client_insert_name+":in_0").c_str());
657     }
658     }
659 }
660 
661 
662 /****************************************************************
663  ** callback installation and port registration
664  */
665 
666 // ----- set gxjack.client callbacks and activate gxjack.client
gx_jack_callbacks()667 void GxJack::gx_jack_callbacks() {
668     // ----- set the jack callbacks
669     jack_set_xrun_callback(client, gx_jack_xrun_callback, this);
670     jack_set_sample_rate_callback(client, gx_jack_srate_callback, this);
671     jack_on_shutdown(client, shutdown_callback_client, this);
672     if (!single_client) {
673         jack_on_shutdown(client_insert, shutdown_callback_client_insert, this);
674     }
675     jack_set_buffer_size_callback(client, gx_jack_buffersize_callback, this);
676     jack_set_port_registration_callback(client, gx_jack_portreg_callback, this);
677     jack_set_port_connect_callback(client, gx_jack_portconn_callback, this);
678 #ifdef HAVE_JACK_SESSION
679     if (jack_set_session_callback_fp) {
680         jack_set_session_callback_fp(client, gx_jack_session_callback, this);
681         if (!single_client) jack_set_session_callback_fp(client_insert, gx_jack_session_callback_ins, this);
682     }
683 #endif
684 
685     // register ports for gx_amp
686     ports.input.port = jack_port_register(
687 	client, "in_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
688     ports.midi_input.port = jack_port_register(
689 	client, "midi_in_1", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
690     if (!single_client) {
691         ports.insert_out.port = jack_port_register(
692         client, "out_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
693     } else {
694         ports.output1.port = jack_port_register(
695         client, "out_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
696         ports.output2.port = jack_port_register(
697         client, "out_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
698     }
699 #if defined(USE_MIDI_OUT) || defined(USE_MIDI_CC_OUT)
700     ports.midi_output.port = jack_port_register(
701 	client, "midi_out_1", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
702 #else
703     ports.midi_output.port = 0;
704 #endif
705 
706     if (!single_client) {
707     // register ports for gx_amp_fx
708         ports.insert_in.port = jack_port_register(
709           client_insert, "in_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
710         ports.output1.port = jack_port_register(
711           client_insert, "out_0", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
712         ports.output2.port = jack_port_register(
713           client_insert, "out_1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
714     }
715 
716     engine.init(jack_sr, jack_bs, SCHED_FIFO,
717 		jack_client_real_time_priority(client));
718     jack_set_process_callback(client, gx_jack_process, this);
719     if (!single_client) jack_set_process_callback(client_insert, gx_jack_insert_process, this);
720     if (jack_activate(client) != 0) {
721         gx_print_fatal(
722 	    _("Jack Activation"),
723 	    string(_("Can't activate JACK gx_amp client")));
724     }
725     if (!single_client) {
726         if (jack_activate(client_insert) != 0) {
727             gx_print_fatal(_("Jack Activation"),
728                         string(_("Can't activate JACK gx_amp_fx client")));
729         }
730     }
731 }
732 
733 
734 /****************************************************************
735  ** jack process callbacks
736  */
737 
process_midi_cc(void * buf,jack_nframes_t nframes)738 void __rt_func GxJack::process_midi_cc(void *buf, jack_nframes_t nframes) {
739     // midi CC output processing
740     for (int i = mmessage.next(); i >= 0; i = mmessage.next(i)) {
741         unsigned char* midi_send = jack_midi_event_reserve(buf, i, mmessage.size(i));
742         if (midi_send) {
743             mmessage.fill(midi_send, i);
744         }
745     }
746 }
747 
748 // must only be used inside gx_jack_process
get_midi_buffer(jack_nframes_t nframes)749 void *GxJack::get_midi_buffer(jack_nframes_t nframes) {
750     if (!ports.midi_output.port) {
751 	return 0;
752     }
753     void *midi_port_buf = jack_port_get_buffer(ports.midi_output.port, nframes);
754     if (midi_port_buf) {
755 	jack_midi_clear_buffer(midi_port_buf);
756     }
757     return midi_port_buf;
758 }
759 
get_float_buf(jack_port_t * port,jack_nframes_t nframes)760 static inline float *get_float_buf(jack_port_t *port, jack_nframes_t nframes) {
761     return static_cast<float *>(jack_port_get_buffer(port, nframes));
762 }
763 
check_overload()764 inline void GxJack::check_overload() {
765     if (!rt_watchdog_check_alive(jack_bs, jack_sr)) {
766 	engine.overload(gx_engine::EngineControl::ov_User, "watchdog thread");
767     }
768 }
769 
770 // ----- main jack process method gx_amp, mono -> mono
771 // RT process thread
gx_jack_process(jack_nframes_t nframes,void * arg)772 int __rt_func GxJack::gx_jack_process(jack_nframes_t nframes, void *arg) {
773     gx_system::measure_start();
774     GxJack& self = *static_cast<GxJack*>(arg);
775     if (!self.is_jack_exit()) {
776 	if (!self.engine.mono_chain.is_stopped()) {
777 	    self.check_overload();
778 	}
779 	self.transport_state = jack_transport_query (self.client, &self.current);
780         // gx_head DSP computing
781     float *obuf = self.insert_buffer;
782     if (!self.single_client) {
783         obuf = get_float_buf(self.ports.insert_out.port, nframes);
784     }
785 	self.engine.mono_chain.process(
786 	    nframes,
787 	    get_float_buf(self.ports.input.port, nframes),
788 	    obuf);
789 
790     if (self.bypass_insert && !self.single_client) {
791         memcpy(self.insert_buffer, obuf, nframes*sizeof(float));
792     }
793 
794         // midi input processing
795 	if (self.ports.midi_input.port) {
796 	    self.engine.controller_map.compute_midi_in(
797 		jack_port_get_buffer(self.ports.midi_input.port, nframes), arg);
798 	}
799         // jack transport support
800     if ( self.transport_state != self.old_transport_state) {
801         self.engine.controller_map.process_trans(self.transport_state);
802         self.old_transport_state = self.transport_state;
803     }
804     }
805     // midi CC output processing
806     void *buf = self.get_midi_buffer(nframes);
807     self.process_midi_cc(buf, nframes);
808 
809     gx_system::measure_pause();
810     self.engine.mono_chain.post_rt_finished();
811     if (self.single_client) {
812         self.gx_jack_insert_process(nframes, arg);
813     }
814     return 0;
815 }
816 
817 // ----- main jack process method, gx_fx_amp, mono -> stereo
818 // RT process_insert thread
gx_jack_insert_process(jack_nframes_t nframes,void * arg)819 int __rt_func GxJack::gx_jack_insert_process(jack_nframes_t nframes, void *arg) {
820     GxJack& self = *static_cast<GxJack*>(arg);
821     gx_system::measure_cont();
822     if (!self.is_jack_exit()) {
823 	if (!self.engine.stereo_chain.is_stopped()) {
824 	    self.check_overload();
825 	}
826         // gx_head DSP computing
827     float *ibuf = NULL;
828     if (!self.bypass_insert && !self.single_client) {
829 	    ibuf = get_float_buf(self.ports.insert_in.port, nframes);
830 	} else {
831 	    ibuf = self.insert_buffer;
832 	}
833 	self.engine.stereo_chain.process(
834 	    nframes, ibuf, ibuf,
835 	    get_float_buf(self.ports.output1.port, nframes),
836 	    get_float_buf(self.ports.output2.port, nframes));
837     }
838     gx_system::measure_stop();
839     self.engine.stereo_chain.post_rt_finished();
840     return 0;
841 }
842 
843 
844 /****************************************************************
845  ** port connection callback
846  */
847 
PortConnRing()848 PortConnRing::PortConnRing()
849     : ring(jack_ringbuffer_create(20*sizeof(PortConnData))), // just a number...
850       send_changes(false),
851       overflow(false),
852       new_data(),
853       portchange() {
854     if (!ring) {
855 	gx_print_fatal(
856 	    _("Jack init"), _("can't get memory for ringbuffer"));
857     }
858     jack_ringbuffer_mlock(ring);
859 }
860 
~PortConnRing()861 PortConnRing::~PortConnRing() {
862     jack_ringbuffer_free(ring);
863 }
864 
push(const char * a,const char * b,bool conn)865 void PortConnRing::push(const char *a, const char *b, bool conn) {
866     if (is_overflow()) {
867 	return;
868     }
869     if (send_changes) {
870 	PortConnData p(a, b, conn);
871 	size_t sz = jack_ringbuffer_write(ring, reinterpret_cast<const char*>(&p), sizeof(p));
872 	if (sz != sizeof(p)) {
873 	    set_overflow();
874 	} else {
875 	    jack_ringbuffer_write_advance(ring, sz);
876 	}
877     }
878     new_data();
879 }
880 
pop(PortConnData * p)881 bool PortConnRing::pop(PortConnData *p) {
882     if (is_overflow()) {
883 	jack_ringbuffer_reset(ring);
884 	portchange();
885 	clear_overflow();
886 	return false;
887     }
888     size_t sz = jack_ringbuffer_read(ring, reinterpret_cast<char*>(p), sizeof(*p));
889     if (sz == 0) {
890 	return false;
891     }
892     assert(sz == sizeof(*p));
893     jack_ringbuffer_read_advance(ring, sz);
894     return true;
895 }
896 
fetch_connection_data()897 void GxJack::fetch_connection_data() {
898     // check if we are connected
899     if (client) {
900 	const char** port = jack_port_get_connections(ports.input.port);
901 	if (port) { // might be 0 (e.g. due to race conditions)
902 	    engine.clear_stateflag(gx_engine::GxEngine::SF_NO_CONNECTION);
903 	    free(port);
904 	} else {
905 	    engine.set_stateflag(gx_engine::GxEngine::SF_NO_CONNECTION);
906 	}
907     }
908     while (true) {
909 	PortConnData p;
910 	bool fetched = connection_queue.pop(&p);
911 	if (!fetched) {
912 	    break;
913 	}
914 	if (client) {
915 	    connection_changed(p.name_a, p.name_b, p.connect);
916 	}
917     }
918 }
919 
920 // jackd1: RT process thread
921 // jackd2: not RT thread
gx_jack_portconn_callback(jack_port_id_t a,jack_port_id_t b,int connect,void * arg)922 void GxJack::gx_jack_portconn_callback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg) {
923     GxJack& self = *static_cast<GxJack*>(arg);
924     if (!self.client) {
925 	return;
926     }
927     jack_port_t* port_a = jack_port_by_id(self.client, a);
928     jack_port_t* port_b = jack_port_by_id(self.client, b);
929     if (!port_a || !port_b) {
930         return;
931     }
932     self.connection_queue.push(jack_port_name(port_a), jack_port_name(port_b), connect);
933 }
934 
935 
936 /****************************************************************
937  ** callbacks: portreg, buffersize, samplerate, shutdown, xrun
938  */
939 
940 // ----- fetch available jack ports other than gx_head ports
941 // jackd1: RT process thread
942 // jackd2: not RT thread
gx_jack_portreg_callback(jack_port_id_t pid,int reg,void * arg)943 void GxJack::gx_jack_portreg_callback(jack_port_id_t pid, int reg, void* arg) {
944     GxJack& self = *static_cast<GxJack*>(arg);
945     if (!self.client) {
946         return;
947     }
948     jack_port_t* port = jack_port_by_id(self.client, pid);
949     if (!port || jack_port_is_mine(self.client, port)) {
950         return;
951     }
952     self.connection_queue.portchange();
953 }
954 
955 // ----jack sample rate change callback
956 // seems to be run in main thread (just once, no possibility
957 // to change the samplerate when jack is running?)
gx_jack_srate_callback(jack_nframes_t samplerate,void * arg)958 int GxJack::gx_jack_srate_callback(jack_nframes_t samplerate, void* arg) {
959     GxJack& self = *static_cast<GxJack*>(arg);
960     if (self.jack_sr == samplerate) {
961 	return 0;
962     }
963     self.engine.set_stateflag(gx_engine::GxEngine::SF_JACK_RECONFIG);
964     self.jack_sr = samplerate;
965     self.engine.set_samplerate(samplerate);
966     self.engine.clear_stateflag(gx_engine::GxEngine::SF_JACK_RECONFIG);
967     return 0;
968 }
969 
970 // ---- jack buffer size change callback
971 // RT process thread
gx_jack_buffersize_callback(jack_nframes_t nframes,void * arg)972 int GxJack::gx_jack_buffersize_callback(jack_nframes_t nframes, void* arg) {
973     GxJack& self = *static_cast<GxJack*>(arg);
974     if (self.jack_bs == nframes) {
975 	return 0;
976     }
977     self.engine.set_stateflag(gx_engine::GxEngine::SF_JACK_RECONFIG);
978     self.jack_bs = nframes;
979     self.engine.set_buffersize(nframes);
980     self.engine.clear_stateflag(gx_engine::GxEngine::SF_JACK_RECONFIG);
981     self.buffersize_change();
982 	// create buffer to bypass the insert ports
983 	delete[] self.insert_buffer;
984 	self.insert_buffer = NULL;
985     self.insert_buffer = new float[self.jack_bs];
986     return 0;
987 }
988 
989 // ---- jack shutdown callback in case jackd shuts down on us
gx_jack_shutdown_callback()990 void GxJack::gx_jack_shutdown_callback() {
991     set_jack_exit(true);
992     engine.set_stateflag(gx_engine::GxEngine::SF_INITIALIZING);
993     shutdown();
994 }
995 
shutdown_callback_client(void * arg)996 void GxJack::shutdown_callback_client(void *arg) {
997     GxJack& self = *static_cast<GxJack*>(arg);
998     if (self.client) {
999 	self.client = 0;
1000 	self.client_change_rt();
1001     }
1002     if (!self.single_client) {
1003     if (self.client_insert) {
1004 	jack_client_close(self.client_insert);
1005 	self.client_insert = 0;
1006     }
1007     }
1008     self.gx_jack_shutdown_callback();
1009 }
1010 
shutdown_callback_client_insert(void * arg)1011 void GxJack::shutdown_callback_client_insert(void *arg) {
1012     GxJack& self = *static_cast<GxJack*>(arg);
1013     self.client_insert = 0;
1014     if (self.client) {
1015 	jack_client_close(self.client);
1016 	self.client = 0;
1017 	self.client_change_rt();
1018     }
1019     self.gx_jack_shutdown_callback();
1020 }
1021 
report_xrun_clear()1022 void GxJack::report_xrun_clear() {
1023     xrun_msg_blocked = false;
1024 }
1025 
report_xrun()1026 void GxJack::report_xrun() {
1027     if (xrun_msg_blocked) {
1028 	return;
1029     }
1030     xrun_msg_blocked = true;
1031     Glib::signal_timeout().connect_once(
1032 	sigc::mem_fun(this, &GxJack::report_xrun_clear), 100);
1033     gx_print_warning(
1034 	_("Jack XRun"),
1035 	(boost::format(_(" delay of at least %1% microsecs")) % last_xrun).str());
1036 }
1037 
1038 // ---- jack xrun callback
gx_jack_xrun_callback(void * arg)1039 int GxJack::gx_jack_xrun_callback(void* arg) {
1040     GxJack& self = *static_cast<GxJack*>(arg);
1041     if (!self.client) {
1042 	return 0;
1043     }
1044     self.last_xrun = jack_get_xrun_delayed_usecs(self.client);
1045     if (!self.engine.mono_chain.is_stopped()) {
1046 	self.engine.overload(gx_engine::EngineControl::ov_XRun, "xrun");
1047     }
1048     self.xrun();
1049     return 0;
1050 }
1051 
1052 /****************************************************************
1053  ** jack session
1054  */
1055 
1056 #ifdef HAVE_JACK_SESSION
1057 jack_set_session_callback_type GxJack::jack_set_session_callback_fp =
1058     reinterpret_cast<jack_set_session_callback_type>(
1059 	dlsym(RTLD_DEFAULT, "jack_set_session_callback"));
1060 jack_get_uuid_for_client_name_type GxJack::jack_get_uuid_for_client_name_fp =
1061     reinterpret_cast<jack_get_uuid_for_client_name_type>(
1062 	dlsym(RTLD_DEFAULT, "jack_get_uuid_for_client_name"));
1063 jack_client_get_uuid_type GxJack::jack_client_get_uuid_fp =
1064     reinterpret_cast<jack_client_get_uuid_type>(
1065 	dlsym(RTLD_DEFAULT, "jack_client_get_uuid"));
1066 
return_last_session_event()1067 int GxJack::return_last_session_event() {
1068     jack_session_event_t *event = get_last_session_event();
1069     if (event) {
1070 	session_callback_seen += 1;
1071 	jack_session_reply(client, event);
1072 	jack_session_event_free(event);
1073 	gx_system::atomic_set_0(&session_event);
1074     }
1075     return session_callback_seen;
1076 }
1077 
return_last_session_event_ins()1078 int GxJack::return_last_session_event_ins() {
1079     jack_session_event_t *event = get_last_session_event_ins();
1080     if (event) {
1081 	session_callback_seen -= 1;
1082 	jack_session_reply(client_insert, event);
1083 	jack_session_event_free(event);
1084 	gx_system::atomic_set_0(&session_event_ins);
1085     }
1086     return session_callback_seen;
1087 }
1088 
get_uuid_insert()1089 string GxJack::get_uuid_insert() {
1090     // should be const char* but jack_free doesn't like it
1091     char* uuid;
1092     if (jack_client_get_uuid_fp) {
1093 	uuid = jack_client_get_uuid_fp(client_insert);
1094     } else if (jack_get_uuid_for_client_name_fp) {
1095 	uuid = jack_get_uuid_for_client_name_fp(
1096 	    client_insert, client_insert_name.c_str());
1097     } else {
1098 	assert(false);
1099 	gx_print_error(_("session save"), _("can't get client uuid"));
1100 	return "";
1101     }
1102     string ret(uuid);
1103     jack_free(uuid);
1104     return ret;
1105 }
1106 
gx_jack_session_callback(jack_session_event_t * event,void * arg)1107 void GxJack::gx_jack_session_callback(jack_session_event_t *event, void *arg) {
1108     GxJack& self = *static_cast<GxJack*>(arg);
1109     jack_session_event_t *np = 0;
1110     if (!gx_system::atomic_compare_and_exchange(&self.session_event, np, event)) {
1111 	gx_print_error("jack","last session not cleared");
1112 	return;
1113     }
1114     self.session();
1115 }
1116 
gx_jack_session_callback_ins(jack_session_event_t * event,void * arg)1117 void GxJack::gx_jack_session_callback_ins(jack_session_event_t *event, void *arg) {
1118     GxJack& self = *static_cast<GxJack*>(arg);
1119     jack_session_event_t *np = 0;
1120     if (!gx_system::atomic_compare_and_exchange(&self.session_event_ins, np, event)) {
1121 	gx_print_error("jack","last session not cleared");
1122 	return;
1123     }
1124     self.session_ins();
1125 }
1126 #endif
1127 
1128 } /* end of gx_jack namespace */
1129