jsweeper/src/jack.cpp

154 lines
3.5 KiB
C++

#include <iostream>
#include <stdlib.h>
#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));
}