New rack rack-ears
[calf.git] / src / connector.cpp
blob73c45b51d4ca37a80296bc395c0deb84f24f383a
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);
106 self->set_toggles(self, 0);
108 void calf_connector::outconnector_clicked(GtkCellRendererToggle *cell_renderer, gchar *path_, gpointer data)
110 calf_connector *self = (calf_connector *)data;
111 gchar *port = NULL;
112 gboolean enabled;
113 self->toggle_port(self, self->outlist, path_, &port, enabled);
114 string source = (string)jack_get_client_name(self->jackclient)
115 + ":" + self->strip->plugin->outputs[self->active_out ? self->active_out->id : 0].nice_name;
116 string dest = port;
117 self->connect(self->jackclient, (gchar*)source.c_str(), (gchar*)dest.c_str(), enabled);
118 self->set_toggles(self, 1);
120 void calf_connector::midiconnector_clicked(GtkCellRendererToggle *cell_renderer, gchar *path_, gpointer data)
122 calf_connector *self = (calf_connector *)data;
123 gchar *port = NULL;
124 gboolean enabled;
125 self->toggle_port(self, self->midilist, path_, &port, enabled);
126 string source = port;
127 string dest = (string)jack_get_client_name(self->jackclient)
128 + ":" + self->strip->plugin->midi_port.nice_name;
129 self->connect(self->jackclient, (gchar*)source.c_str(), (gchar*)dest.c_str(), enabled);
130 self->set_toggles(self, 2);
133 // DISCONNECT CLICKS
134 void calf_connector::disconnect_inputs(GtkWidget *button, gpointer data)
136 ((calf_connector *)data)->_disconnect(0);
138 void calf_connector::disconnect_outputs(GtkWidget *buttconson, gpointer data)
140 ((calf_connector *)data)->_disconnect(1);
142 void calf_connector::disconnect_midi(GtkWidget *button, gpointer data)
144 ((calf_connector *)data)->_disconnect(2);
146 void calf_connector::disconnect_all(GtkWidget *button, gpointer data)
148 ((calf_connector *)data)->_disconnect(-1);
151 // JACK CALLBACKS
152 //void calf_connector::jack_port_connect_callback(jack_port_id_t a, jack_port_id_t b, int connect, gpointer data)
154 //calf_connector *self = (calf_connector *)data;
155 //self->fill_list(data);
157 //void calf_connector::jack_port_rename_callback(jack_port_id_t port, const char *old_name, const char *new_name, gpointer data)
159 //calf_connector *self = (calf_connector *)data;
160 //self->fill_list(data);
162 //void calf_connector::jack_port_registration_callback(jack_port_id_t port, int register, gpointer data)
164 //calf_connector *self = (calf_connector *)data;
165 //self->fill_list(data);
169 void calf_connector::fill_inlist(gpointer data)
171 ((calf_connector *)data)->fill_list((calf_connector *)data, 0);
173 void calf_connector::fill_outlist(gpointer data)
175 ((calf_connector *)data)->fill_list((calf_connector *)data, 1);
177 void calf_connector::fill_midilist(gpointer data)
179 ((calf_connector *)data)->fill_list((calf_connector *)data, 2);
182 void calf_connector::fill_list(calf_connector *self, int type)
184 GtkTreeIter iter;
185 GtkListStore *list;
186 const char **ports;
187 switch (type) {
188 case 0:
189 default:
190 list = self->inlist;
191 gtk_list_store_clear(list);
192 ports = jack_get_ports(self->jackclient, ".*:.*", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput);
193 if (!ports) return;
194 break;
195 case 1:
196 list = self->outlist;
197 gtk_list_store_clear(list);
198 ports = jack_get_ports(self->jackclient, ".*:.*", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput);
199 if (!ports) return;
200 break;
201 case 2:
202 list = self->midilist;
203 gtk_list_store_clear(list);
204 ports = jack_get_ports(self->jackclient, ".*:.*", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput);
205 if (!ports) return;
206 break;
209 int c = 0;
210 do {
211 gtk_list_store_append(list, &iter);
212 if (gtk_list_store_iter_is_valid(list, &iter))
213 gtk_list_store_set(list, &iter, 0, ports[c], 1, ports[c], 2, FALSE, -1);
214 } while (ports[++c]);
215 jack_free(ports);
216 self->set_toggles(self, type);
219 void calf_connector::set_toggles(calf_connector *self, int type)
221 const char** cons;
222 const char** ports;
223 char path[16];
224 GtkTreeIter iter;
225 GtkListStore *list;
226 jack_port_t *port = NULL;
227 int p = 0, c = 0, f = 0, portflag = 0;
228 const char * porttype;
229 string s = "", nn = "";
230 switch (type) {
231 case 0:
232 default:
233 if (!self->active_in)
234 return;
235 portflag = JackPortIsOutput;
236 porttype = JACK_DEFAULT_AUDIO_TYPE;
237 nn = (string)jack_get_client_name(self->jackclient)
238 + ":" + self->strip->plugin->inputs[self->active_in->id].nice_name;
239 list = self->inlist;
240 break;
241 case 1:
242 if (!self->active_out)
243 return;
244 portflag = JackPortIsInput;
245 porttype = JACK_DEFAULT_AUDIO_TYPE;
246 nn = (string)jack_get_client_name(self->jackclient)
247 + ":" + self->strip->plugin->outputs[self->active_out->id].nice_name;
248 list = self->outlist;
249 break;
250 case 2:
251 portflag = JackPortIsOutput;
252 porttype = JACK_DEFAULT_MIDI_TYPE;
253 nn = (string)jack_get_client_name(self->jackclient)
254 + ":" + self->strip->plugin->midi_port.nice_name;
255 list = self->midilist;
256 break;
258 port = jack_port_by_name(self->jackclient, nn.c_str());
259 cons = jack_port_get_all_connections(self->jackclient, port);
260 ports = jack_get_ports(self->jackclient,
261 NULL,
262 porttype,
263 portflag);
264 if (!ports) {
265 jack_free(cons);
266 jack_free(ports);
267 return;
269 p = 0;
270 do {
271 sprintf(path, "%d", p);
272 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(list), &iter, path);
273 c = f = 0;
274 do {
275 if (cons and cons[c] == ports[p]) {
276 gtk_list_store_set (list, &iter, 2, TRUE, -1);
277 f = 1;
279 } while (cons[++c]);
280 if (!f) {
281 gtk_list_store_set (list, &iter, 2, FALSE, -1);
283 } while (ports[++p]);
284 jack_free(cons);
285 jack_free(ports);
288 void calf_connector::_disconnect(int type)
290 string nn = "";
291 const char** cons = NULL;
292 jack_port_t *port = NULL;
293 int c = 0;
294 if (type == 0 or type == -1) {
295 for (int i = 0; i < strip->plugin->in_count; i++) {
296 nn = (string)jack_get_client_name(jackclient)
297 + ":" + strip->plugin->inputs[i].nice_name;
298 port = jack_port_by_name(jackclient, nn.c_str());
299 cons = jack_port_get_all_connections(jackclient, port);
300 if (cons) {
301 c = 0;
302 do {
303 jack_disconnect(jackclient, cons[c], jack_port_name(port));
304 } while (cons[++c]);
305 jack_free(cons);
309 if (type == 1 or type == -1) {
310 for (int i = 0; i < strip->plugin->out_count; i++) {
311 nn = (string)jack_get_client_name(jackclient)
312 + ":" + strip->plugin->outputs[i].nice_name;
313 port = jack_port_by_name(jackclient, nn.c_str());
314 cons = jack_port_get_all_connections(jackclient, port);
315 if (cons) {
316 c = 0;
317 do {
318 jack_disconnect(jackclient, jack_port_name(port), cons[c]);
319 } while (cons[++c]);
320 jack_free(cons);
324 if (type == 2 or type == -1) {
325 nn = (string)jack_get_client_name(jackclient)
326 + ":" + strip->plugin->midi_port.nice_name;
327 port = jack_port_by_name(jackclient, nn.c_str());
328 cons = jack_port_get_all_connections(jackclient, port);
329 if (cons) {
330 c = 0;
331 do {
332 jack_disconnect(jackclient, cons[c], jack_port_name(port));
333 } while (cons[++c]);
334 jack_free(cons);
337 set_toggles(this, 0);
338 set_toggles(this, 1);
339 set_toggles(this, 2);
342 void calf_connector::close()
344 if (window)
345 gtk_widget_destroy(GTK_WIDGET(window));
347 void calf_connector::close_window(GtkWidget *button, gpointer data)
349 calf_connector *self = (calf_connector *)data;
350 if (self->window)
351 gtk_widget_destroy(GTK_WIDGET(self->window));
353 void calf_connector::on_destroy_window(GtkWidget *window, gpointer data)
355 calf_connector *self = (calf_connector *)data;
356 if (self->strip->con)
357 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->strip->con), FALSE);
358 self->strip->connector = NULL;
359 delete self;
363 void calf_connector::create_window()
365 char buf[256];
367 // WINDOW
369 string title = "Calf " + (string)strip->plugin->get_metadata_iface()->get_label() + " Connector";
370 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
371 gtk_window_set_title(GTK_WINDOW(window), title.c_str());
372 gtk_window_set_destroy_with_parent(GTK_WINDOW(window), TRUE);
373 //gtk_window_set_keep_above(GTK_WINDOW(window), TRUE);
374 gtk_window_set_icon_name(GTK_WINDOW(window), "calf_plugin");
375 gtk_window_set_role(GTK_WINDOW(window), "calf_connector");
376 gtk_window_set_default_size(GTK_WINDOW(window), 900, 400);
377 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);
378 gtk_widget_set_name(GTK_WIDGET(window), "Connector");
380 g_signal_connect(G_OBJECT(window), "destroy",
381 G_CALLBACK (on_destroy_window), (gpointer)this);
384 // CONTAINER STUFF
386 GtkVBox *vbox = GTK_VBOX(gtk_vbox_new(false, 8));
387 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));
388 //gtk_widget_set_name(GTK_WIDGET(vbox), "Calf-Container");
389 gtk_container_set_border_width (GTK_CONTAINER(vbox), 8);
391 GtkTable *table = GTK_TABLE(gtk_table_new(2, 5, FALSE));
392 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(table), true, true, 0);
393 gtk_table_set_row_spacings(table, 5);
394 gtk_table_set_col_spacings(table, 5);
397 // FRAMES AND CONTAINER
399 // Button frame
400 GtkWidget *butframe = gtk_frame_new("Bulk Disconnect");
401 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(butframe), 1, 4, 1, 2, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL), 0, 0);
402 // Button container
403 GtkWidget *buttons = gtk_vbox_new(false, 2);
404 gtk_container_add(GTK_CONTAINER(butframe), GTK_WIDGET(buttons));
406 // Input frame
407 GtkWidget *inframe = gtk_frame_new("Plug-In Inputs");
408 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(inframe), 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL|GTK_EXPAND), 0, 0);
409 gtk_widget_set_name(GTK_WIDGET(inframe), "Ports");
410 gtk_widget_set_size_request(GTK_WIDGET(inframe), 100, -1);
411 //gtk_widget_set_size_request(GTK_WIDGET(inframe), -1, 200);
412 // Input container
413 GtkWidget *inputs = gtk_vbox_new(false, 2);
414 gtk_container_add(GTK_CONTAINER(inframe), GTK_WIDGET(inputs));
415 // Disconnect input button
416 GtkWidget *inbut = gtk_button_new_with_label("Inputs");
417 g_signal_connect(G_OBJECT(inbut), "clicked", G_CALLBACK(disconnect_inputs), this);
418 gtk_box_pack_start(GTK_BOX(buttons), inbut, false, false, 0);
419 gtk_widget_show(GTK_WIDGET(inbut));
421 // Output frame
422 GtkWidget *outframe = gtk_frame_new("Plug-In Outputs");
423 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(outframe), 3, 4, 0, 1, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL|GTK_EXPAND), 0, 0);
424 gtk_widget_set_name(GTK_WIDGET(outframe), "Ports");
425 gtk_widget_set_size_request(GTK_WIDGET(outframe), 100, -1);
426 //gtk_widget_set_size_request(GTK_WIDGET(outframe), -1, 200);
427 // Output container
428 GtkWidget *outputs = gtk_vbox_new(false, 2);
429 gtk_container_add(GTK_CONTAINER(outframe), GTK_WIDGET(outputs));
430 // Disconnect output button
431 GtkWidget *outbut = gtk_button_new_with_label("Outputs");
432 g_signal_connect(G_OBJECT(outbut), "clicked", G_CALLBACK(disconnect_outputs), this);
433 gtk_box_pack_start(GTK_BOX(buttons), outbut, false, false, 0);
434 gtk_widget_show(GTK_WIDGET(outbut));
436 // MIDI frame
437 GtkWidget *midiframe = gtk_frame_new("Plug-In MIDI");
438 //gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(midiframe), 1, 2, 1, 2, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)(GTK_FILL), 0, 0);
439 // MIDI container
440 GtkWidget *midi = gtk_vbox_new(false, 2);
441 gtk_container_add(GTK_CONTAINER(midiframe), GTK_WIDGET(midi));
442 // Disconnect midi button
443 GtkWidget *midibut = gtk_button_new_with_label("MIDI");
444 g_signal_connect(G_OBJECT(midibut), "clicked", G_CALLBACK(disconnect_midi), this);
445 gtk_box_pack_start(GTK_BOX(buttons), midibut, false, false, 0);
446 gtk_widget_show(GTK_WIDGET(midibut));
448 // LABEL
449 GtkWidget *label = gtk_label_new(strip->plugin->get_metadata_iface()->get_label());
450 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label), 2, 3, 0, 1, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL), 10, 0);
451 gtk_widget_set_name(GTK_WIDGET(label), "Title");
452 gtk_label_set_angle(GTK_LABEL(label), 90);
454 gtk_widget_show_all(window);
456 // Disconnect all button
457 GtkWidget *allbut = gtk_button_new_with_label("*All*");
458 g_signal_connect(G_OBJECT(allbut), "clicked", G_CALLBACK(disconnect_all), this);
459 gtk_box_pack_start(GTK_BOX(buttons), allbut, false, true, 0);
460 gtk_widget_show(GTK_WIDGET(allbut));
462 // Close button
463 //GtkWidget *_close = gtk_alignment_new(1, 1, 0.5, 0.33);
464 //gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(_close), 3, 4, 1, 2, (GtkAttachOptions)(GTK_FILL), (GtkAttachOptions)(GTK_FILL), 0, 0);
465 GtkWidget *close = gtk_button_new_with_label("Close");
466 g_signal_connect(G_OBJECT(close), "clicked", G_CALLBACK(close_window), this);
467 //gtk_container_add(GTK_CONTAINER(_close), close);
468 gtk_widget_show(GTK_WIDGET(close));
469 //gtk_widget_show(GTK_WIDGET(_close));
470 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(close), false, true, 0);
473 // LIST STUFF
475 GtkTreeViewColumn *col;
476 GtkCellRenderer *renderer;
477 GtkWidget *inscroller, *outscroller, *midiscroller;
478 GtkWidget *inview, *outview, *midiview;
480 // INPUT LIST
482 // scroller
483 inscroller = gtk_scrolled_window_new(NULL, NULL);
484 gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(inscroller), 0, 1, 0, 1);
485 gtk_widget_set_size_request(GTK_WIDGET(inscroller), 300, -1);
486 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(inscroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
487 gtk_widget_show(GTK_WIDGET(inscroller));
489 // list store / tree view
490 inlist = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
491 inview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(inlist));
492 gtk_container_add(GTK_CONTAINER(inscroller), inview);
493 gtk_widget_show(GTK_WIDGET(inview));
495 // text column
496 col = gtk_tree_view_column_new();
497 gtk_tree_view_column_set_expand(col, TRUE);
498 gtk_tree_view_column_set_title(col, "Available JACK Audio Outputs");
499 renderer = gtk_cell_renderer_text_new();
500 gtk_tree_view_column_pack_start(col, renderer, TRUE);
501 gtk_tree_view_column_add_attribute(col, renderer, "text", 1);
502 gtk_tree_view_append_column(GTK_TREE_VIEW(inview), col);
504 // toggle column
505 col = gtk_tree_view_column_new();
506 gtk_tree_view_column_set_expand(col, FALSE);
507 gtk_tree_view_column_set_title(col, "⬌");
508 renderer = gtk_cell_renderer_toggle_new();
509 gtk_tree_view_column_pack_start(col, renderer, FALSE);
510 gtk_tree_view_column_add_attribute(col, renderer, "active", 2);
511 gtk_tree_view_append_column(GTK_TREE_VIEW(inview), col);
512 g_signal_connect(GTK_OBJECT(renderer), "toggled", G_CALLBACK(inconnector_clicked), (gpointer*)this);
515 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(inview)),
516 GTK_SELECTION_NONE);
518 g_object_unref(inlist);
520 // OUTPUT LIST
522 // scroller
523 outscroller = gtk_scrolled_window_new(NULL, NULL);
524 gtk_table_attach_defaults(GTK_TABLE(table), GTK_WIDGET(outscroller), 4, 5, 0, 2);
525 gtk_widget_set_size_request(GTK_WIDGET(outscroller), 280, -1);
526 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(outscroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
527 gtk_widget_show(GTK_WIDGET(outscroller));
529 // list store / tree view
530 outlist = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
531 outview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(outlist));
532 gtk_container_add(GTK_CONTAINER(outscroller), outview);
533 gtk_widget_show(GTK_WIDGET(outview));
535 // toggle column
536 col = gtk_tree_view_column_new();
537 gtk_tree_view_column_set_title(col, "⬌");
538 renderer = gtk_cell_renderer_toggle_new();
539 gtk_tree_view_column_pack_start(col, renderer, FALSE);
540 gtk_tree_view_column_add_attribute(col, renderer, "active", 2);
541 gtk_tree_view_append_column(GTK_TREE_VIEW(outview), col);
542 g_signal_connect(GTK_OBJECT(renderer), "toggled", G_CALLBACK(outconnector_clicked), (gpointer*)this);
544 // text column
545 col = gtk_tree_view_column_new();
546 gtk_tree_view_column_set_title(col, "Available JACK Audio Inputs");
547 renderer = gtk_cell_renderer_text_new();
548 gtk_tree_view_column_pack_start(col, renderer, TRUE);
549 gtk_tree_view_column_add_attribute(col, renderer, "text", 1);
550 gtk_tree_view_append_column(GTK_TREE_VIEW(outview), col);
552 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(outview)),
553 GTK_SELECTION_NONE);
555 g_object_unref(outlist);
557 // MIDI LIST
559 // scroller
560 midiscroller = gtk_scrolled_window_new(NULL, NULL);
561 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(midiscroller), 0, 1, 1, 2, (GtkAttachOptions)(GTK_FILL|GTK_EXPAND), (GtkAttachOptions)(GTK_FILL), 0, 0);
562 gtk_widget_set_size_request(GTK_WIDGET(midiscroller), 280, -1);
563 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(midiscroller), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
564 gtk_widget_show(GTK_WIDGET(midiscroller));
566 // list store / tree view
567 midilist = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
568 midiview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(midilist));
569 gtk_container_add(GTK_CONTAINER(midiscroller), midiview);
570 gtk_widget_show(GTK_WIDGET(midiview));
572 // text column
573 col = gtk_tree_view_column_new();
574 gtk_tree_view_column_set_expand(col, TRUE);
575 gtk_tree_view_column_set_title(col, "Available JACK MIDI Outputs");
576 renderer = gtk_cell_renderer_text_new();
577 gtk_tree_view_column_pack_start(col, renderer, TRUE);
578 gtk_tree_view_column_add_attribute(col, renderer, "text", 1);
579 gtk_tree_view_append_column(GTK_TREE_VIEW(midiview), col);
581 // toggle column
582 col = gtk_tree_view_column_new();
583 gtk_tree_view_column_set_expand(col, FALSE);
584 gtk_tree_view_column_set_title(col, "⬌");
585 renderer = gtk_cell_renderer_toggle_new();
586 gtk_tree_view_column_pack_start(col, renderer, FALSE);
587 gtk_tree_view_column_add_attribute(col, renderer, "active", 2);
588 gtk_tree_view_append_column(GTK_TREE_VIEW(midiview), col);
589 g_signal_connect(GTK_OBJECT(renderer), "toggled", G_CALLBACK(midiconnector_clicked), (gpointer*)this);
591 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(midiview)),
592 GTK_SELECTION_NONE);
594 g_object_unref(midilist);
596 // ALL THOSE PORT BUTTONS
598 active_in = active_out = active_midi = NULL;
599 GtkRadioButton *last = NULL;
600 GtkRadioButton *first = NULL;
601 int c = 0;
602 // Inputs
603 for (int i = 0; i < strip->plugin->in_count; i++) {
604 sprintf(buf, "Input #%d", (i + 1));
605 GtkWidget *in = gtk_radio_button_new_with_label(NULL, buf);
606 gtk_box_pack_start(GTK_BOX(inputs), in, false, true, 0);
607 gtk_widget_show(GTK_WIDGET(in));
608 if (!i)
609 last = GTK_RADIO_BUTTON(in);
610 else
611 gtk_radio_button_set_group(GTK_RADIO_BUTTON(in), gtk_radio_button_get_group(last));
612 inports[c].type = 0;
613 inports[c].id = c;
614 inports[c].connector = this;
615 g_signal_connect(GTK_OBJECT(in), "clicked", G_CALLBACK(inport_clicked), (gpointer*)&inports[c]);
616 if (!first) {
617 first = GTK_RADIO_BUTTON(in);
618 active_in = &inports[c];
619 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(first), TRUE);
621 c++;
623 if (!c) {
624 gtk_widget_set_sensitive(GTK_WIDGET(inframe), FALSE);
625 gtk_widget_set_sensitive(GTK_WIDGET(inview), FALSE);
626 gtk_widget_set_sensitive(GTK_WIDGET(inbut), FALSE);
627 gtk_widget_hide(GTK_WIDGET(inbut));
629 first = NULL;
630 last = NULL;
631 c = 0;
632 // Outputs
633 for (int i = 0; i < strip->plugin->out_count; i++) {
634 sprintf(buf, "Output #%d", (i + 1));
635 GtkWidget *out = gtk_radio_button_new_with_label(NULL, buf);
636 gtk_box_pack_start(GTK_BOX(outputs), out, false, true, 0);
637 gtk_widget_show(GTK_WIDGET(out));
638 if (!i and !last)
639 last = GTK_RADIO_BUTTON(out);
640 else
641 gtk_radio_button_set_group(GTK_RADIO_BUTTON(out), gtk_radio_button_get_group(last));
642 outports[c].type = 1;
643 outports[c].id = c;
644 outports[c].connector = this;
645 g_signal_connect(GTK_OBJECT(out), "clicked", G_CALLBACK(outport_clicked), (gpointer*)&outports[c]);
646 if (!first) {
647 first = GTK_RADIO_BUTTON(out);
648 active_out = &outports[c];
649 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(first), TRUE);
651 c++;
653 if (!c) {
654 gtk_widget_set_sensitive(GTK_WIDGET(outframe), FALSE);
655 gtk_widget_set_sensitive(GTK_WIDGET(outview), FALSE);
656 gtk_widget_set_sensitive(GTK_WIDGET(outbut), FALSE);
657 gtk_widget_hide(GTK_WIDGET(outbut));
659 first = NULL;
660 last = NULL;
661 c = 0;
662 // MIDI
663 if (strip->plugin->get_metadata_iface()->get_midi()) {
664 GtkWidget *mid = gtk_radio_button_new_with_label(NULL, "MIDI");
665 gtk_box_pack_start(GTK_BOX(midi), mid, false, true, 0);
666 midiports[c].type = 2;
667 midiports[c].id = c;
668 midiports[c].connector = this;
669 g_signal_connect(GTK_OBJECT(mid), "clicked", G_CALLBACK(midiport_clicked), (gpointer*)&midiports[c]);
670 gtk_widget_show(GTK_WIDGET(mid));
671 if (!first) {
672 first = GTK_RADIO_BUTTON(mid);
673 active_midi = &midiports[c];
674 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(first), TRUE);
676 c++;
678 if (!c) {
679 //gtk_widget_set_sensitive(GTK_WIDGET(midiframe), FALSE);
680 //gtk_widget_set_sensitive(GTK_WIDGET(midiview), FALSE);
681 //gtk_widget_set_sensitive(GTK_WIDGET(midibut), FALSE);
682 gtk_widget_hide(GTK_WIDGET(midiview));
683 gtk_widget_hide(GTK_WIDGET(midibut));
684 gtk_container_child_set(GTK_CONTAINER(table), GTK_WIDGET(inscroller), "bottom-attach", 2, NULL);
687 // JACK STUFF
689 jackclient = strip->plugin->client->client;
691 //jack_set_port_connect_callback(jackclient, jack_port_connect_callback, this);
692 //jack_set_port_rename_callback(jackclient, jack_port_rename_callback, this);
693 //jack_set_port_registration_callback(jackclient, jack_port_registration_callback , this);
695 fill_inlist(this);
696 fill_outlist(this);
697 fill_midilist(this);