154 lines
3.5 KiB
C++
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));
|
|
}
|
|
|