2013-04-20 12:37:36 +02:00
|
|
|
|
|
|
|
#include "jack.hxx"
|
|
|
|
|
|
|
|
#include <sstream>
|
|
|
|
#include <cstring>
|
|
|
|
#include <iostream>
|
|
|
|
|
2013-08-22 02:29:55 +02:00
|
|
|
#include "audiobuffer.hxx"
|
2013-04-20 12:54:16 +02:00
|
|
|
#include "eventhandler.hxx"
|
2013-08-22 05:32:51 +02:00
|
|
|
#include "controller/guicontroller.hxx"
|
2013-09-06 15:18:27 +02:00
|
|
|
#include "controller/genericmidi.hxx"
|
2013-08-04 19:04:26 +02:00
|
|
|
|
2013-04-20 12:37:36 +02:00
|
|
|
using namespace std;
|
|
|
|
|
2013-08-22 02:29:55 +02:00
|
|
|
int AudioBuffer::privateID = 0;
|
|
|
|
|
2013-08-22 14:53:50 +02:00
|
|
|
// static pointer from main.
|
|
|
|
extern Jack* jack;
|
|
|
|
|
2013-04-20 12:37:36 +02:00
|
|
|
extern int jackSamplerate;
|
|
|
|
|
2013-07-31 18:19:15 +02:00
|
|
|
Jack::Jack() :
|
2013-08-13 17:35:27 +02:00
|
|
|
client( jack_client_open ( "Luppp", JackNullOption , 0 , 0 ) ),
|
2013-08-04 19:04:26 +02:00
|
|
|
timeManager(),
|
2013-08-13 17:35:27 +02:00
|
|
|
controllerUpdater( new ControllerUpdater() ),
|
2013-09-06 01:28:11 +02:00
|
|
|
state( new State() ),
|
2013-08-13 17:35:27 +02:00
|
|
|
clientActive(false)
|
2013-04-20 12:37:36 +02:00
|
|
|
{
|
2013-08-22 14:53:50 +02:00
|
|
|
jack = this;
|
|
|
|
// construct Observer classes here, not in the initializer list as the Jack*
|
|
|
|
// will be 0x0 until then.
|
|
|
|
metronome = new Metronome();
|
|
|
|
logic = new Logic();
|
|
|
|
gridLogic = new GridLogic();
|
|
|
|
|
|
|
|
|
2013-05-14 01:03:43 +02:00
|
|
|
buffers.nframes = jack_get_buffer_size( client );
|
|
|
|
buffers.samplerate = jack_get_sample_rate( client );
|
2013-04-20 12:37:36 +02:00
|
|
|
|
2013-07-28 15:20:54 +02:00
|
|
|
uiUpdateCounter = buffers.samplerate / 30;
|
|
|
|
uiUpdateConstant = buffers.samplerate / 30;
|
2013-07-26 02:39:06 +02:00
|
|
|
|
2013-08-13 01:02:59 +02:00
|
|
|
masterInput = jack_port_register( client,
|
|
|
|
"master_in",
|
|
|
|
JACK_DEFAULT_AUDIO_TYPE,
|
|
|
|
JackPortIsInput,
|
|
|
|
0 );
|
|
|
|
|
2013-09-11 02:32:58 +02:00
|
|
|
masterReturnL = jack_port_register( client,
|
|
|
|
"master_return_left",
|
|
|
|
JACK_DEFAULT_AUDIO_TYPE,
|
|
|
|
JackPortIsInput,
|
|
|
|
0 );
|
|
|
|
|
|
|
|
masterReturnR = jack_port_register( client,
|
|
|
|
"master_return_right",
|
|
|
|
JACK_DEFAULT_AUDIO_TYPE,
|
|
|
|
JackPortIsInput,
|
|
|
|
0 );
|
|
|
|
|
2013-07-31 12:34:28 +02:00
|
|
|
masterOutputL = jack_port_register( client,
|
|
|
|
"master_left",
|
|
|
|
JACK_DEFAULT_AUDIO_TYPE,
|
|
|
|
JackPortIsOutput,
|
|
|
|
0 );
|
2013-08-13 01:02:59 +02:00
|
|
|
|
2013-07-31 12:34:28 +02:00
|
|
|
masterOutputR = jack_port_register( client,
|
|
|
|
"master_right",
|
2013-04-20 12:37:36 +02:00
|
|
|
JACK_DEFAULT_AUDIO_TYPE,
|
|
|
|
JackPortIsOutput,
|
|
|
|
0 );
|
|
|
|
|
2013-09-11 02:32:58 +02:00
|
|
|
sendOutput = jack_port_register( client,
|
|
|
|
"send_out",
|
|
|
|
JACK_DEFAULT_AUDIO_TYPE,
|
|
|
|
JackPortIsOutput,
|
|
|
|
0 );
|
|
|
|
|
|
|
|
sidechainKeyOutput= jack_port_register( client,
|
|
|
|
"sidechain_key",
|
|
|
|
JACK_DEFAULT_AUDIO_TYPE,
|
|
|
|
JackPortIsOutput,
|
|
|
|
0 );
|
|
|
|
|
|
|
|
sidechainSignalOutput= jack_port_register( client,
|
|
|
|
"sidechain_signal",
|
|
|
|
JACK_DEFAULT_AUDIO_TYPE,
|
|
|
|
JackPortIsOutput,
|
|
|
|
0 );
|
|
|
|
|
2013-05-18 17:37:03 +02:00
|
|
|
masterMidiInput = jack_port_register( client,
|
|
|
|
"midi_in",
|
|
|
|
JACK_DEFAULT_MIDI_TYPE,
|
|
|
|
JackPortIsInput,
|
|
|
|
0 );
|
|
|
|
|
2013-08-16 13:50:31 +02:00
|
|
|
masterVol = 0.77;
|
2013-07-28 14:42:05 +02:00
|
|
|
|
|
|
|
/// prepare internal buffers
|
2013-09-11 02:32:58 +02:00
|
|
|
buffers.audio[Buffers::SEND] = new float[ buffers.nframes ];
|
|
|
|
buffers.audio[Buffers::SIDECHAIN_KEY] = new float[ buffers.nframes ];
|
|
|
|
buffers.audio[Buffers::SIDECHAIN_SIGNAL]=new float[ buffers.nframes ];
|
2013-08-13 01:02:59 +02:00
|
|
|
|
2013-08-16 00:21:13 +02:00
|
|
|
buffers.audio[Buffers::MASTER_OUT_L] = new float[ buffers.nframes ];
|
|
|
|
buffers.audio[Buffers::MASTER_OUT_R] = new float[ buffers.nframes ];
|
2013-07-31 02:05:14 +02:00
|
|
|
|
2013-07-26 02:27:19 +02:00
|
|
|
for(int i = 0; i < NTRACKS; i++)
|
|
|
|
{
|
|
|
|
loopers.push_back( new Looper(i) );
|
2013-07-31 02:05:14 +02:00
|
|
|
trackOutputs.push_back( new TrackOutput(i, loopers.back() ) );
|
2013-07-31 03:48:59 +02:00
|
|
|
|
2013-08-16 00:21:13 +02:00
|
|
|
buffers.audio[Buffers::TRACK_0 + i] = new float[ buffers.nframes ];
|
|
|
|
|
2013-07-31 03:48:59 +02:00
|
|
|
timeManager.registerObserver( loopers.back() );
|
2013-07-26 02:27:19 +02:00
|
|
|
}
|
|
|
|
|
2013-09-11 02:32:58 +02:00
|
|
|
/// setup DSP instances
|
2013-07-31 02:43:24 +02:00
|
|
|
masterMeter = new DBMeter( buffers.samplerate );
|
2013-09-10 22:44:47 +02:00
|
|
|
inputMeter = new DBMeter( buffers.samplerate );
|
2013-07-28 15:20:54 +02:00
|
|
|
|
|
|
|
/// setup JACK callbacks
|
2013-04-20 12:37:36 +02:00
|
|
|
if ( jack_set_process_callback( client,
|
2013-05-14 01:03:43 +02:00
|
|
|
static_process,
|
|
|
|
static_cast<void*>(this)) )
|
2013-04-20 12:37:36 +02:00
|
|
|
{
|
|
|
|
cerr << "Jack() error setting process callback" << endl;
|
|
|
|
}
|
2013-05-13 23:04:12 +02:00
|
|
|
|
2013-05-14 01:03:43 +02:00
|
|
|
if ( jack_set_timebase_callback(client,
|
|
|
|
0,
|
|
|
|
(JackTimebaseCallback)static_timebase,
|
|
|
|
static_cast<void*>(this)) )
|
|
|
|
{
|
|
|
|
cerr << "Jack() error setting timebase callback" << endl;
|
|
|
|
}
|
2013-04-20 12:37:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Jack::activate()
|
|
|
|
{
|
2013-09-06 15:05:57 +02:00
|
|
|
Controller* c = new AkaiAPC();
|
2013-09-06 15:18:27 +02:00
|
|
|
Controller* m = new GenericMIDI();
|
|
|
|
|
2013-09-06 15:05:57 +02:00
|
|
|
Controller* g = new LupppGUI();
|
|
|
|
|
2013-08-22 14:53:50 +02:00
|
|
|
/*
|
2013-07-31 19:01:51 +02:00
|
|
|
// move to "settings" class or so
|
2013-07-31 20:50:58 +02:00
|
|
|
Controller* c = new AkaiAPC();
|
|
|
|
controllerUpdater->registerController( c );
|
2013-08-04 19:04:26 +02:00
|
|
|
Controller* g = new LupppGUI();
|
|
|
|
controllerUpdater->registerController( g );
|
2013-08-22 14:53:50 +02:00
|
|
|
*/
|
2013-08-04 19:04:26 +02:00
|
|
|
|
|
|
|
// move to time class, get instantiate order right
|
2013-08-22 14:53:50 +02:00
|
|
|
//jack->getTimeManager()->registerObserver( metronome );
|
|
|
|
//jack->getTimeManager()->registerObserver( gridLogic );
|
2013-07-31 19:01:51 +02:00
|
|
|
|
2013-04-20 12:37:36 +02:00
|
|
|
jack_activate( client );
|
2013-07-26 02:27:19 +02:00
|
|
|
jack_transport_start(client);
|
2013-04-20 12:37:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-26 17:34:51 +02:00
|
|
|
TrackOutput* Jack::getTrackOutput(int t)
|
|
|
|
{
|
|
|
|
if ( t >= 0 && t < NTRACKS )
|
|
|
|
return trackOutputs.at(t);
|
|
|
|
#ifdef DEBUG_TRACKS
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf( "Jack::getTrackOutput() returning 0x0: invalid track requested!\n" );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Looper* Jack::getLooper(int t)
|
|
|
|
{
|
|
|
|
if ( t >= 0 && t < NTRACKS )
|
|
|
|
return loopers.at(t);
|
|
|
|
#ifdef DEBUG_TRACKS
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf( "Jack::getLooper() returning 0x0: invalid track requested!\n" );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-06 15:05:57 +02:00
|
|
|
void Jack::registerMidiObserver( MidiObserver* mo, std::string name )
|
2013-08-26 17:34:51 +02:00
|
|
|
{
|
2013-09-06 15:05:57 +02:00
|
|
|
cout << "Jack::registerMidiObserver() " << name << endl;
|
|
|
|
|
|
|
|
// register the observer
|
2013-08-26 17:34:51 +02:00
|
|
|
midiObservers.push_back( mo );
|
2013-09-06 15:05:57 +02:00
|
|
|
|
|
|
|
//set the index of the MIDI controller port on the MidiObserver
|
|
|
|
midiObservers.back()->port( midiObservers.size() - 1 );
|
|
|
|
|
|
|
|
// register new MIDI I/O ports for this controller
|
|
|
|
stringstream s;
|
|
|
|
s << name << "_in";
|
|
|
|
jack_port_t* tmp = jack_port_register(client,
|
|
|
|
s.str().c_str(),
|
|
|
|
JACK_DEFAULT_MIDI_TYPE,
|
|
|
|
JackPortIsInput,
|
|
|
|
0 );
|
|
|
|
|
|
|
|
midiObserverInputBuffers.push_back( 0 );
|
|
|
|
midiObserverInputPorts.push_back( tmp );
|
|
|
|
|
|
|
|
stringstream s2;
|
|
|
|
s2 << name << "_out";
|
|
|
|
tmp = jack_port_register( client,
|
|
|
|
s2.str().c_str(),
|
|
|
|
JACK_DEFAULT_MIDI_TYPE,
|
|
|
|
JackPortIsOutput,
|
|
|
|
0 );
|
|
|
|
|
|
|
|
midiObserverOutputBuffers.push_back( 0 );
|
|
|
|
midiObserverOutputPorts.push_back( tmp );
|
2013-08-26 17:34:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-20 12:37:36 +02:00
|
|
|
int Jack::process (jack_nframes_t nframes)
|
|
|
|
{
|
2013-08-15 23:45:05 +02:00
|
|
|
|
2013-08-13 01:02:59 +02:00
|
|
|
/// get buffers
|
2013-07-31 02:05:14 +02:00
|
|
|
buffers.audio[Buffers::MASTER_INPUT] = (float*)jack_port_get_buffer( masterInput , nframes );
|
2013-09-11 02:32:58 +02:00
|
|
|
buffers.audio[Buffers::MASTER_RETURN_L] = (float*)jack_port_get_buffer( masterReturnL , nframes );
|
|
|
|
buffers.audio[Buffers::MASTER_RETURN_R] = (float*)jack_port_get_buffer( masterReturnR , nframes );
|
2013-09-11 02:50:47 +02:00
|
|
|
|
|
|
|
buffers.audio[Buffers::JACK_SEND_OUT] = (float*)jack_port_get_buffer( sendOutput , nframes );
|
2013-07-31 12:34:28 +02:00
|
|
|
buffers.audio[Buffers::JACK_MASTER_OUT_L] = (float*)jack_port_get_buffer( masterOutputL , nframes );
|
|
|
|
buffers.audio[Buffers::JACK_MASTER_OUT_R] = (float*)jack_port_get_buffer( masterOutputR , nframes );
|
2013-09-11 02:50:47 +02:00
|
|
|
buffers.audio[Buffers::JACK_SIDECHAIN_KEY] = (float*)jack_port_get_buffer(sidechainKeyOutput,nframes);
|
|
|
|
buffers.audio[Buffers::JACK_SIDECHAIN_SIGNAL]=(float*)jack_port_get_buffer(sidechainSignalOutput,nframes);
|
|
|
|
|
2013-07-31 02:05:14 +02:00
|
|
|
buffers.midi [Buffers::MASTER_MIDI_INPUT] = (void*) jack_port_get_buffer( masterMidiInput, nframes );
|
2013-05-18 20:52:12 +02:00
|
|
|
|
2013-08-13 01:02:59 +02:00
|
|
|
memset( buffers.audio[Buffers::JACK_MASTER_OUT_L] , 0, sizeof(float) * nframes );
|
|
|
|
memset( buffers.audio[Buffers::JACK_MASTER_OUT_R] , 0, sizeof(float) * nframes );
|
|
|
|
memset( buffers.audio[Buffers::MASTER_OUT_L] , 0, sizeof(float) * nframes );
|
|
|
|
memset( buffers.audio[Buffers::MASTER_OUT_R] , 0, sizeof(float) * nframes );
|
2013-09-11 02:32:58 +02:00
|
|
|
memset( buffers.audio[Buffers::SEND] , 0, sizeof(float) * nframes );
|
|
|
|
memset( buffers.audio[Buffers::SIDECHAIN_KEY] , 0, sizeof(float) * nframes );
|
|
|
|
memset( buffers.audio[Buffers::SIDECHAIN_SIGNAL] , 0, sizeof(float) * nframes );
|
2013-08-12 20:01:47 +02:00
|
|
|
|
2013-08-13 01:02:59 +02:00
|
|
|
/// do events from the ringbuffer
|
|
|
|
handleDspEvents();
|
2013-05-18 17:37:03 +02:00
|
|
|
|
2013-08-13 01:02:59 +02:00
|
|
|
/// process incoming MIDI
|
|
|
|
jack_midi_event_t in_event;
|
2013-05-18 17:37:03 +02:00
|
|
|
int masterMidiInputIndex = 0;
|
|
|
|
int event_count = (int) jack_midi_get_event_count( buffers.midi[Buffers::MASTER_MIDI_INPUT] );
|
|
|
|
while ( masterMidiInputIndex < event_count )
|
|
|
|
{
|
|
|
|
jack_midi_event_get(&in_event, buffers.midi[Buffers::MASTER_MIDI_INPUT], masterMidiInputIndex);
|
|
|
|
|
2013-06-29 21:03:05 +02:00
|
|
|
char buffer [50];
|
2013-09-07 03:26:10 +02:00
|
|
|
//sprintf (buffer, "MIDI %i %i %i", int(in_event.buffer[0]), int(in_event.buffer[1]), int(in_event.buffer[2]) );
|
2013-06-29 21:03:05 +02:00
|
|
|
EventGuiPrint e( buffer );
|
|
|
|
writeToGuiRingbuffer( &e );
|
2013-05-18 17:37:03 +02:00
|
|
|
|
2013-09-06 15:05:57 +02:00
|
|
|
masterMidiInputIndex++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// process each MidiObserver registered MIDI port
|
|
|
|
for(unsigned int i = 0; i < midiObservers.size(); i++ )
|
|
|
|
{
|
|
|
|
midiObserverInputBuffers.at( i ) =
|
|
|
|
(void*) jack_port_get_buffer( midiObserverInputPorts.at(i), nframes );
|
|
|
|
|
|
|
|
midiObserverOutputBuffers.at( i ) =
|
|
|
|
(void*) jack_port_get_buffer( midiObserverOutputPorts.at(i), nframes );
|
|
|
|
jack_midi_clear_buffer( midiObserverOutputBuffers.at( i ) );
|
|
|
|
|
|
|
|
|
|
|
|
jack_midi_event_t in_event;
|
|
|
|
int index = 0;
|
|
|
|
int event_count = (int) jack_midi_get_event_count( midiObserverInputBuffers.at( i ) );
|
|
|
|
while ( index < event_count )
|
2013-07-31 19:01:51 +02:00
|
|
|
{
|
2013-09-06 15:05:57 +02:00
|
|
|
jack_midi_event_get(&in_event, midiObserverInputBuffers.at( i ), index);
|
2013-07-31 20:50:58 +02:00
|
|
|
midiObservers.at(i)->midi( (unsigned char*) &in_event.buffer[0] );
|
2013-09-07 03:26:10 +02:00
|
|
|
//printf( "%s MIDI %i %i %i\n", midiObservers.at(i)->getName().c_str(), int(in_event.buffer[0]), int(in_event.buffer[1]), int(in_event.buffer[2]) );
|
2013-09-06 15:05:57 +02:00
|
|
|
index++;
|
2013-07-31 19:01:51 +02:00
|
|
|
}
|
2013-05-18 17:37:03 +02:00
|
|
|
}
|
2013-04-20 12:37:36 +02:00
|
|
|
|
2013-08-13 01:02:59 +02:00
|
|
|
/// process each track, starting at output and working up signal path
|
2013-08-13 17:35:27 +02:00
|
|
|
for(unsigned int i = 0; i < NTRACKS; i++)
|
2013-07-31 02:05:14 +02:00
|
|
|
{
|
2013-07-31 02:43:24 +02:00
|
|
|
trackOutputs.at(i)->process( nframes, &buffers );
|
2013-07-31 02:05:14 +02:00
|
|
|
}
|
2013-05-13 23:04:12 +02:00
|
|
|
|
2013-09-11 02:32:58 +02:00
|
|
|
/// metro signal
|
2013-08-16 02:27:54 +02:00
|
|
|
metronome->process( nframes, &buffers );
|
2013-07-28 17:00:17 +02:00
|
|
|
|
2013-08-16 02:27:54 +02:00
|
|
|
/// mix reverb & post-sidechain in
|
|
|
|
for(unsigned int i = 0; i < buffers.nframes; i++)
|
2013-07-28 15:20:54 +02:00
|
|
|
{
|
2013-08-16 13:50:31 +02:00
|
|
|
float L = buffers.audio[Buffers::MASTER_OUT_L][i];
|
|
|
|
float R = buffers.audio[Buffers::MASTER_OUT_R][i];
|
2013-09-11 02:32:58 +02:00
|
|
|
float returnL = buffers.audio[Buffers::MASTER_RETURN_L][i];
|
|
|
|
float returnR = buffers.audio[Buffers::MASTER_RETURN_R][i];
|
2013-07-28 15:20:54 +02:00
|
|
|
|
2013-09-11 02:32:58 +02:00
|
|
|
buffers.audio[Buffers::MASTER_OUT_L][i] = (L + returnL) * masterVol;
|
|
|
|
buffers.audio[Buffers::MASTER_OUT_R][i] = (R + returnR) * masterVol;
|
2013-09-11 02:50:47 +02:00
|
|
|
|
|
|
|
/// write SEND content to JACK port
|
|
|
|
buffers.audio[Buffers::JACK_SEND_OUT][i] = buffers.audio[Buffers::SEND][i];
|
|
|
|
buffers.audio[Buffers::JACK_SIDECHAIN_KEY][i] = buffers.audio[Buffers::SIDECHAIN_KEY][i];
|
|
|
|
buffers.audio[Buffers::JACK_SIDECHAIN_SIGNAL][i] = buffers.audio[Buffers::SIDECHAIN_SIGNAL][i];
|
2013-07-28 15:20:54 +02:00
|
|
|
}
|
|
|
|
|
2013-07-26 02:39:06 +02:00
|
|
|
|
2013-09-10 22:44:47 +02:00
|
|
|
/// db meter on master input & output
|
|
|
|
inputMeter->process( nframes, buffers.audio[Buffers::MASTER_INPUT], buffers.audio[Buffers::MASTER_INPUT]);
|
2013-08-16 02:27:54 +02:00
|
|
|
masterMeter->process(nframes, buffers.audio[Buffers::MASTER_OUT_L], buffers.audio[Buffers::MASTER_OUT_R] );
|
2013-08-16 01:32:10 +02:00
|
|
|
|
2013-08-16 02:27:54 +02:00
|
|
|
if ( uiUpdateCounter > uiUpdateConstant )
|
2013-08-13 01:02:59 +02:00
|
|
|
{
|
2013-08-16 02:27:54 +02:00
|
|
|
EventTrackSignalLevel e(-1, masterMeter->getLeftDB(), masterMeter->getRightDB() );
|
|
|
|
writeToGuiRingbuffer( &e );
|
2013-09-10 22:44:47 +02:00
|
|
|
EventTrackSignalLevel e2(-2, inputMeter->getLeftDB(), inputMeter->getRightDB() );
|
|
|
|
writeToGuiRingbuffer( &e2 );
|
2013-08-13 01:41:17 +02:00
|
|
|
|
2013-08-16 02:27:54 +02:00
|
|
|
uiUpdateCounter = 0;
|
2013-08-13 01:02:59 +02:00
|
|
|
}
|
|
|
|
|
2013-08-16 02:27:54 +02:00
|
|
|
uiUpdateCounter += nframes;
|
2013-08-16 01:32:10 +02:00
|
|
|
|
|
|
|
|
2013-07-28 17:00:17 +02:00
|
|
|
// memcpy the internal MASTER_OUTPUT buffer to the JACK_MASTER_OUTPUT
|
2013-07-31 12:34:28 +02:00
|
|
|
memcpy( buffers.audio[Buffers::JACK_MASTER_OUT_L],
|
|
|
|
buffers.audio[Buffers::MASTER_OUT_L],
|
2013-08-13 01:02:59 +02:00
|
|
|
//buffers.audio[Buffers::TRACK_7],
|
2013-07-31 12:34:28 +02:00
|
|
|
sizeof(float)*nframes);
|
|
|
|
|
|
|
|
memcpy( buffers.audio[Buffers::JACK_MASTER_OUT_R],
|
|
|
|
buffers.audio[Buffers::MASTER_OUT_R],
|
2013-08-16 02:27:54 +02:00
|
|
|
//buffers.audio[Buffers::POST_SIDECHAIN],
|
2013-09-11 02:32:58 +02:00
|
|
|
//buffers.audio[Buffers::SEND], // uncomment to listen to reverb send only
|
2013-07-28 17:00:17 +02:00
|
|
|
sizeof(float)*nframes);
|
|
|
|
|
2013-04-20 12:37:36 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Jack::getBuffersize()
|
|
|
|
{
|
|
|
|
return jack_get_buffer_size( client );
|
|
|
|
}
|
|
|
|
|
|
|
|
int Jack::getSamplerate()
|
|
|
|
{
|
|
|
|
return jack_get_sample_rate( client );
|
|
|
|
}
|
|
|
|
|
2013-09-06 15:05:57 +02:00
|
|
|
void Jack::midiObserverWriteMIDI( int portIndex, unsigned char* data )
|
2013-05-18 20:52:12 +02:00
|
|
|
{
|
2013-09-06 00:45:06 +02:00
|
|
|
// FIXME: MIDI output needs a QUEUE structure, so we can send more data to the APC "at once"
|
2013-09-06 15:05:57 +02:00
|
|
|
void* portBuffer = midiObserverOutputBuffers.at(portIndex);
|
2013-05-18 20:52:12 +02:00
|
|
|
|
2013-09-06 15:05:57 +02:00
|
|
|
unsigned char* buf = jack_midi_event_reserve( portBuffer, 0, 3);
|
2013-05-18 21:33:13 +02:00
|
|
|
if( buf != 0 )
|
2013-05-18 20:52:12 +02:00
|
|
|
{
|
|
|
|
memcpy( buf, data, sizeof( unsigned char ) * 3);
|
2013-07-25 15:37:55 +02:00
|
|
|
//cout << "writeApcOutput " << int(buf[0]) << ", " << int(buf[1]) << ", " << int(buf[2]) << endl;
|
2013-05-18 20:52:12 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-08-22 06:48:59 +02:00
|
|
|
EventGuiPrint e( "Jack::writeApcOutput(): Buffer full!" );
|
2013-05-18 20:52:12 +02:00
|
|
|
writeToGuiRingbuffer( &e );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-14 01:03:43 +02:00
|
|
|
int Jack::timebase(jack_transport_state_t state,
|
|
|
|
jack_nframes_t nframes,
|
|
|
|
jack_position_t* pos,
|
|
|
|
int newPos)
|
2013-04-20 12:37:36 +02:00
|
|
|
{
|
2013-05-14 01:03:43 +02:00
|
|
|
// fill buffers with data, then pass to timeManager
|
|
|
|
buffers.transportFrame = jack_get_current_transport_frame(client);
|
2013-05-15 03:04:39 +02:00
|
|
|
buffers.transportPosition = pos;
|
|
|
|
buffers.transportState =&state;
|
2013-05-14 01:03:43 +02:00
|
|
|
|
|
|
|
// update "time" from JACK master, or write master?
|
|
|
|
timeManager.process( &buffers );
|
|
|
|
|
2013-04-20 12:37:36 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Jack::static_process(jack_nframes_t nframes, void *instance)
|
|
|
|
{
|
|
|
|
return static_cast<Jack*>(instance)->process(nframes);
|
|
|
|
}
|
|
|
|
|
|
|
|
int Jack::static_timebase(jack_transport_state_t state,
|
|
|
|
jack_nframes_t nframes,
|
|
|
|
jack_position_t* pos,
|
|
|
|
int newPos,
|
|
|
|
void* instance)
|
|
|
|
{
|
|
|
|
return static_cast<Jack*>(instance)->timebase(state,nframes, pos, newPos );
|
|
|
|
}
|