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