37 static PortAttr gx_head_ports[] = {
39 { 0,
false,
"in_0",
true, JACK_DEFAULT_AUDIO_TYPE },
40 { 1,
false,
"out_0",
false, JACK_DEFAULT_AUDIO_TYPE },
41 { 1,
false,
"out_1",
false, JACK_DEFAULT_AUDIO_TYPE },
42 { 0,
false,
"midi_in_1",
true, JACK_DEFAULT_MIDI_TYPE },
43 { 0,
false,
"midi_out_1",
false, JACK_DEFAULT_MIDI_TYPE },
44 { 1,
true,
"in_0",
true, JACK_DEFAULT_AUDIO_TYPE },
45 { 0,
true,
"out_0",
false, JACK_DEFAULT_AUDIO_TYPE },
48 #define ALSA_PCM "alsa_pcm" // special alsa sequencer gxjack.client 49 #define ALSA_PCM_LEN_1 9 62 inline void add(
const char *p) { ports.push_back(p); }
63 inline bool sameclient(
const char *p) {
return strncmp(client, p, len) == 0; }
64 string clientname() {
return string(*ports.begin()).substr(0, len-1); }
69 const char *q = strchr(p,
':');
73 q = strchr(p+
len,
'/');
86 static bool str_compare(
const char *a,
const char *b);
89 void remove(
string excl);
93 return strcmp(b, a) > 0;
98 for (
int i = 0; ports[i]; ++i) {
99 l.push_back(ports[i]);
106 for (list<const char*>::iterator j = l.begin(); j != l.end(); ++j) {
117 for (list<ClientPortList*>::iterator i = begin(); i !=
end(); ++i) {
123 for (list<ClientPortList*>::iterator i = begin(); i !=
end();) {
124 if ((*i)->sameclient(excl.c_str())) {
125 list<ClientPortList*>::iterator n = i++;
144 static string client_from_port(
const string& port) {
145 size_t pos = port.find_first_of(
':');
146 if (pos == string::npos) {
149 string s = port.substr(0, pos);
154 if (p2 == string::npos) {
157 return port.substr(0, p2);
160 static bool compare_client(
const string& name,
const string& p) {
161 if (name.compare(0, name.size(), p, 0, name.size()) == 0) {
162 if (p[name.size()] ==
':' || p.size() == name.size()) {
167 if (name.compare(0, name.size(), p,
ALSA_PCM_LEN_1, name.size()) == 0) {
168 if (p[ALSA_PCM_LEN_1+name.size()] ==
'/' || p.size() == ALSA_PCM_LEN_1+name.size()) {
176 static bool compare_port(
const string& name,
const char *p) {
177 return name.compare(p) == 0;
180 bool PortMapWindow::walk_remove(Glib::RefPtr<Gtk::TreeStore> ts,
bool (*compare)
181 (
const string&,
const char*),
string data) {
182 bool changed =
false;
183 Gtk::TreeIter i(ts->children().begin());
185 if ((*i)[columns.is_port]) {
186 if (data == (*i)[columns.port]) {
192 Gtk::TreeIter j(i->children().begin());
194 if (data == (*j)[columns.port]) {
207 void PortMapWindow::walk_insert(Glib::RefPtr<Gtk::TreeStore> ts,
string name) {
209 for (Gtk::TreeIter i(ts->children().begin()); i; ++i) {
210 Glib::ustring p = (*i)[columns.port];
214 if (!(*i)[columns.is_port] && compare_client(client_from_port(name), p)) {
216 for (Gtk::TreeIter j(i->children().begin()); j; ++j) {
218 if (name == (*j)[columns.port]) {
222 Gtk::TreeRow row = *ts->append(i->children());
223 row[columns.port] = name;
224 row[columns.connected] =
false;
225 row[columns.is_port] =
true;
229 Gtk::TreeRow row = *ts->append();
230 row[columns.port] = name;
231 row[columns.connected] =
false;
232 row[columns.is_port] =
true;
235 void PortMapWindow::port_changed(
string name,
const char *tp,
int flags,
bool reg) {
237 for (
int i = 0; i < number_of_ports; ++i) {
239 if (walk_remove(p.
treestore, compare_port, name)) {
244 for (list<string>::iterator j = excluded_clients.begin();
245 j != excluded_clients.end(); ++j) {
246 if (name.compare(0, j->size(), *j) == 0) {
250 for (
int i = 0; i < number_of_ports; ++i) {
256 if (!(flags & JackPortIsOutput)) {
260 if (!(flags & JackPortIsInput)) {
274 list<string> PortMapWindow::walk(Glib::RefPtr<Gtk::TreeStore> ts,
string *port,
int connect) {
276 for (Gtk::TreeIter i(ts->children().begin()); i; ++i) {
277 Glib::ustring p = (*i)[columns.port];
278 bool is_connected = (*i)[columns.connected];
279 if ((*i)[columns.is_port]) {
280 if (port && port->compare(p) == 0) {
281 is_connected = connect;
282 (*i)[columns.connected] = connect;
288 for (Gtk::TreeIter j(i->children().begin()); j; ++j) {
289 Glib::ustring p = (*j)[columns.port];
290 bool is_connected = (*j)[columns.connected];
291 if (port && port->compare(p) == 0) {
292 is_connected = connect;
293 (*j)[columns.connected] = connect;
304 void PortMapWindow::update_summary(
PortSection& p,
string *port,
bool conn) {
305 list<string> l = walk(p.
treestore, port, conn);
310 list<string>::iterator i = l.begin();
314 for (; i != l.end(); ++i) {
317 p.
label->set_text(q);
318 Glib::signal_idle().connect_once(
320 sigc::mem_fun(*
this, &PortMapWindow::redraw_expander), p.
expander));
324 for (
int i = 0; i < number_of_ports; ++i) {
328 jack.client_name : jack.client_insert_name)
330 if (s.compare(port1) == 0) {
331 update_summary(p, &port2, conn);
332 }
else if (s.compare(port2) == 0) {
333 update_summary(p, &port1, conn);
343 void PortMapWindow::on_check_resize() {
345 if (monitored_expander_child &&
346 !monitored_expander_child->get_child_visible()) {
347 monitored_expander_child = 0;
348 int x, y, width, height, depth;
349 window->get_window()->get_geometry(x, y, width, height, depth);
350 window->resize(width, 1);
354 void PortMapWindow::on_expander(Gtk::Expander& expander) {
355 gboolean expanded = expander.get_expanded();
358 for (
int i = 0; i < number_of_ports; ++i) {
359 Gtk::Expander *w = portsection[i].expander;
360 if (&expander != w) {
367 w->set_expanded(
false);
378 expander.set_expanded(expanded);
386 monitored_expander_child = expander.get_child();
390 void PortMapWindow::redraw_expander(Gtk::Expander* ex) {
394 void PortMapWindow::on_cell_toggle(Glib::ustring path,
PortSection& p) {
395 Gtk::TreeIter iter(p.
treestore->get_iter(path));
396 Glib::ustring q1 = (*iter)[columns.port];
397 bool v = (*iter)[columns.connected];
402 gcln = jack.client_name;
404 gcl = jack.client_insert;
405 gcln = jack.client_insert_name;
409 Glib::ustring sw = q1;
418 ret = jack_connect(gcl, q1.c_str(), q2.c_str());
420 ret = jack_disconnect(gcl, q1.c_str(), q2.c_str());
425 buf <<
"couldn't " << (v ?
"" :
"dis") <<
"connect " << q2 <<
" -> " << q1;
429 (*iter)[columns.connected] = v;
437 inline bool getnumber(
const Glib::ustring& p,
long *pi) {
439 *pi = strtol(p.c_str(), &q, 10);
443 int PortMapWindow::sort_func(
const Gtk::TreeModel::iterator& a,
const Gtk::TreeModel::iterator& b) {
444 Glib::ustring pa((*a)[columns.port]), pb((*b)[columns.port]);
447 if (pa[i] != pb[i]) {
458 return pa.compare(pb);
461 void PortMapWindow::load(
int sect, jack_port_t *jack_port) {
463 const unsigned int max_items_unfolded = 1;
465 Glib::RefPtr<Gtk::TreeStore> tree = ps.
treestore;
467 tree->set_sort_func(0, sigc::mem_fun(*
this, &PortMapWindow::sort_func));
468 tree->set_sort_column_id(0, Gtk::SORT_ASCENDING);
472 : jack.client_insert);
478 const char** conn_ports = jack_port_get_connections(jack_port);
483 for (list<string>::iterator j = excluded_clients.begin(); j !=
484 excluded_clients.end(); ++j, idx++) {
489 Gtk::TreeIter iter, parent, *parentp;
490 for (ClientList::iterator i = cl.begin(); i != cl.end(); ++i) {
492 if (cl.size() > 1 && p->
ports.size() > max_items_unfolded) {
493 parent = tree->append();
495 (*parent)[columns.connected] =
false;
496 (*parent)[columns.is_port] =
false;
502 for (list<const char*>::iterator j = p->
ports.begin(); j != p->
ports.end(); ++j) {
506 for (
const char** q = conn_ports; *q; q++) {
507 if (strcmp(*q, *j) == 0) {
514 iter = tree->append((*parentp)->children());
516 iter = tree->append();
518 (*iter)[columns.port] = *j;
519 (*iter)[columns.connected] = conn;
520 (*iter)[columns.is_port] =
true;
525 update_summary(portsection[sect]);
529 void PortMapWindow::load_all() {
530 #define uslp() usleep(10); // prevents xruns?? (bug in jackd?) 531 load(0, jack.ports.input.port);
533 load(1, jack.ports.output1.port);
535 load(2, jack.ports.output2.port);
537 load(3, jack.ports.midi_input.port);
539 #if defined(USE_MIDI_OUT) || defined(USE_MIDI_CC_OUT) 540 load(4, jack.ports.midi_output.port);
543 load(5, jack.ports.insert_in.port);
545 load(6, jack.ports.insert_out.port);
554 Glib::RefPtr<gx_gui::GxBuilder> bld = gx_gui::GxBuilder::create_from_file(
559 PortMapWindow::PortMapWindow(Glib::RefPtr<gx_gui::GxBuilder> bld,
gx_jack::GxJack& jack_, Glib::RefPtr<Gtk::AccelGroup> ag)
563 monitored_expander_child(0) {
564 bld->get_toplevel(
"PortMapWindow", window);
565 monitored_expander_child = 0;
568 excluded_clients.push_back(
string(jack.client_insert_name) +
":");
569 excluded_clients.push_back(
string(jack.client_name) +
":");
570 excluded_clients.push_back(
string(jack.get_instancename()) +
"_meterbridge:");
571 excluded_clients.push_back(
string(
"jack_capture:"));
576 bld->find_widget(
"button1",b);
578 b->set_name(
"rack_button");
593 for (
int i = 0; i < number_of_ports; ++i) {
594 portsection[i].port_attr = &gx_head_ports[i];
596 snprintf(name,
sizeof(name),
"scrolledwindow%d", i+1);
597 bld->find_widget(name, portsection[i].scrolled_window);
598 snprintf(name,
sizeof(name),
"treeview%d", i+1);
600 bld->find_widget(name, view);
601 Gtk::TreeViewColumn *col = view->get_column(0);
605 Gtk::CellRendererToggle *cell =
dynamic_cast<Gtk::CellRendererToggle*
>(col->get_first_cell_renderer());
607 portsection[i].treestore = Gtk::TreeStore::create(columns);
608 view->set_model(portsection[i].treestore);
614 cell->signal_toggled().connect(
616 sigc::mem_fun(*
this, &PortMapWindow::on_cell_toggle),
617 sigc::ref(portsection[i])));
618 snprintf(name,
sizeof(name),
"expander%d", i+1);
620 if (portsection[i].expander) {
621 portsection[i].expander->property_expanded().signal_changed().connect(
623 sigc::mem_fun(*
this, &PortMapWindow::on_expander),
624 sigc::ref(*portsection[i].expander)));
625 snprintf(name,
sizeof(name),
"port%d", i+1);
626 bld->find_widget(name, portsection[i].label);
632 window->add_accel_group(ag);
633 window->signal_check_resize().connect(sigc::mem_fun(*
this, &PortMapWindow::on_check_resize),
true);
637 jack.send_connection_changes(
true);
643 for (
int i = 0; i< number_of_ports; ++i) {
645 Glib::RefPtr<Gtk::TreeStore> tree = ps.
treestore;
647 tree->set_sort_func(0, sigc::mem_fun(*
this, &PortMapWindow::sort_func));
648 tree->set_sort_column_id(0, Gtk::SORT_ASCENDING);
650 update_summary(portsection[i]);
658 jack.send_connection_changes(
false);
CmdConnection::msg_type end
BasicOptions & get_options()
ClientPortList(const char *p)
void connection_changed(string port1, string port2, bool conn)
virtual gx_jack::GxJack * get_jack()=0
void gx_print_error(const char *, const std::string &)
list< const char * > ports
Glib::RefPtr< Gtk::TreeStore > treestore
bool getnumber(const Glib::ustring &p, long *pi)
static bool str_compare(const char *a, const char *b)
bool sameclient(const char *p)
ClientList(const char **)
static PortMapWindow * create(gx_engine::GxMachineBase &machine, Glib::RefPtr< Gtk::AccelGroup > ag)