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