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);
473 : jack.client_insert);
474 if (jack.single_client) {
483 const char** conn_ports = jack_port_get_connections(jack_port);
488 for (list<string>::iterator j = excluded_clients.begin(); j !=
489 excluded_clients.end(); ++j, idx++) {
494 Gtk::TreeIter iter, parent, *parentp;
495 for (ClientList::iterator i = cl.begin(); i != cl.end(); ++i) {
497 if (cl.size() > 1 && p->
ports.size() > max_items_unfolded) {
498 parent = tree->append();
500 (*parent)[columns.connected] =
false;
501 (*parent)[columns.is_port] =
false;
507 for (list<const char*>::iterator j = p->
ports.begin(); j != p->
ports.end(); ++j) {
511 for (
const char** q = conn_ports; *q; q++) {
512 if (strcmp(*q, *j) == 0) {
519 iter = tree->append((*parentp)->children());
521 iter = tree->append();
523 (*iter)[columns.port] = *j;
524 (*iter)[columns.connected] = conn;
525 (*iter)[columns.is_port] =
true;
530 update_summary(portsection[sect]);
534 void PortMapWindow::load_all() {
535 #define uslp() usleep(10); // prevents xruns?? (bug in jackd?) 536 load(0, jack.ports.input.port);
538 load(1, jack.ports.output1.port);
540 load(2, jack.ports.output2.port);
542 load(3, jack.ports.midi_input.port);
544 #if defined(USE_MIDI_OUT) || defined(USE_MIDI_CC_OUT) 545 load(4, jack.ports.midi_output.port);
548 if (!jack.single_client) {
549 load(5, jack.ports.insert_in.port);
551 load(6, jack.ports.insert_out.port);
561 Glib::RefPtr<gx_gui::GxBuilder> bld = gx_gui::GxBuilder::create_from_file(
566 PortMapWindow::PortMapWindow(Glib::RefPtr<gx_gui::GxBuilder> bld,
gx_jack::GxJack& jack_, Glib::RefPtr<Gtk::AccelGroup> ag)
570 monitored_expander_child(0) {
571 bld->get_toplevel(
"PortMapWindow", window);
572 monitored_expander_child = 0;
575 excluded_clients.push_back(
string(jack.client_insert_name) +
":");
576 excluded_clients.push_back(
string(jack.client_name) +
":");
577 excluded_clients.push_back(
string(jack.get_instancename()) +
"_meterbridge:");
578 excluded_clients.push_back(
string(
"jack_capture:"));
583 bld->find_widget(
"button1",b);
585 b->set_name(
"rack_button");
600 for (
int i = 0; i < number_of_ports; ++i) {
601 portsection[i].port_attr = &gx_head_ports[i];
603 snprintf(name,
sizeof(name),
"scrolledwindow%d", i+1);
604 bld->find_widget(name, portsection[i].scrolled_window);
605 snprintf(name,
sizeof(name),
"treeview%d", i+1);
607 bld->find_widget(name, view);
608 Gtk::TreeViewColumn *col = view->get_column(0);
612 Gtk::CellRendererToggle *cell =
dynamic_cast<Gtk::CellRendererToggle*
>(col->get_first_cell_renderer());
614 portsection[i].treestore = Gtk::TreeStore::create(columns);
615 view->set_model(portsection[i].treestore);
621 cell->signal_toggled().connect(
623 sigc::mem_fun(*
this, &PortMapWindow::on_cell_toggle),
624 sigc::ref(portsection[i])));
625 snprintf(name,
sizeof(name),
"expander%d", i+1);
627 if (portsection[i].expander) {
628 portsection[i].expander->property_expanded().signal_changed().connect(
630 sigc::mem_fun(*
this, &PortMapWindow::on_expander),
631 sigc::ref(*portsection[i].expander)));
632 snprintf(name,
sizeof(name),
"port%d", i+1);
633 bld->find_widget(name, portsection[i].label);
639 window->add_accel_group(ag);
640 window->signal_check_resize().connect(sigc::mem_fun(*
this, &PortMapWindow::on_check_resize),
true);
643 bld->find_widget(
"notebook1",n);
645 t = n->get_nth_page(1);
646 if (jack.single_client) t->hide();
649 jack.send_connection_changes(
true);
655 for (
int i = 0; i< number_of_ports; ++i) {
657 Glib::RefPtr<Gtk::TreeStore> tree = ps.
treestore;
659 tree->set_sort_func(0, sigc::mem_fun(*
this, &PortMapWindow::sort_func));
660 tree->set_sort_column_id(0, Gtk::SORT_ASCENDING);
662 update_summary(portsection[i]);
670 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)