#include "jackEngine.h"
#include
#include
bool jack_process_busy = false;
int jack_process_disable = 0; // Non-zero value = disabled
// ============================================================================
// gidJackClient class
// ============================================================================
jackEngine::jackEngine(QObject *parent) :
QObject(parent)
{
this->clientActive = false;
buffer = midiBuffer();
}
void jackEngine::jackPortConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg)
{
}
void jackEngine::jackPortRegistrationCallback(jack_port_id_t port, int registered, void *arg)
{
}
int jackEngine::jackProcessCallback(jack_nframes_t nframes, void *arg)
{
jack_process_busy = true;
if (jack_process_disable) {
jack_process_busy = false;
return 0;
}
// --------------------------------
jackEngine* e = (jackEngine*)arg;
void* portBuffer = jack_port_get_buffer( e->midi_output_port, nframes );
jack_midi_clear_buffer(portBuffer);
// for each event in our buffer...
for (int size=e->buffer.canRead(); size>0; size=e->buffer.canRead()) {
// Get Jack output buffer
jack_midi_data_t* out_buffer = jack_midi_event_reserve( portBuffer, 0, size);
// Copy buffer data to output buffer
e->buffer.read(out_buffer);
}
// --------------------------------
jack_process_busy = false;
return 0;
}
void jackEngine::startJackTransport()
{
jack_transport_start(client);
}
void jackEngine::stopJackTransport()
{
jack_transport_stop(client);
}
bool jackEngine::isTransportStopped()
{
return jack_transport_query(client, NULL) == JackTransportStopped;
}
bool jackEngine::clientIsActive()
{
return this->clientActive;
}
QString jackEngine::clientName()
{
return ourJackClientName;
}
/* Pauses (pause=true) or unpauses (pause=false) the Jack process callback function.
* When pause=true, the Jack process callback is disabled and this function blocks
* until the current execution of the process callback (if any) competes, before
* returning, thus ensuring that the process callback will not execute until this
* function is called again with pause=false. */
void jackEngine::pauseJackProcessing(bool pause)
{
/* When jack_process_disable is non-zero, Jack process is disabled. Here it is
* incremented or decremented, accounting for the fact that this function might
* be called multiple times within nested functions. Only once all of the callers
* have also called this function with pause=false, will it reach zero, enabling
* the Jack process callback again. */
if (pause) {
jack_process_disable++;
while (jack_process_busy) {}
} else {
if (jack_process_disable) {
jack_process_disable--;
}
}
}
bool jackEngine::InitJackClient(QString name)
{
// Try to become a client of the jack server
if ( (client = jack_client_open(name.toLocal8Bit(), JackNullOption, NULL)) == NULL) {
userMessage("JACK: Error becoming client.");
this->clientActive = false;
return false;
} else {
ourJackClientName = jack_get_client_name(client); // jack_client_open modifies the given name if another client already uses it.
userMessage("JACK: Client created: " + ourJackClientName);
this->clientActive = true;
}
// Set up midi input port
//setOurMidiInputPortName( ourJackClientName + ":" +
// QString::fromLocal8Bit(GID_JACK_MIDI_IN_PORT_NAME));
// Set up callback functions
jack_set_port_connect_callback(client, jackEngine::jackPortConnectCallback, this);
jack_set_port_registration_callback(client, jackEngine::jackPortRegistrationCallback, this);
jack_set_process_callback (client, jackEngine::jackProcessCallback, this);
// Set up output midi port
midi_output_port = jack_port_register ( client,
JACKENGINE_MIDI_OUT_PORT_NAME,
JACK_DEFAULT_MIDI_TYPE,
JackPortIsOutput, 0);
nframes = jack_get_buffer_size(client);
// Activate the client
if (jack_activate(client)) {
userMessage("JACK: Cannot activate client.");
jack_free(client);
this->clientActive = false;
return false;
} else {
userMessage("JACK: Activated client.");
this->clientActive = true;
}
return true;
}
void jackEngine::stopJackClient()
{
if (clientIsActive()) {
jack_client_close(client);
this->clientActive = false;
}
}
// Works exactly the same as the midiBuffer write function.
int jackEngine::addMidiEventToBuffer(unsigned char *data, int size)
{
return buffer.write(data, size);
}
// Print error message to stdout, and abort app.
void jackEngine::error_abort(QString msg)
{
std::cout