#include #include #include #include "jack.h" #include "portmanager.h" void PortManager::Add(jack_port_t *port) { std::string jack_name = jack_port_name(port); std::string client_name; std::string group_name; std::string port_name; char *aliases[2]; aliases[0] = new char[jack_port_name_size()]; aliases[1] = new char[jack_port_name_size()]; int num_aliases = jack_port_get_aliases(port, aliases); if (num_aliases < 2) { pm.AliasBay(port, num_aliases, aliases); num_aliases = jack_port_get_aliases(port, aliases); } if (num_aliases == 2) { jack_name = aliases[1]; } else if (num_aliases == 1) { jack_name = aliases[0]; } delete aliases[0]; delete aliases[1]; size_t pos1 = jack_name.find(':'); size_t pos2 = jack_name.find('.', pos1); // All ports must have a client part if (pos1 == std::string::npos) return; Port *p = new Port(); p->m_port = port; p->m_flags = (JackPortFlags)jack_port_flags(port); std::string type = jack_port_type(port); p->m_is_midi = type == JACK_DEFAULT_MIDI_TYPE; // Client client_name = jack_name.substr(0, pos1); p->m_client = FindOrMakeClient(client_name, p->m_flags & JackPortIsInput, p->m_is_midi); if (pos2 != std::string::npos) { // Group group_name = jack_name.substr(pos1 + 1, pos2 - pos1 - 1); port_name = jack_name.substr(pos2 + 1); } else { group_name = ""; port_name = jack_name.substr(pos1 + 1); } p->m_group = FindOrMakeGroup(p->m_client, p->m_flags, group_name); p->m_group->m_ports.push_back(p); p->m_name = port_name; //std::clog << "New port (" << client_name << ") " << port_name << std::endl; p->m_client->m_ports.push_back(p); m_ports.push_back(p); } void PortManager::Delete(jack_port_t *port) { Port *p = FindPort(port); if (p == NULL) { std::cerr << "Deleting unknown port!" << std::endl; return; } if (p->m_group != NULL) { // Clean up groups p->m_group->m_ports.remove(p); if (p->m_group->m_ports.size() == 0) { p->m_client->m_groups.remove(p->m_group); delete p->m_group; } } // Clean up clients p->m_client->m_ports.remove(p); if (p->m_client->m_ports.size() == 0) { m_clients.remove(p->m_client); delete p->m_client; } // Remove port m_ports.remove(p); //std::clog << "Port '" << p->m_name << "' removed" << std::endl; delete p; } void PortManager::Connect(jack_port_t *port_a, jack_port_t *port_b) { Port *p1 = FindPort(port_a); Port *p2 = FindPort(port_b); if (p1 == NULL || p2 == NULL) { std::cerr << "Connecting unknown ports!" << std::endl; return; } if (p1->m_flags & JackPortIsInput) { p1->m_connections.push_back(p2); } else { p2->m_connections.push_back(p1); } //std::clog << "Connecting '" << jack_port_name(port_a) << "' to '" << jack_port_name(port_b) << "'" << std::endl; } void PortManager::Disconnect(jack_port_t *port_a, jack_port_t *port_b) { Port *p1 = FindPort(port_a); Port *p2 = FindPort(port_b); if (p1 == NULL || p2 == NULL) { std::cerr << "Disconnecting unknown ports!" << std::endl; return; } if (p1->m_flags & JackPortIsInput) { p1->m_connections.remove(p2); } else { p2->m_connections.remove(p1); } //std::clog << "Disconnecting '" << jack_port_name(port_a) << "' from '" << jack_port_name(port_b) << "'" << std::endl; } Client *PortManager::FindOrMakeClient(std::string name, bool is_input, bool is_midi) { ClientList::iterator it; for (it = m_clients.begin(); it != m_clients.end(); ++it) { Client *c = *it; if (c->m_is_input == is_input && c->m_is_midi == is_midi && c->m_name == name) return c; } Client *c = new Client(); c->m_name = name; c->m_is_input = is_input; c->m_is_midi = is_midi; c->m_expanded = true; m_clients.push_back(c); return c; } PortGroup *PortManager::FindOrMakeGroup(Client *client, JackPortFlags flags, std::string name) { PortGroupList::iterator it; for (it = client->m_groups.begin(); it != client->m_groups.end(); ++it) { PortGroup *pg = *it; if (pg->m_flags == flags && pg->m_name == name) return pg; } PortGroup *pg = new PortGroup(); pg->m_name = name; pg->m_flags = flags; pg->m_expanded = false; client->m_groups.push_back(pg); return pg; } Port *PortManager::FindPort(jack_port_t *port) { PortList::iterator it; for (it = m_ports.begin(); it != m_ports.end(); ++it) { Port *p = *it; if (p->m_port == port) return p; } return NULL; } static bool ClientSortPredicate(const Client *lhs, const Client *rhs) { return lhs->m_name < rhs->m_name; } static bool PortGroupSortPredicate(const PortGroup *lhs, const PortGroup *rhs) { return lhs->m_name < rhs->m_name; } static bool PortSortPredicate(const Port *lhs, const Port *rhs) { return lhs->m_name < rhs->m_name; } void PortManager::Sort() { m_clients.sort(&ClientSortPredicate); ClientList::iterator clit; for (clit = m_clients.begin(); clit != m_clients.end(); ++clit) { Client *c = *clit; c->m_groups.sort(&PortGroupSortPredicate); PortGroupList::iterator pglit; for (pglit = c->m_groups.begin(); pglit != c->m_groups.end(); ++pglit) { PortGroup *pg = *pglit; pg->m_ports.sort(&PortSortPredicate); } } } void PortManager::ToggleConnect(Port *a, Port *b) { ConnectionMode cm = a->ConnectedTo(b); if (cm == CM_NONE) { jack.Connect(b->m_port, a->m_port); } else { jack.Disconnect(b->m_port, a->m_port); } } void PortManager::ToggleConnect(Port *a, PortGroup *b) { PortList::iterator plitb; ConnectionMode cm = a->ConnectedTo(b); for (plitb = b->m_ports.begin(); plitb != b->m_ports.end(); ++plitb) { Port *pb = *plitb; // if (connect == 0) { // connect = a->ConnectedTo(pb) ? -1 : 1; // } if (cm == CM_NONE) { jack.Connect(pb->m_port, a->m_port); } else { jack.Disconnect(pb->m_port, a->m_port); } } } void PortManager::ToggleConnect(PortGroup *a, Port *b) { PortList::iterator plita; ConnectionMode cm = a->ConnectedTo(b); for (plita = a->m_ports.begin(); plita != a->m_ports.end(); ++plita) { Port *pa = *plita; // if (connect == 0) { // connect = pa->ConnectedTo(b) ? -1 : 1; // } if (cm == CM_NONE) { jack.Connect(b->m_port, pa->m_port); } else { jack.Disconnect(b->m_port, pa->m_port); } } } void PortManager::ToggleConnect(PortGroup *a, PortGroup *b) { PortList::iterator plita; PortList::iterator plitb; ConnectionMode cm = a->ConnectedTo(b); for (plita = a->m_ports.begin(), plitb = b->m_ports.begin(); plita != a->m_ports.end() && plitb != b->m_ports.end(); ++plita, ++plitb) { Port *pa = *plita; Port *pb = *plitb; if (cm == CM_NONE) { jack.Connect(pb->m_port, pa->m_port); } else { jack.Disconnect(pb->m_port, pa->m_port); } } } void PortManager::AliasBay(jack_port_t *port, int num_aliases, char *aliases[2]) { std::string port_name = jack_port_name(port); AliasList::iterator it; for (it = m_aliases.begin(); it != m_aliases.end(); ++it) { Alias &a = *it; if (a.name == port_name) { bool got = false; for (int i = 0; i < num_aliases; i++) { if (a.alias == aliases[i]) got = true; } if (!got) { jack_port_set_alias(port, a.alias.c_str()); } } } } void PortManager::AliasLoad(std::string filename) { std::ifstream file; file.open(filename.c_str()); if (!file) return; char line[1024]; while (file.getline(line, sizeof line)) { std::istringstream iss(line); Alias a; iss >> a.name; iss >> a.alias; m_aliases.push_back(a); } }