Fix bypass crossfade read/write out of bounds
[calf.git] / src / connector.cpp
blob8db47888c40d78b92f277fa8f1f21d04b590c2d1
1 /* Calf Library
2 * Jack Connector Window
4 * Copyright (C) 2014 Markus Schmidt / Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #include <gtk/gtk.h>
23 #include <gdk/gdk.h>
25 #include <calf/giface.h>
26 #include <calf/connector.h>
27 #include <calf/custom_ctl.h>
28 #include <calf/jackhost.h>
30 #include <jack/jack.h>
31 #include <jack/midiport.h>
33 using namespace std;
34 using namespace calf_plugins;
36 calf_connector::calf_connector(plugin_strip *strip_)
38 strip = strip_;
39 window = NULL;
40 create_window();
43 calf_connector::~calf_connector()
48 // CALLBACKS FOR CALLBACKS
49 void calf_connector::toggle_port(calf_connector *self, GtkListStore *list, gchar *path_, gchar **port, gboolean &enabled)
51 GtkTreeIter iter;
52 gtk_tree_model_get_iter(GTK_TREE_MODEL(list), &iter, gtk_tree_path_new_from_string(path_));
53 gtk_tree_model_get(GTK_TREE_MODEL(list), &iter, 0, port, 2, &enabled, -1);
54 gtk_list_store_set(GTK_LIST_STORE (list), &iter, 2, !enabled, -1);
55 enabled = !enabled;
57 void calf_connector::connect(jack_client_t *client, gchar *source, gchar *dest, gboolean enabled)
59 if (enabled) {
60 jack_connect(client, source, dest);
61 } else {
62 jack_disconnect(client, source, dest);
64 set_toggles(this, 0);
65 set_toggles(this, 1);
66 set_toggles(this, 2);
69 // PORT CLICKS
70 void calf_connector::inport_clicked(GtkWidget *button, gpointer data)
72 connector_port *port = (connector_port *)data;
73 if (port == port->connector->active_in)
74 return;
75 port->connector->active_in = port;
76 port->connector->fill_inlist(port->connector);
78 void calf_connector::outport_clicked(GtkWidget *button, gpointer data)
80 connector_port *port = (connector_port *)data;
81 if (port == port->connector->active_out)
82 return;
83 port->connector->active_out = port;
84 port->connector->fill_outlist(port->connector);
86 void calf_connector::midiport_clicked(GtkWidget *button, gpointer data)
88 connector_port *port = (connector_port *)data;
89 if (port == port->connector->active_midi)
90 return;
91 port->connector->active_midi = port;
92 port->connector->fill_midilist(port->connector);
95 // LIST CLICKS
96 void calf_connector::inconnector_clicked(GtkCellRendererToggle *cell_renderer, gchar *path_, gpointer data)
98 calf_connector *self = (calf_connector *)data;
99 gchar *port;
100 gboolean enabled;
101 self->toggle_port(self, self->inlist, path_, &port, enabled);
102 string source = port;
103 string dest = (string)jack_get_client_name(self->jackclient)
104 + ":" + self->strip->plugin->inputs[self->active_in ? self->active_in->id : 0].nice_name;
105 self->connect(self->jackclient, (gchar*)source.c_str(), (gchar*)dest.c_str(), enabled);
107 void calf_connector::outconnector_clicked(GtkCellRendererToggle *cell_renderer, gchar *path_, gpointer data)
109 calf_connector *self = (calf_connector *)data;
110 gchar *port = NULL;
111 gboolean enabled;
112 self->toggle_port(self, self->outlist, path_, &port, enabled);
113 string source = (string)jack_get_client_name(self->jackclient)
114 + ":" + self->strip->plugin->outputs[self->active_out ? self->active_out->id : 0].nice_name;
115 string dest = port;
116 self->connect(self->jackclient, (gchar*)source.c_str(), (gchar*)dest.c_str(), enabled);
118 void calf_connector::midiconnector_clicked(GtkCellRendererToggle *cell_renderer, gchar *path_, gpointer data)
120 calf_connector *self = (calf_connector *)data;
121 gchar *port = NULL;
122 gboolean enabled;
123 self->toggle_port(self, self->midilist, path_, &port, enabled);
124 string source = port;
125 string dest = (string)jack_get_client_name(self->jackclient)
126 + ":" + self->strip->plugin->midi_port.nice_name;
127 self->connect(self->jackclient, (gchar*)source.c_str(), (gchar*)dest.c_str(), enabled);
130 // DISCONNECT CLICKS
131 void calf_connector::disconnect_inputs(GtkWidget *button, gpointer data)
133 ((calf_connector *)data)->_disconnect(0);
135 void calf_connector::disconnect_outputs(GtkWidget *buttconson, gpointer data)
137 ((calf_connector *)data)->_disconnect(1);
139 void calf_connector::disconnect_midi(GtkWidget *button, gpointer data)
141 ((calf_connector *)data)->_disconnect(2);
143 void calf_connector::disconnect_all(GtkWidget *button, gpointer data)
145 ((calf_connector *)data)->_disconnect(-1);
148 // JACK CALLBACKS
149 //void calf_connector::jack_port_connect_callback(jack_port_id_t a, jack_port_id_t b, int connect, gpointer data)
151 //calf_connector *self = (calf_connector *)data;
152 //self->fill_list(data);
154 //void calf_connector::jack_port_rename_callback(jack_port_id_t port, const char *old_name, const char *new_name, gpointer data)
156 //calf_connector *self = (calf_connector *)data;
157 //self->fill_list(data);
159 //void calf_connector::jack_port_registration_callback(jack_port_id_t port, int register, gpointer data)
161 //calf_connector *self = (calf_connector *)data;
162 //self->fill_list(data);
166 void calf_connector::fill_inlist(gpointer data)
168 ((calf_connector *)data)->fill_list((calf_connector *)data, 0);
170 void calf_connector::fill_outlist(gpointer data)
172 ((calf_connector *)data)->fill_list((calf_connector *)data, 1);
174 void calf_connector::fill_midilist(gpointer data)
176 ((calf_connector *)data)->fill_list((calf_connector *)data, 2);
179 void calf_connector::fill_list(calf_connector *self, int type)
181 GtkTreeIter iter;
182 GtkListStore *list;
183 const char **ports;
184 switch (type) {
185 case 0:
186 default:
187 list = self->inlist;
188 gtk_list_store_clear(list);
189 ports = jack_get_ports(self->jackclient, ".*:.*", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput);
190 if (!ports) return;
191 break;
192 case 1:
193 list = self->outlist;
194 gtk_list_store_clear(list);
195 ports = jack_get_ports(self->jackclient, ".*:.*", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput);
196 if (!ports) return;
197 break;
198 case 2:
199 list = self->midilist;
200 gtk_list_store_clear(list);
201 ports = jack_get_ports(self->jackclient, ".*:.*", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput);
202 if (!ports) return;
203 break;
206 int c = 0;
207 do {
208 gtk_list_store_append(list, &iter);
209 if (gtk_list_store_iter_is_valid(list, &iter))
210 gtk_list_store_set(list, &iter, 0, ports[c], 1, ports[c], 2, FALSE, -1);
211 } while (ports[++c]);
212 jack_free(ports);
213 self->set_toggles(self, type);
216 void calf_connector::set_toggles(calf_connector *self, int type)
218 const char** cons;
219 const char** ports;
220 char path[16];
221 GtkTreeIter iter;
222 GtkListStore *list;
223 jack_port_t *port = NULL;
224 int p = 0, c = 0, f = 0, portflag = 0;
225 const char * porttype;
226 string s = "", nn = "";
227 switch (type) {
228 case 0:
229 default:
230 if (!self->active_in)
231 return;
232 portflag = JackPortIsOutput;
233 porttype = JACK_DEFAULT_AUDIO_TYPE;
234 nn = (string)jack_get_client_name(self->jackclient)
235 + ":" + self->strip->plugin->inputs[self->active_in->id].nice_name;
236 list = self->inlist;
237 break;
238 case 1:
239 if (!self->active_out)
240 return;
241 portflag = JackPortIsInput;
242 porttype = JACK_DEFAULT_AUDIO_TYPE;
243 nn = (string)jack_get_client_name(self->jackclient)
244 + ":" + self->strip->plugin->outputs[self->active_out->id].nice_name;
245 list = self->outlist;
246 break;
247 case 2:
248 portflag = JackPortIsOutput;
249 porttype = JACK_DEFAULT_MIDI_TYPE;
250 nn = (string)jack_get_client_name(self->jackclient)
251 + ":" + self->strip->plugin->midi_port.nice_name;
252 list = self->midilist;
253 break;
255 port = jack_port_by_name(self->jackclient, nn.c_str());
256 cons = jack_port_get_all_connections(self->jackclient, port);
257 ports = jack_get_ports(self->jackclient,
258 NULL,
259 porttype,
260 portflag);
261 if (!ports) {
262 jack_free(cons);
263 jack_free(ports);
264 return;
266 p = 0;
267 do {
268 sprintf(path, "%d", p);
269 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(list), &iter, path);
270 c = f = 0;
271 do {
272 if (cons and cons[c] == ports[p]) {
273 gtk_list_store_set (list, &iter, 2, TRUE, -1);
274 f = 1;
276 } while (cons[++c]);
277 if (!f) {
278 gtk_list_store_set (list, &iter, 2, FALSE, -1);
280 } while (ports[++p]);
281 jack_free(cons);
282 jack_free(ports);
285 void calf_connector::_disconnect(int type)
287 string nn = "";
288 const char** cons = NULL;
289 jack_port_t *port = NULL;
290 int c = 0;
291 if (type == 0 or type == -1) {
292 for (int i = 0; i < strip->plugin->in_count; i++) {
293 nn = (string)jack_get_client_name(jackclient)
294 + ":" + strip->plugin->inputs[i].nice_name;
295 port = jack_port_by_name(jackclient, nn.c_str());
296 cons = jack_port_get_all_connections(jackclient, port);
297 if (cons) {
298 c = 0;
299 do {
300 jack_disconnect(jackclient, cons[c], jack_port_name(port));
301 } while (cons[++c]);
302 jack_free(cons);
306 if (type == 1 or type == -1) {
307 for (int i = 0; i < strip->plugin->out_count; i++) {
308 nn = (string)jack_get_client_name(jackclient)
309 + ":" + strip->plugin->outputs[i].nice_name;
310 port = jack_port_by_name(jackclient, nn.c_str());
311 cons = jack_port_get_all_connections(jackclient, port);
312 if (cons) {
313 c = 0;
314 do {
315 jack_disconnect(jackclient, jack_port_name(port), cons[c]);
316 } while (cons[++c]);
317 jack_free(cons);
321 if (type == 2 or type == -1) {
322 nn = (string)jack_get_client_name(jackclient)
323 + ":" + strip->plugin->midi_port.nice_name;
324 port = jack_port_by_name(jackclient, nn.c_str());
325 cons = jack_port_get_all_connections(jackclient, port);
326 if (cons) {
327 c = 0;
328 do {
329 jack_disconnect(jackclient, cons[c], jack_port_name(port));
330 } while (cons[++c]);
331 jack_free(cons);
334 set_toggles(this, 0);
335 set_toggles(this, 1);
336 set_toggles(this, 2);
339 void calf_connector::close()
341 if (window)
342 gtk_widget_destroy(GTK_WIDGET(window));
344 void calf_connector::close_window(GtkWidget *button, gpointer data)
346 calf_connector *self = (calf_connector *)data;
347 if (self->window)
348 gtk_widget_destroy(GTK_WIDGET(self->window));
350 void calf_connector::on_destroy_window(GtkWidget *window, gpointer data)
352 calf_connector *self = (calf_connector *)data;
353 if (self->strip->con)
354 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->strip->con), FALSE);
355 self->strip->connector = NULL;
356 delete self;
360 void calf_connector::create_window()
362 char buf[256];
364 // WINDOW
366 string title = "Calf " + (string)strip->plugin->get_metadata_iface()->get_label() + " Connector";
367 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
368 gtk_window_set_title(GTK_WINDOW(window), title.c_str());
369 gtk_window_set_destroy_with_parent(GTK_WINDOW(window), TRUE);
370 //gtk_window_set_keep_above(GTK_WINDOW(window), TRUE);
371 gtk_window_set_icon_name(GTK_WINDOW(window), "calf_plugin");
372 gtk_window_set_role(GTK_WINDOW(window), "calf_connector");
373 gtk_window_set_default_size(GTK_WINDOW(window), 900, 400);
374 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);
375 gtk_widget_set_name(GTK_WIDGET(window), "Connector");
377 g_signal_connect(G_OBJECT(window), "destroy",
378 G_CALLBACK (on_destroy_window), (gpointer)this);
381 // CONTAINER STUFF
383 GtkVBox *vbox = GTK_VBOX(gtk_vbox_new(false, 8));
384 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));
385 //gtk_widget_set_name(GTK_WIDGET(vbox), "Calf-Container");
386 gtk_container_set_border_width (GTK_CONTAINER(vbox), 8);
388 GtkTable *table = GTK_TABLE(gtk_table_new(2, 5, FALSE));
389 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), true, true, 0);
390 gtk_table_set_row_spacings(table, 5);
391 gtk_table_set_col_spacings(table, 5);
394 // FRAMES AND CONTAINER
396 // Button frame
397 GtkWidget *butframe = gtk_frame_new("Bulk Disconnect");
398 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(butframe), 1, 4, 1, 2, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL), 0, 0);
399 // Button container
400 GtkWidget *buttons = gtk_vbox_new(false, 2);
401 gtk_container_add(GTK_CONTAINER(butframe), GTK_WIDGET(buttons));
403 // Input frame
404 GtkWidget *inframe = gtk_frame_new("Plug-In Inputs");
405 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(inframe), 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL|GTK_EXPAND), 0, 0);
406 gtk_widget_set_name(GTK_WIDGET(inframe), "Ports");
407 gtk_widget_set_size_request(GTK_WIDGET(inframe), 100, -1);
408 //gtk_widget_set_size_request(GTK_WIDGET(inframe), -1, 200);
409 // Input container
410 GtkWidget *inputs = gtk_vbox_new(false, 2);
411 gtk_container_add(GTK_CONTAINER(inframe), GTK_WIDGET(inputs));
412 // Disconnect input button
413 GtkWidget *inbut = gtk_button_new_with_label("Inputs");
414 g_signal_connect(G_OBJECT(inbut), "clicked", G_CALLBACK(disconnect_inputs), this);
415 gtk_box_pack_start(GTK_BOX(buttons), inbut, false, false, 0);
416 gtk_widget_show(GTK_WIDGET(inbut));
418 // Output frame
419 GtkWidget *outframe = gtk_frame_new("Plug-In Outputs");
420 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(outframe), 3, 4, 0, 1, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL|GTK_EXPAND), 0, 0);
421 gtk_widget_set_name(GTK_WIDGET(outframe), "Ports");
422 gtk_widget_set_size_request(GTK_WIDGET(outframe), 100, -1);
423 //gtk_widget_set_size_request(GTK_WIDGET(outframe), -1, 200);
424 // Output container
425 GtkWidget *outputs = gtk_vbox_new(false, 2);
426 gtk_container_add(GTK_CONTAINER(outframe), GTK_WIDGET(outputs));
427 // Disconnect output button
428 GtkWidget *outbut = gtk_button_new_with_label("Outputs");
429 g_signal_connect(G_OBJECT(outbut), "clicked", G_CALLBACK(disconnect_outputs), this);
430 gtk_box_pack_start(GTK_BOX(buttons), outbut, false, false, 0);
431 gtk_widget_show(GTK_WIDGET(outbut));
433 // MIDI frame
434 GtkWidget *midiframe = gtk_frame_new("Plug-In MIDI");
435 //gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(midiframe), 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)(GTK_FILL), 0, 0);
436 // MIDI container
437 GtkWidget *midi = gtk_vbox_new(false, 2);
438 gtk_container_add(GTK_CONTAINER(midiframe), GTK_WIDGET(midi));
439 // Disconnect midi button
440 GtkWidget *midibut = gtk_button_new_with_label("MIDI");
441 g_signal_connect(G_OBJECT(midibut), "clicked", G_CALLBACK(disconnect_midi), this);
442 gtk_box_pack_start(GTK_BOX(buttons), midibut, false, false, 0);
443 gtk_widget_show(GTK_WIDGET(midibut));
445 // LABEL
446 GtkWidget *label = gtk_label_new(strip->plugin->get_metadata_iface()->get_label());
447 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), 2, 3, 0, 1, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL), 10, 0);
448 gtk_widget_set_name(GTK_WIDGET(label), "Title");
449 gtk_label_set_angle(GTK_LABEL(label), 90);
451 gtk_widget_show_all(window);
453 // Disconnect all button
454 GtkWidget *allbut = gtk_button_new_with_label("*All*");
455 g_signal_connect(G_OBJECT(allbut), "clicked", G_CALLBACK(disconnect_all), this);
456 gtk_box_pack_start(GTK_BOX(buttons), allbut, false, true, 0);
457 gtk_widget_show(GTK_WIDGET(allbut));
459 // Close button
460 //GtkWidget *_close = gtk_alignment_new(1, 1, 0.5, 0.33);
461 //gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(_close), 3, 4, 1, 2, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL), 0, 0);
462 GtkWidget *close = gtk_button_new_with_label("Close");
463 g_signal_connect(G_OBJECT(close), "clicked", G_CALLBACK(close_window), this);
464 //gtk_container_add(GTK_CONTAINER(_close), close);
465 gtk_widget_show(GTK_WIDGET(close));
466 //gtk_widget_show(GTK_WIDGET(_close));
467 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(close), false, true, 0);
470 // LIST STUFF
472 GtkTreeViewColumn *col;
473 GtkCellRenderer *renderer;
474 GtkWidget *inscroller, *outscroller, *midiscroller;
475 GtkWidget *inview, *outview, *midiview;
477 // INPUT LIST
479 // scroller
480 inscroller = gtk_scrolled_window_new(NULL, NULL);
481 gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(inscroller), 0, 1, 0, 1);
482 gtk_widget_set_size_request(GTK_WIDGET(inscroller), 300, -1);
483 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(inscroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
484 gtk_widget_show(GTK_WIDGET(inscroller));
486 // list store / tree view
487 inlist = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
488 inview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(inlist));
489 gtk_container_add(GTK_CONTAINER(inscroller), inview);
490 gtk_widget_show(GTK_WIDGET(inview));
492 // text column
493 col = gtk_tree_view_column_new();
494 gtk_tree_view_column_set_expand(col, TRUE);
495 gtk_tree_view_column_set_title(col, "Available JACK Audio Outputs");
496 renderer = gtk_cell_renderer_text_new();
497 gtk_tree_view_column_pack_start(col, renderer, TRUE);
498 gtk_tree_view_column_add_attribute(col, renderer, "text", 1);
499 gtk_tree_view_append_column(GTK_TREE_VIEW(inview), col);
501 // toggle column
502 col = gtk_tree_view_column_new();
503 gtk_tree_view_column_set_expand(col, FALSE);
504 gtk_tree_view_column_set_title(col, "⬌");
505 renderer = gtk_cell_renderer_toggle_new();
506 gtk_tree_view_column_pack_start(col, renderer, FALSE);
507 gtk_tree_view_column_add_attribute(col, renderer, "active", 2);
508 gtk_tree_view_append_column(GTK_TREE_VIEW(inview), col);
509 g_signal_connect(GTK_OBJECT(renderer), "toggled", G_CALLBACK(inconnector_clicked), (gpointer*)this);
512 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(inview)),
513 GTK_SELECTION_NONE);
515 g_object_unref(inlist);
517 // OUTPUT LIST
519 // scroller
520 outscroller = gtk_scrolled_window_new(NULL, NULL);
521 gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(outscroller), 4, 5, 0, 2);
522 gtk_widget_set_size_request(GTK_WIDGET(outscroller), 280, -1);
523 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(outscroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
524 gtk_widget_show(GTK_WIDGET(outscroller));
526 // list store / tree view
527 outlist = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
528 outview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(outlist));
529 gtk_container_add(GTK_CONTAINER(outscroller), outview);
530 gtk_widget_show(GTK_WIDGET(outview));
532 // toggle column
533 col = gtk_tree_view_column_new();
534 gtk_tree_view_column_set_title(col, "⬌");
535 renderer = gtk_cell_renderer_toggle_new();
536 gtk_tree_view_column_pack_start(col, renderer, FALSE);
537 gtk_tree_view_column_add_attribute(col, renderer, "active", 2);
538 gtk_tree_view_append_column(GTK_TREE_VIEW(outview), col);
539 g_signal_connect(GTK_OBJECT(renderer), "toggled", G_CALLBACK(outconnector_clicked), (gpointer*)this);
541 // text column
542 col = gtk_tree_view_column_new();
543 gtk_tree_view_column_set_title(col, "Available JACK Audio Inputs");
544 renderer = gtk_cell_renderer_text_new();
545 gtk_tree_view_column_pack_start(col, renderer, TRUE);
546 gtk_tree_view_column_add_attribute(col, renderer, "text", 1);
547 gtk_tree_view_append_column(GTK_TREE_VIEW(outview), col);
549 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(outview)),
550 GTK_SELECTION_NONE);
552 g_object_unref(outlist);
554 // MIDI LIST
556 // scroller
557 midiscroller = gtk_scrolled_window_new(NULL, NULL);
558 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(midiscroller), 0, 1, 1, 2, (GtkAttachOptions)(GTK_FILL|GTK_EXPAND), (GtkAttachOptions)(GTK_FILL), 0, 0);
559 gtk_widget_set_size_request(GTK_WIDGET(midiscroller), 280, -1);
560 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(midiscroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
561 gtk_widget_show(GTK_WIDGET(midiscroller));
563 // list store / tree view
564 midilist = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
565 midiview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(midilist));
566 gtk_container_add(GTK_CONTAINER(midiscroller), midiview);
567 gtk_widget_show(GTK_WIDGET(midiview));
569 // text column
570 col = gtk_tree_view_column_new();
571 gtk_tree_view_column_set_expand(col, TRUE);
572 gtk_tree_view_column_set_title(col, "Available JACK MIDI Outputs");
573 renderer = gtk_cell_renderer_text_new();
574 gtk_tree_view_column_pack_start(col, renderer, TRUE);
575 gtk_tree_view_column_add_attribute(col, renderer, "text", 1);
576 gtk_tree_view_append_column(GTK_TREE_VIEW(midiview), col);
578 // toggle column
579 col = gtk_tree_view_column_new();
580 gtk_tree_view_column_set_expand(col, FALSE);
581 gtk_tree_view_column_set_title(col, "⬌");
582 renderer = gtk_cell_renderer_toggle_new();
583 gtk_tree_view_column_pack_start(col, renderer, FALSE);
584 gtk_tree_view_column_add_attribute(col, renderer, "active", 2);
585 gtk_tree_view_append_column(GTK_TREE_VIEW(midiview), col);
586 g_signal_connect(GTK_OBJECT(renderer), "toggled", G_CALLBACK(midiconnector_clicked), (gpointer*)this);
588 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(midiview)),
589 GTK_SELECTION_NONE);
591 g_object_unref(midilist);
593 // ALL THOSE PORT BUTTONS
595 active_in = active_out = active_midi = NULL;
596 GtkRadioButton *last = NULL;
597 GtkRadioButton *first = NULL;
598 int c = 0;
599 // Inputs
600 for (int i = 0; i < strip->plugin->in_count; i++) {
601 sprintf(buf, "Input #%d", (i + 1));
602 GtkWidget *in = gtk_radio_button_new_with_label(NULL, buf);
603 gtk_box_pack_start(GTK_BOX(inputs), in, false, true, 0);
604 gtk_widget_show(GTK_WIDGET(in));
605 if (!i)
606 last = GTK_RADIO_BUTTON(in);
607 else
608 gtk_radio_button_set_group(GTK_RADIO_BUTTON(in), gtk_radio_button_get_group(last));
609 inports[c].type = 0;
610 inports[c].id = c;
611 inports[c].connector = this;
612 g_signal_connect(GTK_OBJECT(in), "clicked", G_CALLBACK(inport_clicked), (gpointer*)&inports[c]);
613 if (!first) {
614 first = GTK_RADIO_BUTTON(in);
615 active_in = &inports[c];
616 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(first), TRUE);
618 c++;
620 if (!c) {
621 gtk_widget_set_sensitive(GTK_WIDGET(inframe), FALSE);
622 gtk_widget_set_sensitive(GTK_WIDGET(inview), FALSE);
623 gtk_widget_set_sensitive(GTK_WIDGET(inbut), FALSE);
624 gtk_widget_hide(GTK_WIDGET(inbut));
626 first = NULL;
627 last = NULL;
628 c = 0;
629 // Outputs
630 for (int i = 0; i < strip->plugin->out_count; i++) {
631 sprintf(buf, "Output #%d", (i + 1));
632 GtkWidget *out = gtk_radio_button_new_with_label(NULL, buf);
633 gtk_box_pack_start(GTK_BOX(outputs), out, false, true, 0);
634 gtk_widget_show(GTK_WIDGET(out));
635 if (!i and !last)
636 last = GTK_RADIO_BUTTON(out);
637 else
638 gtk_radio_button_set_group(GTK_RADIO_BUTTON(out), gtk_radio_button_get_group(last));
639 outports[c].type = 1;
640 outports[c].id = c;
641 outports[c].connector = this;
642 g_signal_connect(GTK_OBJECT(out), "clicked", G_CALLBACK(outport_clicked), (gpointer*)&outports[c]);
643 if (!first) {
644 first = GTK_RADIO_BUTTON(out);
645 active_out = &outports[c];
646 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(first), TRUE);
648 c++;
650 if (!c) {
651 gtk_widget_set_sensitive(GTK_WIDGET(outframe), FALSE);
652 gtk_widget_set_sensitive(GTK_WIDGET(outview), FALSE);
653 gtk_widget_set_sensitive(GTK_WIDGET(outbut), FALSE);
654 gtk_widget_hide(GTK_WIDGET(outbut));
656 first = NULL;
657 last = NULL;
658 c = 0;
659 // MIDI
660 if (strip->plugin->get_metadata_iface()->get_midi()) {
661 GtkWidget *mid = gtk_radio_button_new_with_label(NULL, "MIDI");
662 gtk_box_pack_start(GTK_BOX(midi), mid, false, true, 0);
663 midiports[c].type = 2;
664 midiports[c].id = c;
665 midiports[c].connector = this;
666 g_signal_connect(GTK_OBJECT(mid), "clicked", G_CALLBACK(midiport_clicked), (gpointer*)&midiports[c]);
667 gtk_widget_show(GTK_WIDGET(mid));
668 if (!first) {
669 first = GTK_RADIO_BUTTON(mid);
670 active_midi = &midiports[c];
671 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(first), TRUE);
673 c++;
675 if (!c) {
676 //gtk_widget_set_sensitive(GTK_WIDGET(midiframe), FALSE);
677 //gtk_widget_set_sensitive(GTK_WIDGET(midiview), FALSE);
678 //gtk_widget_set_sensitive(GTK_WIDGET(midibut), FALSE);
679 gtk_widget_hide(GTK_WIDGET(midiview));
680 gtk_widget_hide(GTK_WIDGET(midibut));
681 gtk_container_child_set(GTK_CONTAINER(table), GTK_WIDGET(inscroller), "bottom-attach", 2, NULL);
684 // JACK STUFF
686 jackclient = strip->plugin->client->client;
688 //jack_set_port_connect_callback(jackclient, jack_port_connect_callback, this);
689 //jack_set_port_rename_callback(jackclient, jack_port_rename_callback, this);
690 //jack_set_port_registration_callback(jackclient, jack_port_registration_callback , this);
692 fill_inlist(this);
693 fill_outlist(this);
694 fill_midilist(this);