#include #include #include "jack.h" #include "portmanager.h" JackDriver::JackDriver() { m_connected = false; m_client = NULL; } JackDriver::~JackDriver() { Disconnect(); } void JackDriver::Connect() { if (m_connected) return; jack_status_t status; m_client = jack_client_open("jsweeper", JackNoStartServer, &status); if (m_client == NULL) { if (status & JackServerFailed) { std::cerr << "JACK server not running" << std::endl; } else { std::cerr << "jack_client_open() failed, status = " << status << std::endl; } return; } m_buffer = jack_ringbuffer_create(4096); m_connected = true; jack_on_shutdown(m_client, &ShutdownCallbackHandler, this); jack_set_port_registration_callback(m_client, &PortRegistrationCallbackHandler, this); jack_set_port_connect_callback(m_client, &PortConnectCallbackHandler, this); jack_activate(m_client); const char **ports = jack_get_ports(m_client, NULL, NULL, 0); for (int i = 0; ports[i] != NULL; ++i) { pm.Add(jack_port_by_name(m_client, ports[i])); } for (int i = 0; ports[i] != NULL; ++i) { jack_port_t *port = jack_port_by_name(m_client, ports[i]); if (jack_port_flags(port) & JackPortIsInput) { const char **connections = jack_port_get_all_connections(m_client, port); if (connections != NULL) { for (int j = 0; connections[j] != NULL; ++j) { pm.Connect(port, jack_port_by_name(m_client, connections[j])); } free(connections); } } } free(ports); return; } void JackDriver::Disconnect() { if (!m_connected) return; m_connected = false; jack_deactivate(m_client); jack_client_close(m_client); jack_ringbuffer_free(m_buffer); } void JackDriver::ShutdownCallback() { m_connected = false; } void JackDriver::PortRegistrationCallback(jack_port_id_t port_id, int reg) { PortEvent pe; pe.type = reg ? PET_REGISTER : PET_UNREGISTER; pe.port_id_a = port_id; if (jack_ringbuffer_write_space(m_buffer) < sizeof pe) { std::cerr << "Ringbuffer full!" << std::endl; } else { jack_ringbuffer_write(m_buffer, (const char *)&pe, sizeof pe); } } void JackDriver::PortConnectCallback(jack_port_id_t port_id_a, jack_port_id_t port_id_b, int connect) { PortEvent pe; pe.type = connect ? PET_CONNECT : PET_DISCONNECT; pe.port_id_a = port_id_a; pe.port_id_b = port_id_b; if (jack_ringbuffer_write_space(m_buffer) < sizeof pe) { std::cerr << "Ringbuffer full!" << std::endl; } else { jack_ringbuffer_write(m_buffer, (const char *)&pe, sizeof pe); } } bool JackDriver::ProcessEvents() { bool ret = false; if (!m_connected) return false; PortEvent pe; while (jack_ringbuffer_read_space(m_buffer) >= sizeof pe) { jack_ringbuffer_read(m_buffer, (char *)&pe, sizeof pe); switch (pe.type) { case PET_REGISTER: pm.Add(jack_port_by_id(m_client, pe.port_id_a)); ret = true; break; case PET_UNREGISTER: pm.Delete(jack_port_by_id(m_client, pe.port_id_a)); ret = true; break; case PET_CONNECT: pm.Connect(jack_port_by_id(m_client, pe.port_id_a), jack_port_by_id(m_client, pe.port_id_b)); ret = true; break; case PET_DISCONNECT: pm.Disconnect(jack_port_by_id(m_client, pe.port_id_a), jack_port_by_id(m_client, pe.port_id_b)); ret = true; break; } } return ret; } void JackDriver::Connect(jack_port_t *a, jack_port_t *b) { jack_connect(m_client, jack_port_name(a), jack_port_name(b)); } void JackDriver::Disconnect(jack_port_t *a, jack_port_t *b) { jack_disconnect(m_client, jack_port_name(a), jack_port_name(b)); }