VulcanoLE/src/VulcanoLE/Audio/JackClient.cpp

134 lines
5.1 KiB
C++

#include <VulcanoLE/Audio/JackClient.h>
#include <VUtils/Logging.h>
int JackClient::processSamples(jack_nframes_t frames, void *arg) {
JackClient &client = JackClient::get();
jack_default_audio_sample_t *inl;
jack_default_audio_sample_t *inr;
unsigned int i;
if (client.input_port_l == nullptr || client.input_port_r == nullptr) {
return 0;
}
inl = (jack_default_audio_sample_t *) jack_port_get_buffer(client.input_port_l, frames);
inr = (jack_default_audio_sample_t *) jack_port_get_buffer(client.input_port_r, frames);
client.addFrames(inl, inr, frames);
return 0;
}
void JackClient::onExit() {
DBG("SHUTDOWN JACK!")
JackClient &jackClient = JackClient::get();
const char **all_ports;
unsigned int i;
if (jackClient.input_port_l != nullptr) {
all_ports = jack_port_get_all_connections(jackClient.client, jackClient.input_port_l);
for (i = 0; all_ports && all_ports[i]; i++) {
jack_disconnect(jackClient.client, all_ports[i], jack_port_name(jackClient.input_port_l));
}
all_ports = jack_port_get_all_connections(jackClient.client, jackClient.input_port_r);
for (i = 0; all_ports && all_ports[i]; i++) {
jack_disconnect(jackClient.client, all_ports[i], jack_port_name(jackClient.input_port_r));
}
}
jack_client_close(jackClient.client);
}
void JackClient::connect(const char *port_name, jack_port_t *channel) {
jack_port_t *port;
port = jack_port_by_name(client, port_name);
if (port == nullptr) {
ERR("Cannot Find Port: %s", port_name)
exit(1);
}
LOG("Connecting %s to %s", jack_port_name(port), jack_port_name(channel))
if (jack_connect(client, jack_port_name(port), jack_port_name(channel))) {
ERR("Cannot connect port '%s' to '%s'", jack_port_name(port), jack_port_name(channel))
exit(1);
}
}
void JackClient::start() {
jack_status_t status;
client = jack_client_open("Keyboard Visual", options, &status);
if (client == nullptr) {
ERR("Failed to start JACK client: %d", status)
exit(1);
}
DBG("Register as %s", jack_get_client_name(client))
input_port_l = jack_port_register(client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, BUFFER_SIZE);
input_port_r = jack_port_register(client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, BUFFER_SIZE);
if (!input_port_l || !input_port_r) {
ERR("Cannot Register input port left")
exit(1);
}
atexit(JackClient::onExit);
jack_set_process_callback(client, JackClient::processSamples, nullptr);
if (jack_activate(client)) {
ERR("Cannot Activate Client")
exit(1);
}
auto inputL = env->getEnv("input_l", "");
auto inputR = env->getEnv("input_r", "");
DBG("Try Using InputL: %s", inputL.c_str())
DBG("Try Using InputR: %s", inputR.c_str())
if (inputL.empty() || inputR.empty() || !checkPort(inputL) || !checkPort(inputR)) {
inputL = getPort(true);
inputR = getPort(false);
DBG("Picking new InputL: %s", inputL.c_str())
DBG("Picking new InputR: %s", inputR.c_str())
env->set("input_l", inputL.c_str());
env->set("input_r", inputR.c_str());
}
if (inputL.empty() || inputR.empty()) return;
connect(inputL.c_str(), input_port_l);
connect(inputR.c_str(), input_port_r);
}
bool JackClient::isData() {
std::lock_guard<std::mutex> lockGuard(guard);
return m_newDataAvailable;
}
std::string JackClient::getPort(bool isLeft) {
std::string type = isLeft ? ":monitor_FL" : ":monitor_FR";
auto port = jack_get_ports(client, type.c_str(), nullptr,
JackPortIsOutput);
if (port == nullptr)
return "";
return std::string(port[0]);
}
bool JackClient::checkPort(const std::string &port) {
return jack_get_ports(client, port.c_str(), nullptr,
JackPortIsOutput) != nullptr;
}
void JackClient::addFrames(jack_default_audio_sample_t *l, jack_default_audio_sample_t *r, jack_nframes_t i) {
std::lock_guard<std::mutex> lockGuard(guard);
if (!grabber)
return;
if (grabber->requestMode == AudioGrabber::ReqMode::FFT || grabber->requestMode == AudioGrabber::ReqMode::ALL) {
for (int j = 0; j < i; ++j) {
if (samplesAdded >= BUFFER_SIZE) {
for (int k = 0; k < BUFFER_SIZE; ++k) {
samples[k].l = ringBuffer[k].l;
samples[k].r = ringBuffer[k].r;
}
m_newDataAvailable = true;
samplesAdded = 0;
}
ringBuffer[samplesAdded].l = l[j];
ringBuffer[samplesAdded].r = r[j];
samplesAdded++;
}
} else {
for (int k = 0; k < i; ++k) {
samples[k].l = l[k];
samples[k].r = r[k];
}
m_newDataAvailable = true;
samplesAdded = (int) i;
}
}
int JackClient::getFrames() {
std::lock_guard<std::mutex> lockGuard(guard);
return grabber->requestMode == AudioGrabber::ReqMode::FFT || grabber->requestMode == AudioGrabber::ReqMode::ALL
? BUFFER_SIZE : samplesAdded;
}