Guitarix
gx_jack.h
Go to the documentation of this file.
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 
21 /* ------- This is the JACK namespace ------- */
22 
23 #pragma once
24 
25 #ifndef SRC_HEADERS_GX_JACK_H_
26 #define SRC_HEADERS_GX_JACK_H_
27 
28 #include <atomic>
29 
30 #ifndef GUITARIX_AS_PLUGIN
31 
32 #include <jack/jack.h> // NOLINT
33 #include <jack/midiport.h>
34 #include <jack/ringbuffer.h>
35 
36 #ifdef HAVE_JACK_SESSION
37 #include <jack/session.h>
38 #endif
39 
40 namespace gx_engine {
41 class GxEngine;
42 }
43 
44 namespace gx_jack {
45 
46 /****************************************************************
47  ** port connection callback
48  */
49 
50 struct PortConnData {
51 public:
52  PortConnData() {} // no init
53  PortConnData(const char *a, const char *b, bool conn)
54  : name_a(a), name_b(b), connect(conn) {}
56  const char *name_a;
57  const char *name_b;
58  bool connect;
59 };
60 
61 class PortConnRing {
62 private:
63  jack_ringbuffer_t *ring;
65  int overflow; // should be bool but gives compiler error
69 public:
70  Glib::Dispatcher new_data;
71  Glib::Dispatcher portchange;
72  void push(const char *a, const char *b, bool conn);
73  bool pop(PortConnData*);
74  void set_send(bool v) { send_changes = v; }
77 };
78 
79 
80 /****************************************************************
81  ** class GxJack
82  */
83 
85 public:
86  jack_port_t *port;
87  list<string> conn;
88 };
89 
90 class JackPorts {
91 public:
99 };
100 
101 #ifdef HAVE_JACK_SESSION
102 extern "C" {
103  typedef int (*jack_set_session_callback_type)(
104  jack_client_t *, JackSessionCallback, void *arg);
105  typedef char *(*jack_get_uuid_for_client_name_type)(
106  jack_client_t *, const char *);
107  typedef char *(*jack_client_get_uuid_type)(jack_client_t *);
108 }
109 #endif
110 
111 
112 class MidiCC {
113 private:
115  static const int max_midi_cc_cnt = 25;
116  std::atomic<bool> send_cc[max_midi_cc_cnt];
121 public:
123  bool send_midi_cc(int _cc, int _pg, int _bgn, int _num);
124  inline int next(int i = -1) const;
125  inline int size(int i) const { return me_num[i]; }
126  inline void fill(unsigned char *midi_send, int i);
127 };
128 
129 inline int MidiCC::next(int i) const {
130  while (++i < max_midi_cc_cnt) {
131  if (send_cc[i].load(std::memory_order_acquire)) {
132  return i;
133  }
134  }
135  return -1;
136 }
137 
138 inline void MidiCC::fill(unsigned char *midi_send, int i) {
139  if (size(i) == 3) {
140  midi_send[2] = bg_num[i];
141  }
142  midi_send[1] = pg_num[i]; // program value
143  midi_send[0] = cc_num[i]; // controller+ channel
144  send_cc[i].store(false, std::memory_order_release);
145 }
146 
147 class GxJack: public sigc::trackable {
148  private:
154  static int gx_jack_srate_callback(jack_nframes_t, void* arg);
155  static int gx_jack_xrun_callback(void* arg);
156  static int gx_jack_buffersize_callback(jack_nframes_t, void* arg);
157  static int gx_jack_process(jack_nframes_t, void* arg);
158  static int gx_jack_insert_process(jack_nframes_t, void* arg);
159 
160  static void shutdown_callback_client(void* arg);
161  static void shutdown_callback_client_insert(void* arg);
163  static void gx_jack_portreg_callback(jack_port_id_t, int, void* arg);
164  static void gx_jack_portconn_callback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg);
165 #ifdef HAVE_JACK_SESSION
166  jack_session_event_t *session_event;
167  jack_session_event_t *session_event_ins;
168  int session_callback_seen;
169  static void gx_jack_session_callback(jack_session_event_t *event, void *arg);
170  static void gx_jack_session_callback_ins(jack_session_event_t *event, void *arg);
171  static jack_set_session_callback_type jack_set_session_callback_fp;
172  static jack_get_uuid_for_client_name_type jack_get_uuid_for_client_name_fp;
173  static jack_client_get_uuid_type jack_client_get_uuid_fp;
174 #endif
175  void cleanup_slot(bool otherthread);
178  sigc::signal<void,string,string,bool> connection_changed;
179  Glib::Dispatcher buffersize_change;
180 
181  Glib::Dispatcher client_change_rt;
182  sigc::signal<void> client_change;
184  jack_nframes_t jack_sr; // jack sample rate
185  jack_nframes_t jack_bs; // jack buffer size
187  Glib::Dispatcher xrun;
188  float last_xrun;
191  void report_xrun();
193  gx_system::JsonWriter& w, const char *key, const PortConnection& pc, bool replace=false);
194  std::string make_clientvar(const std::string& s);
195  std::string replace_clientvar(const std::string& s);
196  int is_power_of_two (unsigned int x);
197  bool gx_jack_init(bool startserver, int wait_after_connect,
198  const gx_system::CmdlineOptions& opt);
202  inline void check_overload();
203  void process_midi_cc(void *buf, jack_nframes_t nframes);
204 
205  public:
207 
208  jack_client_t* client;
209  jack_client_t* client_insert;
210 
211  jack_position_t current;
212  jack_transport_state_t transport_state;
213  jack_transport_state_t old_transport_state;
214 
215  jack_nframes_t get_jack_sr() { return jack_sr; }
216  jack_nframes_t get_jack_bs() { return jack_bs; }
217  float get_jcpu_load() { return client ? jack_cpu_load(client) : -1; }
218  bool get_is_rt() { return client ? jack_is_realtime(client) : false; }
219  jack_nframes_t get_time_is() { return client ? jack_frame_time(client) : 0; }
220 
221 public:
224 
225  void set_jack_down(bool v) { jack_is_down = v; }
226  void set_jack_exit(bool v) { jack_is_exit = v; }
227 
228  void set_jack_insert(bool v) { bypass_insert = v;}
229  bool gx_jack_connection(bool connect, bool startserver,
230  int wait_after_connect, const gx_system::CmdlineOptions& opt);
231  float get_last_xrun() { return last_xrun; }
232  void* get_midi_buffer(jack_nframes_t nframes);
233  bool send_midi_cc(int cc_num, int pgm_num, int bgn, int num);
234 
237  static string get_default_instancename();
238  const string& get_instancename() { return client_instance; }
239  string client_name;
241  Glib::Dispatcher session;
242  Glib::Dispatcher session_ins;
243  Glib::Dispatcher shutdown;
244  bool is_jack_down() { return jack_is_down; }
245  Glib::Dispatcher connection;
246  bool is_jack_exit() { return jack_is_exit; }
247  sigc::signal<void>& signal_client_change() { return client_change; }
248  sigc::signal<void,string,string,bool>& signal_connection_changed() { return connection_changed; }
249  Glib::Dispatcher& signal_portchange() { return connection_queue.portchange; }
250  Glib::Dispatcher& signal_buffersize_change() { return buffersize_change; }
252  static void rt_watchdog_set_limit(int limit);
255 #ifdef HAVE_JACK_SESSION
256  jack_session_event_t *get_last_session_event() {
257  return gx_system::atomic_get(session_event);
258  }
259  jack_session_event_t *get_last_session_event_ins() {
260  return gx_system::atomic_get(session_event_ins);
261  }
262  int return_last_session_event();
263  int return_last_session_event_ins();
264  string get_uuid_insert();
265 #endif
266 };
267 
268 inline bool GxJack::send_midi_cc(int cc_num, int pgm_num, int bgn, int num) {
269  if (!client) {
270  return false;
271  }
272  return mmessage.send_midi_cc(cc_num, pgm_num, bgn, num);
273 }
274 
275 } /* end of jack namespace */
276 
277 #endif // SRC_HEADERS_GX_JACK_H_
278 #endif
static int gx_jack_insert_process(jack_nframes_t, void *arg)
bool is_jack_down()
Definition: gx_jack.h:244
string client_insert_name
Definition: gx_jack.h:240
static void gx_jack_portreg_callback(jack_port_id_t, int, void *arg)
void set_jack_exit(bool v)
Definition: gx_jack.h:226
string client_name
Definition: gx_jack.h:239
bool gx_jack_init(bool startserver, int wait_after_connect, const gx_system::CmdlineOptions &opt)
static string get_default_instancename()
void write_connections(gx_system::JsonWriter &w)
Glib::Dispatcher shutdown
Definition: gx_jack.h:243
JackPorts ports
Definition: gx_jack.h:206
bool send_midi_cc(int cc_num, int pgm_num, int bgn, int num)
Definition: gx_jack.h:268
static void gx_jack_portconn_callback(jack_port_id_t a, jack_port_id_t b, int connect, void *arg)
void write_jack_port_connections(gx_system::JsonWriter &w, const char *key, const PortConnection &pc, bool replace=false)
bool jack_is_down
Definition: gx_jack.h:150
jack_nframes_t get_jack_sr()
Definition: gx_jack.h:215
float get_last_xrun()
Definition: gx_jack.h:231
void gx_jack_cleanup()
void report_xrun_clear()
gx_engine::GxEngine & get_engine()
Definition: gx_jack.h:253
sigc::signal< void > & signal_client_change()
Definition: gx_jack.h:247
void set_jack_insert(bool v)
Definition: gx_jack.h:228
float * insert_buffer
Definition: gx_jack.h:186
Glib::Dispatcher & signal_portchange()
Definition: gx_jack.h:249
void gx_jack_init_port_connection(const gx_system::CmdlineOptions &opt)
bool is_jack_exit()
Definition: gx_jack.h:246
bool single_client
Definition: gx_jack.h:254
void check_overload()
gx_engine::GxEngine & engine
Definition: gx_jack.h:149
bool jack_is_exit
Definition: gx_jack.h:151
float get_jcpu_load()
Definition: gx_jack.h:217
static int gx_jack_process(jack_nframes_t, void *arg)
Glib::Dispatcher connection
Definition: gx_jack.h:245
bool xrun_msg_blocked
Definition: gx_jack.h:189
void process_midi_cc(void *buf, jack_nframes_t nframes)
Glib::Dispatcher session
Definition: gx_jack.h:241
const string & get_instancename()
Definition: gx_jack.h:238
sigc::signal< void > client_change
Definition: gx_jack.h:182
static void shutdown_callback_client(void *arg)
jack_client_t * client
Definition: gx_jack.h:208
Glib::Dispatcher session_ins
Definition: gx_jack.h:242
void * get_midi_buffer(jack_nframes_t nframes)
std::string replace_clientvar(const std::string &s)
void read_connections(gx_system::JsonParser &jp)
static int gx_jack_buffersize_callback(jack_nframes_t, void *arg)
static void shutdown_callback_client_insert(void *arg)
GxJack(gx_engine::GxEngine &engine_)
static void rt_watchdog_set_limit(int limit)
jack_transport_state_t transport_state
Definition: gx_jack.h:212
Glib::Dispatcher & signal_buffersize_change()
Definition: gx_jack.h:250
PortConnRing connection_queue
Definition: gx_jack.h:177
static int gx_jack_xrun_callback(void *arg)
Glib::Dispatcher client_change_rt
Definition: gx_jack.h:181
jack_nframes_t jack_bs
Definition: gx_jack.h:185
MidiCC mmessage
Definition: gx_jack.h:153
void fetch_connection_data()
void gx_jack_callbacks()
jack_transport_state_t old_transport_state
Definition: gx_jack.h:213
sigc::signal< void, string, string, bool > & signal_connection_changed()
Definition: gx_jack.h:248
Glib::Dispatcher xrun
Definition: gx_jack.h:187
Glib::Dispatcher buffersize_change
Definition: gx_jack.h:179
sigc::signal< void, string, string, bool > connection_changed
Definition: gx_jack.h:178
static int gx_jack_srate_callback(jack_nframes_t, void *arg)
void gx_jack_shutdown_callback()
void set_jack_down(bool v)
Definition: gx_jack.h:225
bool gx_jack_connection(bool connect, bool startserver, int wait_after_connect, const gx_system::CmdlineOptions &opt)
jack_position_t current
Definition: gx_jack.h:211
bool bypass_insert
Definition: gx_jack.h:152
float last_xrun
Definition: gx_jack.h:188
jack_nframes_t jack_sr
Definition: gx_jack.h:184
void cleanup_slot(bool otherthread)
bool get_is_rt()
Definition: gx_jack.h:218
jack_client_t * client_insert
Definition: gx_jack.h:209
jack_nframes_t get_time_is()
Definition: gx_jack.h:219
string client_instance
Definition: gx_jack.h:183
jack_nframes_t get_jack_bs()
Definition: gx_jack.h:216
void send_connection_changes(bool v)
Definition: gx_jack.h:251
int is_power_of_two(unsigned int x)
std::string make_clientvar(const std::string &s)
PortConnection output2
Definition: gx_jack.h:98
PortConnection midi_input
Definition: gx_jack.h:93
PortConnection midi_output
Definition: gx_jack.h:95
PortConnection insert_out
Definition: gx_jack.h:94
PortConnection input
Definition: gx_jack.h:92
PortConnection insert_in
Definition: gx_jack.h:96
PortConnection output1
Definition: gx_jack.h:97
void fill(unsigned char *midi_send, int i)
Definition: gx_jack.h:138
int next(int i=-1) const
Definition: gx_jack.h:129
int me_num[max_midi_cc_cnt]
Definition: gx_jack.h:120
std::atomic< bool > send_cc[max_midi_cc_cnt]
Definition: gx_jack.h:116
static const int max_midi_cc_cnt
Definition: gx_jack.h:115
bool send_midi_cc(int _cc, int _pg, int _bgn, int _num)
int pg_num[max_midi_cc_cnt]
Definition: gx_jack.h:118
gx_engine::GxEngine & engine
Definition: gx_jack.h:114
int size(int i) const
Definition: gx_jack.h:125
int cc_num[max_midi_cc_cnt]
Definition: gx_jack.h:117
int bg_num[max_midi_cc_cnt]
Definition: gx_jack.h:119
MidiCC(gx_engine::GxEngine &engine_)
bool pop(PortConnData *)
void push(const char *a, const char *b, bool conn)
Glib::Dispatcher portchange
Definition: gx_jack.h:71
jack_ringbuffer_t * ring
Definition: gx_jack.h:63
Glib::Dispatcher new_data
Definition: gx_jack.h:70
void clear_overflow()
Definition: gx_jack.h:67
void set_send(bool v)
Definition: gx_jack.h:74
jack_port_t * port
Definition: gx_jack.h:86
list< string > conn
Definition: gx_jack.h:87
int atomic_get(volatile int &p)
Definition: gx_system.h:98
void atomic_set(volatile int *p, int v)
Definition: gx_system.h:90
const char * name_a
Definition: gx_jack.h:56
const char * name_b
Definition: gx_jack.h:57
PortConnData(const char *a, const char *b, bool conn)
Definition: gx_jack.h:53