@@ -32,172 +32,188 @@ using namespace std; | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
//static methods *********************************************************** | |||||
int JackAudioAdapter::Process (jack_nframes_t frames, void* arg) | |||||
{ | |||||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | |||||
jack_default_audio_sample_t* inputBuffer[adapter->fAudioAdapter->GetInputs()]; | |||||
jack_default_audio_sample_t* outputBuffer[adapter->fAudioAdapter->GetOutputs()]; | |||||
// Always clear output | |||||
for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { | |||||
#ifdef OPTIMIZED_PROTOCOL | |||||
inputBuffer[i] = (jack_port_connected(adapter->fCapturePortList[i]) > 0) | |||||
? (jack_default_audio_sample_t*)(adapter->fCapturePortList[i], frames) | |||||
: NULL; | |||||
if (inputBuffer[i]) { | |||||
memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t)); | |||||
} | |||||
#else | |||||
inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fCapturePortList[i], frames); | |||||
memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t)); | |||||
#endif | |||||
} | |||||
for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { | |||||
#ifdef OPTIMIZED_PROTOCOL | |||||
outputBuffer[i] = (jack_port_connected(fAudioCapturePorts[audio_port_index] > 0) | |||||
? (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames) | |||||
: NULL; | |||||
#else | |||||
outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames); | |||||
#endif | |||||
} | |||||
adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames); | |||||
return 0; | |||||
int JackAudioAdapter::Process(jack_nframes_t frames, void* arg) | |||||
{ | |||||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | |||||
jack_default_audio_sample_t* inputBuffer[adapter->fAudioAdapter->GetInputs()]; | |||||
jack_default_audio_sample_t* outputBuffer[adapter->fAudioAdapter->GetOutputs()]; | |||||
// Always clear output | |||||
for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { | |||||
inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fCapturePortList[i], frames); | |||||
memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t)); | |||||
} | } | ||||
int JackAudioAdapter::BufferSize ( jack_nframes_t buffer_size, void* arg ) | |||||
{ | |||||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*> ( arg ); | |||||
adapter->Reset(); | |||||
adapter->fAudioAdapter->SetHostBufferSize ( buffer_size ); | |||||
return 0; | |||||
for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { | |||||
outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames); | |||||
} | } | ||||
int JackAudioAdapter::SampleRate ( jack_nframes_t sample_rate, void* arg ) | |||||
{ | |||||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*> ( arg ); | |||||
adapter->Reset(); | |||||
adapter->fAudioAdapter->SetHostSampleRate ( sample_rate ); | |||||
return 0; | |||||
} | |||||
adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames); | |||||
return 0; | |||||
} | |||||
int JackAudioAdapter::BufferSize(jack_nframes_t buffer_size, void* arg) | |||||
{ | |||||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | |||||
adapter->Reset(); | |||||
adapter->fAudioAdapter->SetHostBufferSize(buffer_size); | |||||
return 0; | |||||
} | |||||
//JackAudioAdapter ********************************************************* | |||||
int JackAudioAdapter::SampleRate(jack_nframes_t sample_rate, void* arg) | |||||
{ | |||||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | |||||
adapter->Reset(); | |||||
adapter->fAudioAdapter->SetHostSampleRate(sample_rate); | |||||
return 0; | |||||
} | |||||
JackAudioAdapter::JackAudioAdapter (jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params, bool system) | |||||
:fJackClient(jack_client), fAudioAdapter(audio_io) | |||||
{ | |||||
const JSList* node; | |||||
const jack_driver_param_t* param; | |||||
fAutoConnect = false; | |||||
void JackAudioAdapter::Latency(jack_latency_callback_mode_t mode, void* arg) | |||||
{ | |||||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | |||||
for (node = params; node; node = jack_slist_next(node)) { | |||||
param = (const jack_driver_param_t*) node->data; | |||||
switch (param->character) { | |||||
case 'c': | |||||
fAutoConnect = true; | |||||
break; | |||||
} | |||||
if (mode == JackCaptureLatency) { | |||||
for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { | |||||
jack_latency_range_t range; | |||||
range.min = range.max = adapter->fAudioAdapter->GetInputLatency(i); | |||||
jack_port_set_latency_range(adapter->fCapturePortList[i], JackCaptureLatency, &range); | |||||
} | |||||
} else { | |||||
for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { | |||||
jack_latency_range_t range; | |||||
range.min = range.max = adapter->fAudioAdapter->GetOutputLatency(i); | |||||
jack_port_set_latency_range(adapter->fPlaybackPortList[i], JackPlaybackLatency, &range); | |||||
} | } | ||||
} | } | ||||
} | |||||
JackAudioAdapter::~JackAudioAdapter() | |||||
{ | |||||
// When called, Close has already been used for the client, thus ports are already unregistered. | |||||
delete fAudioAdapter; | |||||
JackAudioAdapter::JackAudioAdapter(jack_client_t* client, JackAudioAdapterInterface* audio_io, const JSList* params) | |||||
:fClient(client), fAudioAdapter(audio_io) | |||||
{ | |||||
const JSList* node; | |||||
const jack_driver_param_t* param; | |||||
fAutoConnect = false; | |||||
for (node = params; node; node = jack_slist_next(node)) { | |||||
param = (const jack_driver_param_t*)node->data; | |||||
switch (param->character) { | |||||
case 'c': | |||||
fAutoConnect = true; | |||||
break; | |||||
} | |||||
} | } | ||||
} | |||||
void JackAudioAdapter::FreePorts() | |||||
{ | |||||
for (int i = 0; i < fAudioAdapter->GetInputs(); i++ ) | |||||
if ( fCapturePortList[i] ) | |||||
jack_port_unregister ( fJackClient, fCapturePortList[i] ); | |||||
for (int i = 0; i < fAudioAdapter->GetOutputs(); i++ ) | |||||
if ( fPlaybackPortList[i] ) | |||||
jack_port_unregister ( fJackClient, fPlaybackPortList[i] ); | |||||
JackAudioAdapter::~JackAudioAdapter() | |||||
{ | |||||
// When called, Close has already been used for the client, thus ports are already unregistered. | |||||
delete fAudioAdapter; | |||||
} | |||||
delete[] fCapturePortList; | |||||
delete[] fPlaybackPortList; | |||||
void JackAudioAdapter::FreePorts() | |||||
{ | |||||
for (int i = 0; i < fAudioAdapter->GetInputs(); i++) { | |||||
if (fCapturePortList[i]) { | |||||
jack_port_unregister(fClient, fCapturePortList[i]); | |||||
} | |||||
} | |||||
for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) { | |||||
if (fPlaybackPortList[i]) { | |||||
jack_port_unregister(fClient, fPlaybackPortList[i]); | |||||
} | |||||
} | } | ||||
void JackAudioAdapter::ConnectPorts() | |||||
{ | |||||
const char **ports; | |||||
delete[] fCapturePortList; | |||||
delete[] fPlaybackPortList; | |||||
} | |||||
ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); | |||||
if (ports != NULL) { | |||||
for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) { | |||||
jack_connect(fJackClient, jack_port_name(fCapturePortList[i]), ports[i]); | |||||
} | |||||
free(ports); | |||||
} | |||||
void JackAudioAdapter::ConnectPorts() | |||||
{ | |||||
const char** ports; | |||||
ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); | |||||
if (ports != NULL) { | |||||
for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) { | |||||
jack_connect(fJackClient, ports[i], jack_port_name(fPlaybackPortList[i])); | |||||
} | |||||
free(ports); | |||||
ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); | |||||
if (ports != NULL) { | |||||
for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) { | |||||
jack_connect(fClient,jack_port_name(fCapturePortList[i]), ports[i]); | |||||
} | } | ||||
jack_free(ports); | |||||
} | } | ||||
void JackAudioAdapter::Reset() | |||||
{ | |||||
fAudioAdapter->Reset(); | |||||
ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); | |||||
if (ports != NULL) { | |||||
for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) { | |||||
jack_connect(fClient, ports[i], jack_port_name(fPlaybackPortList[i])); | |||||
} | |||||
jack_free(ports); | |||||
} | } | ||||
} | |||||
int JackAudioAdapter::Open() | |||||
{ | |||||
char name[32]; | |||||
jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs()); | |||||
fAudioAdapter->Create(); | |||||
void JackAudioAdapter::Reset() | |||||
{ | |||||
fAudioAdapter->Reset(); | |||||
} | |||||
//jack ports | |||||
fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()]; | |||||
fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()]; | |||||
int JackAudioAdapter::Open() | |||||
{ | |||||
char name[32]; | |||||
jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs()); | |||||
fAudioAdapter->Create(); | |||||
for (int i = 0; i < fAudioAdapter->GetInputs(); i++) { | |||||
sprintf(name, "capture_%d", i + 1); | |||||
if ((fCapturePortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL) | |||||
goto fail; | |||||
} | |||||
//jack ports | |||||
fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()]; | |||||
fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()]; | |||||
for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) { | |||||
sprintf(name, "playback_%d", i + 1); | |||||
if ((fPlaybackPortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == NULL) | |||||
goto fail; | |||||
for (int i = 0; i < fAudioAdapter->GetInputs(); i++) { | |||||
sprintf(name, "capture_%d", i + 1); | |||||
if ((fCapturePortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, 0)) == NULL) { | |||||
goto fail; | |||||
} | } | ||||
} | |||||
//callbacks and activation | |||||
if (jack_set_process_callback(fJackClient, Process, this) < 0) | |||||
goto fail; | |||||
if (jack_set_buffer_size_callback(fJackClient, BufferSize, this) < 0) | |||||
for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) { | |||||
sprintf(name, "playback_%d", i + 1); | |||||
if ((fPlaybackPortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, 0)) == NULL) { | |||||
goto fail; | goto fail; | ||||
if (jack_set_sample_rate_callback(fJackClient, SampleRate, this) < 0) | |||||
goto fail; | |||||
if (jack_activate(fJackClient) < 0) | |||||
goto fail; | |||||
if (fAutoConnect) | |||||
ConnectPorts(); | |||||
// Ring buffers are now allocated.. | |||||
return fAudioAdapter->Open(); | |||||
return 0; | |||||
} | |||||
} | |||||
fail: | |||||
FreePorts(); | |||||
fAudioAdapter->Destroy(); | |||||
return -1; | |||||
//callbacks and activation | |||||
if (jack_set_process_callback(fClient, Process, this) < 0) { | |||||
goto fail; | |||||
} | |||||
if (jack_set_buffer_size_callback(fClient, BufferSize, this) < 0) { | |||||
goto fail; | |||||
} | |||||
if (jack_set_sample_rate_callback(fClient, SampleRate, this) < 0) { | |||||
goto fail; | |||||
} | |||||
if (jack_set_latency_callback(fClient, Latency, this) < 0) { | |||||
goto fail; | |||||
} | |||||
if (jack_activate(fClient) < 0) { | |||||
goto fail; | |||||
} | } | ||||
int JackAudioAdapter::Close() | |||||
{ | |||||
fAudioAdapter->Close(); | |||||
fAudioAdapter->Destroy(); | |||||
return 0; | |||||
if (fAutoConnect) { | |||||
ConnectPorts(); | |||||
} | } | ||||
// Ring buffers are now allocated... | |||||
return fAudioAdapter->Open(); | |||||
return 0; | |||||
fail: | |||||
FreePorts(); | |||||
fAudioAdapter->Destroy(); | |||||
return -1; | |||||
} | |||||
int JackAudioAdapter::Close() | |||||
{ | |||||
fAudioAdapter->Close(); | |||||
fAudioAdapter->Destroy(); | |||||
return 0; | |||||
} | |||||
} //namespace | } //namespace |
@@ -37,11 +37,12 @@ namespace Jack | |||||
static int Process(jack_nframes_t, void* arg); | static int Process(jack_nframes_t, void* arg); | ||||
static int BufferSize(jack_nframes_t buffer_size, void* arg); | static int BufferSize(jack_nframes_t buffer_size, void* arg); | ||||
static int SampleRate(jack_nframes_t sample_rate, void* arg); | static int SampleRate(jack_nframes_t sample_rate, void* arg); | ||||
static void Latency(jack_latency_callback_mode_t mode, void* arg); | |||||
jack_port_t** fCapturePortList; | jack_port_t** fCapturePortList; | ||||
jack_port_t** fPlaybackPortList; | jack_port_t** fPlaybackPortList; | ||||
jack_client_t* fJackClient; | |||||
jack_client_t* fClient; | |||||
JackAudioAdapterInterface* fAudioAdapter; | JackAudioAdapterInterface* fAudioAdapter; | ||||
bool fAutoConnect; | bool fAutoConnect; | ||||
@@ -51,7 +52,7 @@ namespace Jack | |||||
public: | public: | ||||
JackAudioAdapter(jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params = NULL, bool system = false); | |||||
JackAudioAdapter(jack_client_t* client, JackAudioAdapterInterface* audio_io, const JSList* params = NULL); | |||||
~JackAudioAdapter(); | ~JackAudioAdapter(); | ||||
int Open(); | int Open(); | ||||
@@ -60,4 +61,7 @@ namespace Jack | |||||
} | } | ||||
#define CaptureDriverFlags static_cast<JackPortFlags>(JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal) | |||||
#define PlaybackDriverFlags static_cast<JackPortFlags>(JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal) | |||||
#endif | #endif |
@@ -49,8 +49,7 @@ namespace Jack | |||||
FILE* file = fopen("JackAudioAdapter.log", "w"); | FILE* file = fopen("JackAudioAdapter.log", "w"); | ||||
int max = (fCount) % TABLE_MAX - 1; | int max = (fCount) % TABLE_MAX - 1; | ||||
for (int i = 1; i < max; i++) | |||||
{ | |||||
for (int i = 1; i < max; i++) { | |||||
fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n", | fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n", | ||||
fTable[i].delta, fTable[i].time1, fTable[i].time2, | fTable[i].delta, fTable[i].time1, fTable[i].time2, | ||||
fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2); | fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2); | ||||
@@ -158,21 +157,25 @@ namespace Jack | |||||
void JackAudioAdapterInterface::AdaptRingBufferSize() | void JackAudioAdapterInterface::AdaptRingBufferSize() | ||||
{ | { | ||||
if (fHostBufferSize > fAdaptedBufferSize) | |||||
if (fHostBufferSize > fAdaptedBufferSize) { | |||||
fRingbufferCurSize = 4 * fHostBufferSize; | fRingbufferCurSize = 4 * fHostBufferSize; | ||||
else | |||||
} else { | |||||
fRingbufferCurSize = 4 * fAdaptedBufferSize; | fRingbufferCurSize = 4 * fAdaptedBufferSize; | ||||
} | |||||
} | } | ||||
void JackAudioAdapterInterface::ResetRingBuffers() | void JackAudioAdapterInterface::ResetRingBuffers() | ||||
{ | { | ||||
if (fRingbufferCurSize > DEFAULT_RB_SIZE) | |||||
if (fRingbufferCurSize > DEFAULT_RB_SIZE) { | |||||
fRingbufferCurSize = DEFAULT_RB_SIZE; | fRingbufferCurSize = DEFAULT_RB_SIZE; | ||||
} | |||||
for (int i = 0; i < fCaptureChannels; i++) | |||||
for (int i = 0; i < fCaptureChannels; i++) { | |||||
fCaptureRingBuffer[i]->Reset(fRingbufferCurSize); | fCaptureRingBuffer[i]->Reset(fRingbufferCurSize); | ||||
for (int i = 0; i < fPlaybackChannels; i++) | |||||
} | |||||
for (int i = 0; i < fPlaybackChannels; i++) { | |||||
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); | fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); | ||||
} | |||||
} | } | ||||
void JackAudioAdapterInterface::Reset() | void JackAudioAdapterInterface::Reset() | ||||
@@ -195,8 +198,9 @@ namespace Jack | |||||
AdaptRingBufferSize(); | AdaptRingBufferSize(); | ||||
jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize); | jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize); | ||||
} else { | } else { | ||||
if (fRingbufferCurSize > DEFAULT_RB_SIZE) | |||||
if (fRingbufferCurSize > DEFAULT_RB_SIZE) { | |||||
fRingbufferCurSize = DEFAULT_RB_SIZE; | fRingbufferCurSize = DEFAULT_RB_SIZE; | ||||
} | |||||
jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize); | jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize); | ||||
} | } | ||||
@@ -209,19 +213,23 @@ namespace Jack | |||||
fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); | fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); | ||||
} | } | ||||
if (fCaptureChannels > 0) | |||||
if (fCaptureChannels > 0) { | |||||
jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); | jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); | ||||
if (fPlaybackChannels > 0) | |||||
} | |||||
if (fPlaybackChannels > 0) { | |||||
jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace()); | jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace()); | ||||
} | |||||
} | } | ||||
#endif | #endif | ||||
void JackAudioAdapterInterface::Destroy() | void JackAudioAdapterInterface::Destroy() | ||||
{ | { | ||||
for (int i = 0; i < fCaptureChannels; i++ ) | |||||
delete ( fCaptureRingBuffer[i] ); | |||||
for (int i = 0; i < fPlaybackChannels; i++ ) | |||||
delete ( fPlaybackRingBuffer[i] ); | |||||
for (int i = 0; i < fCaptureChannels; i++) { | |||||
delete(fCaptureRingBuffer[i]); | |||||
} | |||||
for (int i = 0; i < fPlaybackChannels; i++) { | |||||
delete (fPlaybackRingBuffer[i]); | |||||
} | |||||
delete[] fCaptureRingBuffer; | delete[] fCaptureRingBuffer; | ||||
delete[] fPlaybackRingBuffer; | delete[] fPlaybackRingBuffer; | ||||
@@ -238,10 +246,11 @@ namespace Jack | |||||
double ratio = 1; | double ratio = 1; | ||||
// TODO : done like this just to avoid crash when input only or output only... | // TODO : done like this just to avoid crash when input only or output only... | ||||
if (fCaptureChannels > 0) | |||||
if (fCaptureChannels > 0) { | |||||
ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames); | ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames); | ||||
else if (fPlaybackChannels > 0) | |||||
} else if (fPlaybackChannels > 0) { | |||||
ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames); | ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames); | ||||
} | |||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL) | if (fCaptureRingBuffer && fCaptureRingBuffer[0] != NULL) | ||||
@@ -49,7 +49,7 @@ namespace Jack | |||||
Measure fTable[TABLE_MAX]; | Measure fTable[TABLE_MAX]; | ||||
int fCount; | int fCount; | ||||
MeasureTable() :fCount ( 0 ) | |||||
MeasureTable() :fCount(0) | |||||
{} | {} | ||||
void Write(int time1, int time2, float r1, float r2, int pos1, int pos2); | void Write(int time1, int time2, float r1, float r2, int pos1, int pos2); | ||||
@@ -102,13 +102,13 @@ namespace Jack | |||||
public: | public: | ||||
JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE): | |||||
fCaptureChannels ( 0 ), | |||||
fPlaybackChannels ( 0 ), | |||||
fHostBufferSize ( buffer_size ), | |||||
fHostSampleRate ( sample_rate ), | |||||
fAdaptedBufferSize ( buffer_size), | |||||
fAdaptedSampleRate ( sample_rate ), | |||||
JackAudioAdapterInterface(jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE): | |||||
fCaptureChannels(0), | |||||
fPlaybackChannels(0), | |||||
fHostBufferSize(buffer_size), | |||||
fHostSampleRate(sample_rate), | |||||
fAdaptedBufferSize(buffer_size), | |||||
fAdaptedSampleRate(sample_rate), | |||||
fPIControler(sample_rate / sample_rate, 256), | fPIControler(sample_rate / sample_rate, 256), | ||||
fCaptureRingBuffer(NULL), fPlaybackRingBuffer(NULL), | fCaptureRingBuffer(NULL), fPlaybackRingBuffer(NULL), | ||||
fQuality(0), | fQuality(0), | ||||
@@ -117,23 +117,23 @@ namespace Jack | |||||
fRunning(false), | fRunning(false), | ||||
fAdaptative(true) | fAdaptative(true) | ||||
{} | {} | ||||
JackAudioAdapterInterface ( jack_nframes_t host_buffer_size, | |||||
JackAudioAdapterInterface(jack_nframes_t host_buffer_size, | |||||
jack_nframes_t host_sample_rate, | jack_nframes_t host_sample_rate, | ||||
jack_nframes_t adapted_buffer_size, | jack_nframes_t adapted_buffer_size, | ||||
jack_nframes_t adapted_sample_rate, | jack_nframes_t adapted_sample_rate, | ||||
jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE ) : | |||||
fCaptureChannels ( 0 ), | |||||
fPlaybackChannels ( 0 ), | |||||
fHostBufferSize ( host_buffer_size ), | |||||
fHostSampleRate ( host_sample_rate ), | |||||
fAdaptedBufferSize ( adapted_buffer_size), | |||||
fAdaptedSampleRate ( adapted_sample_rate ), | |||||
fPIControler(host_sample_rate / host_sample_rate, 256), | |||||
fQuality(0), | |||||
fRingbufferCurSize(ring_buffer_size), | |||||
fPullAndPushTime(0), | |||||
fRunning(false), | |||||
fAdaptative(true) | |||||
jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE) : | |||||
fCaptureChannels(0), | |||||
fPlaybackChannels(0), | |||||
fHostBufferSize(host_buffer_size), | |||||
fHostSampleRate(host_sample_rate), | |||||
fAdaptedBufferSize(adapted_buffer_size), | |||||
fAdaptedSampleRate(adapted_sample_rate), | |||||
fPIControler(host_sample_rate / host_sample_rate, 256), | |||||
fQuality(0), | |||||
fRingbufferCurSize(ring_buffer_size), | |||||
fPullAndPushTime(0), | |||||
fRunning(false), | |||||
fAdaptative(true) | |||||
{} | {} | ||||
virtual ~JackAudioAdapterInterface() | virtual ~JackAudioAdapterInterface() | ||||
@@ -154,59 +154,61 @@ namespace Jack | |||||
return 0; | return 0; | ||||
} | } | ||||
virtual int SetHostBufferSize ( jack_nframes_t buffer_size ) | |||||
virtual int SetHostBufferSize(jack_nframes_t buffer_size) | |||||
{ | { | ||||
fHostBufferSize = buffer_size; | fHostBufferSize = buffer_size; | ||||
if (fAdaptative) | |||||
if (fAdaptative) { | |||||
AdaptRingBufferSize(); | AdaptRingBufferSize(); | ||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
virtual int SetAdaptedBufferSize ( jack_nframes_t buffer_size ) | |||||
virtual int SetAdaptedBufferSize(jack_nframes_t buffer_size) | |||||
{ | { | ||||
fAdaptedBufferSize = buffer_size; | fAdaptedBufferSize = buffer_size; | ||||
if (fAdaptative) | |||||
if (fAdaptative) { | |||||
AdaptRingBufferSize(); | AdaptRingBufferSize(); | ||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
virtual int SetBufferSize ( jack_nframes_t buffer_size ) | |||||
virtual int SetBufferSize(jack_nframes_t buffer_size) | |||||
{ | { | ||||
SetHostBufferSize ( buffer_size ); | |||||
SetAdaptedBufferSize ( buffer_size ); | |||||
SetHostBufferSize(buffer_size); | |||||
SetAdaptedBufferSize(buffer_size); | |||||
return 0; | return 0; | ||||
} | } | ||||
virtual int SetHostSampleRate ( jack_nframes_t sample_rate ) | |||||
virtual int SetHostSampleRate(jack_nframes_t sample_rate) | |||||
{ | { | ||||
fHostSampleRate = sample_rate; | fHostSampleRate = sample_rate; | ||||
fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate)); | fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate)); | ||||
return 0; | return 0; | ||||
} | } | ||||
virtual int SetAdaptedSampleRate ( jack_nframes_t sample_rate ) | |||||
virtual int SetAdaptedSampleRate(jack_nframes_t sample_rate) | |||||
{ | { | ||||
fAdaptedSampleRate = sample_rate; | fAdaptedSampleRate = sample_rate; | ||||
fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate)); | fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate)); | ||||
return 0; | return 0; | ||||
} | } | ||||
virtual int SetSampleRate ( jack_nframes_t sample_rate ) | |||||
virtual int SetSampleRate(jack_nframes_t sample_rate) | |||||
{ | { | ||||
SetHostSampleRate ( sample_rate ); | |||||
SetAdaptedSampleRate ( sample_rate ); | |||||
SetHostSampleRate(sample_rate); | |||||
SetAdaptedSampleRate(sample_rate); | |||||
return 0; | return 0; | ||||
} | } | ||||
void SetInputs ( int inputs ) | |||||
void SetInputs(int inputs) | |||||
{ | { | ||||
jack_log ( "JackAudioAdapterInterface::SetInputs %d", inputs ); | |||||
jack_log("JackAudioAdapterInterface::SetInputs %d", inputs); | |||||
fCaptureChannels = inputs; | fCaptureChannels = inputs; | ||||
} | } | ||||
void SetOutputs ( int outputs ) | |||||
void SetOutputs(int outputs) | |||||
{ | { | ||||
jack_log ( "JackAudioAdapterInterface::SetOutputs %d", outputs ); | |||||
jack_log("JackAudioAdapterInterface::SetOutputs %d", outputs); | |||||
fPlaybackChannels = outputs; | fPlaybackChannels = outputs; | ||||
} | } | ||||
@@ -222,6 +224,9 @@ namespace Jack | |||||
return fPlaybackChannels; | return fPlaybackChannels; | ||||
} | } | ||||
virtual int GetInputLatency(int port_index) { return 0; } | |||||
virtual int GetOutputLatency(int port_index) { return 0; } | |||||
int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames); | int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames); | ||||
int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames); | int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames); | ||||
@@ -50,8 +50,9 @@ int JackAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | |||||
fEngineControl->fBufferSize = buffer_size; | fEngineControl->fBufferSize = buffer_size; | ||||
fGraphManager->SetBufferSize(buffer_size); | fGraphManager->SetBufferSize(buffer_size); | ||||
fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | ||||
if (!fEngineControl->fTimeOut) | |||||
if (!fEngineControl->fTimeOut) { | |||||
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | ||||
} | |||||
UpdateLatencies(); | UpdateLatencies(); | ||||
@@ -63,8 +64,9 @@ int JackAudioDriver::SetSampleRate(jack_nframes_t sample_rate) | |||||
{ | { | ||||
fEngineControl->fSampleRate = sample_rate; | fEngineControl->fSampleRate = sample_rate; | ||||
fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | ||||
if (!fEngineControl->fTimeOut) | |||||
if (!fEngineControl->fTimeOut) { | |||||
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | ||||
} | |||||
return JackDriver::SetSampleRate(sample_rate); | return JackDriver::SetSampleRate(sample_rate); | ||||
} | } | ||||
@@ -87,7 +89,8 @@ int JackAudioDriver::Open(jack_nframes_t buffer_size, | |||||
memset(fCapturePortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | memset(fCapturePortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | ||||
memset(fPlaybackPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | memset(fPlaybackPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | ||||
memset(fMonitorPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | memset(fMonitorPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | ||||
return JackDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | |||||
return JackDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, | |||||
monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | |||||
} | } | ||||
int JackAudioDriver::Open(bool capturing, | int JackAudioDriver::Open(bool capturing, | ||||
@@ -106,26 +109,32 @@ int JackAudioDriver::Open(bool capturing, | |||||
memset(fCapturePortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | memset(fCapturePortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | ||||
memset(fPlaybackPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | memset(fPlaybackPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | ||||
memset(fMonitorPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | memset(fMonitorPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM); | ||||
return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | |||||
return JackDriver::Open(capturing, playing, inchannels, outchannels, | |||||
monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | |||||
} | } | ||||
void JackAudioDriver::UpdateLatencies() | void JackAudioDriver::UpdateLatencies() | ||||
{ | { | ||||
jack_latency_range_t range; | |||||
jack_latency_range_t input_range; | |||||
jack_latency_range_t output_range; | |||||
jack_latency_range_t monitor_range; | |||||
for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
range.max = range.min = fEngineControl->fBufferSize; | |||||
fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
input_range.max = input_range.min = fEngineControl->fBufferSize + fCaptureLatency; | |||||
fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range); | |||||
} | } | ||||
for (int i = 0; i < fPlaybackChannels; i++) { | for (int i = 0; i < fPlaybackChannels; i++) { | ||||
if (! fEngineControl->fSyncMode) { | |||||
range.max = range.min = fEngineControl->fBufferSize * 2; | |||||
output_range.max = output_range.min = fPlaybackLatency; | |||||
if (fEngineControl->fSyncMode) { | |||||
output_range.max = output_range.min += fEngineControl->fBufferSize; | |||||
} else { | |||||
output_range.max = output_range.min += fEngineControl->fBufferSize * 2; | |||||
} | } | ||||
fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &range); | |||||
fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range); | |||||
if (fWithMonitorPorts) { | if (fWithMonitorPorts) { | ||||
range.min = range.max = fEngineControl->fBufferSize; | |||||
fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
monitor_range.min = monitor_range.max = fEngineControl->fBufferSize; | |||||
fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -220,6 +229,16 @@ int JackAudioDriver::Process() | |||||
return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync(); | return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync(); | ||||
} | } | ||||
void JackAudioDriver::ProcessGraphAsync() | |||||
{ | |||||
// Process graph | |||||
if (fIsMaster) { | |||||
ProcessGraphAsyncMaster(); | |||||
} else { | |||||
ProcessGraphAsyncSlave(); | |||||
} | |||||
} | |||||
/* | /* | ||||
The driver ASYNC mode: output buffers computed at the *previous cycle* are used, the server does not | The driver ASYNC mode: output buffers computed at the *previous cycle* are used, the server does not | ||||
synchronize to the end of client graph execution. | synchronize to the end of client graph execution. | ||||
@@ -240,17 +259,30 @@ int JackAudioDriver::ProcessAsync() | |||||
} | } | ||||
// Process graph | // Process graph | ||||
if (fIsMaster) { | |||||
ProcessGraphAsyncMaster(); | |||||
} else { | |||||
ProcessGraphAsyncSlave(); | |||||
} | |||||
ProcessGraphAsync(); | |||||
// Keep end cycle time | // Keep end cycle time | ||||
JackDriver::CycleTakeEndTime(); | JackDriver::CycleTakeEndTime(); | ||||
return 0; | return 0; | ||||
} | } | ||||
void JackAudioDriver::ProcessGraphSync() | |||||
{ | |||||
// Process graph | |||||
if (fIsMaster) { | |||||
if (ProcessGraphSyncMaster() < 0) { | |||||
//jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); | |||||
//goto end; | |||||
} | |||||
} else { | |||||
if (ProcessGraphSyncSlave() < 0) { | |||||
//jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); | |||||
//goto end; | |||||
} | |||||
} | |||||
} | |||||
/* | /* | ||||
The driver SYNC mode: the server does synchronize to the end of client graph execution, | The driver SYNC mode: the server does synchronize to the end of client graph execution, | ||||
if graph process succeed, output buffers computed at the *current cycle* are used. | if graph process succeed, output buffers computed at the *current cycle* are used. | ||||
@@ -265,17 +297,7 @@ int JackAudioDriver::ProcessSync() | |||||
} | } | ||||
// Process graph | // Process graph | ||||
if (fIsMaster) { | |||||
if (ProcessGraphSyncMaster() < 0) { | |||||
//jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); | |||||
//goto end; | |||||
} | |||||
} else { | |||||
if (ProcessGraphSyncSlave() < 0) { | |||||
//jack_error("JackAudioDriver::ProcessSync: process error, skip cycle..."); | |||||
//goto end; | |||||
} | |||||
} | |||||
ProcessGraphSync(); | |||||
// Write output buffers from the current cycle | // Write output buffers from the current cycle | ||||
if (Write() < 0) { | if (Write() < 0) { | ||||
@@ -283,8 +305,6 @@ int JackAudioDriver::ProcessSync() | |||||
return -1; | return -1; | ||||
} | } | ||||
end: | |||||
// Keep end cycle time | // Keep end cycle time | ||||
JackDriver::CycleTakeEndTime(); | JackDriver::CycleTakeEndTime(); | ||||
return 0; | return 0; | ||||
@@ -371,34 +391,24 @@ int JackAudioDriver::Stop() | |||||
return res; | return res; | ||||
} | } | ||||
/* | |||||
void JackAudioDriver::WaitUntilNextCycle() | |||||
{ | |||||
int wait_time_usec = (int((float(fEngineControl->fBufferSize) / (float(fEngineControl->fSampleRate))) * 1000000.0f)); | |||||
wait_time_usec = int(wait_time_usec - (GetMicroSeconds() - fBeginDateUst)); | |||||
if (wait_time_usec > 0) | |||||
JackSleep(wait_time_usec); | |||||
} | |||||
*/ | |||||
jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index, bool nulled) | |||||
jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index) | |||||
{ | { | ||||
return fCapturePortList[port_index] | return fCapturePortList[port_index] | ||||
? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize, nulled) | |||||
? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize) | |||||
: NULL; | : NULL; | ||||
} | } | ||||
jack_default_audio_sample_t* JackAudioDriver::GetOutputBuffer(int port_index, bool nulled) | |||||
jack_default_audio_sample_t* JackAudioDriver::GetOutputBuffer(int port_index) | |||||
{ | { | ||||
return fPlaybackPortList[port_index] | return fPlaybackPortList[port_index] | ||||
? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize, nulled) | |||||
? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize) | |||||
: NULL; | : NULL; | ||||
} | } | ||||
jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index, bool nulled) | |||||
jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index) | |||||
{ | { | ||||
return fPlaybackPortList[port_index] | return fPlaybackPortList[port_index] | ||||
? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize, nulled) | |||||
? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize) | |||||
: NULL; | : NULL; | ||||
} | } | ||||
@@ -35,15 +35,6 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver | |||||
protected: | protected: | ||||
void ProcessGraphAsyncMaster(); | |||||
void ProcessGraphAsyncSlave(); | |||||
int ProcessGraphSyncMaster(); | |||||
int ProcessGraphSyncSlave(); | |||||
virtual int ProcessAsync(); | |||||
virtual int ProcessSync(); | |||||
int fCaptureChannels; | int fCaptureChannels; | ||||
int fPlaybackChannels; | int fPlaybackChannels; | ||||
@@ -57,12 +48,22 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver | |||||
std::list<std::pair<std::string, std::string> > fConnections; // Connections list | std::list<std::pair<std::string, std::string> > fConnections; // Connections list | ||||
jack_default_audio_sample_t* GetInputBuffer(int port_index, bool nulled = false); | |||||
jack_default_audio_sample_t* GetOutputBuffer(int port_index, bool nulled = false); | |||||
jack_default_audio_sample_t* GetMonitorBuffer(int port_index, bool nulled = false); | |||||
jack_default_audio_sample_t* GetInputBuffer(int port_index); | |||||
jack_default_audio_sample_t* GetOutputBuffer(int port_index); | |||||
jack_default_audio_sample_t* GetMonitorBuffer(int port_index); | |||||
void HandleLatencyCallback(int status); | void HandleLatencyCallback(int status); | ||||
void UpdateLatencies(); | |||||
virtual void UpdateLatencies(); | |||||
int ProcessAsync(); | |||||
void ProcessGraphAsync(); | |||||
void ProcessGraphAsyncMaster(); | |||||
void ProcessGraphAsyncSlave(); | |||||
int ProcessSync(); | |||||
void ProcessGraphSync(); | |||||
int ProcessGraphSyncMaster(); | |||||
int ProcessGraphSyncSlave(); | |||||
public: | public: | ||||
@@ -124,8 +124,9 @@ int JackDriver::Open(bool capturing, | |||||
strcpy(fPlaybackDriverName, playback_driver_name); | strcpy(fPlaybackDriverName, playback_driver_name); | ||||
fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | ||||
if (!fEngineControl->fTimeOut) | |||||
if (!fEngineControl->fTimeOut) { | |||||
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | ||||
} | |||||
fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode | fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode | ||||
SetupDriverSync(fClientControl.fRefNum, false); | SetupDriverSync(fClientControl.fRefNum, false); | ||||
@@ -177,8 +178,9 @@ int JackDriver::Open(jack_nframes_t buffer_size, | |||||
strcpy(fPlaybackDriverName, playback_driver_name); | strcpy(fPlaybackDriverName, playback_driver_name); | ||||
fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | ||||
if (!fEngineControl->fTimeOut) | |||||
if (!fEngineControl->fTimeOut) { | |||||
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | ||||
} | |||||
fGraphManager->SetBufferSize(buffer_size); | fGraphManager->SetBufferSize(buffer_size); | ||||
fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode | fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode | ||||
@@ -309,9 +311,9 @@ int JackDriver::ProcessReadSlaves() | |||||
list<JackDriverInterface*>::const_iterator it; | list<JackDriverInterface*>::const_iterator it; | ||||
for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | ||||
JackDriverInterface* slave = *it; | JackDriverInterface* slave = *it; | ||||
if (slave->ProcessRead() < 0) | |||||
if (slave->ProcessRead() < 0) { | |||||
res = -1; | res = -1; | ||||
} | |||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
@@ -322,9 +324,9 @@ int JackDriver::ProcessWriteSlaves() | |||||
list<JackDriverInterface*>::const_iterator it; | list<JackDriverInterface*>::const_iterator it; | ||||
for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | ||||
JackDriverInterface* slave = *it; | JackDriverInterface* slave = *it; | ||||
if (slave->ProcessWrite() < 0) | |||||
if (slave->ProcessWrite() < 0) { | |||||
res = -1; | res = -1; | ||||
} | |||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
@@ -387,10 +389,8 @@ int JackDriver::StartSlaves() | |||||
JackDriverInterface* slave = *it; | JackDriverInterface* slave = *it; | ||||
if (slave->Start() < 0) { | if (slave->Start() < 0) { | ||||
res = -1; | res = -1; | ||||
// XXX: We should attempt to stop all of the slaves that we've | // XXX: We should attempt to stop all of the slaves that we've | ||||
// started here. | // started here. | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -403,8 +403,9 @@ int JackDriver::StopSlaves() | |||||
list<JackDriverInterface*>::const_iterator it; | list<JackDriverInterface*>::const_iterator it; | ||||
for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | ||||
JackDriverInterface* slave = *it; | JackDriverInterface* slave = *it; | ||||
if (slave->Stop() < 0) | |||||
if (slave->Stop() < 0) { | |||||
res = -1; | res = -1; | ||||
} | |||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
@@ -417,14 +418,13 @@ bool JackDriver::IsFixedBufferSize() | |||||
int JackDriver::SetBufferSize(jack_nframes_t buffer_size) | int JackDriver::SetBufferSize(jack_nframes_t buffer_size) | ||||
{ | { | ||||
int res = 0; | int res = 0; | ||||
list<JackDriverInterface*>::const_iterator it; | list<JackDriverInterface*>::const_iterator it; | ||||
for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | ||||
JackDriverInterface* slave = *it; | JackDriverInterface* slave = *it; | ||||
if (slave->SetBufferSize(buffer_size) < 0) | |||||
if (slave->SetBufferSize(buffer_size) < 0) { | |||||
res = -1; | res = -1; | ||||
} | |||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
@@ -434,8 +434,9 @@ int JackDriver::SetSampleRate(jack_nframes_t sample_rate) | |||||
list<JackDriverInterface*>::const_iterator it; | list<JackDriverInterface*>::const_iterator it; | ||||
for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | ||||
JackDriverInterface* slave = *it; | JackDriverInterface* slave = *it; | ||||
if (slave->SetSampleRate(sample_rate) < 0) | |||||
if (slave->SetSampleRate(sample_rate) < 0) { | |||||
res = -1; | res = -1; | ||||
} | |||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
@@ -445,5 +446,4 @@ bool JackDriver::Initialize() | |||||
return true; | return true; | ||||
} | } | ||||
} // end of namespace | } // end of namespace |
@@ -31,7 +31,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include <dirent.h> | #include <dirent.h> | ||||
#endif | #endif | ||||
jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver_t * driver); | |||||
jack_driver_desc_t* jackctl_driver_get_desc(jackctl_driver_t * driver); | |||||
SERVER_EXPORT void jack_print_driver_options(jack_driver_desc_t* desc, FILE* file) | SERVER_EXPORT void jack_print_driver_options(jack_driver_desc_t* desc, FILE* file) | ||||
{ | { | ||||
@@ -50,17 +50,18 @@ SERVER_EXPORT void jack_print_driver_options(jack_driver_desc_t* desc, FILE* fil | |||||
sprintf (arg_default, "%c", desc->params[i].value.c); | sprintf (arg_default, "%c", desc->params[i].value.c); | ||||
break; | break; | ||||
case JackDriverParamString: | case JackDriverParamString: | ||||
if (desc->params[i].value.str && strcmp (desc->params[i].value.str, "") != 0) | |||||
if (desc->params[i].value.str && strcmp (desc->params[i].value.str, "") != 0) { | |||||
sprintf (arg_default, "%s", desc->params[i].value.str); | sprintf (arg_default, "%s", desc->params[i].value.str); | ||||
else | |||||
} else { | |||||
sprintf (arg_default, "none"); | sprintf (arg_default, "none"); | ||||
} | |||||
break; | break; | ||||
case JackDriverParamBool: | case JackDriverParamBool: | ||||
sprintf (arg_default, "%s", desc->params[i].value.i ? "true" : "false"); | sprintf (arg_default, "%s", desc->params[i].value.i ? "true" : "false"); | ||||
break; | break; | ||||
} | } | ||||
fprintf (file, "\t-%c, --%s \t%s (default: %s)\n", | |||||
fprintf(file, "\t-%c, --%s \t%s (default: %s)\n", | |||||
desc->params[i].character, | desc->params[i].character, | ||||
desc->params[i].name, | desc->params[i].name, | ||||
desc->params[i].long_desc, | desc->params[i].long_desc, | ||||
@@ -69,7 +70,7 @@ SERVER_EXPORT void jack_print_driver_options(jack_driver_desc_t* desc, FILE* fil | |||||
} | } | ||||
static void | static void | ||||
jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, FILE *file) | |||||
jack_print_driver_param_usage (jack_driver_desc_t* desc, unsigned long param, FILE *file) | |||||
{ | { | ||||
fprintf (file, "Usage information for the '%s' parameter for driver '%s':\n", | fprintf (file, "Usage information for the '%s' parameter for driver '%s':\n", | ||||
desc->params[param].name, desc->name); | desc->params[param].name, desc->name); | ||||
@@ -78,8 +79,8 @@ jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, F | |||||
SERVER_EXPORT void jack_free_driver_params(JSList * driver_params) | SERVER_EXPORT void jack_free_driver_params(JSList * driver_params) | ||||
{ | { | ||||
JSList *node_ptr = driver_params; | |||||
JSList *next_node_ptr; | |||||
JSList*node_ptr = driver_params; | |||||
JSList*next_node_ptr; | |||||
while (node_ptr) { | while (node_ptr) { | ||||
next_node_ptr = node_ptr->next; | next_node_ptr = node_ptr->next; | ||||
@@ -90,14 +91,14 @@ SERVER_EXPORT void jack_free_driver_params(JSList * driver_params) | |||||
} | } | ||||
SERVER_EXPORT int | SERVER_EXPORT int | ||||
jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr) | |||||
jack_parse_driver_params(jack_driver_desc_t* desc, int argc, char* argv[], JSList** param_ptr) | |||||
{ | { | ||||
struct option * long_options; | struct option * long_options; | ||||
char * options, * options_ptr; | |||||
char* options, * options_ptr; | |||||
unsigned long i; | unsigned long i; | ||||
int opt; | int opt; | ||||
unsigned int param_index; | unsigned int param_index; | ||||
JSList * params = NULL; | |||||
JSList* params = NULL; | |||||
jack_driver_param_t * driver_param; | jack_driver_param_t * driver_param; | ||||
if (argc <= 1) { | if (argc <= 1) { | ||||
@@ -192,11 +193,8 @@ jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSLi | |||||
strcasecmp("0", optarg) == 0 || | strcasecmp("0", optarg) == 0 || | ||||
strcasecmp("(null)", optarg) == 0 ) { | strcasecmp("(null)", optarg) == 0 ) { | ||||
driver_param->value.i = false; | driver_param->value.i = false; | ||||
} else { | } else { | ||||
driver_param->value.i = true; | driver_param->value.i = true; | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
@@ -214,31 +212,33 @@ jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSLi | |||||
free (options); | free (options); | ||||
free (long_options); | free (long_options); | ||||
if (param_ptr) | |||||
if (param_ptr) { | |||||
*param_ptr = params; | *param_ptr = params; | ||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
SERVER_EXPORT int | SERVER_EXPORT int | ||||
jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[]) | jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[]) | ||||
{ | { | ||||
struct option * long_options; | |||||
char * options, * options_ptr; | |||||
struct option* long_options; | |||||
char* options, * options_ptr; | |||||
unsigned long i; | unsigned long i; | ||||
int opt; | int opt; | ||||
JSList * node_ptr; | |||||
JSList* node_ptr; | |||||
jackctl_parameter_t * param = NULL; | jackctl_parameter_t * param = NULL; | ||||
union jackctl_parameter_value value; | union jackctl_parameter_value value; | ||||
if (argc <= 1) | |||||
if (argc <= 1) { | |||||
return 0; | return 0; | ||||
} | |||||
const JSList * driver_params = jackctl_driver_get_parameters(driver_ptr); | |||||
if (driver_params == NULL) | |||||
const JSList* driver_params = jackctl_driver_get_parameters(driver_ptr); | |||||
if (driver_params == NULL) { | |||||
return 1; | return 1; | ||||
} | |||||
jack_driver_desc_t * desc = jackctl_driver_get_desc(driver_ptr); | |||||
jack_driver_desc_t* desc = jackctl_driver_get_desc(driver_ptr); | |||||
/* check for help */ | /* check for help */ | ||||
if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) { | if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) { | ||||
@@ -352,14 +352,14 @@ jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[]) | |||||
return 0; | return 0; | ||||
} | } | ||||
jack_driver_desc_t * | |||||
jack_find_driver_descriptor (JSList * drivers, const char * name) | |||||
jack_driver_desc_t* | |||||
jack_find_driver_descriptor (JSList * drivers, const char* name) | |||||
{ | { | ||||
jack_driver_desc_t * desc = 0; | |||||
JSList * node; | |||||
jack_driver_desc_t* desc = 0; | |||||
JSList* node; | |||||
for (node = drivers; node; node = jack_slist_next (node)) { | for (node = drivers; node; node = jack_slist_next (node)) { | ||||
desc = (jack_driver_desc_t *) node->data; | |||||
desc = (jack_driver_desc_t*) node->data; | |||||
if (strcmp (desc->name, name) != 0) { | if (strcmp (desc->name, name) != 0) { | ||||
desc = NULL; | desc = NULL; | ||||
@@ -371,18 +371,18 @@ jack_find_driver_descriptor (JSList * drivers, const char * name) | |||||
return desc; | return desc; | ||||
} | } | ||||
static jack_driver_desc_t * | |||||
jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol) | |||||
static jack_driver_desc_t* | |||||
jack_get_descriptor (JSList * drivers, const char* sofile, const char* symbol) | |||||
{ | { | ||||
jack_driver_desc_t * descriptor, * other_descriptor; | |||||
jack_driver_desc_t* descriptor, * other_descriptor; | |||||
JackDriverDescFunction so_get_descriptor = NULL; | JackDriverDescFunction so_get_descriptor = NULL; | ||||
JSList * node; | |||||
JSList* node; | |||||
void * dlhandle; | void * dlhandle; | ||||
char * filename; | |||||
char* filename; | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
int dlerr; | int dlerr; | ||||
#else | #else | ||||
const char * dlerr; | |||||
const char* dlerr; | |||||
#endif | #endif | ||||
int err; | int err; | ||||
@@ -410,7 +410,7 @@ jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol) | |||||
#endif | #endif | ||||
} | } | ||||
filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1); | |||||
filename = (char*)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1); | |||||
sprintf (filename, "%s/%s", driver_dir, sofile); | sprintf (filename, "%s/%s", driver_dir, sofile); | ||||
if ((dlhandle = LoadDriverModule(filename)) == NULL) { | if ((dlhandle = LoadDriverModule(filename)) == NULL) { | ||||
@@ -458,7 +458,7 @@ jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol) | |||||
/* check it doesn't exist already */ | /* check it doesn't exist already */ | ||||
for (node = drivers; node; node = jack_slist_next (node)) { | for (node = drivers; node; node = jack_slist_next (node)) { | ||||
other_descriptor = (jack_driver_desc_t *) node->data; | |||||
other_descriptor = (jack_driver_desc_t*) node->data; | |||||
if (strcmp(descriptor->name, other_descriptor->name) == 0) { | if (strcmp(descriptor->name, other_descriptor->name) == 0) { | ||||
jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first", | jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first", | ||||
@@ -502,7 +502,7 @@ static bool check_symbol(const char* sofile, const char* symbol) | |||||
#endif | #endif | ||||
} | } | ||||
char* filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1); | |||||
char* filename = (char*)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1); | |||||
sprintf (filename, "%s/%s", driver_dir, sofile); | sprintf (filename, "%s/%s", driver_dir, sofile); | ||||
if ((dlhandle = LoadDriverModule(filename)) == NULL) { | if ((dlhandle = LoadDriverModule(filename)) == NULL) { | ||||
@@ -524,14 +524,14 @@ static bool check_symbol(const char* sofile, const char* symbol) | |||||
JSList * | JSList * | ||||
jack_drivers_load (JSList * drivers) { | jack_drivers_load (JSList * drivers) { | ||||
char * driver_dir; | |||||
char* driver_dir; | |||||
char driver_dir_storage[512]; | char driver_dir_storage[512]; | ||||
char dll_filename[512]; | char dll_filename[512]; | ||||
WIN32_FIND_DATA filedata; | WIN32_FIND_DATA filedata; | ||||
HANDLE file; | HANDLE file; | ||||
const char * ptr = NULL; | |||||
JSList * driver_list = NULL; | |||||
jack_driver_desc_t * desc = NULL; | |||||
const char* ptr = NULL; | |||||
JSList* driver_list = NULL; | |||||
jack_driver_desc_t* desc = NULL; | |||||
if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | ||||
// for WIN32 ADDON_DIR is defined in JackConstants.h as relative path | // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path | ||||
@@ -601,10 +601,10 @@ JSList * | |||||
jack_drivers_load (JSList * drivers) { | jack_drivers_load (JSList * drivers) { | ||||
struct dirent * dir_entry; | struct dirent * dir_entry; | ||||
DIR * dir_stream; | DIR * dir_stream; | ||||
const char * ptr; | |||||
const char* ptr; | |||||
int err; | int err; | ||||
JSList * driver_list = NULL; | |||||
jack_driver_desc_t * desc = NULL; | |||||
JSList* driver_list = NULL; | |||||
jack_driver_desc_t* desc = NULL; | |||||
const char* driver_dir; | const char* driver_dir; | ||||
if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | ||||
@@ -669,14 +669,14 @@ jack_drivers_load (JSList * drivers) { | |||||
JSList * | JSList * | ||||
jack_internals_load (JSList * internals) { | jack_internals_load (JSList * internals) { | ||||
char * driver_dir; | |||||
char* driver_dir; | |||||
char driver_dir_storage[512]; | char driver_dir_storage[512]; | ||||
char dll_filename[512]; | char dll_filename[512]; | ||||
WIN32_FIND_DATA filedata; | WIN32_FIND_DATA filedata; | ||||
HANDLE file; | HANDLE file; | ||||
const char * ptr = NULL; | |||||
JSList * driver_list = NULL; | |||||
jack_driver_desc_t * desc; | |||||
const char* ptr = NULL; | |||||
JSList* driver_list = NULL; | |||||
jack_driver_desc_t* desc; | |||||
if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | ||||
// for WIN32 ADDON_DIR is defined in JackConstants.h as relative path | // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path | ||||
@@ -742,10 +742,10 @@ JSList * | |||||
jack_internals_load (JSList * internals) { | jack_internals_load (JSList * internals) { | ||||
struct dirent * dir_entry; | struct dirent * dir_entry; | ||||
DIR * dir_stream; | DIR * dir_stream; | ||||
const char * ptr; | |||||
const char* ptr; | |||||
int err; | int err; | ||||
JSList * driver_list = NULL; | |||||
jack_driver_desc_t * desc; | |||||
JSList* driver_list = NULL; | |||||
jack_driver_desc_t* desc; | |||||
const char* driver_dir; | const char* driver_dir; | ||||
if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | ||||
@@ -809,7 +809,7 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
int errstr; | int errstr; | ||||
#else | #else | ||||
const char * errstr; | |||||
const char* errstr; | |||||
#endif | #endif | ||||
fHandle = LoadDriverModule (driver_desc->file); | fHandle = LoadDriverModule (driver_desc->file); | ||||
@@ -852,7 +852,7 @@ JackDriverInfo::~JackDriverInfo() | |||||
} | } | ||||
SERVER_EXPORT | SERVER_EXPORT | ||||
jack_driver_desc_t * | |||||
jack_driver_desc_t* | |||||
jack_driver_descriptor_construct( | jack_driver_descriptor_construct( | ||||
const char * name, | const char * name, | ||||
jack_driver_type_t type, | jack_driver_type_t type, | ||||
@@ -861,7 +861,7 @@ jack_driver_descriptor_construct( | |||||
{ | { | ||||
size_t name_len; | size_t name_len; | ||||
size_t description_len; | size_t description_len; | ||||
jack_driver_desc_t * desc_ptr; | |||||
jack_driver_desc_t* desc_ptr; | |||||
name_len = strlen(name); | name_len = strlen(name); | ||||
description_len = strlen(description); | description_len = strlen(description); | ||||
@@ -894,15 +894,15 @@ jack_driver_descriptor_construct( | |||||
SERVER_EXPORT | SERVER_EXPORT | ||||
int | int | ||||
jack_driver_descriptor_add_parameter( | jack_driver_descriptor_add_parameter( | ||||
jack_driver_desc_t * desc_ptr, | |||||
jack_driver_desc_t* desc_ptr, | |||||
jack_driver_desc_filler_t * filler_ptr, | jack_driver_desc_filler_t * filler_ptr, | ||||
const char * name, | |||||
const char* name, | |||||
char character, | char character, | ||||
jack_driver_param_type_t type, | jack_driver_param_type_t type, | ||||
const jack_driver_param_value_t * value_ptr, | const jack_driver_param_value_t * value_ptr, | ||||
jack_driver_param_constraint_desc_t * constraint, | jack_driver_param_constraint_desc_t * constraint, | ||||
const char * short_desc, | |||||
const char * long_desc) | |||||
const char* short_desc, | |||||
const char* long_desc) | |||||
{ | { | ||||
size_t name_len; | size_t name_len; | ||||
size_t short_desc_len; | size_t short_desc_len; | ||||
@@ -27,7 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackDriver.h" | #include "JackDriver.h" | ||||
#include "JackSystemDeps.h" | #include "JackSystemDeps.h" | ||||
typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | |||||
typedef jack_driver_desc_t* (*JackDriverDescFunction) (); | |||||
typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | ||||
class SERVER_EXPORT JackDriverInfo | class SERVER_EXPORT JackDriverInfo | ||||
@@ -54,10 +54,10 @@ class SERVER_EXPORT JackDriverInfo | |||||
}; | }; | ||||
jack_driver_desc_t * jack_find_driver_descriptor(JSList * drivers, const char * name); | |||||
jack_driver_desc_t* jack_find_driver_descriptor(JSList* drivers, const char* name); | |||||
JSList * jack_drivers_load(JSList * drivers); | |||||
JSList * jack_internals_load(JSList * internals); | |||||
JSList* jack_drivers_load(JSList* drivers); | |||||
JSList* jack_internals_load(JSList* internals); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" | extern "C" | ||||
@@ -32,7 +32,7 @@ namespace Jack | |||||
class JackDummyDriver : public JackTimedDriver | class JackDummyDriver : public JackTimedDriver | ||||
{ | { | ||||
public: | public: | ||||
JackDummyDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | JackDummyDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | ||||
@@ -41,6 +41,18 @@ class JackDummyDriver : public JackTimedDriver | |||||
virtual ~JackDummyDriver() | virtual ~JackDummyDriver() | ||||
{} | {} | ||||
virtual int Process() | |||||
{ | |||||
JackDriver::CycleTakeBeginTime(); | |||||
if (JackAudioDriver::Process() < 0) { | |||||
return -1; | |||||
} else { | |||||
ProcessWait(); | |||||
return 0; | |||||
} | |||||
} | |||||
}; | }; | ||||
} // end of namespace | } // end of namespace | ||||
@@ -166,7 +166,7 @@ bool JackGraphManager::IsDirectConnection(int ref1, int ref2) | |||||
} | } | ||||
// RT | // RT | ||||
void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buffer_size, bool nulled) | |||||
void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buffer_size) | |||||
{ | { | ||||
AssertPort(port_index); | AssertPort(port_index); | ||||
AssertBufferSize(buffer_size); | AssertBufferSize(buffer_size); | ||||
@@ -184,17 +184,13 @@ void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buff | |||||
// Output port | // Output port | ||||
if (port->fFlags & JackPortIsOutput) { | if (port->fFlags & JackPortIsOutput) { | ||||
if (port->fTied != NO_PORT) { | |||||
return GetBuffer(port->fTied, buffer_size); | |||||
} else { | |||||
return (len == 0 && nulled) ? NULL : GetBuffer(port_index); | |||||
} | |||||
} | |||||
return (port->fTied != NO_PORT) ? GetBuffer(port->fTied, buffer_size) : GetBuffer(port_index); | |||||
} | |||||
// No connections : return a zero-filled buffer | // No connections : return a zero-filled buffer | ||||
if (len == 0) { | if (len == 0) { | ||||
port->ClearBuffer(buffer_size); | port->ClearBuffer(buffer_size); | ||||
return (nulled) ? NULL : port->GetBuffer(); | |||||
return port->GetBuffer(); | |||||
// One connection | // One connection | ||||
} else if (len == 1) { | } else if (len == 1) { | ||||
@@ -114,7 +114,7 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState | |||||
int GetOutputRefNum(jack_port_id_t port_index); | int GetOutputRefNum(jack_port_id_t port_index); | ||||
// Buffer management | // Buffer management | ||||
void* GetBuffer(jack_port_id_t port_index, jack_nframes_t frames, bool nulled = false); | |||||
void* GetBuffer(jack_port_id_t port_index, jack_nframes_t frames); | |||||
// Activation management | // Activation management | ||||
void RunCurrentGraph(); | void RunCurrentGraph(); | ||||
@@ -58,8 +58,9 @@ JackLibSampleRateResampler::JackLibSampleRateResampler(unsigned int quality) | |||||
int error; | int error; | ||||
fResampler = src_new(quality, 1, &error); | fResampler = src_new(quality, 1, &error); | ||||
if (error != 0) | |||||
if (error != 0) { | |||||
jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error)); | jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error)); | ||||
} | |||||
} | } | ||||
JackLibSampleRateResampler::~JackLibSampleRateResampler() | JackLibSampleRateResampler::~JackLibSampleRateResampler() | ||||
@@ -110,16 +110,6 @@ int JackMidiDriver::Detach() | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackMidiDriver::Read() | |||||
{ | |||||
return 0; | |||||
} | |||||
int JackMidiDriver::Write() | |||||
{ | |||||
return 0; | |||||
} | |||||
void JackMidiDriver::UpdateLatencies() | void JackMidiDriver::UpdateLatencies() | ||||
{ | { | ||||
jack_latency_range_t range; | jack_latency_range_t range; | ||||
@@ -77,9 +77,6 @@ class SERVER_EXPORT JackMidiDriver : public JackDriver | |||||
virtual int Attach(); | virtual int Attach(); | ||||
virtual int Detach(); | virtual int Detach(); | ||||
virtual int Read(); | |||||
virtual int Write(); | |||||
}; | }; | ||||
} // end of namespace | } // end of namespace | ||||
@@ -166,36 +166,36 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
{ | { | ||||
// Init socket API (win32) | // Init socket API (win32) | ||||
if (SocketAPIInit() < 0) { | if (SocketAPIInit() < 0) { | ||||
fprintf(stderr, "Can't init Socket API, exiting...\n"); | |||||
jack_error("Can't init Socket API, exiting..."); | |||||
return -1; | return -1; | ||||
} | } | ||||
// Request socket | // Request socket | ||||
if (fSocket.NewSocket() == SOCKET_ERROR) { | if (fSocket.NewSocket() == SOCKET_ERROR) { | ||||
fprintf(stderr, "Can't create the network management input socket : %s\n", StrError(NET_ERROR_CODE)); | |||||
jack_error("Can't create the network management input socket : %s", StrError(NET_ERROR_CODE)); | |||||
return -1; | return -1; | ||||
} | } | ||||
// Bind the socket to the local port | // Bind the socket to the local port | ||||
if (fSocket.Bind() == SOCKET_ERROR) { | if (fSocket.Bind() == SOCKET_ERROR) { | ||||
fprintf(stderr, "Can't bind the network manager socket : %s\n", StrError(NET_ERROR_CODE)); | |||||
jack_error("Can't bind the network manager socket : %s", StrError(NET_ERROR_CODE)); | |||||
fSocket.Close(); | fSocket.Close(); | ||||
return -1; | return -1; | ||||
} | } | ||||
// Join multicast group | // Join multicast group | ||||
if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) { | if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) { | ||||
fprintf(stderr, "Can't join multicast group : %s\n", StrError(NET_ERROR_CODE)); | |||||
jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE)); | |||||
} | } | ||||
// Local loop | // Local loop | ||||
if (fSocket.SetLocalLoop() == SOCKET_ERROR) { | if (fSocket.SetLocalLoop() == SOCKET_ERROR) { | ||||
fprintf(stderr, "Can't set local loop : %s\n", StrError(NET_ERROR_CODE)); | |||||
jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE)); | |||||
} | } | ||||
// Set a timeout on the multicast receive (the thread can now be cancelled) | // Set a timeout on the multicast receive (the thread can now be cancelled) | ||||
if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) { | if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) { | ||||
fprintf(stderr, "Can't set timeout : %s\n", StrError(NET_ERROR_CODE)); | |||||
jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE)); | |||||
} | } | ||||
// Main loop, wait for data, deal with it and wait again | // Main loop, wait for data, deal with it and wait again | ||||
@@ -209,9 +209,9 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
SessionParamsNToH(&net_params, &fParams); | SessionParamsNToH(&net_params, &fParams); | ||||
if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) { | if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) { | ||||
fprintf(stderr, "Error in receive : %s\n", StrError(NET_ERROR_CODE)); | |||||
jack_error("Error in receive : %s", StrError(NET_ERROR_CODE)); | |||||
if (++attempt == 10) { | if (++attempt == 10) { | ||||
fprintf(stderr, "Can't receive on the socket, exiting net manager.\n" ); | |||||
jack_error("Can't receive on the socket, exiting net manager" ); | |||||
goto error; | goto error; | ||||
} | } | ||||
} | } | ||||
@@ -225,10 +225,10 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
SessionParamsDisplay(&fParams); | SessionParamsDisplay(&fParams); | ||||
fRunning = false; | fRunning = false; | ||||
} else { | } else { | ||||
fprintf(stderr, "Can't init new net master...\n"); | |||||
jack_error("Can't init new net master..."); | |||||
goto error; | goto error; | ||||
} | } | ||||
jack_info ( "Waiting for a slave..." ); | |||||
jack_info("Waiting for a slave..."); | |||||
break; | break; | ||||
case KILL_MASTER: | case KILL_MASTER: | ||||
@@ -259,7 +259,7 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
{ | { | ||||
// Check MASTER <==> SLAVE network protocol coherency | // Check MASTER <==> SLAVE network protocol coherency | ||||
if (fParams.fProtocolVersion != MASTER_PROTOCOL) { | if (fParams.fProtocolVersion != MASTER_PROTOCOL) { | ||||
fprintf(stderr, "Error : slave is running with a different protocol %s\n", fParams.fName); | |||||
jack_error("Error : slave is running with a different protocol %s", fParams.fName); | |||||
return -1; | return -1; | ||||
} | } | ||||
@@ -465,7 +465,6 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
// Request parameters | // Request parameters | ||||
assert(strlen(ip) < 32); | assert(strlen(ip) < 32); | ||||
strcpy(fMulticastIP, ip); | strcpy(fMulticastIP, ip); | ||||
fParams.fMtu = request->mtu; | fParams.fMtu = request->mtu; | ||||
fParams.fTransportSync = 0; | fParams.fTransportSync = 0; | ||||
fParams.fSendAudioChannels = request->audio_input; | fParams.fSendAudioChannels = request->audio_input; | ||||
@@ -494,17 +493,25 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
int Open(jack_master_t* result) | int Open(jack_master_t* result) | ||||
{ | { | ||||
if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) { | if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) { | ||||
printf("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY); | |||||
jack_error("Error : network latency is limited to %d", NETWORK_MAX_LATENCY); | |||||
return -1; | return -1; | ||||
} | } | ||||
// Init network connection | // Init network connection | ||||
if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) { | if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) { | ||||
jack_error("Initing network fails..."); | |||||
return -1; | |||||
} | |||||
// Finish connection... | |||||
if (!JackNetSlaveInterface::InitRendering()) { | |||||
jack_error("Starting network fails..."); | |||||
return -1; | return -1; | ||||
} | } | ||||
// Then set global parameters | // Then set global parameters | ||||
if (!SetParams()) { | if (!SetParams()) { | ||||
jack_error("SetParams error..."); | |||||
return -1; | return -1; | ||||
} | } | ||||
@@ -532,11 +539,19 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
// Init network connection | // Init network connection | ||||
if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) { | if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) { | ||||
jack_error("Initing network fails..."); | |||||
return -1; | |||||
} | |||||
// Finish connection... | |||||
if (!JackNetSlaveInterface::InitRendering()) { | |||||
jack_error("Starting network fails..."); | |||||
return -1; | return -1; | ||||
} | } | ||||
// Then set global parameters | // Then set global parameters | ||||
if (!SetParams()) { | if (!SetParams()) { | ||||
jack_error("SetParams error..."); | |||||
return -1; | return -1; | ||||
} | } | ||||
@@ -630,8 +645,8 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
{ | { | ||||
// Will do "something" on OSX only... | // Will do "something" on OSX only... | ||||
UInt64 period, constraint; | UInt64 period, constraint; | ||||
period = constraint = float(fParams.fPeriodSize) / float(fParams.fSampleRate) * 1000000; | |||||
UInt64 computation = JackTools::ComputationMicroSec(fParams.fPeriodSize); | |||||
period = constraint = UInt64(1000000000.f * (float(fParams.fPeriodSize) / float(fParams.fSampleRate))); | |||||
UInt64 computation = JackTools::ComputationMicroSec(fParams.fPeriodSize) * 1000; | |||||
fThread.SetParams(period, computation, constraint); | fThread.SetParams(period, computation, constraint); | ||||
return (fThread.AcquireRealTime(80) == 0); // TODO: get a value from the server | return (fThread.AcquireRealTime(80) == 0); // TODO: get a value from the server | ||||
@@ -713,11 +728,6 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
int Start() | int Start() | ||||
{ | { | ||||
// Finish connection... | |||||
if (!JackNetSlaveInterface::InitRendering()) { | |||||
return -1; | |||||
} | |||||
return (fProcessCallback == 0) ? -1 : fThread.StartSync(); | return (fProcessCallback == 0) ? -1 : fThread.StartSync(); | ||||
} | } | ||||
@@ -974,7 +984,8 @@ SERVER_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** in | |||||
} | } | ||||
#ifdef MY_TARGET_OS_IPHONE | |||||
//#ifdef MY_TARGET_OS_IPHONE | |||||
#if 1 | |||||
static void jack_format_and_log(int level, const char *prefix, const char *fmt, va_list ap) | static void jack_format_and_log(int level, const char *prefix, const char *fmt, va_list ap) | ||||
{ | { | ||||
@@ -1031,3 +1042,4 @@ SERVER_EXPORT void jack_log(const char *fmt, ...) | |||||
{} | {} | ||||
#endif | #endif | ||||
@@ -35,9 +35,8 @@ namespace Jack | |||||
because we don't have full parametering right now, parameters will be parsed from the param list, | because we don't have full parametering right now, parameters will be parsed from the param list, | ||||
and then JackNetSlaveInterface will be filled with proper values. | and then JackNetSlaveInterface will be filled with proper values. | ||||
*/ | */ | ||||
strcpy(fMulticastIP, DEFAULT_MULTICAST_IP); | |||||
uint port = DEFAULT_PORT; | |||||
char multicast_ip[32]; | |||||
uint udp_port; | |||||
GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE); | GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE); | ||||
fSocket.GetName(fParams.fSlaveNetName); | fSocket.GetName(fParams.fSlaveNetName); | ||||
fParams.fMtu = DEFAULT_MTU; | fParams.fMtu = DEFAULT_MTU; | ||||
@@ -52,7 +51,18 @@ namespace Jack | |||||
fParams.fSlaveSyncMode = 1; | fParams.fSlaveSyncMode = 1; | ||||
fParams.fNetworkLatency = 2; | fParams.fNetworkLatency = 2; | ||||
fParams.fSampleEncoder = JackFloatEncoder; | fParams.fSampleEncoder = JackFloatEncoder; | ||||
fJackClient = jack_client; | |||||
fClient = jack_client; | |||||
// Possibly use env variable | |||||
const char* default_udp_port = getenv("JACK_NETJACK_PORT"); | |||||
udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT; | |||||
const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST"); | |||||
if (default_multicast_ip) { | |||||
strcpy(multicast_ip, default_multicast_ip); | |||||
} else { | |||||
strcpy(multicast_ip, DEFAULT_MULTICAST_IP); | |||||
} | |||||
//options parsing | //options parsing | ||||
const JSList* node; | const JSList* node; | ||||
@@ -63,14 +73,11 @@ namespace Jack | |||||
switch (param->character) { | switch (param->character) { | ||||
case 'a' : | case 'a' : | ||||
if (strlen(param->value.str) < 32) { | |||||
strcpy(fMulticastIP, param->value.str); | |||||
} else { | |||||
jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP); | |||||
} | |||||
assert(strlen(param->value.str) < 32); | |||||
strcpy(multicast_ip, param->value.str); | |||||
break; | break; | ||||
case 'p' : | case 'p' : | ||||
fSocket.SetPort(param->value.ui); | |||||
udp_port = param->value.ui; | |||||
break; | break; | ||||
case 'M' : | case 'M' : | ||||
fParams.fMtu = param->value.i; | fParams.fMtu = param->value.i; | ||||
@@ -85,7 +92,7 @@ namespace Jack | |||||
strncpy(fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE); | strncpy(fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE); | ||||
break; | break; | ||||
case 't' : | case 't' : | ||||
//fParams.fTransportSync = param->value.ui; | |||||
fParams.fTransportSync = param->value.ui; | |||||
break; | break; | ||||
#if HAVE_CELT | #if HAVE_CELT | ||||
case 'c': | case 'c': | ||||
@@ -112,9 +119,11 @@ namespace Jack | |||||
} | } | ||||
} | } | ||||
strcpy(fMulticastIP, multicast_ip); | |||||
// Set the socket parameters | // Set the socket parameters | ||||
fSocket.SetPort(port); | |||||
fSocket.SetAddress(fMulticastIP, port); | |||||
fSocket.SetPort(udp_port); | |||||
fSocket.SetAddress(fMulticastIP, udp_port); | |||||
// If not set, takes default | // If not set, takes default | ||||
fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio; | fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio; | ||||
@@ -136,13 +145,15 @@ namespace Jack | |||||
jack_log("JackNetAdapter::~JackNetAdapter"); | jack_log("JackNetAdapter::~JackNetAdapter"); | ||||
if (fSoftCaptureBuffer) { | if (fSoftCaptureBuffer) { | ||||
for (int port_index = 0; port_index < fCaptureChannels; port_index++) | |||||
for (int port_index = 0; port_index < fCaptureChannels; port_index++) { | |||||
delete[] fSoftCaptureBuffer[port_index]; | delete[] fSoftCaptureBuffer[port_index]; | ||||
} | |||||
delete[] fSoftCaptureBuffer; | delete[] fSoftCaptureBuffer; | ||||
} | } | ||||
if (fSoftPlaybackBuffer) { | if (fSoftPlaybackBuffer) { | ||||
for (int port_index = 0; port_index < fPlaybackChannels; port_index++) | |||||
for (int port_index = 0; port_index < fPlaybackChannels; port_index++) { | |||||
delete[] fSoftPlaybackBuffer[port_index]; | delete[] fSoftPlaybackBuffer[port_index]; | ||||
} | |||||
delete[] fSoftPlaybackBuffer; | delete[] fSoftPlaybackBuffer; | ||||
} | } | ||||
} | } | ||||
@@ -244,8 +255,9 @@ namespace Jack | |||||
try { | try { | ||||
// Keep running even in case of error | // Keep running even in case of error | ||||
while (fThread.GetStatus() == JackThread::kRunning) | while (fThread.GetStatus() == JackThread::kRunning) | ||||
if (Process() == SOCKET_ERROR) | |||||
if (Process() == SOCKET_ERROR) { | |||||
return false; | return false; | ||||
} | |||||
return false; | return false; | ||||
} catch (JackNetException& e) { | } catch (JackNetException& e) { | ||||
e.PrintMessage(); | e.PrintMessage(); | ||||
@@ -268,17 +280,17 @@ namespace Jack | |||||
//TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver) | //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver) | ||||
//is there a new transport state ? | //is there a new transport state ? | ||||
if (fSendTransportData.fNewState &&(fSendTransportData.fState != jack_transport_query(fJackClient, NULL))) { | |||||
if (fSendTransportData.fNewState &&(fSendTransportData.fState != jack_transport_query(fClient, NULL))) { | |||||
switch (fSendTransportData.fState) | switch (fSendTransportData.fState) | ||||
{ | { | ||||
case JackTransportStopped : | case JackTransportStopped : | ||||
jack_transport_stop(fJackClient); | |||||
jack_transport_stop(fClient); | |||||
jack_info("NetMaster : transport stops"); | jack_info("NetMaster : transport stops"); | ||||
break; | break; | ||||
case JackTransportStarting : | case JackTransportStarting : | ||||
jack_transport_reposition(fJackClient, &fSendTransportData.fPosition); | |||||
jack_transport_start(fJackClient); | |||||
jack_transport_reposition(fClient, &fSendTransportData.fPosition); | |||||
jack_transport_start(fClient); | |||||
jack_info("NetMaster : transport starts"); | jack_info("NetMaster : transport starts"); | ||||
break; | break; | ||||
@@ -314,13 +326,14 @@ namespace Jack | |||||
} | } | ||||
//update transport state and position | //update transport state and position | ||||
fReturnTransportData.fState = jack_transport_query(fJackClient, &fReturnTransportData.fPosition); | |||||
fReturnTransportData.fState = jack_transport_query(fClient, &fReturnTransportData.fPosition); | |||||
//is it a new state (that the master need to know...) ? | //is it a new state (that the master need to know...) ? | ||||
fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) && | fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) && | ||||
(fReturnTransportData.fState != fSendTransportData.fState)); | (fReturnTransportData.fState != fSendTransportData.fState)); | ||||
if (fReturnTransportData.fNewState) | |||||
if (fReturnTransportData.fNewState) { | |||||
jack_info("Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState)); | jack_info("Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState)); | ||||
} | |||||
fLastTransportState = fReturnTransportData.fState; | fLastTransportState = fReturnTransportData.fState; | ||||
} | } | ||||
@@ -329,8 +342,9 @@ namespace Jack | |||||
{ | { | ||||
//don't return -1 in case of sync recv failure | //don't return -1 in case of sync recv failure | ||||
//we need the process to continue for network error detection | //we need the process to continue for network error detection | ||||
if (SyncRecv() == SOCKET_ERROR) | |||||
if (SyncRecv() == SOCKET_ERROR) { | |||||
return 0; | return 0; | ||||
} | |||||
DecodeSyncPacket(); | DecodeSyncPacket(); | ||||
return DataRecv(); | return DataRecv(); | ||||
@@ -340,8 +354,9 @@ namespace Jack | |||||
{ | { | ||||
EncodeSyncPacket(); | EncodeSyncPacket(); | ||||
if (SyncSend() == SOCKET_ERROR) | |||||
if (SyncSend() == SOCKET_ERROR) { | |||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
} | |||||
return DataSend(); | return DataSend(); | ||||
} | } | ||||
@@ -351,15 +366,17 @@ namespace Jack | |||||
{ | { | ||||
//read data from the network | //read data from the network | ||||
//in case of fatal network error, stop the process | //in case of fatal network error, stop the process | ||||
if (Read() == SOCKET_ERROR) | |||||
if (Read() == SOCKET_ERROR) { | |||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
} | |||||
PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize); | PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize); | ||||
//then write data to network | //then write data to network | ||||
//in case of failure, stop process | //in case of failure, stop process | ||||
if (Write() == SOCKET_ERROR) | |||||
if (Write() == SOCKET_ERROR) { | |||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -386,10 +403,10 @@ extern "C" | |||||
desc = jack_driver_descriptor_construct("netadapter", JackDriverNone, "netjack net <==> audio backend adapter", &filler); | desc = jack_driver_descriptor_construct("netadapter", JackDriverNone, "netjack net <==> audio backend adapter", &filler); | ||||
strcpy(value.str, DEFAULT_MULTICAST_IP); | strcpy(value.str, DEFAULT_MULTICAST_IP); | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast_ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL); | |||||
value.i = DEFAULT_PORT; | value.i = DEFAULT_PORT; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "udp_net_port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||||
value.i = DEFAULT_MTU; | value.i = DEFAULT_MTU; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL); | ||||
@@ -406,7 +423,7 @@ extern "C" | |||||
strcpy(value.str, "'hostname'"); | strcpy(value.str, "'hostname'"); | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL); | ||||
value.ui = 1U; | |||||
value.ui = 0U; | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); | ||||
value.ui = 5U; | value.ui = 5U; | ||||
@@ -424,17 +441,17 @@ extern "C" | |||||
return desc; | return desc; | ||||
} | } | ||||
SERVER_EXPORT int jack_internal_initialize(jack_client_t* jack_client, const JSList* params) | |||||
SERVER_EXPORT int jack_internal_initialize(jack_client_t* client, const JSList* params) | |||||
{ | { | ||||
jack_log("Loading netadapter"); | jack_log("Loading netadapter"); | ||||
Jack::JackAudioAdapter* adapter; | Jack::JackAudioAdapter* adapter; | ||||
jack_nframes_t buffer_size = jack_get_buffer_size(jack_client); | |||||
jack_nframes_t sample_rate = jack_get_sample_rate(jack_client); | |||||
jack_nframes_t buffer_size = jack_get_buffer_size(client); | |||||
jack_nframes_t sample_rate = jack_get_sample_rate(client); | |||||
try { | try { | ||||
adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackNetAdapter(jack_client, buffer_size, sample_rate, params), params, false); | |||||
adapter = new Jack::JackAudioAdapter(client, new Jack::JackNetAdapter(client, buffer_size, sample_rate, params), params); | |||||
assert(adapter); | assert(adapter); | ||||
if (adapter->Open() == 0) { | if (adapter->Open() == 0) { | ||||
@@ -458,8 +475,9 @@ extern "C" | |||||
jack_driver_desc_t* desc = jack_get_descriptor(); | jack_driver_desc_t* desc = jack_get_descriptor(); | ||||
Jack::JackArgParser parser(load_init); | Jack::JackArgParser parser(load_init); | ||||
if (parser.GetArgc() > 0) | |||||
if (parser.GetArgc() > 0) { | |||||
parse_params = parser.ParseParams(desc, ¶ms); | parse_params = parser.ParseParams(desc, ¶ms); | ||||
} | |||||
if (parse_params) { | if (parse_params) { | ||||
res = jack_internal_initialize(jack_client, params); | res = jack_internal_initialize(jack_client, params); | ||||
@@ -38,7 +38,7 @@ namespace Jack | |||||
private: | private: | ||||
//jack data | //jack data | ||||
jack_client_t* fJackClient; | |||||
jack_client_t* fClient; | |||||
//transport data | //transport data | ||||
int fLastTransportState; | int fLastTransportState; | ||||
@@ -29,7 +29,7 @@ namespace Jack | |||||
JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, | ||||
const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports, | const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports, | ||||
char* net_name, uint transport_sync, int network_latency, int celt_encoding) | char* net_name, uint transport_sync, int network_latency, int celt_encoding) | ||||
: JackTimedDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port) | |||||
: JackWaiterDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port) | |||||
{ | { | ||||
jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port); | jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port); | ||||
@@ -46,6 +46,7 @@ namespace Jack | |||||
fParams.fKBps = celt_encoding; | fParams.fKBps = celt_encoding; | ||||
} else { | } else { | ||||
fParams.fSampleEncoder = JackFloatEncoder; | fParams.fSampleEncoder = JackFloatEncoder; | ||||
//fParams.fSampleEncoder = JackIntEncoder; | |||||
} | } | ||||
strcpy(fParams.fName, net_name); | strcpy(fParams.fName, net_name); | ||||
fSocket.GetName(fParams.fSlaveNetName); | fSocket.GetName(fParams.fSlaveNetName); | ||||
@@ -82,7 +83,7 @@ namespace Jack | |||||
} | } | ||||
#endif | #endif | ||||
FreeAll(); | FreeAll(); | ||||
return JackTimedDriver::Close(); | |||||
return JackWaiterDriver::Close(); | |||||
} | } | ||||
// Attach and Detach are defined as empty methods: port allocation is done when driver actually start (that is in Init) | // Attach and Detach are defined as empty methods: port allocation is done when driver actually start (that is in Init) | ||||
@@ -104,7 +105,7 @@ namespace Jack | |||||
bool JackNetDriver::Initialize() | bool JackNetDriver::Initialize() | ||||
{ | { | ||||
jack_log("JackNetDriver::Initialize()"); | |||||
jack_log("JackNetDriver::Initialize"); | |||||
SaveConnections(); | SaveConnections(); | ||||
FreePorts(); | FreePorts(); | ||||
@@ -233,22 +234,29 @@ namespace Jack | |||||
{ | { | ||||
jack_log("JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | jack_log("JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | ||||
/* | |||||
fNetAudioCaptureBuffer fNetAudioPlaybackBuffer | |||||
fSendAudioChannels fReturnAudioChannels | |||||
fCapturePortList fPlaybackPortList | |||||
fCaptureChannels ==> SLAVE ==> fPlaybackChannels | |||||
"capture_" "playback_" | |||||
*/ | |||||
JackPort* port; | JackPort* port; | ||||
jack_port_id_t port_index; | jack_port_id_t port_index; | ||||
char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | ||||
char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | ||||
unsigned long port_flags; | |||||
int audio_port_index; | int audio_port_index; | ||||
int midi_port_index; | int midi_port_index; | ||||
jack_latency_range_t range; | jack_latency_range_t range; | ||||
//audio | //audio | ||||
port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; | |||||
for (audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) { | for (audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1); | ||||
snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, audio_port_index + 1); | snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, audio_port_index + 1); | ||||
if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, | if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, | ||||
static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) { | |||||
CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | |||||
jack_error("driver: cannot register port for %s", name); | jack_error("driver: cannot register port for %s", name); | ||||
return -1; | return -1; | ||||
} | } | ||||
@@ -262,12 +270,11 @@ namespace Jack | |||||
jack_log("JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency()); | jack_log("JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency()); | ||||
} | } | ||||
port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; | |||||
for (audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { | for (audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1); | ||||
snprintf(name, sizeof(name) - 1, "%s:playback_%d",fClientControl.fName, audio_port_index + 1); | snprintf(name, sizeof(name) - 1, "%s:playback_%d",fClientControl.fName, audio_port_index + 1); | ||||
if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, | if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, | ||||
static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) { | |||||
PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | |||||
jack_error("driver: cannot register port for %s", name); | jack_error("driver: cannot register port for %s", name); | ||||
return -1; | return -1; | ||||
} | } | ||||
@@ -282,12 +289,11 @@ namespace Jack | |||||
} | } | ||||
//midi | //midi | ||||
port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; | |||||
for (midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | for (midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1); | ||||
snprintf(name, sizeof (name) - 1, "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1); | snprintf(name, sizeof (name) - 1, "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1); | ||||
if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, | if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, | ||||
static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) { | |||||
CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | |||||
jack_error("driver: cannot register port for %s", name); | jack_error("driver: cannot register port for %s", name); | ||||
return -1; | return -1; | ||||
} | } | ||||
@@ -300,12 +306,11 @@ namespace Jack | |||||
jack_log("JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency()); | jack_log("JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency()); | ||||
} | } | ||||
port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; | |||||
for (midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | for (midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1); | ||||
snprintf(name, sizeof(name) - 1, "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1); | snprintf(name, sizeof(name) - 1, "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1); | ||||
if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, | if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, | ||||
static_cast<JackPortFlags>(port_flags), fEngineControl->fBufferSize, &port_index) < 0) { | |||||
PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | |||||
jack_error("driver: cannot register port for %s", name); | jack_error("driver: cannot register port for %s", name); | ||||
return -1; | return -1; | ||||
} | } | ||||
@@ -469,20 +474,20 @@ namespace Jack | |||||
//driver processes-------------------------------------------------------------------- | //driver processes-------------------------------------------------------------------- | ||||
int JackNetDriver::Process() | |||||
{ | |||||
return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync(); | |||||
} | |||||
int JackNetDriver::Read() | int JackNetDriver::Read() | ||||
{ | { | ||||
//buffers | //buffers | ||||
for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | ||||
fNetMidiCaptureBuffer->SetBuffer(midi_port_index, GetMidiInputBuffer(midi_port_index)); | fNetMidiCaptureBuffer->SetBuffer(midi_port_index, GetMidiInputBuffer(midi_port_index)); | ||||
} | } | ||||
for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) { | for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) { | ||||
#ifdef OPTIMIZED_PROTOCOL | #ifdef OPTIMIZED_PROTOCOL | ||||
fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index, true)); | |||||
if (fGraphManager->GetConnectionsNum(fCapturePortList[audio_port_index]) > 0) { | |||||
fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index)); | |||||
} else { | |||||
fNetAudioCaptureBuffer->SetBuffer(audio_port_index, NULL); | |||||
} | |||||
#else | #else | ||||
fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index)); | fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index)); | ||||
#endif | #endif | ||||
@@ -507,7 +512,7 @@ namespace Jack | |||||
DecodeSyncPacket(); | DecodeSyncPacket(); | ||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
fNetTimeMon->Add(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); | |||||
fNetTimeMon->Add((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||||
#endif | #endif | ||||
//audio, midi or sync if driver is late | //audio, midi or sync if driver is late | ||||
int res = DataRecv(); | int res = DataRecv(); | ||||
@@ -515,14 +520,14 @@ namespace Jack | |||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
} else if (res == NET_PACKET_ERROR) { | } else if (res == NET_PACKET_ERROR) { | ||||
jack_time_t cur_time = GetMicroSeconds(); | jack_time_t cur_time = GetMicroSeconds(); | ||||
NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing... | |||||
NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing... | |||||
} | } | ||||
//take the time at the beginning of the cycle | //take the time at the beginning of the cycle | ||||
JackDriver::CycleTakeBeginTime(); | JackDriver::CycleTakeBeginTime(); | ||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
fNetTimeMon->Add(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); | |||||
fNetTimeMon->Add((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||||
#endif | #endif | ||||
return 0; | return 0; | ||||
@@ -534,11 +539,16 @@ namespace Jack | |||||
for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | ||||
fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, GetMidiOutputBuffer(midi_port_index)); | fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, GetMidiOutputBuffer(midi_port_index)); | ||||
} | } | ||||
for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { | for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { | ||||
#ifdef OPTIMIZED_PROTOCOL | #ifdef OPTIMIZED_PROTOCOL | ||||
// Port is connected on other side... | // Port is connected on other side... | ||||
if (fNetAudioPlaybackBuffer->GetConnected(audio_port_index)) { | if (fNetAudioPlaybackBuffer->GetConnected(audio_port_index)) { | ||||
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index, true)); | |||||
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[audio_port_index]) > 0) { | |||||
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index)); | |||||
} else { | |||||
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL); | |||||
} | |||||
} else { | } else { | ||||
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL); | fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL); | ||||
} | } | ||||
@@ -548,7 +558,7 @@ namespace Jack | |||||
} | } | ||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
fNetTimeMon->Add(((float) (GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); | |||||
fNetTimeMon->AddLast((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||||
#endif | #endif | ||||
//sync | //sync | ||||
@@ -590,31 +600,31 @@ namespace Jack | |||||
desc = jack_driver_descriptor_construct("net", JackDriverMaster, "netjack slave backend component", &filler); | desc = jack_driver_descriptor_construct("net", JackDriverMaster, "netjack slave backend component", &filler); | ||||
strcpy(value.str, DEFAULT_MULTICAST_IP); | strcpy(value.str, DEFAULT_MULTICAST_IP); | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast_ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL); | |||||
value.i = DEFAULT_PORT; | value.i = DEFAULT_PORT; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "udp_net_port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL); | |||||
value.i = DEFAULT_MTU; | value.i = DEFAULT_MTU; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL); | ||||
value.i = -1; | value.i = -1; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "input_ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", "Number of audio input ports. If -1, audio physical input from the master"); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "output_ports", 'P', JackDriverParamInt, &value, NULL, "Number of audio output ports", "Number of audio output ports. If -1, audio physical output from the master"); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", "Number of audio input ports. If -1, audio physical input from the master"); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'P', JackDriverParamInt, &value, NULL, "Number of audio output ports", "Number of audio output ports. If -1, audio physical output from the master"); | |||||
value.i = 0; | value.i = 0; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "midi_in_ports", 'i', JackDriverParamInt, &value, NULL, "Number of midi input ports", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "midi_out_ports", 'o', JackDriverParamInt, &value, NULL, "Number of midi output ports", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "midi-in-ports", 'i', JackDriverParamInt, &value, NULL, "Number of midi input ports", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "midi-out-ports", 'o', JackDriverParamInt, &value, NULL, "Number of midi output ports", NULL); | |||||
#if HAVE_CELT | #if HAVE_CELT | ||||
value.i = -1; | value.i = -1; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL); | ||||
#endif | #endif | ||||
strcpy(value.str, "'hostname'"); | strcpy(value.str, "'hostname'"); | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "client_name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL); | |||||
value.ui = 0U; | value.ui = 0U; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "transport_sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); | |||||
value.ui = 5U; | value.ui = 5U; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL); | ||||
@@ -624,13 +634,13 @@ namespace Jack | |||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | ||||
{ | { | ||||
char multicast_ip[16]; | |||||
char multicast_ip[32]; | |||||
char net_name[JACK_CLIENT_NAME_SIZE + 1]; | char net_name[JACK_CLIENT_NAME_SIZE + 1]; | ||||
int udp_port; | int udp_port; | ||||
int mtu = DEFAULT_MTU; | int mtu = DEFAULT_MTU; | ||||
// Desactivated for now... | // Desactivated for now... | ||||
uint transport_sync = 0; | uint transport_sync = 0; | ||||
jack_nframes_t period_size = 128; | |||||
jack_nframes_t period_size = 256; | |||||
jack_nframes_t sample_rate = 48000; | jack_nframes_t sample_rate = 48000; | ||||
int audio_capture_ports = -1; | int audio_capture_ports = -1; | ||||
int audio_playback_ports = -1; | int audio_playback_ports = -1; | ||||
@@ -660,7 +670,8 @@ namespace Jack | |||||
switch (param->character) | switch (param->character) | ||||
{ | { | ||||
case 'a' : | case 'a' : | ||||
strncpy(multicast_ip, param->value.str, 15); | |||||
assert(strlen(param->value.str) < 32); | |||||
strcpy(multicast_ip, param->value.str); | |||||
break; | break; | ||||
case 'p': | case 'p': | ||||
udp_port = param->value.ui; | udp_port = param->value.ui; | ||||
@@ -25,17 +25,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
//#define JACK_MONITOR | //#define JACK_MONITOR | ||||
#ifdef JACK_MONITOR | |||||
#include "JackFrameTimer.h" | |||||
#endif | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
/** | /** | ||||
\Brief This class describes the Net Backend | \Brief This class describes the Net Backend | ||||
*/ | */ | ||||
class JackNetDriver : public JackTimedDriver, public JackNetSlaveInterface | |||||
class JackNetDriver : public JackWaiterDriver, public JackNetSlaveInterface | |||||
{ | { | ||||
private: | private: | ||||
@@ -77,10 +73,7 @@ namespace Jack | |||||
virtual ~JackNetDriver(); | virtual ~JackNetDriver(); | ||||
int Close(); | int Close(); | ||||
// The | |||||
int Process(); | |||||
int Attach(); | int Attach(); | ||||
int Detach(); | int Detach(); | ||||
@@ -50,7 +50,7 @@ JackNetOneDriver::JackNetOneDriver(const char* name, const char* alias, JackLock | |||||
int sample_rate, int period_size, int resample_factor, | int sample_rate, int period_size, int resample_factor, | ||||
const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, | const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, | ||||
int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val) | int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val) | ||||
: JackTimedDriver(name, alias, engine, table) | |||||
: JackWaiterDriver(name, alias, engine, table) | |||||
{ | { | ||||
jack_log("JackNetOneDriver::JackNetOneDriver port %d", port); | jack_log("JackNetOneDriver::JackNetOneDriver port %d", port); | ||||
@@ -91,7 +91,7 @@ JackNetOneDriver::~JackNetOneDriver() | |||||
int JackNetOneDriver::Close() | int JackNetOneDriver::Close() | ||||
{ | { | ||||
// Generic audio driver close | // Generic audio driver close | ||||
int res = JackTimedDriver::Close(); | |||||
int res = JackWaiterDriver::Close(); | |||||
FreePorts(); | FreePorts(); | ||||
netjack_release(&netj); | netjack_release(&netj); | ||||
@@ -122,10 +122,10 @@ int JackNetOneDriver::AllocPorts() | |||||
if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE, | if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE, | ||||
CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | ||||
jack_error ( "driver: cannot register port for %s", buf ); | |||||
jack_error("driver: cannot register port for %s", buf); | |||||
return -1; | return -1; | ||||
} | } | ||||
//port = fGraphManager->GetPort ( port_index ); | |||||
//port = fGraphManager->GetPort(port_index); | |||||
netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index); | netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index); | ||||
@@ -133,18 +133,18 @@ int JackNetOneDriver::AllocPorts() | |||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_11 | #if HAVE_CELT_API_0_11 | ||||
celt_int32 lookahead; | celt_int32 lookahead; | ||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | |||||
netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create_custom( celt_mode, 1, NULL ) ); | |||||
CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL); | |||||
netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create_custom(celt_mode, 1, NULL)); | |||||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | ||||
celt_int32 lookahead; | celt_int32 lookahead; | ||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | |||||
netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); | |||||
CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL); | |||||
netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create(celt_mode, 1, NULL)); | |||||
#else | #else | ||||
celt_int32_t lookahead; | celt_int32_t lookahead; | ||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, 1, netj.period_size, NULL ); | |||||
netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode ) ); | |||||
CELTMode *celt_mode = celt_mode_create(netj.sample_rate, 1, netj.period_size, NULL); | |||||
netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create(celt_mode)); | |||||
#endif | #endif | ||||
celt_mode_info( celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); | |||||
celt_mode_info(celt_mode, CELT_GET_LOOKAHEAD, &lookahead); | |||||
netj.codec_latency = 2 * lookahead; | netj.codec_latency = 2 * lookahead; | ||||
#endif | #endif | ||||
} else { | } else { | ||||
@@ -159,10 +159,10 @@ int JackNetOneDriver::AllocPorts() | |||||
if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE, | if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE, | ||||
CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | ||||
jack_error ( "driver: cannot register port for %s", buf ); | |||||
jack_error("driver: cannot register port for %s", buf); | |||||
return -1; | return -1; | ||||
} | } | ||||
//port = fGraphManager->GetPort ( port_index ); | |||||
//port = fGraphManager->GetPort(port_index); | |||||
netj.capture_ports = | netj.capture_ports = | ||||
jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index); | jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index); | ||||
@@ -173,23 +173,23 @@ int JackNetOneDriver::AllocPorts() | |||||
if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE, | if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE, | ||||
PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | ||||
jack_error ( "driver: cannot register port for %s", buf ); | |||||
jack_error("driver: cannot register port for %s", buf); | |||||
return -1; | return -1; | ||||
} | } | ||||
//port = fGraphManager->GetPort ( port_index ); | |||||
//port = fGraphManager->GetPort(port_index); | |||||
netj.playback_ports = jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index); | netj.playback_ports = jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index); | ||||
if( netj.bitdepth == CELT_MODE ) { | |||||
if (netj.bitdepth == CELT_MODE) { | |||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_11 | #if HAVE_CELT_API_0_11 | ||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | |||||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create_custom( celt_mode, 1, NULL ) ); | |||||
CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL); | |||||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create_custom(celt_mode, 1, NULL)); | |||||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | ||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | |||||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); | |||||
CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL); | |||||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create(celt_mode, 1, NULL)); | |||||
#else | #else | ||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, 1, netj.period_size, NULL ); | |||||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode ) ); | |||||
CELTMode *celt_mode = celt_mode_create(netj.sample_rate, 1, netj.period_size, NULL); | |||||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create(celt_mode)); | |||||
#endif | #endif | ||||
#endif | #endif | ||||
} else { | } else { | ||||
@@ -203,10 +203,10 @@ int JackNetOneDriver::AllocPorts() | |||||
if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE, | if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE, | ||||
PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) { | ||||
jack_error ( "driver: cannot register port for %s", buf ); | |||||
jack_error("driver: cannot register port for %s", buf); | |||||
return -1; | return -1; | ||||
} | } | ||||
//port = fGraphManager->GetPort ( port_index ); | |||||
//port = fGraphManager->GetPort(port_index); | |||||
netj.playback_ports = | netj.playback_ports = | ||||
jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index); | jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index); | ||||
@@ -217,33 +217,33 @@ int JackNetOneDriver::AllocPorts() | |||||
//init and restart-------------------------------------------------------------------- | //init and restart-------------------------------------------------------------------- | ||||
bool JackNetOneDriver::Initialize() | bool JackNetOneDriver::Initialize() | ||||
{ | { | ||||
jack_log ( "JackNetOneDriver::Init()" ); | |||||
jack_log("JackNetOneDriver::Init"); | |||||
FreePorts(); | FreePorts(); | ||||
netjack_release( &netj ); | |||||
netjack_release(&netj); | |||||
//display some additional infos | //display some additional infos | ||||
jack_info ( "NetOne driver started" ); | |||||
if( netjack_startup( &netj ) ) { | |||||
jack_info("NetOne driver started"); | |||||
if (netjack_startup(&netj)) { | |||||
return false; | return false; | ||||
} | } | ||||
//register jack ports | //register jack ports | ||||
if ( AllocPorts() != 0 ) { | |||||
jack_error ( "Can't allocate ports." ); | |||||
if (AllocPorts() != 0) { | |||||
jack_error("Can't allocate ports."); | |||||
return false; | return false; | ||||
} | } | ||||
//monitor | //monitor | ||||
//driver parametering | //driver parametering | ||||
JackTimedDriver::SetBufferSize ( netj.period_size ); | |||||
JackTimedDriver::SetSampleRate ( netj.sample_rate ); | |||||
JackTimedDriver::SetBufferSize(netj.period_size); | |||||
JackTimedDriver::SetSampleRate(netj.sample_rate); | |||||
JackDriver::NotifyBufferSize ( netj.period_size ); | |||||
JackDriver::NotifySampleRate ( netj.sample_rate ); | |||||
JackDriver::NotifyBufferSize(netj.period_size); | |||||
JackDriver::NotifySampleRate(netj.sample_rate); | |||||
//transport engine parametering | //transport engine parametering | ||||
fEngineControl->fTransport.SetNetworkSync ( true ); | |||||
fEngineControl->fTransport.SetNetworkSync(true); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -252,24 +252,19 @@ bool JackNetOneDriver::Initialize() | |||||
//driver processes-------------------------------------------------------------------- | //driver processes-------------------------------------------------------------------- | ||||
int JackNetOneDriver::Process() | |||||
{ | |||||
return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync(); | |||||
} | |||||
int JackNetOneDriver::Read() | int JackNetOneDriver::Read() | ||||
{ | { | ||||
int delay; | int delay; | ||||
delay = netjack_wait( &netj ); | |||||
if( delay ) { | |||||
delay = netjack_wait(&netj); | |||||
if (delay) { | |||||
NotifyXRun(fBeginDateUst, (float) delay); | NotifyXRun(fBeginDateUst, (float) delay); | ||||
jack_error( "netxruns... duration: %dms", delay / 1000 ); | |||||
jack_error("netxruns... duration: %dms", delay / 1000); | |||||
} | } | ||||
if( (netj.num_lost_packets * netj.period_size / netj.sample_rate) > 2 ) | |||||
if ((netj.num_lost_packets * netj.period_size / netj.sample_rate) > 2) | |||||
JackTools::ThrowJackNetException(); | JackTools::ThrowJackNetException(); | ||||
//netjack_read( &netj, netj.period_size ); | |||||
//netjack_read(&netj, netj.period_size); | |||||
JackDriver::CycleTakeBeginTime(); | JackDriver::CycleTakeBeginTime(); | ||||
jack_position_t local_trans_pos; | jack_position_t local_trans_pos; | ||||
@@ -277,9 +272,9 @@ int JackNetOneDriver::Read() | |||||
unsigned int *packet_buf, *packet_bufX; | unsigned int *packet_buf, *packet_bufX; | ||||
if( ! netj.packet_data_valid ) { | |||||
jack_log( "data not valid" ); | |||||
render_payload_to_jack_ports (netj.bitdepth, NULL, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats ); | |||||
if (! netj.packet_data_valid) { | |||||
jack_log("data not valid"); | |||||
render_payload_to_jack_ports (netj.bitdepth, NULL, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats); | |||||
return 0; | return 0; | ||||
} | } | ||||
packet_buf = netj.rx_buf; | packet_buf = netj.rx_buf; | ||||
@@ -292,10 +287,10 @@ int JackNetOneDriver::Read() | |||||
netj.latency = pkthdr->latency; | netj.latency = pkthdr->latency; | ||||
// Special handling for latency=0 | // Special handling for latency=0 | ||||
if( netj.latency == 0 ) | |||||
if (netj.latency == 0) | |||||
netj.resync_threshold = 0; | netj.resync_threshold = 0; | ||||
else | else | ||||
netj.resync_threshold = MIN( 15, pkthdr->latency - 1 ); | |||||
netj.resync_threshold = MIN(15, pkthdr->latency - 1); | |||||
// check whether, we should handle the transport sync stuff, or leave trnasports untouched. | // check whether, we should handle the transport sync stuff, or leave trnasports untouched. | ||||
if (netj.handle_transport_sync) { | if (netj.handle_transport_sync) { | ||||
@@ -305,7 +300,7 @@ int JackNetOneDriver::Read() | |||||
// read local transport info.... | // read local transport info.... | ||||
//local_trans_state = jack_transport_query(netj.client, &local_trans_pos); | //local_trans_state = jack_transport_query(netj.client, &local_trans_pos); | ||||
local_trans_state = fEngineControl->fTransport.Query ( &local_trans_pos ); | |||||
local_trans_state = fEngineControl->fTransport.Query(&local_trans_pos); | |||||
// Now check if we have to start or stop local transport to sync to remote... | // Now check if we have to start or stop local transport to sync to remote... | ||||
switch (pkthdr->transport_state) { | switch (pkthdr->transport_state) { | ||||
@@ -313,7 +308,7 @@ int JackNetOneDriver::Read() | |||||
case JackTransportStarting: | case JackTransportStarting: | ||||
// the master transport is starting... so we set our reply to the sync_callback; | // the master transport is starting... so we set our reply to the sync_callback; | ||||
if (local_trans_state == JackTransportStopped) { | if (local_trans_state == JackTransportStopped) { | ||||
fEngineControl->fTransport.SetCommand ( TransportCommandStart ); | |||||
fEngineControl->fTransport.SetCommand(TransportCommandStart); | |||||
//jack_transport_start(netj.client); | //jack_transport_start(netj.client); | ||||
//last_transport_state = JackTransportStopped; | //last_transport_state = JackTransportStopped; | ||||
netj.sync_state = 0; | netj.sync_state = 0; | ||||
@@ -326,11 +321,11 @@ int JackNetOneDriver::Read() | |||||
new_pos.valid = (jack_position_bits_t) 0; | new_pos.valid = (jack_position_bits_t) 0; | ||||
fEngineControl->fTransport.RequestNewPos ( &new_pos ); | |||||
fEngineControl->fTransport.RequestNewPos(&new_pos); | |||||
//jack_transport_locate(netj.client, compensated_tranport_pos); | //jack_transport_locate(netj.client, compensated_tranport_pos); | ||||
//last_transport_state = JackTransportRolling; | //last_transport_state = JackTransportRolling; | ||||
netj.sync_state = 0; | netj.sync_state = 0; | ||||
jack_info("starting locate to %d", compensated_tranport_pos ); | |||||
jack_info("starting locate to %d", compensated_tranport_pos); | |||||
} | } | ||||
break; | break; | ||||
@@ -340,13 +335,13 @@ int JackNetOneDriver::Read() | |||||
jack_position_t new_pos = local_trans_pos; | jack_position_t new_pos = local_trans_pos; | ||||
new_pos.frame = pkthdr->transport_frame; | new_pos.frame = pkthdr->transport_frame; | ||||
new_pos.valid = (jack_position_bits_t)0; | new_pos.valid = (jack_position_bits_t)0; | ||||
fEngineControl->fTransport.RequestNewPos ( &new_pos ); | |||||
fEngineControl->fTransport.RequestNewPos(&new_pos); | |||||
//jack_transport_locate(netj.client, (pkthdr->transport_frame)); | //jack_transport_locate(netj.client, (pkthdr->transport_frame)); | ||||
jack_info("transport is stopped locate to %d", pkthdr->transport_frame); | jack_info("transport is stopped locate to %d", pkthdr->transport_frame); | ||||
} | } | ||||
if (local_trans_state != JackTransportStopped) | if (local_trans_state != JackTransportStopped) | ||||
//jack_transport_stop(netj.client); | //jack_transport_stop(netj.client); | ||||
fEngineControl->fTransport.SetCommand ( TransportCommandStop ); | |||||
fEngineControl->fTransport.SetCommand(TransportCommandStop); | |||||
break; | break; | ||||
case JackTransportRolling: | case JackTransportRolling: | ||||
@@ -356,7 +351,7 @@ int JackNetOneDriver::Read() | |||||
// jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size); | // jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size); | ||||
// } | // } | ||||
if (local_trans_state != JackTransportRolling) | if (local_trans_state != JackTransportRolling) | ||||
fEngineControl->fTransport.SetState ( JackTransportRolling ); | |||||
fEngineControl->fTransport.SetState(JackTransportRolling); | |||||
break; | break; | ||||
case JackTransportLooping: | case JackTransportLooping: | ||||
@@ -365,14 +360,14 @@ int JackNetOneDriver::Read() | |||||
#endif | #endif | ||||
} | } | ||||
render_payload_to_jack_ports (netj.bitdepth, packet_bufX, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats ); | |||||
packet_cache_release_packet(netj.packcache, netj.expected_framecnt ); | |||||
render_payload_to_jack_ports (netj.bitdepth, packet_bufX, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats); | |||||
packet_cache_release_packet(netj.packcache, netj.expected_framecnt); | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackNetOneDriver::Write() | int JackNetOneDriver::Write() | ||||
{ | { | ||||
int syncstate = netj.sync_state | ((fEngineControl->fTransport.GetState() == JackTransportNetStarting) ? 1 : 0 ); | |||||
int syncstate = netj.sync_state | ((fEngineControl->fTransport.GetState() == JackTransportNetStarting) ? 1 : 0); | |||||
uint32_t *packet_buf, *packet_bufX; | uint32_t *packet_buf, *packet_bufX; | ||||
int packet_size = get_sample_size(netj.bitdepth) * netj.playback_channels * netj.net_period_up + sizeof(jacknet_packet_header); | int packet_size = get_sample_size(netj.bitdepth) * netj.playback_channels * netj.net_period_up + sizeof(jacknet_packet_header); | ||||
@@ -381,7 +376,7 @@ int JackNetOneDriver::Write() | |||||
packet_buf = (uint32_t *) alloca(packet_size); | packet_buf = (uint32_t *) alloca(packet_size); | ||||
pkthdr = (jacknet_packet_header *)packet_buf; | pkthdr = (jacknet_packet_header *)packet_buf; | ||||
if( netj.running_free ) { | |||||
if (netj.running_free) { | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -390,10 +385,10 @@ int JackNetOneDriver::Write() | |||||
pkthdr->sync_state = syncstate;; | pkthdr->sync_state = syncstate;; | ||||
pkthdr->latency = netj.time_to_deadline; | pkthdr->latency = netj.time_to_deadline; | ||||
//printf( "time to deadline = %d goodness=%d\n", (int)netj.time_to_deadline, netj.deadline_goodness ); | |||||
//printf("time to deadline = %d goodness=%d\n", (int)netj.time_to_deadline, netj.deadline_goodness); | |||||
pkthdr->framecnt = netj.expected_framecnt; | pkthdr->framecnt = netj.expected_framecnt; | ||||
render_jack_ports_to_payload(netj.bitdepth, netj.playback_ports, netj.playback_srcs, netj.period_size, packet_bufX, netj.net_period_up, netj.dont_htonl_floats ); | |||||
render_jack_ports_to_payload(netj.bitdepth, netj.playback_ports, netj.playback_srcs, netj.period_size, packet_bufX, netj.net_period_up, netj.dont_htonl_floats); | |||||
packet_header_hton(pkthdr); | packet_header_hton(pkthdr); | ||||
if (netj.srcaddress_valid) { | if (netj.srcaddress_valid) { | ||||
@@ -403,7 +398,7 @@ int JackNetOneDriver::Write() | |||||
if (netj.reply_port) | if (netj.reply_port) | ||||
netj.syncsource_address.sin_port = htons(netj.reply_port); | netj.syncsource_address.sin_port = htons(netj.reply_port); | ||||
for( r = 0; r < netj.redundancy; r++ ) | |||||
for (r = 0; r < netj.redundancy; r++) | |||||
netjack_sendto(netj.sockfd, (char *)packet_buf, packet_size, | netjack_sendto(netj.sockfd, (char *)packet_buf, packet_size, | ||||
flag, (struct sockaddr*) & (netj.syncsource_address), sizeof(struct sockaddr_in), netj.mtu); | flag, (struct sockaddr*) & (netj.syncsource_address), sizeof(struct sockaddr_in), netj.mtu); | ||||
} | } | ||||
@@ -415,66 +410,66 @@ JackNetOneDriver::FreePorts () | |||||
{ | { | ||||
JSList *node = netj.capture_ports; | JSList *node = netj.capture_ports; | ||||
while( node != NULL ) { | |||||
while (node != NULL) { | |||||
JSList *this_node = node; | JSList *this_node = node; | ||||
jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | ||||
node = jack_slist_remove_link( node, this_node ); | |||||
jack_slist_free_1( this_node ); | |||||
node = jack_slist_remove_link(node, this_node); | |||||
jack_slist_free_1(this_node); | |||||
fEngine->PortUnRegister(fClientControl.fRefNum, port_index); | fEngine->PortUnRegister(fClientControl.fRefNum, port_index); | ||||
} | } | ||||
netj.capture_ports = NULL; | netj.capture_ports = NULL; | ||||
node = netj.playback_ports; | node = netj.playback_ports; | ||||
while( node != NULL ) { | |||||
while (node != NULL) { | |||||
JSList *this_node = node; | JSList *this_node = node; | ||||
jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | ||||
node = jack_slist_remove_link( node, this_node ); | |||||
jack_slist_free_1( this_node ); | |||||
node = jack_slist_remove_link(node, this_node); | |||||
jack_slist_free_1(this_node); | |||||
fEngine->PortUnRegister(fClientControl.fRefNum, port_index); | fEngine->PortUnRegister(fClientControl.fRefNum, port_index); | ||||
} | } | ||||
netj.playback_ports = NULL; | netj.playback_ports = NULL; | ||||
if( netj.bitdepth == CELT_MODE ) { | |||||
if (netj.bitdepth == CELT_MODE) { | |||||
#if HAVE_CELT | #if HAVE_CELT | ||||
node = netj.playback_srcs; | node = netj.playback_srcs; | ||||
while( node != NULL ) { | |||||
while (node != NULL) { | |||||
JSList *this_node = node; | JSList *this_node = node; | ||||
CELTEncoder *enc = (CELTEncoder *) node->data; | CELTEncoder *enc = (CELTEncoder *) node->data; | ||||
node = jack_slist_remove_link( node, this_node ); | |||||
jack_slist_free_1( this_node ); | |||||
celt_encoder_destroy( enc ); | |||||
node = jack_slist_remove_link(node, this_node); | |||||
jack_slist_free_1(this_node); | |||||
celt_encoder_destroy(enc); | |||||
} | } | ||||
netj.playback_srcs = NULL; | netj.playback_srcs = NULL; | ||||
node = netj.capture_srcs; | node = netj.capture_srcs; | ||||
while( node != NULL ) { | |||||
while (node != NULL) { | |||||
JSList *this_node = node; | JSList *this_node = node; | ||||
CELTDecoder *dec = (CELTDecoder *) node->data; | CELTDecoder *dec = (CELTDecoder *) node->data; | ||||
node = jack_slist_remove_link( node, this_node ); | |||||
jack_slist_free_1( this_node ); | |||||
celt_decoder_destroy( dec ); | |||||
node = jack_slist_remove_link(node, this_node); | |||||
jack_slist_free_1(this_node); | |||||
celt_decoder_destroy(dec); | |||||
} | } | ||||
netj.capture_srcs = NULL; | netj.capture_srcs = NULL; | ||||
#endif | #endif | ||||
} else { | } else { | ||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
node = netj.playback_srcs; | node = netj.playback_srcs; | ||||
while( node != NULL ) { | |||||
while (node != NULL) { | |||||
JSList *this_node = node; | JSList *this_node = node; | ||||
SRC_STATE *state = (SRC_STATE *) node->data; | SRC_STATE *state = (SRC_STATE *) node->data; | ||||
node = jack_slist_remove_link( node, this_node ); | |||||
jack_slist_free_1( this_node ); | |||||
src_delete( state ); | |||||
node = jack_slist_remove_link(node, this_node); | |||||
jack_slist_free_1(this_node); | |||||
src_delete(state); | |||||
} | } | ||||
netj.playback_srcs = NULL; | netj.playback_srcs = NULL; | ||||
node = netj.capture_srcs; | node = netj.capture_srcs; | ||||
while( node != NULL ) { | |||||
while (node != NULL) { | |||||
JSList *this_node = node; | JSList *this_node = node; | ||||
SRC_STATE *state = (SRC_STATE *) node->data; | SRC_STATE *state = (SRC_STATE *) node->data; | ||||
node = jack_slist_remove_link( node, this_node ); | |||||
jack_slist_free_1( this_node ); | |||||
src_delete( state ); | |||||
node = jack_slist_remove_link(node, this_node); | |||||
jack_slist_free_1(this_node); | |||||
src_delete(state); | |||||
} | } | ||||
netj.capture_srcs = NULL; | netj.capture_srcs = NULL; | ||||
#endif | #endif | ||||
@@ -485,7 +480,7 @@ JackNetOneDriver::FreePorts () | |||||
// render functions for float | // render functions for float | ||||
void | void | ||||
JackNetOneDriver::render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats) | |||||
JackNetOneDriver::render_payload_to_jack_ports_float(void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats) | |||||
{ | { | ||||
uint32_t chn = 0; | uint32_t chn = 0; | ||||
JSList *node = capture_ports; | JSList *node = capture_ports; | ||||
@@ -495,7 +490,7 @@ JackNetOneDriver::render_payload_to_jack_ports_float ( void *packet_payload, jac | |||||
uint32_t *packet_bufX = (uint32_t *)packet_payload; | uint32_t *packet_bufX = (uint32_t *)packet_payload; | ||||
if( !packet_payload ) | |||||
if (!packet_payload) | |||||
return; | return; | ||||
while (node != NULL) { | while (node != NULL) { | ||||
@@ -505,7 +500,7 @@ JackNetOneDriver::render_payload_to_jack_ports_float ( void *packet_payload, jac | |||||
SRC_DATA src; | SRC_DATA src; | ||||
#endif | #endif | ||||
jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | ||||
JackPort *port = fGraphManager->GetPort( port_index ); | |||||
JackPort *port = fGraphManager->GetPort(port_index); | |||||
jack_default_audio_sample_t* buf = | jack_default_audio_sample_t* buf = | ||||
(jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | ||||
@@ -536,8 +531,8 @@ JackNetOneDriver::render_payload_to_jack_ports_float ( void *packet_payload, jac | |||||
} else | } else | ||||
#endif | #endif | ||||
{ | { | ||||
if( dont_htonl_floats ) { | |||||
memcpy( buf, packet_bufX, net_period_down * sizeof(jack_default_audio_sample_t)); | |||||
if (dont_htonl_floats) { | |||||
memcpy(buf, packet_bufX, net_period_down * sizeof(jack_default_audio_sample_t)); | |||||
} else { | } else { | ||||
for (i = 0; i < net_period_down; i++) { | for (i = 0; i < net_period_down; i++) { | ||||
val.i = packet_bufX[i]; | val.i = packet_bufX[i]; | ||||
@@ -560,7 +555,7 @@ JackNetOneDriver::render_payload_to_jack_ports_float ( void *packet_payload, jac | |||||
} | } | ||||
void | void | ||||
JackNetOneDriver::render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats ) | |||||
JackNetOneDriver::render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats) | |||||
{ | { | ||||
uint32_t chn = 0; | uint32_t chn = 0; | ||||
JSList *node = playback_ports; | JSList *node = playback_ports; | ||||
@@ -577,7 +572,7 @@ JackNetOneDriver::render_jack_ports_to_payload_float (JSList *playback_ports, JS | |||||
unsigned int i; | unsigned int i; | ||||
int_float_t val; | int_float_t val; | ||||
jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data; | ||||
JackPort *port = fGraphManager->GetPort( port_index ); | |||||
JackPort *port = fGraphManager->GetPort(port_index); | |||||
jack_default_audio_sample_t* buf = | jack_default_audio_sample_t* buf = | ||||
(jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | ||||
@@ -609,8 +604,8 @@ JackNetOneDriver::render_jack_ports_to_payload_float (JSList *playback_ports, JS | |||||
} else | } else | ||||
#endif | #endif | ||||
{ | { | ||||
if( dont_htonl_floats ) { | |||||
memcpy( packet_bufX, buf, net_period_up * sizeof(jack_default_audio_sample_t) ); | |||||
if (dont_htonl_floats) { | |||||
memcpy(packet_bufX, buf, net_period_up * sizeof(jack_default_audio_sample_t)); | |||||
} else { | } else { | ||||
for (i = 0; i < net_period_up; i++) { | for (i = 0; i < net_period_up; i++) { | ||||
val.f = buf[i]; | val.f = buf[i]; | ||||
@@ -644,7 +639,7 @@ JackNetOneDriver::render_payload_to_jack_ports_celt (void *packet_payload, jack_ | |||||
while (node != NULL) { | while (node != NULL) { | ||||
jack_port_id_t port_index = (jack_port_id_t) (intptr_t)node->data; | jack_port_id_t port_index = (jack_port_id_t) (intptr_t)node->data; | ||||
JackPort *port = fGraphManager->GetPort( port_index ); | |||||
JackPort *port = fGraphManager->GetPort(port_index); | |||||
jack_default_audio_sample_t* buf = | jack_default_audio_sample_t* buf = | ||||
(jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | ||||
@@ -656,15 +651,15 @@ JackNetOneDriver::render_payload_to_jack_ports_celt (void *packet_payload, jack_ | |||||
CELTDecoder *decoder = (CELTDecoder *)src_node->data; | CELTDecoder *decoder = (CELTDecoder *)src_node->data; | ||||
#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | ||||
if( !packet_payload ) | |||||
celt_decode_float( decoder, NULL, net_period_down, buf, nframes ); | |||||
if (!packet_payload) | |||||
celt_decode_float(decoder, NULL, net_period_down, buf, nframes); | |||||
else | else | ||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes ); | |||||
celt_decode_float(decoder, packet_bufX, net_period_down, buf, nframes); | |||||
#else | #else | ||||
if( !packet_payload ) | |||||
celt_decode_float( decoder, NULL, net_period_down, buf ); | |||||
if (!packet_payload) | |||||
celt_decode_float(decoder, NULL, net_period_down, buf); | |||||
else | else | ||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf ); | |||||
celt_decode_float(decoder, packet_bufX, net_period_down, buf); | |||||
#endif | #endif | ||||
src_node = jack_slist_next (src_node); | src_node = jack_slist_next (src_node); | ||||
@@ -673,7 +668,7 @@ JackNetOneDriver::render_payload_to_jack_ports_celt (void *packet_payload, jack_ | |||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_down / 2; | unsigned int buffer_size_uint32 = net_period_down / 2; | ||||
uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; | uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; | ||||
if( packet_payload ) | |||||
if (packet_payload) | |||||
decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | ||||
} | } | ||||
packet_bufX = (packet_bufX + net_period_down); | packet_bufX = (packet_bufX + net_period_down); | ||||
@@ -693,7 +688,7 @@ JackNetOneDriver::render_jack_ports_to_payload_celt (JSList *playback_ports, JSL | |||||
while (node != NULL) { | while (node != NULL) { | ||||
jack_port_id_t port_index = (jack_port_id_t) (intptr_t) node->data; | jack_port_id_t port_index = (jack_port_id_t) (intptr_t) node->data; | ||||
JackPort *port = fGraphManager->GetPort( port_index ); | |||||
JackPort *port = fGraphManager->GetPort(port_index); | |||||
jack_default_audio_sample_t* buf = | jack_default_audio_sample_t* buf = | ||||
(jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize); | ||||
@@ -704,17 +699,17 @@ JackNetOneDriver::render_jack_ports_to_payload_celt (JSList *playback_ports, JSL | |||||
// audio port, encode celt data. | // audio port, encode celt data. | ||||
int encoded_bytes; | int encoded_bytes; | ||||
jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes ); | |||||
memcpy( floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t) ); | |||||
jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes); | |||||
memcpy(floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t)); | |||||
CELTEncoder *encoder = (CELTEncoder *)src_node->data; | CELTEncoder *encoder = (CELTEncoder *)src_node->data; | ||||
#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | ||||
encoded_bytes = celt_encode_float( encoder, floatbuf, nframes, packet_bufX, net_period_up ); | |||||
encoded_bytes = celt_encode_float(encoder, floatbuf, nframes, packet_bufX, net_period_up); | |||||
#else | #else | ||||
encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up ); | |||||
encoded_bytes = celt_encode_float(encoder, floatbuf, NULL, packet_bufX, net_period_up); | |||||
#endif | #endif | ||||
if( encoded_bytes != (int)net_period_up ) | |||||
jack_error( "something in celt changed. netjack needs to be changed to handle this." ); | |||||
src_node = jack_slist_next( src_node ); | |||||
if (encoded_bytes != (int)net_period_up) | |||||
jack_error("something in celt changed. netjack needs to be changed to handle this."); | |||||
src_node = jack_slist_next(src_node); | |||||
} else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) { | } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) { | ||||
// encode midi events from port to packet | // encode midi events from port to packet | ||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
@@ -820,7 +815,7 @@ extern "C" | |||||
return desc; | return desc; | ||||
} | } | ||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params ) | |||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||||
{ | { | ||||
jack_nframes_t sample_rate = 48000; | jack_nframes_t sample_rate = 48000; | ||||
jack_nframes_t resample_factor = 1; | jack_nframes_t resample_factor = 1; | ||||
@@ -845,9 +840,9 @@ extern "C" | |||||
const JSList * node; | const JSList * node; | ||||
const jack_driver_param_t * param; | const jack_driver_param_t * param; | ||||
for ( node = params; node; node = jack_slist_next ( node ) ) { | |||||
param = ( const jack_driver_param_t* ) node->data; | |||||
switch ( param->character ) { | |||||
for (node = params; node; node = jack_slist_next(node)) { | |||||
param = (const jack_driver_param_t*) node->data; | |||||
switch (param->character) { | |||||
case 'i': | case 'i': | ||||
capture_ports = param->value.ui; | capture_ports = param->value.ui; | ||||
break; | break; | ||||
@@ -880,7 +875,7 @@ extern "C" | |||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
resample_factor = param->value.ui; | resample_factor = param->value.ui; | ||||
#else | #else | ||||
jack_error( "not built with libsamplerate support" ); | |||||
jack_error("not built with libsamplerate support"); | |||||
return NULL; | return NULL; | ||||
#endif | #endif | ||||
break; | break; | ||||
@@ -889,7 +884,7 @@ extern "C" | |||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
resample_factor_up = param->value.ui; | resample_factor_up = param->value.ui; | ||||
#else | #else | ||||
jack_error( "not built with libsamplerate support" ); | |||||
jack_error("not built with libsamplerate support"); | |||||
return NULL; | return NULL; | ||||
#endif | #endif | ||||
break; | break; | ||||
@@ -903,7 +898,7 @@ extern "C" | |||||
bitdepth = CELT_MODE; | bitdepth = CELT_MODE; | ||||
resample_factor = param->value.ui; | resample_factor = param->value.ui; | ||||
#else | #else | ||||
jack_error( "not built with celt support" ); | |||||
jack_error("not built with celt support"); | |||||
return NULL; | return NULL; | ||||
#endif | #endif | ||||
break; | break; | ||||
@@ -940,21 +935,21 @@ extern "C" | |||||
try { | try { | ||||
Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver ( | Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver ( | ||||
new Jack::JackNetOneDriver ( "system", "net_pcm", engine, table, listen_port, mtu, | |||||
new Jack::JackNetOneDriver("system", "net_pcm", engine, table, listen_port, mtu, | |||||
capture_ports_midi, playback_ports_midi, capture_ports, playback_ports, | capture_ports_midi, playback_ports_midi, capture_ports, playback_ports, | ||||
sample_rate, period_size, resample_factor, | sample_rate, period_size, resample_factor, | ||||
"net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy, | "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy, | ||||
dont_htonl_floats, always_deadline, jitter_val ) ); | |||||
dont_htonl_floats, always_deadline, jitter_val)); | |||||
if ( driver->Open ( period_size, sample_rate, 1, 1, capture_ports, playback_ports, | |||||
0, "from_master_", "to_master_", 0, 0 ) == 0 ) { | |||||
if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports, | |||||
0, "from_master_", "to_master_", 0, 0) == 0) { | |||||
return driver; | return driver; | ||||
} else { | } else { | ||||
delete driver; | delete driver; | ||||
return NULL; | return NULL; | ||||
} | } | ||||
} catch ( ... ) { | |||||
} catch (...) { | |||||
return NULL; | return NULL; | ||||
} | } | ||||
} | } | ||||
@@ -30,7 +30,7 @@ namespace Jack | |||||
\Brief This class describes the Net Backend | \Brief This class describes the Net Backend | ||||
*/ | */ | ||||
class JackNetOneDriver : public JackTimedDriver | |||||
class JackNetOneDriver : public JackWaiterDriver | |||||
{ | { | ||||
private: | private: | ||||
@@ -63,8 +63,6 @@ class JackNetOneDriver : public JackTimedDriver | |||||
int Close(); | int Close(); | ||||
int Attach(); | int Attach(); | ||||
int Detach(); | int Detach(); | ||||
int Process(); | |||||
int Read(); | int Read(); | ||||
int Write(); | int Write(); | ||||
@@ -74,17 +72,17 @@ class JackNetOneDriver : public JackTimedDriver | |||||
void FreePorts(); | void FreePorts(); | ||||
// BufferSize can't be changed | // BufferSize can't be changed | ||||
bool IsFixedBufferSize() | |||||
bool IsFixedBufferSize() | |||||
{ | { | ||||
return true; | return true; | ||||
} | } | ||||
int SetBufferSize(jack_nframes_t buffer_size) | |||||
int SetBufferSize(jack_nframes_t buffer_size) | |||||
{ | { | ||||
return -1; | return -1; | ||||
} | } | ||||
int SetSampleRate(jack_nframes_t sample_rate) | |||||
int SetSampleRate(jack_nframes_t sample_rate) | |||||
{ | { | ||||
return -1; | return -1; | ||||
} | } | ||||
@@ -24,7 +24,7 @@ namespace Jack | |||||
{ | { | ||||
JackResampler::JackResampler() | JackResampler::JackResampler() | ||||
:fRatio(1),fRingBufferSize(DEFAULT_RB_SIZE) | |||||
:fRatio(1), fRingBufferSize(DEFAULT_RB_SIZE) | |||||
{ | { | ||||
fRingBuffer = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * fRingBufferSize); | fRingBuffer = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * fRingBufferSize); | ||||
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize) / 2); | jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize) / 2); | ||||
@@ -32,8 +32,9 @@ JackResampler::JackResampler() | |||||
JackResampler::~JackResampler() | JackResampler::~JackResampler() | ||||
{ | { | ||||
if (fRingBuffer) | |||||
if (fRingBuffer) { | |||||
jack_ringbuffer_free(fRingBuffer); | jack_ringbuffer_free(fRingBuffer); | ||||
} | |||||
} | } | ||||
void JackResampler::Reset(unsigned int new_size) | void JackResampler::Reset(unsigned int new_size) | ||||
@@ -44,16 +44,16 @@ int JackThreadedDriver::Open() | |||||
} | } | ||||
int JackThreadedDriver::Open(jack_nframes_t buffer_size, | int JackThreadedDriver::Open(jack_nframes_t buffer_size, | ||||
jack_nframes_t samplerate, | |||||
bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) | |||||
jack_nframes_t samplerate, | |||||
bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_name, | |||||
const char* playback_driver_name, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) | |||||
{ | { | ||||
return fDriver->Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | return fDriver->Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | ||||
} | } | ||||
@@ -245,7 +245,7 @@ void JackThreadedDriver::SetRealTime() | |||||
set_threaded_log_function(); | set_threaded_log_function(); | ||||
} | } | ||||
} else { | } else { | ||||
jack_log("JackThreadedDriver::Init non non-realtime "); | |||||
jack_log("JackThreadedDriver::Init non-realtime"); | |||||
} | } | ||||
} | } | ||||
@@ -29,58 +29,61 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
int JackTimedDriver::FirstCycle(jack_time_t cur_time) | |||||
int JackTimedDriver::FirstCycle(jack_time_t cur_time_usec) | |||||
{ | { | ||||
fAnchorTime = cur_time; | |||||
fAnchorTimeUsec = cur_time_usec; | |||||
return int((double(fEngineControl->fBufferSize) * 1000000) / double(fEngineControl->fSampleRate)); | return int((double(fEngineControl->fBufferSize) * 1000000) / double(fEngineControl->fSampleRate)); | ||||
} | } | ||||
int JackTimedDriver::CurrentCycle(jack_time_t cur_time) | |||||
int JackTimedDriver::CurrentCycle(jack_time_t cur_time_usec) | |||||
{ | |||||
return int(((double(fCycleCount) * double(fEngineControl->fBufferSize) * 1000000.) / double(fEngineControl->fSampleRate)) - (cur_time_usec - fAnchorTimeUsec)); | |||||
} | |||||
int JackTimedDriver::Start() | |||||
{ | { | ||||
return int((double(fCycleCount) * double(fEngineControl->fBufferSize) * 1000000.) / double(fEngineControl->fSampleRate)) - (cur_time - fAnchorTime); | |||||
fCycleCount = 0; | |||||
return JackAudioDriver::Start(); | |||||
} | } | ||||
int JackTimedDriver::ProcessAux() | |||||
void JackTimedDriver::ProcessWait() | |||||
{ | { | ||||
jack_time_t cur_time = GetMicroSeconds(); | |||||
int wait_time; | |||||
jack_time_t cur_time_usec = GetMicroSeconds(); | |||||
int wait_time_usec; | |||||
if (fCycleCount++ == 0) { | if (fCycleCount++ == 0) { | ||||
wait_time = FirstCycle(cur_time); | |||||
wait_time_usec = FirstCycle(cur_time_usec); | |||||
} else { | } else { | ||||
wait_time = CurrentCycle(cur_time); | |||||
wait_time_usec = CurrentCycle(cur_time_usec); | |||||
} | } | ||||
if (wait_time < 0) { | |||||
NotifyXRun(cur_time, float(cur_time -fBeginDateUst)); | |||||
if (wait_time_usec < 0) { | |||||
NotifyXRun(cur_time_usec, float(cur_time_usec - fBeginDateUst)); | |||||
fCycleCount = 0; | fCycleCount = 0; | ||||
wait_time = 0; | |||||
wait_time_usec = 0; | |||||
jack_error("JackTimedDriver::Process XRun = %ld usec", (cur_time_usec - fBeginDateUst)); | |||||
} | } | ||||
//jack_log("JackTimedDriver::Process wait_time = %d", wait_time); | |||||
JackSleep(wait_time); | |||||
return 0; | |||||
} | |||||
int JackTimedDriver::Process() | |||||
{ | |||||
JackDriver::CycleTakeBeginTime(); | |||||
JackAudioDriver::Process(); | |||||
return ProcessAux(); | |||||
//jack_log("JackTimedDriver::Process wait_time = %d", wait_time_usec); | |||||
JackSleep(wait_time_usec); | |||||
} | } | ||||
int JackTimedDriver::ProcessNull() | |||||
int JackWaiterDriver::ProcessNull() | |||||
{ | { | ||||
JackDriver::CycleTakeBeginTime(); | JackDriver::CycleTakeBeginTime(); | ||||
// Graph processing without Read/Write | |||||
if (fEngineControl->fSyncMode) { | if (fEngineControl->fSyncMode) { | ||||
ProcessGraphSyncMaster(); | |||||
ProcessGraphSync(); | |||||
} else { | } else { | ||||
ProcessGraphAsyncMaster(); | |||||
ProcessGraphAsync(); | |||||
} | } | ||||
return ProcessAux(); | |||||
// Keep end cycle time | |||||
JackDriver::CycleTakeEndTime(); | |||||
ProcessWait(); | |||||
return 0; | |||||
} | } | ||||
} // end of namespace | } // end of namespace |
@@ -32,33 +32,47 @@ namespace Jack | |||||
class SERVER_EXPORT JackTimedDriver : public JackAudioDriver | class SERVER_EXPORT JackTimedDriver : public JackAudioDriver | ||||
{ | { | ||||
private: | |||||
protected: | |||||
int fCycleCount; | int fCycleCount; | ||||
jack_time_t fAnchorTime; | |||||
jack_time_t fAnchorTimeUsec; | |||||
int FirstCycle(jack_time_t cur_time); | int FirstCycle(jack_time_t cur_time); | ||||
int CurrentCycle(jack_time_t cur_time); | int CurrentCycle(jack_time_t cur_time); | ||||
int ProcessAux(); | |||||
void ProcessWait(); | |||||
public: | public: | ||||
JackTimedDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | JackTimedDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | ||||
: JackAudioDriver(name, alias, engine, table), fCycleCount(0), fAnchorTime(0) | |||||
: JackAudioDriver(name, alias, engine, table), fCycleCount(0), fAnchorTimeUsec(0) | |||||
{} | {} | ||||
virtual ~JackTimedDriver() | virtual ~JackTimedDriver() | ||||
{} | {} | ||||
virtual int Process(); | |||||
virtual int ProcessNull(); | |||||
// BufferSize can be changed | // BufferSize can be changed | ||||
bool IsFixedBufferSize() | bool IsFixedBufferSize() | ||||
{ | { | ||||
return false; | return false; | ||||
} | } | ||||
int Start(); | |||||
}; | |||||
class SERVER_EXPORT JackWaiterDriver : public JackTimedDriver | |||||
{ | |||||
public: | |||||
JackWaiterDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | |||||
: JackTimedDriver(name, alias, engine, table) | |||||
{} | |||||
virtual ~JackWaiterDriver() | |||||
{} | |||||
virtual int ProcessNull(); | |||||
}; | }; | ||||
} // end of namespace | } // end of namespace | ||||
@@ -43,9 +43,9 @@ bool JackWaitThreadedDriver::Execute() | |||||
// Process a null cycle until NetDriver has started | // Process a null cycle until NetDriver has started | ||||
while (!fStarter.fRunning && fThread.GetStatus() == JackThread::kRunning) { | while (!fStarter.fRunning && fThread.GetStatus() == JackThread::kRunning) { | ||||
// Use the base method | |||||
assert(static_cast<JackTimedDriver*>(fDriver)); | |||||
static_cast<JackTimedDriver*>(fDriver)->ProcessNull(); | |||||
// Use base class method | |||||
assert(static_cast<JackWaiterDriver*>(fDriver)); | |||||
static_cast<JackWaiterDriver*>(fDriver)->ProcessNull(); | |||||
} | } | ||||
// Switch to keep running even in case of error | // Switch to keep running even in case of error | ||||
@@ -39,7 +39,7 @@ class SERVER_EXPORT JackWaitThreadedDriver : public JackThreadedDriver | |||||
{ | { | ||||
private: | private: | ||||
struct SERVER_EXPORT JackDriverStarter : public JackRunnableInterface | |||||
struct JackDriverStarter : public JackRunnableInterface | |||||
{ | { | ||||
JackDriver* fDriver; | JackDriver* fDriver; | ||||
@@ -47,7 +47,7 @@ class SERVER_EXPORT JackWaitThreadedDriver : public JackThreadedDriver | |||||
volatile bool fRunning; | volatile bool fRunning; | ||||
JackDriverStarter(JackDriver* driver) | JackDriverStarter(JackDriver* driver) | ||||
:fDriver(driver),fThread(this),fRunning(false) | |||||
:fDriver(driver), fThread(this), fRunning(false) | |||||
{} | {} | ||||
~JackDriverStarter() | ~JackDriverStarter() | ||||
@@ -37,7 +37,7 @@ extern "C" { | |||||
/** | /** | ||||
* Session event type. | * Session event type. | ||||
* | * | ||||
* if a client cant save templates, i might just do a normal save. | |||||
* If a client cant save templates, i might just do a normal save. | |||||
* | * | ||||
* There is no "quit without saving" event because a client might refuse to | * There is no "quit without saving" event because a client might refuse to | ||||
* quit when it has unsaved data, but other clients may have already quit. | * quit when it has unsaved data, but other clients may have already quit. | ||||
@@ -192,15 +192,13 @@ int jack_session_reply (jack_client_t *client, | |||||
/** | /** | ||||
* Free memory used by a jack_session_event_t. | * Free memory used by a jack_session_event_t. | ||||
* | * | ||||
* This also frees the memory used by the command_line pointer. | |||||
* if its non NULL. | |||||
* This also frees the memory used by the command_line pointer, if its non NULL. | |||||
*/ | */ | ||||
void jack_session_event_free (jack_session_event_t *event) JACK_WEAK_EXPORT; | void jack_session_event_free (jack_session_event_t *event) JACK_WEAK_EXPORT; | ||||
/** | /** | ||||
* Get the assigned uuid for client. | * Get the assigned uuid for client. | ||||
* | |||||
* Safe to call from callback and all other threads. | * Safe to call from callback and all other threads. | ||||
* | * | ||||
* The caller is responsible for calling jack_free(3) on any non-NULL | * The caller is responsible for calling jack_free(3) on any non-NULL | ||||
@@ -114,7 +114,7 @@ int jack_drop_real_time_scheduling (jack_native_thread_t thread) JACK_OPTIONAL_W | |||||
int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; | int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; | ||||
/** | /** | ||||
* Cancel the thread then waits for the thread handler to terminate. | |||||
* Kill the thread. | |||||
* | * | ||||
* @param thread POSIX thread ID. | * @param thread POSIX thread ID. | ||||
* | * | ||||
@@ -16,11 +16,11 @@ | |||||
jack_client_t *client; | jack_client_t *client; | ||||
static void signal_handler ( int sig ) | |||||
static void signal_handler(int sig) | |||||
{ | { | ||||
jack_client_close ( client ); | |||||
fprintf ( stderr, "signal received, exiting ...\n" ); | |||||
exit ( 0 ); | |||||
jack_client_close(client ; | |||||
fprintf(stderr, "signal received, exiting ...\n"); | |||||
exit(0); | |||||
} | } | ||||
@@ -29,13 +29,13 @@ static void signal_handler ( int sig ) | |||||
* decides to disconnect the client. | * decides to disconnect the client. | ||||
*/ | */ | ||||
void | void | ||||
jack_shutdown ( void *arg ) | |||||
jack_shutdown(void *arg) | |||||
{ | { | ||||
exit ( 1 ); | |||||
exit(1); | |||||
} | } | ||||
int | int | ||||
main ( int argc, char *argv[] ) | |||||
main(int argc, char *argv[]) | |||||
{ | { | ||||
jack_options_t options = JackNullOption; | jack_options_t options = JackNullOption; | ||||
jack_status_t status; | jack_status_t status; | ||||
@@ -43,50 +43,46 @@ main ( int argc, char *argv[] ) | |||||
/* open a client connection to the JACK server */ | /* open a client connection to the JACK server */ | ||||
client = jack_client_open ("jack_cpu_load", options, &status); | client = jack_client_open ("jack_cpu_load", options, &status); | ||||
if ( client == NULL ) | |||||
{ | |||||
fprintf ( stderr, "jack_client_open() failed, " | |||||
"status = 0x%2.0x\n", status ); | |||||
if ( status & JackServerFailed ) | |||||
{ | |||||
fprintf ( stderr, "Unable to connect to JACK server\n" ); | |||||
if (client == NULL) { | |||||
fprintf(stderr, "jack_client_open() failed, " | |||||
"status = 0x%2.0x\n", status); | |||||
if (status & JackServerFailed) { | |||||
fprintf(stderr, "Unable to connect to JACK server\n"); | |||||
} | } | ||||
exit ( 1 ); | |||||
exit(1); | |||||
} | } | ||||
jack_on_shutdown ( client, jack_shutdown, 0 ); | |||||
jack_on_shutdown(client, jack_shutdown, 0); | |||||
/* Tell the JACK server that we are ready to roll. Our | /* Tell the JACK server that we are ready to roll. Our | ||||
* process() callback will start running now. */ | * process() callback will start running now. */ | ||||
if ( jack_activate ( client ) ) | |||||
{ | |||||
fprintf ( stderr, "cannot activate client" ); | |||||
exit ( 1 ); | |||||
if (jack_activate(client)) { | |||||
fprintf(stderr, "cannot activate client"); | |||||
exit(1); | |||||
} | } | ||||
/* install a signal handler to properly quits jack client */ | /* install a signal handler to properly quits jack client */ | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
signal ( SIGINT, signal_handler ); | |||||
signal ( SIGABRT, signal_handler ); | |||||
signal ( SIGTERM, signal_handler ); | |||||
signal(SIGINT, signal_handler); | |||||
signal(SIGABRT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
#else | #else | ||||
signal ( SIGQUIT, signal_handler ); | |||||
signal ( SIGTERM, signal_handler ); | |||||
signal ( SIGHUP, signal_handler ); | |||||
signal ( SIGINT, signal_handler ); | |||||
signal(SIGQUIT, signal_handler); | |||||
signal(SIGTERM, signal_handler); | |||||
signal(SIGHUP, signal_handler); | |||||
signal(SIGINT, signal_handler); | |||||
#endif | #endif | ||||
while (1) | |||||
{ | |||||
while (1) { | |||||
printf("jack DSP load %f\n", jack_cpu_load(client)); | printf("jack DSP load %f\n", jack_cpu_load(client)); | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
Sleep ( 1000 ); | |||||
Sleep(1000); | |||||
#else | #else | ||||
sleep ( 1 ); | |||||
sleep(1); | |||||
#endif | #endif | ||||
} | } | ||||
jack_client_close ( client ); | |||||
exit ( 0 ); | |||||
jack_client_close(client); | |||||
exit(0 ); | |||||
} | } |
@@ -57,9 +57,9 @@ main (int argc, char *argv[]) | |||||
{ | { | ||||
int buffer_size = BUFFER_SIZE; | int buffer_size = BUFFER_SIZE; | ||||
int sample_rate = SAMPLE_RATE; | int sample_rate = SAMPLE_RATE; | ||||
int port = DEFAULT_PORT; | |||||
int udp_port = DEFAULT_PORT; | |||||
char* multicast_ip = DEFAULT_MULTICAST_IP; | char* multicast_ip = DEFAULT_MULTICAST_IP; | ||||
const char *options = "b:r:a:p:"; | |||||
const char *options = "b:r:a:p:h"; | |||||
int option_index; | int option_index; | ||||
int opt; | int opt; | ||||
@@ -89,7 +89,7 @@ main (int argc, char *argv[]) | |||||
break; | break; | ||||
case 'p': | case 'p': | ||||
port = atoi(optarg); | |||||
udp_port = atoi(optarg); | |||||
break; | break; | ||||
case 'h': | case 'h': | ||||
@@ -107,7 +107,7 @@ main (int argc, char *argv[]) | |||||
printf("Waiting for a slave...\n"); | printf("Waiting for a slave...\n"); | ||||
if ((net = jack_net_master_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "net_master", &request, &result)) == 0) { | |||||
if ((net = jack_net_master_open(multicast_ip, udp_port, "net_master", &request, &result)) == 0) { | |||||
fprintf(stderr, "NetJack master can not be opened\n"); | fprintf(stderr, "NetJack master can not be opened\n"); | ||||
return 1; | return 1; | ||||
} | } | ||||
@@ -79,9 +79,9 @@ main (int argc, char *argv[]) | |||||
{ | { | ||||
int audio_input = 2; | int audio_input = 2; | ||||
int audio_output = 2; | int audio_output = 2; | ||||
int port = DEFAULT_PORT; | |||||
int udp_port = DEFAULT_PORT; | |||||
char* multicast_ip = DEFAULT_MULTICAST_IP; | char* multicast_ip = DEFAULT_MULTICAST_IP; | ||||
const char *options = "C:P:a:p:"; | |||||
const char *options = "C:P:a:p:h"; | |||||
int option_index; | int option_index; | ||||
int opt; | int opt; | ||||
@@ -111,7 +111,7 @@ main (int argc, char *argv[]) | |||||
break; | break; | ||||
case 'p': | case 'p': | ||||
port = atoi(optarg); | |||||
udp_port = atoi(optarg); | |||||
break; | break; | ||||
case 'h': | case 'h': | ||||
@@ -125,7 +125,7 @@ main (int argc, char *argv[]) | |||||
printf("Waiting for a master...\n"); | printf("Waiting for a master...\n"); | ||||
if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "net_slave", &request, &result)) == 0) { | |||||
if ((net = jack_net_slave_open(multicast_ip, udp_port, "net_slave", &request, &result)) == 0) { | |||||
fprintf(stderr, "JACK server not running?\n"); | fprintf(stderr, "JACK server not running?\n"); | ||||
return 1; | return 1; | ||||
} | } | ||||
@@ -11,22 +11,22 @@ | |||||
char * my_name; | char * my_name; | ||||
void | void | ||||
show_usage (void) | |||||
show_usage(void) | |||||
{ | { | ||||
fprintf (stderr, "\nUsage: %s [options]\n", my_name); | |||||
fprintf (stderr, "Check for jack existence, or wait, until it either quits, or gets started\n"); | |||||
fprintf (stderr, "options:\n"); | |||||
fprintf (stderr, " -s, --server <name> Connect to the jack server named <name>\n"); | |||||
fprintf (stderr, " -w, --wait Wait for server to become available\n"); | |||||
fprintf (stderr, " -q, --quit Wait until server is quit\n"); | |||||
fprintf (stderr, " -c, --check Check wether server is running\n"); | |||||
fprintf (stderr, " -t, --timeout Wait timeout in seconds\n"); | |||||
fprintf (stderr, " -h, --help Display this help message\n"); | |||||
fprintf (stderr, "For more information see http://jackaudio.org/\n"); | |||||
fprintf(stderr, "\nUsage: %s [options]\n", my_name); | |||||
fprintf(stderr, "Check for jack existence, or wait, until it either quits, or gets started\n"); | |||||
fprintf(stderr, "options:\n"); | |||||
fprintf(stderr, " -s, --server <name> Connect to the jack server named <name>\n"); | |||||
fprintf(stderr, " -w, --wait Wait for server to become available\n"); | |||||
fprintf(stderr, " -q, --quit Wait until server is quit\n"); | |||||
fprintf(stderr, " -c, --check Check wether server is running\n"); | |||||
fprintf(stderr, " -t, --timeout Wait timeout in seconds\n"); | |||||
fprintf(stderr, " -h, --help Display this help message\n"); | |||||
fprintf(stderr, "For more information see http://jackaudio.org/\n"); | |||||
} | } | ||||
int | int | ||||
main (int argc, char *argv[]) | |||||
main(int argc, char *argv[]) | |||||
{ | { | ||||
jack_client_t *client; | jack_client_t *client; | ||||
jack_status_t status; | jack_status_t status; | ||||
@@ -78,11 +78,11 @@ main (int argc, char *argv[]) | |||||
wait_timeout = atoi(optarg); | wait_timeout = atoi(optarg); | ||||
break; | break; | ||||
case 'h': | case 'h': | ||||
show_usage (); | |||||
show_usage(); | |||||
return 1; | return 1; | ||||
break; | break; | ||||
default: | default: | ||||
show_usage (); | |||||
show_usage(); | |||||
return 1; | return 1; | ||||
break; | break; | ||||
} | } | ||||
@@ -90,40 +90,40 @@ main (int argc, char *argv[]) | |||||
/* try to open server in a loop. breaking under certein conditions */ | /* try to open server in a loop. breaking under certein conditions */ | ||||
start_timestamp = time( NULL ); | |||||
start_timestamp = time(NULL); | |||||
while(1) { | |||||
while (1) { | |||||
client = jack_client_open ("wait", options, &status, server_name); | client = jack_client_open ("wait", options, &status, server_name); | ||||
/* check for some real error and bail out */ | /* check for some real error and bail out */ | ||||
if( (client == NULL) && !(status & JackServerFailed) ) { | |||||
if ((client == NULL) && !(status & JackServerFailed)) { | |||||
fprintf (stderr, "jack_client_open() failed, " | fprintf (stderr, "jack_client_open() failed, " | ||||
"status = 0x%2.0x\n", status); | "status = 0x%2.0x\n", status); | ||||
return 1; | return 1; | ||||
} | } | ||||
if( client == NULL ) { | |||||
if( wait_for_quit ) { | |||||
fprintf( stdout, "server is gone\n" ); | |||||
if (client == NULL) { | |||||
if (wait_for_quit) { | |||||
fprintf(stdout, "server is gone\n"); | |||||
break; | break; | ||||
} | } | ||||
if( just_check ) { | |||||
fprintf( stdout, "not running\n" ); | |||||
if (just_check) { | |||||
fprintf(stdout, "not running\n"); | |||||
break; | break; | ||||
} | } | ||||
} else { | } else { | ||||
jack_client_close( client ); | |||||
if( wait_for_start ) { | |||||
fprintf( stdout, "server is available\n" ); | |||||
jack_client_close(client); | |||||
if (wait_for_start) { | |||||
fprintf(stdout, "server is available\n"); | |||||
break; | break; | ||||
} | } | ||||
if( just_check ) { | |||||
fprintf( stdout, "running\n" ); | |||||
if (just_check) { | |||||
fprintf(stdout, "running\n"); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if( wait_timeout ) { | |||||
if( (time( NULL ) - start_timestamp) > wait_timeout ) { | |||||
fprintf( stdout, "timeout\n" ); | |||||
if (wait_timeout) { | |||||
if ((time(NULL) - start_timestamp) > wait_timeout) { | |||||
fprintf(stdout, "timeout\n"); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -132,5 +132,5 @@ main (int argc, char *argv[]) | |||||
sleep(1); | sleep(1); | ||||
} | } | ||||
exit (0); | |||||
exit(0); | |||||
} | } |
@@ -213,8 +213,8 @@ extern "C" | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL); | ||||
value.i = 0; | value.i = 0; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamInt, &value, NULL, "Number of capture channels (defaults to hardware max)", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamInt, &value, NULL, "Number of playback channels (defaults to hardware max)", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Number of capture channels (defaults to hardware max)", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Number of playback channels (defaults to hardware max)", NULL); | |||||
value.ui = 0; | value.ui = 0; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamUInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamUInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL); | ||||
@@ -2656,7 +2656,6 @@ | |||||
4BA3873B079479C2008D8992 /* Graph */, | 4BA3873B079479C2008D8992 /* Graph */, | ||||
4BA550FA05E241F200569492 /* Ports */, | 4BA550FA05E241F200569492 /* Ports */, | ||||
4BD56D74079687D7006D44F9 /* Client */, | 4BD56D74079687D7006D44F9 /* Client */, | ||||
4BA550FB05E2420000569492 /* Engine */, | |||||
4B9B627005E60A9E001E19AA /* Server */, | 4B9B627005E60A9E001E19AA /* Server */, | ||||
); | ); | ||||
name = Source; | name = Source; | ||||
@@ -3111,6 +3110,7 @@ | |||||
4BA550FA05E241F200569492 /* Ports */ = { | 4BA550FA05E241F200569492 /* Ports */ = { | ||||
isa = PBXGroup; | isa = PBXGroup; | ||||
children = ( | children = ( | ||||
4BA550FB05E2420000569492 /* Engine */, | |||||
4B80D7E60BA0D17400F035BB /* JackMidiPort.cpp */, | 4B80D7E60BA0D17400F035BB /* JackMidiPort.cpp */, | ||||
4B80D7E50BA0D17400F035BB /* JackMidiPort.h */, | 4B80D7E50BA0D17400F035BB /* JackMidiPort.h */, | ||||
4BAB95EC0B9E21A500A0C723 /* JackAudioPort.cpp */, | 4BAB95EC0B9E21A500A0C723 /* JackAudioPort.cpp */, | ||||
@@ -11701,8 +11701,12 @@ | |||||
INSTALL_PATH = /usr/local/lib; | INSTALL_PATH = /usr/local/lib; | ||||
LIBRARY_STYLE = DYNAMIC; | LIBRARY_STYLE = DYNAMIC; | ||||
MACH_O_TYPE = mh_dylib; | MACH_O_TYPE = mh_dylib; | ||||
OTHER_CFLAGS = ""; | |||||
OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; | |||||
OTHER_CFLAGS = "-DJACK_32_64"; | |||||
OTHER_CPLUSPLUSFLAGS = ( | |||||
"-DSERVER_SIDE", | |||||
"-DMACH_RPC_MACH_SEMA", | |||||
"-DJACK_32_64", | |||||
); | |||||
OTHER_LDFLAGS = ( | OTHER_LDFLAGS = ( | ||||
"-framework", | "-framework", | ||||
Jackservermp, | Jackservermp, | ||||
@@ -12000,8 +12004,12 @@ | |||||
INSTALL_PATH = /usr/local/lib; | INSTALL_PATH = /usr/local/lib; | ||||
LIBRARY_STYLE = DYNAMIC; | LIBRARY_STYLE = DYNAMIC; | ||||
MACH_O_TYPE = mh_dylib; | MACH_O_TYPE = mh_dylib; | ||||
OTHER_CFLAGS = ""; | |||||
OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA"; | |||||
OTHER_CFLAGS = "-DJACK_32_64"; | |||||
OTHER_CPLUSPLUSFLAGS = ( | |||||
"-DSERVER_SIDE", | |||||
"-DMACH_RPC_MACH_SEMA", | |||||
"-DJACK_32_64", | |||||
); | |||||
OTHER_LDFLAGS = ( | OTHER_LDFLAGS = ( | ||||
"-framework", | "-framework", | ||||
Jackservermp, | Jackservermp, | ||||
@@ -49,15 +49,17 @@ static OSStatus DisplayDeviceNames() | |||||
CFStringRef UIname; | CFStringRef UIname; | ||||
err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable); | err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable); | ||||
if (err != noErr) | |||||
if (err != noErr) { | |||||
return err; | return err; | ||||
} | |||||
deviceNum = size / sizeof(AudioDeviceID); | deviceNum = size / sizeof(AudioDeviceID); | ||||
AudioDeviceID devices[deviceNum]; | AudioDeviceID devices[deviceNum]; | ||||
err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices); | err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices); | ||||
if (err != noErr) | |||||
if (err != noErr) { | |||||
return err; | return err; | ||||
} | |||||
for (i = 0; i < deviceNum; i++) { | for (i = 0; i < deviceNum; i++) { | ||||
char device_name[256]; | char device_name[256]; | ||||
@@ -74,8 +76,9 @@ static OSStatus DisplayDeviceNames() | |||||
size = 256; | size = 256; | ||||
err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name); | err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name); | ||||
if (err != noErr) | |||||
if (err != noErr) { | |||||
return err; | return err; | ||||
} | |||||
jack_info("Device name = \'%s\', internal_name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name); | jack_info("Device name = \'%s\', internal_name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name); | ||||
} | } | ||||
@@ -83,8 +86,9 @@ static OSStatus DisplayDeviceNames() | |||||
return noErr; | return noErr; | ||||
error: | error: | ||||
if (UIname != NULL) | |||||
if (UIname != NULL) { | |||||
CFRelease(UIname); | CFRelease(UIname); | ||||
} | |||||
return err; | return err; | ||||
} | } | ||||
@@ -267,27 +271,31 @@ void JackCoreAudioAdapter::RemoveListeners() | |||||
} | } | ||||
OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | ||||
AudioUnitRenderActionFlags *ioActionFlags, | |||||
const AudioTimeStamp *inTimeStamp, | |||||
UInt32 inBusNumber, | |||||
UInt32 inNumberFrames, | |||||
AudioBufferList *ioData) | |||||
AudioUnitRenderActionFlags *ioActionFlags, | |||||
const AudioTimeStamp *inTimeStamp, | |||||
UInt32 inBusNumber, | |||||
UInt32 inNumberFrames, | |||||
AudioBufferList *ioData) | |||||
{ | { | ||||
JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon); | JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon); | ||||
AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData); | |||||
OSStatus err = AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData); | |||||
jack_default_audio_sample_t* inputBuffer[adapter->fCaptureChannels]; | |||||
jack_default_audio_sample_t* outputBuffer[adapter->fPlaybackChannels]; | |||||
if (err == noErr) { | |||||
jack_default_audio_sample_t* inputBuffer[adapter->fCaptureChannels]; | |||||
jack_default_audio_sample_t* outputBuffer[adapter->fPlaybackChannels]; | |||||
for (int i = 0; i < adapter->fCaptureChannels; i++) { | |||||
inputBuffer[i] = (jack_default_audio_sample_t*)adapter->fInputData->mBuffers[i].mData; | |||||
} | |||||
for (int i = 0; i < adapter->fPlaybackChannels; i++) { | |||||
outputBuffer[i] = (jack_default_audio_sample_t*)ioData->mBuffers[i].mData; | |||||
} | |||||
for (int i = 0; i < adapter->fCaptureChannels; i++) { | |||||
inputBuffer[i] = (jack_default_audio_sample_t*)adapter->fInputData->mBuffers[i].mData; | |||||
} | |||||
for (int i = 0; i < adapter->fPlaybackChannels; i++) { | |||||
outputBuffer[i] = (jack_default_audio_sample_t*)ioData->mBuffers[i].mData; | |||||
} | |||||
adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, inNumberFrames); | |||||
return noErr; | |||||
adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, inNumberFrames); | |||||
return noErr; | |||||
} else { | |||||
return err; | |||||
} | |||||
} | } | ||||
JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) | JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) | ||||
@@ -420,6 +428,9 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra | |||||
if (AddListeners() < 0) { | if (AddListeners() < 0) { | ||||
throw std::bad_alloc(); | throw std::bad_alloc(); | ||||
} | } | ||||
GetStreamLatencies(fDeviceID, true, fInputLatencies); | |||||
GetStreamLatencies(fDeviceID, false, fOutputLatencies); | |||||
} | } | ||||
OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id) | OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id) | ||||
@@ -429,11 +440,13 @@ OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id) | |||||
AudioDeviceID inDefault; | AudioDeviceID inDefault; | ||||
AudioDeviceID outDefault; | AudioDeviceID outDefault; | ||||
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) | |||||
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) { | |||||
return res; | return res; | ||||
} | |||||
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) | |||||
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) { | |||||
return res; | return res; | ||||
} | |||||
jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault); | jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault); | ||||
@@ -462,8 +475,9 @@ OSStatus JackCoreAudioAdapter::GetTotalChannels(AudioDeviceID device, int& chann | |||||
AudioBufferList bufferList[outSize]; | AudioBufferList bufferList[outSize]; | ||||
err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList); | err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList); | ||||
if (err == noErr) { | if (err == noErr) { | ||||
for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++) | |||||
for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++) { | |||||
channelCount += bufferList->mBuffers[i].mNumberChannels; | channelCount += bufferList->mBuffers[i].mNumberChannels; | ||||
} | |||||
} | } | ||||
} | } | ||||
@@ -492,11 +506,12 @@ OSStatus JackCoreAudioAdapter::GetDefaultInputDevice(AudioDeviceID* id) | |||||
UInt32 theSize = sizeof(UInt32); | UInt32 theSize = sizeof(UInt32); | ||||
AudioDeviceID inDefault; | AudioDeviceID inDefault; | ||||
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) | |||||
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) { | |||||
return res; | return res; | ||||
} | |||||
if (inDefault == 0) { | if (inDefault == 0) { | ||||
jack_error("Error : input device is 0, please select a correct one !!"); | |||||
jack_error("Error: default input device is 0, please select a correct one !!"); | |||||
return -1; | return -1; | ||||
} | } | ||||
jack_log("GetDefaultInputDevice: input = %ld ", inDefault); | jack_log("GetDefaultInputDevice: input = %ld ", inDefault); | ||||
@@ -510,11 +525,12 @@ OSStatus JackCoreAudioAdapter::GetDefaultOutputDevice(AudioDeviceID* id) | |||||
UInt32 theSize = sizeof(UInt32); | UInt32 theSize = sizeof(UInt32); | ||||
AudioDeviceID outDefault; | AudioDeviceID outDefault; | ||||
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) | |||||
if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) { | |||||
return res; | return res; | ||||
} | |||||
if (outDefault == 0) { | if (outDefault == 0) { | ||||
jack_error("Error : output device is 0, please select a correct one !!"); | |||||
jack_error("Error: default output device is 0, please select a correct one !!"); | |||||
return -1; | return -1; | ||||
} | } | ||||
jack_log("GetDefaultOutputDevice: output = %ld", outDefault); | jack_log("GetDefaultOutputDevice: output = %ld", outDefault); | ||||
@@ -528,6 +544,39 @@ OSStatus JackCoreAudioAdapter::GetDeviceNameFromID(AudioDeviceID id, char* name) | |||||
return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name); | return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name); | ||||
} | } | ||||
AudioDeviceID JackCoreAudioAdapter::GetDeviceIDFromName(const char* name) | |||||
{ | |||||
UInt32 size; | |||||
Boolean isWritable; | |||||
int i, deviceNum; | |||||
OSStatus err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable); | |||||
if (err != noErr) { | |||||
return -1; | |||||
} | |||||
deviceNum = size / sizeof(AudioDeviceID); | |||||
AudioDeviceID devices[deviceNum]; | |||||
err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices); | |||||
if (err != noErr) { | |||||
return err; | |||||
} | |||||
for (i = 0; i < deviceNum; i++) { | |||||
char device_name[256]; | |||||
size = 256; | |||||
err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name); | |||||
if (err != noErr) { | |||||
return -1; | |||||
} else if (strcmp(device_name, name) == 0) { | |||||
return devices[i]; | |||||
} | |||||
} | |||||
return -1; | |||||
} | |||||
// Setup | // Setup | ||||
int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | ||||
const char* playback_driver_uid, | const char* playback_driver_uid, | ||||
@@ -540,6 +589,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||||
// Duplex | // Duplex | ||||
if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) { | if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) { | ||||
jack_log("JackCoreAudioDriver::Open duplex"); | |||||
// Same device for capture and playback... | // Same device for capture and playback... | ||||
if (strcmp(capture_driver_uid, playback_driver_uid) == 0) { | if (strcmp(capture_driver_uid, playback_driver_uid) == 0) { | ||||
@@ -577,8 +627,9 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||||
} | } | ||||
} | } | ||||
if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) | |||||
if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) { | |||||
return -1; | return -1; | ||||
} | |||||
} | } | ||||
// Capture only | // Capture only | ||||
@@ -616,13 +667,13 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||||
jack_error("Cannot open default device in duplex mode, so aggregate default input and default output"); | jack_error("Cannot open default device in duplex mode, so aggregate default input and default output"); | ||||
// Creates aggregate device | // Creates aggregate device | ||||
AudioDeviceID captureID, playbackID; | |||||
AudioDeviceID captureID = -1, playbackID = -1; | |||||
if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { | if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { | ||||
jack_log("Will take default input"); | jack_log("Will take default input"); | ||||
if (GetDefaultInputDevice(&captureID) != noErr) { | if (GetDefaultInputDevice(&captureID) != noErr) { | ||||
jack_error("Cannot open default input device"); | jack_error("Cannot open default input device"); | ||||
return -1; | |||||
goto built_in; | |||||
} | } | ||||
} | } | ||||
@@ -630,15 +681,38 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||||
jack_log("Will take default output"); | jack_log("Will take default output"); | ||||
if (GetDefaultOutputDevice(&playbackID) != noErr) { | if (GetDefaultOutputDevice(&playbackID) != noErr) { | ||||
jack_error("Cannot open default output device"); | jack_error("Cannot open default output device"); | ||||
return -1; | |||||
goto built_in; | |||||
} | } | ||||
} | } | ||||
if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) | |||||
return -1; | |||||
if (captureID > 0 && playbackID > 0) { | |||||
if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) { | |||||
goto built_in; | |||||
} | |||||
} else { | |||||
jack_error("Cannot use default input/output"); | |||||
goto built_in; | |||||
} | |||||
} | } | ||||
} | } | ||||
return 0; | |||||
built_in: | |||||
// Aggregate built-in input and output | |||||
AudioDeviceID captureID = GetDeviceIDFromName("Built-in Input"); | |||||
AudioDeviceID playbackID = GetDeviceIDFromName("Built-in Output"); | |||||
if (captureID > 0 && playbackID > 0) { | |||||
if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) { | |||||
return -1; | |||||
} | |||||
} else { | |||||
jack_error("Cannot aggregate built-in input and output"); | |||||
return -1; | |||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -676,14 +750,16 @@ int JackCoreAudioAdapter::SetupChannels(bool capturing, | |||||
if (inchannels > in_nChannels) { | if (inchannels > in_nChannels) { | ||||
jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels); | jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels); | ||||
if (strict) | |||||
if (strict) { | |||||
return -1; | return -1; | ||||
} | |||||
} | } | ||||
if (outchannels > out_nChannels) { | if (outchannels > out_nChannels) { | ||||
jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels); | jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels); | ||||
if (strict) | |||||
if (strict) { | |||||
return -1; | return -1; | ||||
} | |||||
} | } | ||||
if (inchannels == -1) { | if (inchannels == -1) { | ||||
@@ -785,8 +861,9 @@ int JackCoreAudioAdapter::SetupBuffers(int inchannels) | |||||
void JackCoreAudioAdapter::DisposeBuffers() | void JackCoreAudioAdapter::DisposeBuffers() | ||||
{ | { | ||||
if (fInputData) { | if (fInputData) { | ||||
for (int i = 0; i < fCaptureChannels; i++) | |||||
for (int i = 0; i < fCaptureChannels; i++) { | |||||
free(fInputData->mBuffers[i].mData); | free(fInputData->mBuffers[i].mData); | ||||
} | |||||
free(fInputData); | free(fInputData); | ||||
fInputData = 0; | fInputData = 0; | ||||
} | } | ||||
@@ -901,7 +978,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||||
} | } | ||||
// Setup channel map | // Setup channel map | ||||
if (capturing && inchannels > 0 && inchannels < in_nChannels) { | |||||
if (capturing && inchannels > 0 && inchannels <= in_nChannels) { | |||||
SInt32 chanArr[in_nChannels]; | SInt32 chanArr[in_nChannels]; | ||||
for (int i = 0; i < in_nChannels; i++) { | for (int i = 0; i < in_nChannels; i++) { | ||||
chanArr[i] = -1; | chanArr[i] = -1; | ||||
@@ -917,7 +994,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||||
} | } | ||||
} | } | ||||
if (playing && outchannels > 0 && outchannels < out_nChannels) { | |||||
if (playing && outchannels > 0 && outchannels <= out_nChannels) { | |||||
SInt32 chanArr[out_nChannels]; | SInt32 chanArr[out_nChannels]; | ||||
for (int i = 0; i < out_nChannels; i++) { | for (int i = 0; i < out_nChannels; i++) { | ||||
chanArr[i] = -1; | chanArr[i] = -1; | ||||
@@ -1284,8 +1361,9 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||||
vector<CFStringRef> captureDeviceUID; | vector<CFStringRef> captureDeviceUID; | ||||
for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | ||||
CFStringRef ref = GetDeviceName(captureDeviceID[i]); | CFStringRef ref = GetDeviceName(captureDeviceID[i]); | ||||
if (ref == NULL) | |||||
if (ref == NULL) { | |||||
return -1; | return -1; | ||||
} | |||||
captureDeviceUID.push_back(ref); | captureDeviceUID.push_back(ref); | ||||
// input sub-devices in this example, so append the sub-device's UID to the CFArray | // input sub-devices in this example, so append the sub-device's UID to the CFArray | ||||
CFArrayAppendValue(subDevicesArray, ref); | CFArrayAppendValue(subDevicesArray, ref); | ||||
@@ -1294,8 +1372,9 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||||
vector<CFStringRef> playbackDeviceUID; | vector<CFStringRef> playbackDeviceUID; | ||||
for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | ||||
CFStringRef ref = GetDeviceName(playbackDeviceID[i]); | CFStringRef ref = GetDeviceName(playbackDeviceID[i]); | ||||
if (ref == NULL) | |||||
if (ref == NULL) { | |||||
return -1; | return -1; | ||||
} | |||||
playbackDeviceUID.push_back(ref); | playbackDeviceUID.push_back(ref); | ||||
// output sub-devices in this example, so append the sub-device's UID to the CFArray | // output sub-devices in this example, so append the sub-device's UID to the CFArray | ||||
CFArrayAppendValue(subDevicesArray, ref); | CFArrayAppendValue(subDevicesArray, ref); | ||||
@@ -1421,8 +1500,9 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||||
CFRelease(aggDeviceDict); | CFRelease(aggDeviceDict); | ||||
CFRelease(subDevicesArray); | CFRelease(subDevicesArray); | ||||
if (subDevicesArrayClock) | |||||
if (subDevicesArrayClock) { | |||||
CFRelease(subDevicesArrayClock); | CFRelease(subDevicesArrayClock); | ||||
} | |||||
// release the device UID | // release the device UID | ||||
for (UInt32 i = 0; i < captureDeviceUID.size(); i++) { | for (UInt32 i = 0; i < captureDeviceUID.size(); i++) { | ||||
@@ -1479,23 +1559,112 @@ int JackCoreAudioAdapter::Close() | |||||
DisposeBuffers(); | DisposeBuffers(); | ||||
CloseAUHAL(); | CloseAUHAL(); | ||||
RemoveListeners(); | RemoveListeners(); | ||||
if (fPluginID > 0) | |||||
if (fPluginID > 0) { | |||||
DestroyAggregateDevice(); | DestroyAggregateDevice(); | ||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackCoreAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) { | |||||
JackAudioAdapterInterface::SetHostSampleRate ( sample_rate ); | |||||
int JackCoreAudioAdapter::SetSampleRate(jack_nframes_t sample_rate) | |||||
{ | |||||
JackAudioAdapterInterface::SetHostSampleRate(sample_rate); | |||||
Close(); | Close(); | ||||
return Open(); | return Open(); | ||||
} | } | ||||
int JackCoreAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) { | |||||
JackAudioAdapterInterface::SetHostBufferSize ( buffer_size ); | |||||
int JackCoreAudioAdapter::SetBufferSize(jack_nframes_t buffer_size) | |||||
{ | |||||
JackAudioAdapterInterface::SetHostBufferSize(buffer_size); | |||||
Close(); | Close(); | ||||
return Open(); | return Open(); | ||||
} | } | ||||
OSStatus JackCoreAudioAdapter::GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies) | |||||
{ | |||||
OSStatus err = noErr; | |||||
UInt32 outSize1, outSize2, outSize3; | |||||
Boolean outWritable; | |||||
err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable); | |||||
if (err == noErr) { | |||||
int stream_count = outSize1 / sizeof(UInt32); | |||||
AudioStreamID streamIDs[stream_count]; | |||||
AudioBufferList bufferList[stream_count]; | |||||
UInt32 streamLatency; | |||||
outSize2 = sizeof(UInt32); | |||||
err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs); | |||||
if (err != noErr) { | |||||
jack_error("GetStreamLatencies kAudioDevicePropertyStreams err = %d", err); | |||||
return err; | |||||
} | |||||
err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable); | |||||
if (err != noErr) { | |||||
jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err); | |||||
return err; | |||||
} | |||||
for (int i = 0; i < stream_count; i++) { | |||||
err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency); | |||||
if (err != noErr) { | |||||
jack_error("GetStreamLatencies kAudioStreamPropertyLatency err = %d", err); | |||||
return err; | |||||
} | |||||
err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList); | |||||
if (err != noErr) { | |||||
jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err); | |||||
return err; | |||||
} | |||||
// Push 'channel' time the stream latency | |||||
for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) { | |||||
latencies.push_back(streamLatency); | |||||
} | |||||
} | |||||
} | |||||
return err; | |||||
} | |||||
int JackCoreAudioAdapter::GetLatency(int port_index, bool input) | |||||
{ | |||||
UInt32 size = sizeof(UInt32); | |||||
UInt32 value1 = 0; | |||||
UInt32 value2 = 0; | |||||
OSStatus err = AudioDeviceGetProperty(fDeviceID, 0, input, kAudioDevicePropertyLatency, &size, &value1); | |||||
if (err != noErr) { | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
} | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, input, kAudioDevicePropertySafetyOffset, &size, &value2); | |||||
if (err != noErr) { | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
} | |||||
// TODO : add stream latency | |||||
return value1 + value2 + fAdaptedBufferSize; | |||||
} | |||||
int JackCoreAudioAdapter::GetInputLatency(int port_index) | |||||
{ | |||||
if (port_index < int(fInputLatencies.size())) { | |||||
return GetLatency(port_index, true) + fInputLatencies[port_index]; | |||||
} else { | |||||
// No stream latency | |||||
return GetLatency(port_index, true); | |||||
} | |||||
} | |||||
int JackCoreAudioAdapter::GetOutputLatency(int port_index) | |||||
{ | |||||
if (port_index < int(fOutputLatencies.size())) { | |||||
return GetLatency(port_index, false) + fOutputLatencies[port_index]; | |||||
} else { | |||||
// No stream latency | |||||
return GetLatency(port_index, false); | |||||
} | |||||
} | |||||
} // namespace | } // namespace | ||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
@@ -1513,8 +1682,8 @@ extern "C" | |||||
value.i = -1; | value.i = -1; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamInt, &value, NULL, "Maximum number of channels", "Maximum number of channels. If -1, max possible number of channels will be used"); | jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamInt, &value, NULL, "Maximum number of channels", "Maximum number of channels. If -1, max possible number of channels will be used"); | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used"); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used"); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used"); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used"); | |||||
value.str[0] = 0; | value.str[0] = 0; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL); | ||||
@@ -41,7 +41,7 @@ typedef UInt8 CAAudioHardwareDeviceSectionID; | |||||
#define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF) | #define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF) | ||||
#define WAIT_COUNTER 60 | #define WAIT_COUNTER 60 | ||||
/*! | /*! | ||||
\brief Audio adapter using CoreAudio API. | \brief Audio adapter using CoreAudio API. | ||||
*/ | */ | ||||
@@ -53,16 +53,19 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface | |||||
AudioUnit fAUHAL; | AudioUnit fAUHAL; | ||||
AudioBufferList* fInputData; | AudioBufferList* fInputData; | ||||
char fCaptureUID[256]; | char fCaptureUID[256]; | ||||
char fPlaybackUID[256]; | char fPlaybackUID[256]; | ||||
bool fCapturing; | bool fCapturing; | ||||
bool fPlaying; | bool fPlaying; | ||||
AudioDeviceID fDeviceID; // Used "duplex" device | AudioDeviceID fDeviceID; // Used "duplex" device | ||||
AudioObjectID fPluginID; // Used for aggregate device | AudioObjectID fPluginID; // Used for aggregate device | ||||
vector<int> fInputLatencies; | |||||
vector<int> fOutputLatencies; | |||||
bool fState; | bool fState; | ||||
AudioUnitRenderActionFlags* fActionFags; | AudioUnitRenderActionFlags* fActionFags; | ||||
@@ -93,13 +96,14 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface | |||||
OSStatus GetDefaultInputDevice(AudioDeviceID* id); | OSStatus GetDefaultInputDevice(AudioDeviceID* id); | ||||
OSStatus GetDefaultOutputDevice(AudioDeviceID* id); | OSStatus GetDefaultOutputDevice(AudioDeviceID* id); | ||||
OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name); | OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name); | ||||
AudioDeviceID GetDeviceIDFromName(const char* name); | |||||
// Setup | // Setup | ||||
OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | ||||
OSStatus CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | OSStatus CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | ||||
OSStatus DestroyAggregateDevice(); | OSStatus DestroyAggregateDevice(); | ||||
bool IsAggregateDevice(AudioDeviceID device); | bool IsAggregateDevice(AudioDeviceID device); | ||||
int SetupDevices(const char* capture_driver_uid, | int SetupDevices(const char* capture_driver_uid, | ||||
const char* playback_driver_uid, | const char* playback_driver_uid, | ||||
char* capture_driver_name, | char* capture_driver_name, | ||||
@@ -126,14 +130,17 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface | |||||
int SetupBufferSize(jack_nframes_t buffer_size); | int SetupBufferSize(jack_nframes_t buffer_size); | ||||
int SetupSampleRate(jack_nframes_t samplerate); | int SetupSampleRate(jack_nframes_t samplerate); | ||||
int SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate); | int SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate); | ||||
int SetupBuffers(int inchannels); | int SetupBuffers(int inchannels); | ||||
void DisposeBuffers(); | void DisposeBuffers(); | ||||
void CloseAUHAL(); | void CloseAUHAL(); | ||||
int AddListeners(); | int AddListeners(); | ||||
void RemoveListeners(); | void RemoveListeners(); | ||||
int GetLatency(int port_index, bool input); | |||||
OSStatus GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies); | |||||
public: | public: | ||||
JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params); | JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params); | ||||
@@ -146,8 +153,12 @@ class JackCoreAudioAdapter : public JackAudioAdapterInterface | |||||
virtual int SetSampleRate(jack_nframes_t sample_rate); | virtual int SetSampleRate(jack_nframes_t sample_rate); | ||||
virtual int SetBufferSize(jack_nframes_t buffer_size); | virtual int SetBufferSize(jack_nframes_t buffer_size); | ||||
virtual int GetInputLatency(int port_index); | |||||
virtual int GetOutputLatency(int port_index); | |||||
}; | }; | ||||
} | |||||
} // end of namepace | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" | extern "C" | ||||
@@ -203,16 +203,16 @@ static void ParseChannelList(const string& list, vector<int>& result) | |||||
} | } | ||||
} | } | ||||
OSStatus JackCoreAudioDriver::Render(void *inRefCon, | |||||
AudioUnitRenderActionFlags *ioActionFlags, | |||||
const AudioTimeStamp *inTimeStamp, | |||||
OSStatus JackCoreAudioDriver::Render(void* inRefCon, | |||||
AudioUnitRenderActionFlags* ioActionFlags, | |||||
const AudioTimeStamp* inTimeStamp, | |||||
UInt32 inBusNumber, | UInt32 inBusNumber, | ||||
UInt32 inNumberFrames, | UInt32 inNumberFrames, | ||||
AudioBufferList *ioData) | |||||
AudioBufferList* ioData) | |||||
{ | { | ||||
JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon; | JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon; | ||||
driver->fActionFags = ioActionFlags; | driver->fActionFags = ioActionFlags; | ||||
driver->fCurrentTime = (AudioTimeStamp *)inTimeStamp; | |||||
driver->fCurrentTime = inTimeStamp; | |||||
driver->fDriverOutputData = ioData; | driver->fDriverOutputData = ioData; | ||||
// Setup threaded based log function et get RT thread parameters once... | // Setup threaded based log function et get RT thread parameters once... | ||||
@@ -475,7 +475,7 @@ OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id) | |||||
} | } | ||||
if (inDefault == 0) { | if (inDefault == 0) { | ||||
jack_error("Error : input device is 0, please select a correct one !!"); | |||||
jack_error("Error: default input device is 0, please select a correct one !!"); | |||||
return -1; | return -1; | ||||
} | } | ||||
jack_log("GetDefaultInputDevice: input = %ld ", inDefault); | jack_log("GetDefaultInputDevice: input = %ld ", inDefault); | ||||
@@ -494,7 +494,7 @@ OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id) | |||||
} | } | ||||
if (outDefault == 0) { | if (outDefault == 0) { | ||||
jack_error("Error : output device is 0, please select a correct one !!"); | |||||
jack_error("Error: default output device is 0, please select a correct one !!"); | |||||
return -1; | return -1; | ||||
} | } | ||||
jack_log("GetDefaultOutputDevice: output = %ld", outDefault); | jack_log("GetDefaultOutputDevice: output = %ld", outDefault); | ||||
@@ -511,17 +511,65 @@ OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID id, char* name) | |||||
OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput) | OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput) | ||||
{ | { | ||||
OSStatus err = noErr; | OSStatus err = noErr; | ||||
UInt32 outSize; | |||||
UInt32 outSize; | |||||
Boolean outWritable; | Boolean outWritable; | ||||
channelCount = 0; | channelCount = 0; | ||||
err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable); | err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable); | ||||
if (err == noErr) { | if (err == noErr) { | ||||
AudioBufferList bufferList[outSize]; | |||||
int stream_count = outSize / sizeof(AudioBufferList); | |||||
AudioBufferList bufferList[stream_count]; | |||||
err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList); | err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList); | ||||
if (err == noErr) { | if (err == noErr) { | ||||
for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++) { | |||||
for (uint i = 0; i < bufferList->mNumberBuffers; i++) { | |||||
channelCount += bufferList->mBuffers[i].mNumberChannels; | channelCount += bufferList->mBuffers[i].mNumberChannels; | ||||
//jack_info("GetTotalChannels stream = %d channels = %d", i, bufferList->mBuffers[i].mNumberChannels); | |||||
} | |||||
} | |||||
} | |||||
return err; | |||||
} | |||||
OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies) | |||||
{ | |||||
OSStatus err = noErr; | |||||
UInt32 outSize1, outSize2, outSize3; | |||||
Boolean outWritable; | |||||
err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable); | |||||
if (err == noErr) { | |||||
int stream_count = outSize1 / sizeof(UInt32); | |||||
AudioStreamID streamIDs[stream_count]; | |||||
AudioBufferList bufferList[stream_count]; | |||||
UInt32 streamLatency; | |||||
outSize2 = sizeof(UInt32); | |||||
err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs); | |||||
if (err != noErr) { | |||||
jack_error("GetStreamLatencies kAudioDevicePropertyStreams err = %d", err); | |||||
return err; | |||||
} | |||||
err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable); | |||||
if (err != noErr) { | |||||
jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err); | |||||
return err; | |||||
} | |||||
for (int i = 0; i < stream_count; i++) { | |||||
err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency); | |||||
if (err != noErr) { | |||||
jack_error("GetStreamLatencies kAudioStreamPropertyLatency err = %d", err); | |||||
return err; | |||||
} | |||||
err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList); | |||||
if (err != noErr) { | |||||
jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err); | |||||
return err; | |||||
} | |||||
// Push 'channel' time the stream latency | |||||
for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) { | |||||
latencies.push_back(streamLatency); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -1787,49 +1835,69 @@ void JackCoreAudioDriver::UpdateLatencies() | |||||
{ | { | ||||
UInt32 size; | UInt32 size; | ||||
OSStatus err; | OSStatus err; | ||||
jack_latency_range_t range; | |||||
range.max = fEngineControl->fBufferSize; | |||||
range.min = fEngineControl->fBufferSize; | |||||
jack_latency_range_t input_range; | |||||
jack_latency_range_t output_range; | |||||
jack_latency_range_t monitor_range; | |||||
// Get Input latency | |||||
size = sizeof(UInt32); | |||||
UInt32 value1 = 0; | |||||
UInt32 value2 = 0; | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1); | |||||
if (err != noErr) { | |||||
jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
} | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2); | |||||
if (err != noErr) { | |||||
jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
} | |||||
input_range.min = input_range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency; | |||||
// Get input stream latencies | |||||
vector<int> input_latencies; | |||||
err = GetStreamLatencies(fDeviceID, true, input_latencies); | |||||
for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
size = sizeof(UInt32); | |||||
UInt32 value1 = 0; | |||||
UInt32 value2 = 0; | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1); | |||||
if (err != noErr) { | if (err != noErr) { | ||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
} | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2); | |||||
if (err != noErr) { | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
input_range.min += input_latencies[i]; | |||||
input_range.max += input_latencies[i]; | |||||
} | } | ||||
fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range); | |||||
} | |||||
range.min = range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency; | |||||
fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
// Get Output latency | |||||
size = sizeof(UInt32); | |||||
value1 = 0; | |||||
value2 = 0; | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1); | |||||
if (err != noErr) { | |||||
jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
} | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2); | |||||
if (err != noErr) { | |||||
jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
} | } | ||||
// Get output stream latencies | |||||
vector<int> output_latencies; | |||||
err = GetStreamLatencies(fDeviceID, false, output_latencies); | |||||
// Add more latency if "async" mode is used... | |||||
output_range.min = output_range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) | |||||
? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency; | |||||
for (int i = 0; i < fPlaybackChannels; i++) { | for (int i = 0; i < fPlaybackChannels; i++) { | ||||
size = sizeof(UInt32); | |||||
UInt32 value1 = 0; | |||||
UInt32 value2 = 0; | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1); | |||||
if (err != noErr) { | if (err != noErr) { | ||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
output_range.min += output_latencies[i]; | |||||
output_range.max += output_latencies[i]; | |||||
} | } | ||||
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2); | |||||
if (err != noErr) { | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
} | |||||
// Add more latency if "async" mode is used... | |||||
range.min = range.max | |||||
= fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency; | |||||
fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &range); | |||||
fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range); | |||||
// Monitor port | // Monitor port | ||||
if (fWithMonitorPorts) { | if (fWithMonitorPorts) { | ||||
range.min = range.max = fEngineControl->fBufferSize; | |||||
fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
monitor_range.min = monitor_range.max = fEngineControl->fBufferSize; | |||||
fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -64,7 +64,7 @@ class JackCoreAudioDriver : public JackAudioDriver | |||||
AudioObjectID fPluginID; // Used for aggregate device | AudioObjectID fPluginID; // Used for aggregate device | ||||
AudioUnitRenderActionFlags* fActionFags; | AudioUnitRenderActionFlags* fActionFags; | ||||
AudioTimeStamp* fCurrentTime; | |||||
const AudioTimeStamp* fCurrentTime; | |||||
bool fState; | bool fState; | ||||
bool fHogged; | bool fHogged; | ||||
@@ -107,6 +107,7 @@ class JackCoreAudioDriver : public JackAudioDriver | |||||
OSStatus GetDefaultOutputDevice(AudioDeviceID* id); | OSStatus GetDefaultOutputDevice(AudioDeviceID* id); | ||||
OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name); | OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name); | ||||
OSStatus GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput); | OSStatus GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput); | ||||
OSStatus GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies); | |||||
// Setup | // Setup | ||||
OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | ||||
@@ -24,12 +24,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
//utility ********************************************************************************************************* | //utility ********************************************************************************************************* | ||||
int GetHostName ( char * name, int size ) | |||||
int GetHostName(char * name, int size) | |||||
{ | { | ||||
if ( gethostname ( name, size ) == SOCKET_ERROR ) | |||||
{ | |||||
jack_error ( "Can't get 'hostname' : %s", strerror ( NET_ERROR_CODE ) ); | |||||
strcpy ( name, "default" ); | |||||
if (gethostname(name, size) == SOCKET_ERROR) { | |||||
jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE)); | |||||
strcpy(name, "default"); | |||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
} | } | ||||
return 0; | return 0; | ||||
@@ -42,29 +41,29 @@ namespace Jack | |||||
fPort = 0; | fPort = 0; | ||||
fTimeOut = 0; | fTimeOut = 0; | ||||
fSendAddr.sin_family = AF_INET; | fSendAddr.sin_family = AF_INET; | ||||
fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||||
memset ( &fSendAddr.sin_zero, 0, 8 ); | |||||
fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY); | |||||
memset(&fSendAddr.sin_zero, 0, 8); | |||||
fRecvAddr.sin_family = AF_INET; | fRecvAddr.sin_family = AF_INET; | ||||
fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||||
memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||||
fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY); | |||||
memset(&fRecvAddr.sin_zero, 0, 8); | |||||
} | } | ||||
JackNetUnixSocket::JackNetUnixSocket ( const char* ip, int port ) | |||||
JackNetUnixSocket::JackNetUnixSocket(const char* ip, int port) | |||||
{ | { | ||||
fSockfd = 0; | fSockfd = 0; | ||||
fPort = port; | fPort = port; | ||||
fTimeOut = 0; | fTimeOut = 0; | ||||
fSendAddr.sin_family = AF_INET; | fSendAddr.sin_family = AF_INET; | ||||
fSendAddr.sin_port = htons ( port ); | |||||
inet_aton ( ip, &fSendAddr.sin_addr ); | |||||
memset ( &fSendAddr.sin_zero, 0, 8 ); | |||||
fSendAddr.sin_port = htons(port); | |||||
inet_aton(ip, &fSendAddr.sin_addr); | |||||
memset(&fSendAddr.sin_zero, 0, 8); | |||||
fRecvAddr.sin_family = AF_INET; | fRecvAddr.sin_family = AF_INET; | ||||
fRecvAddr.sin_port = htons ( port ); | |||||
fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||||
memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||||
fRecvAddr.sin_port = htons(port); | |||||
fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY); | |||||
memset(&fRecvAddr.sin_zero, 0, 8); | |||||
} | } | ||||
JackNetUnixSocket::JackNetUnixSocket ( const JackNetUnixSocket& socket ) | |||||
JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket& socket) | |||||
{ | { | ||||
fSockfd = 0; | fSockfd = 0; | ||||
fTimeOut = 0; | fTimeOut = 0; | ||||
@@ -78,10 +77,9 @@ namespace Jack | |||||
Close(); | Close(); | ||||
} | } | ||||
JackNetUnixSocket& JackNetUnixSocket::operator= ( const JackNetUnixSocket& socket ) | |||||
JackNetUnixSocket& JackNetUnixSocket::operator=(const JackNetUnixSocket& socket) | |||||
{ | { | ||||
if ( this != &socket ) | |||||
{ | |||||
if (this != &socket) { | |||||
fSockfd = 0; | fSockfd = 0; | ||||
fPort = socket.fPort; | fPort = socket.fPort; | ||||
fSendAddr = socket.fSendAddr; | fSendAddr = socket.fSendAddr; | ||||
@@ -93,84 +91,106 @@ namespace Jack | |||||
//socket*********************************************************************************************************** | //socket*********************************************************************************************************** | ||||
int JackNetUnixSocket::NewSocket() | int JackNetUnixSocket::NewSocket() | ||||
{ | { | ||||
if ( fSockfd ) | |||||
{ | |||||
if (fSockfd) { | |||||
Close(); | Close(); | ||||
Reset(); | Reset(); | ||||
} | } | ||||
fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 ); | |||||
fSockfd = socket(AF_INET, SOCK_DGRAM, 0); | |||||
/* Enable address reuse */ | /* Enable address reuse */ | ||||
int res, on = 1; | int res, on = 1; | ||||
if ((res = setsockopt( fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) { | |||||
if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) { | |||||
StrError(NET_ERROR_CODE); | StrError(NET_ERROR_CODE); | ||||
} | } | ||||
return fSockfd; | return fSockfd; | ||||
} | } | ||||
bool JackNetUnixSocket::IsLocal(char* ip) | |||||
{ | |||||
if (strcmp(ip, "127.0.0.1") == 0) { | |||||
return true; | |||||
} | |||||
char host_name[32]; | |||||
gethostname(host_name, sizeof(host_name)); | |||||
struct hostent* host = gethostbyname(host_name); | |||||
if (host) { | |||||
for (int i = 0; host->h_addr_list[i] != 0; ++i) { | |||||
struct in_addr addr; | |||||
memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr)); | |||||
if (strcmp(inet_ntoa(addr), ip) == 0) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} else { | |||||
return false; | |||||
} | |||||
} | |||||
int JackNetUnixSocket::Bind() | int JackNetUnixSocket::Bind() | ||||
{ | { | ||||
return bind ( fSockfd, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), sizeof ( socket_address_t ) ); | |||||
return bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t)); | |||||
} | } | ||||
int JackNetUnixSocket::BindWith ( const char* ip ) | |||||
int JackNetUnixSocket::BindWith(const char* ip) | |||||
{ | { | ||||
int addr_conv = inet_aton ( ip, &fRecvAddr.sin_addr ); | |||||
if ( addr_conv < 0 ) | |||||
int addr_conv = inet_aton(ip, &fRecvAddr.sin_addr); | |||||
if (addr_conv < 0) | |||||
return addr_conv; | return addr_conv; | ||||
return Bind(); | return Bind(); | ||||
} | } | ||||
int JackNetUnixSocket::BindWith ( int port ) | |||||
int JackNetUnixSocket::BindWith(int port) | |||||
{ | { | ||||
fRecvAddr.sin_port = htons ( port ); | |||||
fRecvAddr.sin_port = htons(port); | |||||
return Bind(); | return Bind(); | ||||
} | } | ||||
int JackNetUnixSocket::Connect() | int JackNetUnixSocket::Connect() | ||||
{ | { | ||||
return connect ( fSockfd, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) ); | |||||
return connect(fSockfd, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t)); | |||||
} | } | ||||
int JackNetUnixSocket::ConnectTo ( const char* ip ) | |||||
int JackNetUnixSocket::ConnectTo(const char* ip) | |||||
{ | { | ||||
int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); | |||||
if ( addr_conv < 0 ) | |||||
int addr_conv = inet_aton(ip, &fSendAddr.sin_addr); | |||||
if (addr_conv < 0) | |||||
return addr_conv; | return addr_conv; | ||||
return Connect(); | return Connect(); | ||||
} | } | ||||
void JackNetUnixSocket::Close() | void JackNetUnixSocket::Close() | ||||
{ | { | ||||
if ( fSockfd ) | |||||
close ( fSockfd ); | |||||
if (fSockfd) | |||||
close(fSockfd); | |||||
fSockfd = 0; | fSockfd = 0; | ||||
} | } | ||||
void JackNetUnixSocket::Reset() | void JackNetUnixSocket::Reset() | ||||
{ | { | ||||
fSendAddr.sin_family = AF_INET; | fSendAddr.sin_family = AF_INET; | ||||
fSendAddr.sin_port = htons ( fPort ); | |||||
fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||||
memset ( &fSendAddr.sin_zero, 0, 8 ); | |||||
fSendAddr.sin_port = htons(fPort); | |||||
fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY); | |||||
memset(&fSendAddr.sin_zero, 0, 8); | |||||
fRecvAddr.sin_family = AF_INET; | fRecvAddr.sin_family = AF_INET; | ||||
fRecvAddr.sin_port = htons ( fPort ); | |||||
fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); | |||||
memset ( &fRecvAddr.sin_zero, 0, 8 ); | |||||
fRecvAddr.sin_port = htons(fPort); | |||||
fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY); | |||||
memset(&fRecvAddr.sin_zero, 0, 8); | |||||
} | } | ||||
bool JackNetUnixSocket::IsSocket() | bool JackNetUnixSocket::IsSocket() | ||||
{ | { | ||||
return ( fSockfd ) ? true : false; | |||||
return(fSockfd) ? true : false; | |||||
} | } | ||||
//IP/PORT*********************************************************************************************************** | //IP/PORT*********************************************************************************************************** | ||||
void JackNetUnixSocket::SetPort ( int port ) | |||||
void JackNetUnixSocket::SetPort(int port) | |||||
{ | { | ||||
fPort = port; | fPort = port; | ||||
fSendAddr.sin_port = htons ( port ); | |||||
fRecvAddr.sin_port = htons ( port ); | |||||
fSendAddr.sin_port = htons(port); | |||||
fRecvAddr.sin_port = htons(port); | |||||
} | } | ||||
int JackNetUnixSocket::GetPort() | int JackNetUnixSocket::GetPort() | ||||
@@ -179,54 +199,54 @@ namespace Jack | |||||
} | } | ||||
//address*********************************************************************************************************** | //address*********************************************************************************************************** | ||||
int JackNetUnixSocket::SetAddress ( const char* ip, int port ) | |||||
int JackNetUnixSocket::SetAddress(const char* ip, int port) | |||||
{ | { | ||||
int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); | |||||
if ( addr_conv < 0 ) | |||||
int addr_conv = inet_aton(ip, &fSendAddr.sin_addr); | |||||
if (addr_conv < 0) | |||||
return addr_conv; | return addr_conv; | ||||
fSendAddr.sin_port = htons ( port ); | |||||
fSendAddr.sin_port = htons(port); | |||||
return 0; | return 0; | ||||
} | } | ||||
char* JackNetUnixSocket::GetSendIP() | char* JackNetUnixSocket::GetSendIP() | ||||
{ | { | ||||
return inet_ntoa ( fSendAddr.sin_addr ); | |||||
return inet_ntoa(fSendAddr.sin_addr); | |||||
} | } | ||||
char* JackNetUnixSocket::GetRecvIP() | char* JackNetUnixSocket::GetRecvIP() | ||||
{ | { | ||||
return inet_ntoa ( fRecvAddr.sin_addr ); | |||||
return inet_ntoa(fRecvAddr.sin_addr); | |||||
} | } | ||||
//utility************************************************************************************************************ | //utility************************************************************************************************************ | ||||
int JackNetUnixSocket::GetName ( char* name ) | |||||
int JackNetUnixSocket::GetName(char* name) | |||||
{ | { | ||||
return gethostname ( name, 255 ); | |||||
return gethostname(name, 255); | |||||
} | } | ||||
int JackNetUnixSocket::JoinMCastGroup ( const char* ip ) | |||||
int JackNetUnixSocket::JoinMCastGroup(const char* ip) | |||||
{ | { | ||||
struct ip_mreq multicast_req; | struct ip_mreq multicast_req; | ||||
inet_aton ( ip, &multicast_req.imr_multiaddr ); | |||||
multicast_req.imr_interface.s_addr = htonl ( INADDR_ANY ); | |||||
return SetOption ( IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof ( multicast_req ) ); | |||||
inet_aton(ip, &multicast_req.imr_multiaddr); | |||||
multicast_req.imr_interface.s_addr = htonl(INADDR_ANY); | |||||
return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req)); | |||||
} | } | ||||
//options************************************************************************************************************ | //options************************************************************************************************************ | ||||
int JackNetUnixSocket::SetOption ( int level, int optname, const void* optval, socklen_t optlen ) | |||||
int JackNetUnixSocket::SetOption(int level, int optname, const void* optval, socklen_t optlen) | |||||
{ | { | ||||
return setsockopt ( fSockfd, level, optname, optval, optlen ); | |||||
return setsockopt(fSockfd, level, optname, optval, optlen); | |||||
} | } | ||||
int JackNetUnixSocket::GetOption ( int level, int optname, void* optval, socklen_t* optlen ) | |||||
int JackNetUnixSocket::GetOption(int level, int optname, void* optval, socklen_t* optlen) | |||||
{ | { | ||||
return getsockopt ( fSockfd, level, optname, optval, optlen ); | |||||
return getsockopt(fSockfd, level, optname, optval, optlen); | |||||
} | } | ||||
//timeout************************************************************************************************************ | //timeout************************************************************************************************************ | ||||
#if defined(__sun__) || defined(sun) | #if defined(__sun__) || defined(sun) | ||||
int JackNetUnixSocket::SetTimeOut ( int us ) | |||||
int JackNetUnixSocket::SetTimeOut(int us) | |||||
{ | { | ||||
int flags; | int flags; | ||||
fTimeOut = us; | fTimeOut = us; | ||||
@@ -261,7 +281,7 @@ namespace Jack | |||||
do { | do { | ||||
res = select(fSockfd + 1, &fdset, NULL, NULL, &tv); | res = select(fSockfd + 1, &fdset, NULL, NULL, &tv); | ||||
} while (res < 0 && errno == EINTR); | |||||
} while(res < 0 && errno == EINTR); | |||||
if (res < 0) { | if (res < 0) { | ||||
return res; | return res; | ||||
@@ -290,7 +310,7 @@ namespace Jack | |||||
do { | do { | ||||
res = select(fSockfd + 1, NULL, &fdset, NULL, &tv); | res = select(fSockfd + 1, NULL, &fdset, NULL, &tv); | ||||
} while (res < 0 && errno == EINTR); | |||||
} while(res < 0 && errno == EINTR); | |||||
if (res < 0) { | if (res < 0) { | ||||
return res; | return res; | ||||
@@ -304,30 +324,27 @@ namespace Jack | |||||
} | } | ||||
#else | #else | ||||
int JackNetUnixSocket::SetTimeOut ( int us ) | |||||
int JackNetUnixSocket::SetTimeOut(int us) | |||||
{ | { | ||||
jack_log ( "JackNetUnixSocket::SetTimeout %d usecs", us ); | |||||
jack_log("JackNetUnixSocket::SetTimeout %d usecs", us); | |||||
//negative timeout, or exceding 10s, return | //negative timeout, or exceding 10s, return | ||||
if ( ( us < 0 ) || ( us > 10000000 ) ) | |||||
if ((us < 0) ||(us > 10000000)) | |||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
struct timeval timeout; | struct timeval timeout; | ||||
//less than 1sec | //less than 1sec | ||||
if ( us < 1000000 ) | |||||
{ | |||||
if (us < 1000000) { | |||||
timeout.tv_sec = 0; | timeout.tv_sec = 0; | ||||
timeout.tv_usec = us; | timeout.tv_usec = us; | ||||
} | |||||
} else { | |||||
//more than 1sec | //more than 1sec | ||||
else | |||||
{ | |||||
float sec = static_cast<float> ( us ) / 1000000.f; | |||||
timeout.tv_sec = ( int ) sec; | |||||
float usec = ( sec - static_cast<float> ( timeout.tv_sec ) ) * 1000000; | |||||
timeout.tv_usec = ( int ) usec; | |||||
float sec = static_cast<float>(us) / 1000000.f; | |||||
timeout.tv_sec =(int) sec; | |||||
float usec = (sec - static_cast<float>(timeout.tv_sec)) * 1000000; | |||||
timeout.tv_usec =(int) usec; | |||||
} | } | ||||
return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) ); | |||||
return SetOption(SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); | |||||
} | } | ||||
#endif | #endif | ||||
@@ -335,72 +352,72 @@ namespace Jack | |||||
int JackNetUnixSocket::SetLocalLoop() | int JackNetUnixSocket::SetLocalLoop() | ||||
{ | { | ||||
char disable = 0; | char disable = 0; | ||||
return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) ); | |||||
return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable)); | |||||
} | } | ||||
//network operations************************************************************************************************** | //network operations************************************************************************************************** | ||||
int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags ) | |||||
int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags) | |||||
{ | { | ||||
#if defined(__sun__) || defined(sun) | #if defined(__sun__) || defined(sun) | ||||
if (WaitWrite() < 0) | if (WaitWrite() < 0) | ||||
return -1; | return -1; | ||||
#endif | #endif | ||||
return sendto ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) ); | |||||
return sendto(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t)); | |||||
} | } | ||||
int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ) | |||||
int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip) | |||||
{ | { | ||||
int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); | |||||
if ( addr_conv < 1 ) | |||||
int addr_conv = inet_aton(ip, &fSendAddr.sin_addr); | |||||
if (addr_conv < 1) | |||||
return addr_conv; | return addr_conv; | ||||
#if defined(__sun__) || defined(sun) | #if defined(__sun__) || defined(sun) | ||||
if (WaitWrite() < 0) | if (WaitWrite() < 0) | ||||
return -1; | return -1; | ||||
#endif | #endif | ||||
return SendTo ( buffer, nbytes, flags ); | |||||
return SendTo(buffer, nbytes, flags); | |||||
} | } | ||||
int JackNetUnixSocket::Send ( const void* buffer, size_t nbytes, int flags ) | |||||
int JackNetUnixSocket::Send(const void* buffer, size_t nbytes, int flags) | |||||
{ | { | ||||
#if defined(__sun__) || defined(sun) | #if defined(__sun__) || defined(sun) | ||||
if (WaitWrite() < 0) | if (WaitWrite() < 0) | ||||
return -1; | return -1; | ||||
#endif | #endif | ||||
return send ( fSockfd, buffer, nbytes, flags ); | |||||
return send(fSockfd, buffer, nbytes, flags); | |||||
} | } | ||||
int JackNetUnixSocket::RecvFrom ( void* buffer, size_t nbytes, int flags ) | |||||
int JackNetUnixSocket::RecvFrom(void* buffer, size_t nbytes, int flags) | |||||
{ | { | ||||
socklen_t addr_len = sizeof ( socket_address_t ); | |||||
socklen_t addr_len = sizeof(socket_address_t); | |||||
#if defined(__sun__) || defined(sun) | #if defined(__sun__) || defined(sun) | ||||
if (WaitRead() < 0) | if (WaitRead() < 0) | ||||
return -1; | return -1; | ||||
#endif | #endif | ||||
return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), &addr_len ); | |||||
return recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fRecvAddr), &addr_len); | |||||
} | } | ||||
int JackNetUnixSocket::Recv ( void* buffer, size_t nbytes, int flags ) | |||||
int JackNetUnixSocket::Recv(void* buffer, size_t nbytes, int flags) | |||||
{ | { | ||||
#if defined(__sun__) || defined(sun) | #if defined(__sun__) || defined(sun) | ||||
if (WaitRead() < 0) | if (WaitRead() < 0) | ||||
return -1; | return -1; | ||||
#endif | #endif | ||||
return recv ( fSockfd, buffer, nbytes, flags ); | |||||
return recv(fSockfd, buffer, nbytes, flags); | |||||
} | } | ||||
int JackNetUnixSocket::CatchHost ( void* buffer, size_t nbytes, int flags ) | |||||
int JackNetUnixSocket::CatchHost(void* buffer, size_t nbytes, int flags) | |||||
{ | { | ||||
socklen_t addr_len = sizeof ( socket_address_t ); | |||||
socklen_t addr_len = sizeof(socket_address_t); | |||||
#if defined(__sun__) || defined(sun) | #if defined(__sun__) || defined(sun) | ||||
if (WaitRead() < 0) | if (WaitRead() < 0) | ||||
return -1; | return -1; | ||||
#endif | #endif | ||||
return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), &addr_len ); | |||||
return recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), &addr_len); | |||||
} | } | ||||
net_error_t JackNetUnixSocket::GetError() | net_error_t JackNetUnixSocket::GetError() | ||||
{ | { | ||||
switch ( errno ) | |||||
switch(errno) | |||||
{ | { | ||||
case EAGAIN: | case EAGAIN: | ||||
case ETIMEDOUT: | case ETIMEDOUT: | ||||
@@ -55,53 +55,55 @@ namespace Jack | |||||
public: | public: | ||||
JackNetUnixSocket(); | JackNetUnixSocket(); | ||||
JackNetUnixSocket ( const char* ip, int port ); | |||||
JackNetUnixSocket ( const JackNetUnixSocket& ); | |||||
JackNetUnixSocket(const char* ip, int port); | |||||
JackNetUnixSocket(const JackNetUnixSocket&); | |||||
~JackNetUnixSocket(); | ~JackNetUnixSocket(); | ||||
JackNetUnixSocket& operator= ( const JackNetUnixSocket& socket ); | |||||
JackNetUnixSocket& operator=(const JackNetUnixSocket& socket); | |||||
//socket management | //socket management | ||||
int NewSocket(); | int NewSocket(); | ||||
int Bind(); | int Bind(); | ||||
int BindWith ( const char* ip ); | |||||
int BindWith ( int port ); | |||||
int BindWith(const char* ip); | |||||
int BindWith(int port); | |||||
int Connect(); | int Connect(); | ||||
int ConnectTo ( const char* ip ); | |||||
int ConnectTo(const char* ip); | |||||
void Close(); | void Close(); | ||||
void Reset(); | void Reset(); | ||||
bool IsSocket(); | bool IsSocket(); | ||||
//IP/PORT management | //IP/PORT management | ||||
void SetPort ( int port ); | |||||
void SetPort(int port); | |||||
int GetPort(); | int GetPort(); | ||||
//address management | //address management | ||||
int SetAddress ( const char* ip, int port ); | |||||
int SetAddress(const char* ip, int port); | |||||
char* GetSendIP(); | char* GetSendIP(); | ||||
char* GetRecvIP(); | char* GetRecvIP(); | ||||
//utility | //utility | ||||
int GetName ( char* name ); | |||||
int JoinMCastGroup ( const char* mcast_ip ); | |||||
int GetName(char* name); | |||||
int JoinMCastGroup(const char* mcast_ip); | |||||
//options management | //options management | ||||
int SetOption ( int level, int optname, const void* optval, socklen_t optlen ); | |||||
int GetOption ( int level, int optname, void* optval, socklen_t* optlen ); | |||||
int SetOption(int level, int optname, const void* optval, socklen_t optlen); | |||||
int GetOption(int level, int optname, void* optval, socklen_t* optlen); | |||||
//timeout | //timeout | ||||
int SetTimeOut ( int us ); | |||||
int SetTimeOut(int us); | |||||
//disable local loop | //disable local loop | ||||
int SetLocalLoop(); | int SetLocalLoop(); | ||||
bool IsLocal(char* ip); | |||||
//network operations | //network operations | ||||
int SendTo ( const void* buffer, size_t nbytes, int flags ); | |||||
int SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip ); | |||||
int Send ( const void* buffer, size_t nbytes, int flags ); | |||||
int RecvFrom ( void* buffer, size_t nbytes, int flags ); | |||||
int Recv ( void* buffer, size_t nbytes, int flags ); | |||||
int CatchHost ( void* buffer, size_t nbytes, int flags ); | |||||
int SendTo(const void* buffer, size_t nbytes, int flags); | |||||
int SendTo(const void* buffer, size_t nbytes, int flags, const char* ip); | |||||
int Send(const void* buffer, size_t nbytes, int flags); | |||||
int RecvFrom(void* buffer, size_t nbytes, int flags); | |||||
int Recv(void* buffer, size_t nbytes, int flags); | |||||
int CatchHost(void* buffer, size_t nbytes, int flags); | |||||
//error management | //error management | ||||
net_error_t GetError(); | net_error_t GetError(); | ||||
@@ -652,10 +652,10 @@ extern "C" | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL); | ||||
value.ui = OSS_DRIVER_DEF_INS; | value.ui = OSS_DRIVER_DEF_INS; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL); | |||||
value.ui = OSS_DRIVER_DEF_OUTS; | value.ui = OSS_DRIVER_DEF_OUTS; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL); | |||||
value.i = false; | value.i = false; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusif (O_EXCL) access mode", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusif (O_EXCL) access mode", NULL); | ||||
@@ -76,9 +76,9 @@ MTDM::MTDM (void) : _cnt (0), _inv (0) | |||||
for (i = 0, F = _freq; i < 5; i++, F++) | for (i = 0, F = _freq; i < 5; i++, F++) | ||||
{ | { | ||||
F->p = 128; | |||||
F->xa = F->ya = 0.0f; | |||||
F->xf = F->yf = 0.0f; | |||||
F->p = 128; | |||||
F->xa = F->ya = 0.0f; | |||||
F->xf = F->yf = 0.0f; | |||||
} | } | ||||
} | } | ||||
@@ -91,28 +91,28 @@ int MTDM::process (size_t len, float *ip, float *op) | |||||
while (len--) | while (len--) | ||||
{ | { | ||||
vop = 0.0f; | vop = 0.0f; | ||||
vip = *ip++; | |||||
for (i = 0, F = _freq; i < 5; i++, F++) | |||||
{ | |||||
a = 2 * (float) M_PI * (F->p & 65535) / 65536.0; | |||||
F->p += F->f; | |||||
c = cosf (a); | |||||
s = -sinf (a); | |||||
vop += F->a * s; | |||||
F->xa += s * vip; | |||||
F->ya += c * vip; | |||||
} | |||||
*op++ = vop; | |||||
if (++_cnt == 16) | |||||
{ | |||||
for (i = 0, F = _freq; i < 5; i++, F++) | |||||
{ | |||||
F->xf += 1e-3f * (F->xa - F->xf + 1e-20); | |||||
F->yf += 1e-3f * (F->ya - F->yf + 1e-20); | |||||
F->xa = F->ya = 0.0f; | |||||
} | |||||
vip = *ip++; | |||||
for (i = 0, F = _freq; i < 5; i++, F++) | |||||
{ | |||||
a = 2 * (float) M_PI * (F->p & 65535) / 65536.0; | |||||
F->p += F->f; | |||||
c = cosf (a); | |||||
s = -sinf (a); | |||||
vop += F->a * s; | |||||
F->xa += s * vip; | |||||
F->ya += c * vip; | |||||
} | |||||
*op++ = vop; | |||||
if (++_cnt == 16) | |||||
{ | |||||
for (i = 0, F = _freq; i < 5; i++, F++) | |||||
{ | |||||
F->xf += 1e-3f * (F->xa - F->xf + 1e-20); | |||||
F->yf += 1e-3f * (F->ya - F->yf + 1e-20); | |||||
F->xa = F->ya = 0.0f; | |||||
} | |||||
_cnt = 0; | _cnt = 0; | ||||
} | |||||
} | |||||
} | } | ||||
return 0; | return 0; | ||||
@@ -133,17 +133,17 @@ int MTDM::resolve (void) | |||||
_err = 0.0; | _err = 0.0; | ||||
for (i = 0; i < 4; i++) | for (i = 0; i < 4; i++) | ||||
{ | { | ||||
F++; | |||||
p = atan2 (F->yf, F->xf) / (2 * M_PI) - d * F->f / f0; | |||||
F++; | |||||
p = atan2 (F->yf, F->xf) / (2 * M_PI) - d * F->f / f0; | |||||
if (_inv) p += 0.5f; | if (_inv) p += 0.5f; | ||||
p -= floor (p); | |||||
p *= 8; | |||||
k = (int)(floor (p + 0.5)); | |||||
e = fabs (p - k); | |||||
p -= floor (p); | |||||
p *= 8; | |||||
k = (int)(floor (p + 0.5)); | |||||
e = fabs (p - k); | |||||
if (e > _err) _err = e; | if (e > _err) _err = e; | ||||
if (e > 0.4) return 1; | if (e > 0.4) return 1; | ||||
d += m * (k & 7); | |||||
m *= 8; | |||||
d += m * (k & 7); | |||||
m *= 8; | |||||
} | } | ||||
_del = 16 * d; | _del = 16 * d; | ||||
@@ -246,7 +246,7 @@ int main (int ac, char *av []) | |||||
, mtdm._del, mtdm._del * t, | , mtdm._del, mtdm._del * t, | ||||
systemic_latency, systemic_latency/2); | systemic_latency, systemic_latency/2); | ||||
if (mtdm._err > 0.2) printf (" ??"); | if (mtdm._err > 0.2) printf (" ??"); | ||||
if (mtdm._inv) printf (" Inv"); | |||||
if (mtdm._inv) printf (" Inv"); | |||||
printf ("\n"); | printf ("\n"); | ||||
} | } | ||||
} | } | ||||
@@ -221,8 +221,8 @@ extern "C" | |||||
desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler); | desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler); | ||||
value.ui = 0; | value.ui = 0; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", NULL); | |||||
strcpy(value.str, "default input device"); | strcpy(value.str, "default input device"); | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set PortAudio device name", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set PortAudio device name", NULL); | ||||
@@ -28,15 +28,17 @@ PortAudioDevices::PortAudioDevices() | |||||
PaError err; | PaError err; | ||||
PaDeviceIndex id; | PaDeviceIndex id; | ||||
jack_log("Initializing PortAudio..."); | jack_log("Initializing PortAudio..."); | ||||
if ((err = Pa_Initialize() ) == paNoError) { | |||||
if ((err = Pa_Initialize()) == paNoError) { | |||||
fNumHostApi = Pa_GetHostApiCount(); | fNumHostApi = Pa_GetHostApiCount(); | ||||
fNumDevice = Pa_GetDeviceCount(); | fNumDevice = Pa_GetDeviceCount(); | ||||
fDeviceInfo = new PaDeviceInfo*[fNumDevice]; | fDeviceInfo = new PaDeviceInfo*[fNumDevice]; | ||||
for (id = 0; id < fNumDevice; id++) | |||||
for (id = 0; id < fNumDevice; id++) { | |||||
fDeviceInfo[id] = const_cast<PaDeviceInfo*>(Pa_GetDeviceInfo(id)); | fDeviceInfo[id] = const_cast<PaDeviceInfo*>(Pa_GetDeviceInfo(id)); | ||||
} | |||||
fHostName = new string[fNumHostApi]; | fHostName = new string[fNumHostApi]; | ||||
for (id = 0; id < fNumHostApi; id++) | |||||
fHostName[id] = string ( Pa_GetHostApiInfo(id)->name ); | |||||
for (id = 0; id < fNumHostApi; id++) { | |||||
fHostName[id] = string (Pa_GetHostApiInfo(id)->name); | |||||
} | |||||
} else { | } else { | ||||
jack_error("JackPortAudioDriver::Pa_Initialize error = %s", Pa_GetErrorText(err)); | jack_error("JackPortAudioDriver::Pa_Initialize error = %s", Pa_GetErrorText(err)); | ||||
} | } | ||||
@@ -56,70 +58,73 @@ PaDeviceIndex PortAudioDevices::GetNumDevice() | |||||
return fNumDevice; | return fNumDevice; | ||||
} | } | ||||
PaDeviceInfo* PortAudioDevices::GetDeviceInfo ( PaDeviceIndex id ) | |||||
PaDeviceInfo* PortAudioDevices::GetDeviceInfo(PaDeviceIndex id) | |||||
{ | { | ||||
return fDeviceInfo[id]; | return fDeviceInfo[id]; | ||||
} | } | ||||
string PortAudioDevices::GetDeviceName ( PaDeviceIndex id ) | |||||
string PortAudioDevices::GetDeviceName(PaDeviceIndex id) | |||||
{ | { | ||||
return string ( fDeviceInfo[id]->name ); | |||||
return string(fDeviceInfo[id]->name); | |||||
} | } | ||||
string PortAudioDevices::GetHostFromDevice ( PaDeviceInfo* device ) | |||||
string PortAudioDevices::GetHostFromDevice(PaDeviceInfo* device) | |||||
{ | { | ||||
return fHostName[device->hostApi]; | return fHostName[device->hostApi]; | ||||
} | } | ||||
string PortAudioDevices::GetHostFromDevice ( PaDeviceIndex id ) | |||||
string PortAudioDevices::GetHostFromDevice(PaDeviceIndex id) | |||||
{ | { | ||||
return fHostName[fDeviceInfo[id]->hostApi]; | return fHostName[fDeviceInfo[id]->hostApi]; | ||||
} | } | ||||
string PortAudioDevices::GetFullName ( PaDeviceIndex id ) | |||||
string PortAudioDevices::GetFullName(PaDeviceIndex id) | |||||
{ | { | ||||
string hostname = GetHostFromDevice ( id ); | |||||
string devicename = GetDeviceName ( id ); | |||||
string hostname = GetHostFromDevice(id); | |||||
string devicename = GetDeviceName(id); | |||||
//some hostname are quite long...use shortcuts | //some hostname are quite long...use shortcuts | ||||
if ( hostname.compare ( "Windows DirectSound" ) == 0 ) | |||||
hostname = string ( "DirectSound" ); | |||||
return ( hostname + "::" + devicename ); | |||||
if (hostname.compare("Windows DirectSound") == 0) { | |||||
hostname = string("DirectSound"); | |||||
} | |||||
return (hostname + "::" + devicename); | |||||
} | } | ||||
string PortAudioDevices::GetFullName ( std::string hostname, std::string devicename ) | |||||
string PortAudioDevices::GetFullName(std::string hostname, std::string devicename) | |||||
{ | { | ||||
//some hostname are quite long...use shortcuts | //some hostname are quite long...use shortcuts | ||||
if ( hostname.compare ( "Windows DirectSound" ) == 0 ) | |||||
hostname = string ( "DirectSound" ); | |||||
return ( hostname + "::" + devicename ); | |||||
if (hostname.compare("Windows DirectSound") == 0) { | |||||
hostname = string("DirectSound"); | |||||
} | |||||
return (hostname + "::" + devicename); | |||||
} | } | ||||
PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName ( string fullname, PaDeviceIndex& id, bool isInput ) | |||||
PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName (string fullname, PaDeviceIndex& id, bool isInput) | |||||
{ | { | ||||
PaDeviceInfo* ret = NULL; | PaDeviceInfo* ret = NULL; | ||||
//no driver to find | //no driver to find | ||||
if ( fullname.size() == 0 ) | |||||
if (fullname.size() == 0) { | |||||
return NULL; | return NULL; | ||||
} | |||||
//first get host and device names from fullname | //first get host and device names from fullname | ||||
string::size_type separator = fullname.find ( "::", 0 ); | |||||
if ( separator == 0 ) | |||||
string::size_type separator = fullname.find ("::", 0); | |||||
if (separator == 0) { | |||||
return NULL; | return NULL; | ||||
} | |||||
char* hostname = (char*)malloc(separator + 9); | char* hostname = (char*)malloc(separator + 9); | ||||
fill_n ( hostname, separator + 9, 0 ); | |||||
fullname.copy ( hostname, separator ); | |||||
fill_n (hostname, separator + 9, 0); | |||||
fullname.copy (hostname, separator); | |||||
//we need the entire hostname, replace shortcuts | //we need the entire hostname, replace shortcuts | ||||
if ( strcmp ( hostname, "DirectSound" ) == 0 ) | |||||
strcpy ( hostname, "Windows DirectSound" ); | |||||
string devicename = fullname.substr ( separator + 2 ); | |||||
if (strcmp (hostname, "DirectSound") == 0) { | |||||
strcpy (hostname, "Windows DirectSound"); | |||||
} | |||||
string devicename = fullname.substr (separator + 2); | |||||
//then find the corresponding device | //then find the corresponding device | ||||
for ( PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++ ) | |||||
{ | |||||
for (PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++) { | |||||
bool flag = (isInput) ? (fDeviceInfo[dev_id]->maxInputChannels > 0) : (fDeviceInfo[dev_id]->maxOutputChannels > 0); | bool flag = (isInput) ? (fDeviceInfo[dev_id]->maxInputChannels > 0) : (fDeviceInfo[dev_id]->maxOutputChannels > 0); | ||||
if ( ( GetHostFromDevice(dev_id).compare(hostname) == 0 ) | |||||
&& ( GetDeviceName(dev_id).compare(devicename) == 0 ) | |||||
&& flag ) | |||||
{ | |||||
if ((GetHostFromDevice(dev_id).compare(hostname) == 0) | |||||
&& (GetDeviceName(dev_id).compare(devicename) == 0) | |||||
&& flag) { | |||||
id = dev_id; | id = dev_id; | ||||
ret = fDeviceInfo[dev_id]; | ret = fDeviceInfo[dev_id]; | ||||
} | } | ||||
@@ -139,23 +144,16 @@ void PortAudioDevices::PrintSupportedStandardSampleRates(const PaStreamParameter | |||||
PaError err; | PaError err; | ||||
printCount = 0; | printCount = 0; | ||||
for (i = 0; standardSampleRates[i] > 0; i++) | |||||
{ | |||||
for (i = 0; standardSampleRates[i] > 0; i++) { | |||||
err = Pa_IsFormatSupported(inputParameters, outputParameters, standardSampleRates[i]); | err = Pa_IsFormatSupported(inputParameters, outputParameters, standardSampleRates[i]); | ||||
if (err == paFormatIsSupported) | |||||
{ | |||||
if (printCount == 0) | |||||
{ | |||||
if (err == paFormatIsSupported) { | |||||
if (printCount == 0) { | |||||
jack_info("\t%8.2f", standardSampleRates[i]); | jack_info("\t%8.2f", standardSampleRates[i]); | ||||
printCount = 1; | printCount = 1; | ||||
} | |||||
else if (printCount == 4) | |||||
{ | |||||
} else if (printCount == 4) { | |||||
jack_info(",\n\t%8.2f", standardSampleRates[i]); | jack_info(",\n\t%8.2f", standardSampleRates[i]); | ||||
printCount = 1; | printCount = 1; | ||||
} | |||||
else | |||||
{ | |||||
} else { | |||||
jack_info(", %8.2f", standardSampleRates[i]); | jack_info(", %8.2f", standardSampleRates[i]); | ||||
++printCount; | ++printCount; | ||||
} | } | ||||
@@ -170,17 +168,18 @@ void PortAudioDevices::PrintSupportedStandardSampleRates(const PaStreamParameter | |||||
int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_input) | int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_input) | ||||
{ | { | ||||
string fullname = string ( devicename ); | |||||
PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id, true ); | |||||
if ( device ) | |||||
string fullname = string (devicename); | |||||
PaDeviceInfo* device = GetDeviceFromFullName (fullname, id, true); | |||||
if (device) { | |||||
max_input = device->maxInputChannels; | max_input = device->maxInputChannels; | ||||
else | |||||
{ | |||||
} else { | |||||
id = Pa_GetDefaultInputDevice(); | id = Pa_GetDefaultInputDevice(); | ||||
if ( fullname.size() ) | |||||
if (fullname.size()) { | |||||
jack_error("Can't open %s, PortAudio will use default input device.", devicename); | jack_error("Can't open %s, PortAudio will use default input device.", devicename); | ||||
if ( id == paNoDevice ) | |||||
} | |||||
if (id == paNoDevice) { | |||||
return -1; | return -1; | ||||
} | |||||
max_input = GetDeviceInfo(id)->maxInputChannels; | max_input = GetDeviceInfo(id)->maxInputChannels; | ||||
} | } | ||||
return id; | return id; | ||||
@@ -188,17 +187,18 @@ int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceInd | |||||
int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_output) | int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_output) | ||||
{ | { | ||||
string fullname = string ( devicename ); | |||||
PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id, false ); | |||||
if ( device ) | |||||
string fullname = string (devicename); | |||||
PaDeviceInfo* device = GetDeviceFromFullName (fullname, id, false); | |||||
if (device) { | |||||
max_output = device->maxOutputChannels; | max_output = device->maxOutputChannels; | ||||
else | |||||
{ | |||||
} else { | |||||
id = Pa_GetDefaultOutputDevice(); | id = Pa_GetDefaultOutputDevice(); | ||||
if ( fullname.size() ) | |||||
if (fullname.size()) { | |||||
jack_error("Can't open %s, PortAudio will use default output device.", devicename); | jack_error("Can't open %s, PortAudio will use default output device.", devicename); | ||||
if ( id == paNoDevice ) | |||||
} | |||||
if (id == paNoDevice) { | |||||
return -1; | return -1; | ||||
} | |||||
max_output = GetDeviceInfo(id)->maxOutputChannels; | max_output = GetDeviceInfo(id)->maxOutputChannels; | ||||
} | } | ||||
return id; | return id; | ||||
@@ -208,57 +208,50 @@ void PortAudioDevices::DisplayDevicesNames() | |||||
{ | { | ||||
PaDeviceIndex id; | PaDeviceIndex id; | ||||
PaStreamParameters inputParameters, outputParameters; | PaStreamParameters inputParameters, outputParameters; | ||||
jack_info ( "********************** Devices list, %d detected **********************", fNumDevice ); | |||||
jack_info ("********************** Devices list, %d detected **********************", fNumDevice); | |||||
for ( id = 0; id < fNumDevice; id++ ) | |||||
{ | |||||
jack_info ( "-------- device #%d ------------------------------------------------", id ); | |||||
for (id = 0; id < fNumDevice; id++) { | |||||
jack_info ("-------- device #%d ------------------------------------------------", id); | |||||
if ( id == Pa_GetDefaultInputDevice() ) | |||||
{ | |||||
if (id == Pa_GetDefaultInputDevice()) { | |||||
jack_info("[ Default Input ]"); | jack_info("[ Default Input ]"); | ||||
} | |||||
else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi)->defaultInputDevice ) | |||||
{ | |||||
const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi ); | |||||
jack_info ( "[ Default %s Input ]", host_info->name ); | |||||
} else if (id == Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi)->defaultInputDevice) { | |||||
const PaHostApiInfo *host_info = Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi); | |||||
jack_info("[ Default %s Input ]", host_info->name); | |||||
} | } | ||||
if ( id == Pa_GetDefaultOutputDevice() ) | |||||
{ | |||||
jack_info ( "[ Default Output ]" ); | |||||
} | |||||
else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi )->defaultOutputDevice ) | |||||
{ | |||||
const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi ); | |||||
jack_info ( "[ Default %s Output ]", host_info->name ); | |||||
if (id == Pa_GetDefaultOutputDevice()) { | |||||
jack_info ("[ Default Output ]"); | |||||
} else if (id == Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi)->defaultOutputDevice) { | |||||
const PaHostApiInfo *host_info = Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi); | |||||
jack_info("[ Default %s Output ]", host_info->name); | |||||
} | } | ||||
/* print device info fields */ | /* print device info fields */ | ||||
jack_info ( "Name = %s", GetFullName ( id ).c_str() ); | |||||
jack_info ( "Max inputs = %d", fDeviceInfo[id]->maxInputChannels ); | |||||
jack_info ( "Max outputs = %d", fDeviceInfo[id]->maxOutputChannels ); | |||||
jack_info ("Name = %s", GetFullName (id).c_str()); | |||||
jack_info ("Max inputs = %d", fDeviceInfo[id]->maxInputChannels); | |||||
jack_info ("Max outputs = %d", fDeviceInfo[id]->maxOutputChannels); | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
/* ASIO specific latency information */ | /* ASIO specific latency information */ | ||||
if ( Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO ) | |||||
{ | |||||
if (Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO) { | |||||
long minLatency, maxLatency, preferredLatency, granularity; | long minLatency, maxLatency, preferredLatency, granularity; | ||||
PaAsio_GetAvailableLatencyValues ( id, &minLatency, &maxLatency, &preferredLatency, &granularity ); | |||||
PaAsio_GetAvailableLatencyValues (id, &minLatency, &maxLatency, &preferredLatency, &granularity); | |||||
jack_info ( "ASIO minimum buffer size = %ld", minLatency ); | |||||
jack_info ( "ASIO maximum buffer size = %ld", maxLatency ); | |||||
jack_info ( "ASIO preferred buffer size = %ld", preferredLatency ); | |||||
jack_info ("ASIO minimum buffer size = %ld", minLatency); | |||||
jack_info ("ASIO maximum buffer size = %ld", maxLatency); | |||||
jack_info ("ASIO preferred buffer size = %ld", preferredLatency); | |||||
if ( granularity == -1 ) | |||||
jack_info ( "ASIO buffer granularity = power of 2" ); | |||||
else | |||||
jack_info ( "ASIO buffer granularity = %ld", granularity ); | |||||
if (granularity == -1) { | |||||
jack_info ("ASIO buffer granularity = power of 2"); | |||||
} else { | |||||
jack_info ("ASIO buffer granularity = %ld", granularity); | |||||
} | |||||
} | } | ||||
#endif | #endif | ||||
jack_info ( "Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate ); | |||||
jack_info ("Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate); | |||||
/* poll for standard sample rates */ | /* poll for standard sample rates */ | ||||
inputParameters.device = id; | inputParameters.device = id; | ||||
@@ -273,20 +266,24 @@ void PortAudioDevices::DisplayDevicesNames() | |||||
outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */ | outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */ | ||||
outputParameters.hostApiSpecificStreamInfo = NULL; | outputParameters.hostApiSpecificStreamInfo = NULL; | ||||
} | } | ||||
jack_info ( "**************************** End of list ****************************" ); | |||||
jack_info("**************************** End of list ****************************"); | |||||
} | } | ||||
bool PortAudioDevices::IsDuplex ( PaDeviceIndex id ) | |||||
bool PortAudioDevices::IsDuplex (PaDeviceIndex id) | |||||
{ | { | ||||
//does the device has in and out facilities | //does the device has in and out facilities | ||||
if ( fDeviceInfo[id]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels ) | |||||
if (fDeviceInfo[id]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels) { | |||||
return true; | return true; | ||||
} | |||||
//else is another complementary device ? (search in devices with the same name) | //else is another complementary device ? (search in devices with the same name) | ||||
for ( PaDeviceIndex i = 0; i < fNumDevice; i++ ) | |||||
if ( ( i != id ) && ( GetDeviceName ( i ) == GetDeviceName ( id ) ) ) | |||||
if ( ( fDeviceInfo[i]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels ) | |||||
|| ( fDeviceInfo[i]->maxOutputChannels && fDeviceInfo[id]->maxInputChannels ) ) | |||||
for (PaDeviceIndex i = 0; i < fNumDevice; i++) { | |||||
if ((i != id) && (GetDeviceName (i) == GetDeviceName (id))) { | |||||
if ((fDeviceInfo[i]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels) { | |||||
|| (fDeviceInfo[i]->maxOutputChannels && fDeviceInfo[id]->maxInputChannels)) | |||||
return true; | return true; | ||||
} | |||||
} | |||||
} | |||||
//then the device isn't full duplex | //then the device isn't full duplex | ||||
return false; | return false; | ||||
} | } | ||||
@@ -33,11 +33,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
class PortAudioDevices | class PortAudioDevices | ||||
{ | { | ||||
private: | private: | ||||
PaHostApiIndex fNumHostApi; //number of hosts | PaHostApiIndex fNumHostApi; //number of hosts | ||||
PaDeviceIndex fNumDevice; //number of devices | PaDeviceIndex fNumDevice; //number of devices | ||||
PaDeviceInfo** fDeviceInfo; //array of device info | PaDeviceInfo** fDeviceInfo; //array of device info | ||||
std::string* fHostName; //array of host names (matched with host id's) | std::string* fHostName; //array of host names (matched with host id's) | ||||
public: | public: | ||||
PortAudioDevices(); | PortAudioDevices(); | ||||
~PortAudioDevices(); | ~PortAudioDevices(); | ||||
@@ -48,12 +51,13 @@ class PortAudioDevices | |||||
std::string GetHostFromDevice(PaDeviceIndex id); | std::string GetHostFromDevice(PaDeviceIndex id); | ||||
std::string GetFullName(PaDeviceIndex id); | std::string GetFullName(PaDeviceIndex id); | ||||
std::string GetFullName(std::string hostname, std::string devicename); | std::string GetFullName(std::string hostname, std::string devicename); | ||||
PaDeviceInfo* GetDeviceFromFullName(std::string fullname, PaDeviceIndex& id, bool isInput ); | |||||
PaDeviceInfo* GetDeviceFromFullName(std::string fullname, PaDeviceIndex& id, bool isInput); | |||||
void PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters); | void PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters); | ||||
int GetInputDeviceFromName(const char* name, PaDeviceIndex& device, int& in_max); | int GetInputDeviceFromName(const char* name, PaDeviceIndex& device, int& in_max); | ||||
int GetOutputDeviceFromName(const char* name, PaDeviceIndex& device, int& out_max); | int GetOutputDeviceFromName(const char* name, PaDeviceIndex& device, int& out_max); | ||||
void DisplayDevicesNames(); | void DisplayDevicesNames(); | ||||
bool IsDuplex ( PaDeviceIndex id ); | |||||
bool IsDuplex(PaDeviceIndex id); | |||||
}; | }; | ||||
#endif | #endif |
@@ -31,225 +31,263 @@ using namespace std; | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer, | |||||
unsigned long framesPerBuffer, | |||||
const PaStreamCallbackTimeInfo* timeInfo, | |||||
PaStreamCallbackFlags statusFlags, | |||||
void* userData) | |||||
{ | |||||
JackPortAudioDriver* driver = (JackPortAudioDriver*)userData; | |||||
driver->fInputBuffer = (jack_default_audio_sample_t**)inputBuffer; | |||||
driver->fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer; | |||||
MMCSSAcquireRealTime(GetCurrentThread()); | |||||
if (statusFlags) { | |||||
if (statusFlags & paOutputUnderflow) | |||||
jack_error("JackPortAudioDriver::Render paOutputUnderflow"); | |||||
if (statusFlags & paInputUnderflow) | |||||
jack_error("JackPortAudioDriver::Render paInputUnderflow"); | |||||
if (statusFlags & paOutputOverflow) | |||||
jack_error("JackPortAudioDriver::Render paOutputOverflow"); | |||||
if (statusFlags & paInputOverflow) | |||||
jack_error("JackPortAudioDriver::Render paInputOverflow"); | |||||
if (statusFlags & paPrimingOutput) | |||||
jack_error("JackPortAudioDriver::Render paOutputUnderflow"); | |||||
if (statusFlags != paPrimingOutput) { | |||||
jack_time_t cur_time = GetMicroSeconds(); | |||||
driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing... | |||||
} | |||||
} | |||||
// Setup threadded based log function | |||||
set_threaded_log_function(); | |||||
driver->CycleTakeBeginTime(); | |||||
return (driver->Process() == 0) ? paContinue : paAbort; | |||||
int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer, | |||||
unsigned long framesPerBuffer, | |||||
const PaStreamCallbackTimeInfo* timeInfo, | |||||
PaStreamCallbackFlags statusFlags, | |||||
void* userData) | |||||
{ | |||||
JackPortAudioDriver* driver = (JackPortAudioDriver*)userData; | |||||
driver->fInputBuffer = (jack_default_audio_sample_t**)inputBuffer; | |||||
driver->fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer; | |||||
MMCSSAcquireRealTime(GetCurrentThread()); | |||||
if (statusFlags) { | |||||
if (statusFlags & paOutputUnderflow) | |||||
jack_error("JackPortAudioDriver::Render paOutputUnderflow"); | |||||
if (statusFlags & paInputUnderflow) | |||||
jack_error("JackPortAudioDriver::Render paInputUnderflow"); | |||||
if (statusFlags & paOutputOverflow) | |||||
jack_error("JackPortAudioDriver::Render paOutputOverflow"); | |||||
if (statusFlags & paInputOverflow) | |||||
jack_error("JackPortAudioDriver::Render paInputOverflow"); | |||||
if (statusFlags & paPrimingOutput) | |||||
jack_error("JackPortAudioDriver::Render paOutputUnderflow"); | |||||
if (statusFlags != paPrimingOutput) { | |||||
jack_time_t cur_time = GetMicroSeconds(); | |||||
driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing... | |||||
} | |||||
} | } | ||||
int JackPortAudioDriver::Read() | |||||
{ | |||||
for (int i = 0; i < fCaptureChannels; i++) | |||||
memcpy(GetInputBuffer(i), fInputBuffer[i], sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | |||||
return 0; | |||||
} | |||||
// Setup threadded based log function | |||||
set_threaded_log_function(); | |||||
driver->CycleTakeBeginTime(); | |||||
return (driver->Process() == 0) ? paContinue : paAbort; | |||||
} | |||||
int JackPortAudioDriver::Write() | |||||
{ | |||||
for (int i = 0; i < fPlaybackChannels; i++) | |||||
memcpy(fOutputBuffer[i], GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | |||||
return 0; | |||||
int JackPortAudioDriver::Read() | |||||
{ | |||||
for (int i = 0; i < fCaptureChannels; i++) { | |||||
memcpy(GetInputBuffer(i), fInputBuffer[i], sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | |||||
} | } | ||||
return 0; | |||||
} | |||||
PaError JackPortAudioDriver::OpenStream(jack_nframes_t buffer_size) | |||||
{ | |||||
PaStreamParameters inputParameters; | |||||
PaStreamParameters outputParameters; | |||||
// Update parameters | |||||
inputParameters.device = fInputDevice; | |||||
inputParameters.channelCount = fCaptureChannels; | |||||
inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output | |||||
inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO | |||||
? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency | |||||
: 0; | |||||
inputParameters.hostApiSpecificStreamInfo = NULL; | |||||
outputParameters.device = fOutputDevice; | |||||
outputParameters.channelCount = fPlaybackChannels; | |||||
outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output | |||||
outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO | |||||
? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency | |||||
: 0; | |||||
outputParameters.hostApiSpecificStreamInfo = NULL; | |||||
return Pa_OpenStream(&fStream, | |||||
(fInputDevice == paNoDevice) ? 0 : &inputParameters, | |||||
(fOutputDevice == paNoDevice) ? 0 : &outputParameters, | |||||
fEngineControl->fSampleRate, | |||||
buffer_size, | |||||
paNoFlag, // Clipping is on... | |||||
Render, | |||||
this); | |||||
int JackPortAudioDriver::Write() | |||||
{ | |||||
for (int i = 0; i < fPlaybackChannels; i++) { | |||||
memcpy(fOutputBuffer[i], GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | |||||
} | } | ||||
return 0; | |||||
} | |||||
int JackPortAudioDriver::Open(jack_nframes_t buffer_size, | |||||
jack_nframes_t samplerate, | |||||
bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_uid, | |||||
const char* playback_driver_uid, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) | |||||
{ | |||||
int in_max = 0; | |||||
int out_max = 0; | |||||
PaError err = paNoError; | |||||
PaError JackPortAudioDriver::OpenStream(jack_nframes_t buffer_size) | |||||
{ | |||||
PaStreamParameters inputParameters; | |||||
PaStreamParameters outputParameters; | |||||
// Update parameters | |||||
inputParameters.device = fInputDevice; | |||||
inputParameters.channelCount = fCaptureChannels; | |||||
inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output | |||||
inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO | |||||
? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency | |||||
: 0; | |||||
inputParameters.hostApiSpecificStreamInfo = NULL; | |||||
outputParameters.device = fOutputDevice; | |||||
outputParameters.channelCount = fPlaybackChannels; | |||||
outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output | |||||
outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO | |||||
? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency | |||||
: 0; | |||||
outputParameters.hostApiSpecificStreamInfo = NULL; | |||||
return Pa_OpenStream(&fStream, | |||||
(fInputDevice == paNoDevice) ? 0 : &inputParameters, | |||||
(fOutputDevice == paNoDevice) ? 0 : &outputParameters, | |||||
fEngineControl->fSampleRate, | |||||
buffer_size, | |||||
paNoFlag, // Clipping is on... | |||||
Render, | |||||
this); | |||||
} | |||||
jack_log("JackPortAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s samplerate = %ld", | |||||
buffer_size, inchannels, outchannels, capture_driver_uid, playback_driver_uid, samplerate); | |||||
void JackPortAudioDriver::UpdateLatencies() | |||||
{ | |||||
jack_latency_range_t input_range; | |||||
jack_latency_range_t output_range; | |||||
jack_latency_range_t monitor_range; | |||||
const PaStreamInfo* info = Pa_GetStreamInfo(fStream); | |||||
assert(info); | |||||
// Generic JackAudioDriver Open | |||||
if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) | |||||
return -1; | |||||
for (int i = 0; i < fCaptureChannels; i++) { | |||||
input_range.max = input_range.min = fEngineControl->fBufferSize + (info->inputLatency * fEngineControl->fSampleRate) + fCaptureLatency; | |||||
fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range); | |||||
} | |||||
//get devices | |||||
if (capturing) { | |||||
if (fPaDevices->GetInputDeviceFromName(capture_driver_uid, fInputDevice, in_max) < 0) | |||||
goto error; | |||||
for (int i = 0; i < fPlaybackChannels; i++) { | |||||
output_range.max = output_range.min = (info->outputLatency * fEngineControl->fSampleRate) + fPlaybackLatency; | |||||
if (fEngineControl->fSyncMode) { | |||||
output_range.max = output_range.min += fEngineControl->fBufferSizey; | |||||
} else { | |||||
output_range.max = output_range.min += fEngineControl->fBufferSize * 2; | |||||
} | } | ||||
if (playing) { | |||||
if (fPaDevices->GetOutputDeviceFromName(playback_driver_uid, fOutputDevice, out_max) < 0) | |||||
goto error; | |||||
fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range); | |||||
if (fWithMonitorPorts) { | |||||
monitor_range.min = monitor_range.max = fEngineControl->fBufferSize; | |||||
fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range); | |||||
} | } | ||||
} | |||||
} | |||||
jack_log("JackPortAudioDriver::Open fInputDevice = %d, fOutputDevice %d", fInputDevice, fOutputDevice); | |||||
int JackPortAudioDriver::Open(jack_nframes_t buffer_size, | |||||
jack_nframes_t samplerate, | |||||
bool capturing, | |||||
bool playing, | |||||
int inchannels, | |||||
int outchannels, | |||||
bool monitor, | |||||
const char* capture_driver_uid, | |||||
const char* playback_driver_uid, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency) | |||||
{ | |||||
int in_max = 0; | |||||
int out_max = 0; | |||||
PaError err = paNoError; | |||||
//default channels number required | |||||
if (inchannels == 0) { | |||||
jack_log("JackPortAudioDriver::Open setup max in channels = %ld", in_max); | |||||
inchannels = in_max; | |||||
} | |||||
if (outchannels == 0) { | |||||
jack_log("JackPortAudioDriver::Open setup max out channels = %ld", out_max); | |||||
outchannels = out_max; | |||||
} | |||||
fCaptureLatency = capture_latency; | |||||
fPlaybackLatency = playback_latency; | |||||
//too many channels required, take max available | |||||
if (inchannels > in_max) { | |||||
jack_error("This device has only %d available input channels.", in_max); | |||||
inchannels = in_max; | |||||
} | |||||
if (outchannels > out_max) { | |||||
jack_error("This device has only %d available output channels.", out_max); | |||||
outchannels = out_max; | |||||
} | |||||
jack_log("JackPortAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s samplerate = %ld", | |||||
buffer_size, inchannels, outchannels, capture_driver_uid, playback_driver_uid, samplerate); | |||||
// Core driver may have changed the in/out values | |||||
fCaptureChannels = inchannels; | |||||
fPlaybackChannels = outchannels; | |||||
// Generic JackAudioDriver Open | |||||
if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, | |||||
capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) { | |||||
return -1; | |||||
} | |||||
err = OpenStream(buffer_size); | |||||
if (err != paNoError) { | |||||
jack_error("Pa_OpenStream error %d = %s", err, Pa_GetErrorText(err)); | |||||
//get devices | |||||
if (capturing) { | |||||
if (fPaDevices->GetInputDeviceFromName(capture_driver_uid, fInputDevice, in_max) < 0) { | |||||
goto error; | goto error; | ||||
} | } | ||||
} | |||||
if (playing) { | |||||
if (fPaDevices->GetOutputDeviceFromName(playback_driver_uid, fOutputDevice, out_max) < 0) { | |||||
goto error; | |||||
} | |||||
} | |||||
jack_log("JackPortAudioDriver::Open fInputDevice = %d, fOutputDevice %d", fInputDevice, fOutputDevice); | |||||
//default channels number required | |||||
if (inchannels == 0) { | |||||
jack_log("JackPortAudioDriver::Open setup max in channels = %ld", in_max); | |||||
inchannels = in_max; | |||||
} | |||||
if (outchannels == 0) { | |||||
jack_log("JackPortAudioDriver::Open setup max out channels = %ld", out_max); | |||||
outchannels = out_max; | |||||
} | |||||
//too many channels required, take max available | |||||
if (inchannels > in_max) { | |||||
jack_error("This device has only %d available input channels.", in_max); | |||||
inchannels = in_max; | |||||
} | |||||
if (outchannels > out_max) { | |||||
jack_error("This device has only %d available output channels.", out_max); | |||||
outchannels = out_max; | |||||
} | |||||
// Core driver may have changed the in/out values | |||||
fCaptureChannels = inchannels; | |||||
fPlaybackChannels = outchannels; | |||||
err = OpenStream(buffer_size); | |||||
if (err != paNoError) { | |||||
jack_error("Pa_OpenStream error %d = %s", err, Pa_GetErrorText(err)); | |||||
goto error; | |||||
} | |||||
#ifdef __APPLE__ | #ifdef __APPLE__ | ||||
fEngineControl->fPeriod = fEngineControl->fPeriodUsecs * 1000; | |||||
fEngineControl->fComputation = 500 * 1000; | |||||
fEngineControl->fConstraint = fEngineControl->fPeriodUsecs * 1000; | |||||
fEngineControl->fPeriod = fEngineControl->fPeriodUsecs * 1000; | |||||
fEngineControl->fComputation = 500 * 1000; | |||||
fEngineControl->fConstraint = fEngineControl->fPeriodUsecs * 1000; | |||||
#endif | #endif | ||||
assert(strlen(capture_driver_uid) < JACK_CLIENT_NAME_SIZE); | |||||
assert(strlen(playback_driver_uid) < JACK_CLIENT_NAME_SIZE); | |||||
assert(strlen(capture_driver_uid) < JACK_CLIENT_NAME_SIZE); | |||||
assert(strlen(playback_driver_uid) < JACK_CLIENT_NAME_SIZE); | |||||
strcpy(fCaptureDriverName, capture_driver_uid); | |||||
strcpy(fPlaybackDriverName, playback_driver_uid); | |||||
strcpy(fCaptureDriverName, capture_driver_uid); | |||||
strcpy(fPlaybackDriverName, playback_driver_uid); | |||||
return 0; | |||||
return 0; | |||||
error: | error: | ||||
JackAudioDriver::Close(); | |||||
jack_error("Can't open default PortAudio device"); | |||||
return -1; | |||||
} | |||||
int JackPortAudioDriver::Close() | |||||
{ | |||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | |||||
JackAudioDriver::Close(); | |||||
jack_error("Can't open default PortAudio device"); | |||||
return -1; | |||||
} | |||||
jack_log("JackPortAudioDriver::Close"); | |||||
Pa_CloseStream(fStream); | |||||
return res; | |||||
} | |||||
int JackPortAudioDriver::Close() | |||||
{ | |||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | |||||
jack_log("JackPortAudioDriver::Close"); | |||||
Pa_CloseStream(fStream); | |||||
return res; | |||||
} | |||||
int JackPortAudioDriver::Start() | |||||
{ | |||||
jack_log("JackPortAudioDriver::Start"); | |||||
if (JackAudioDriver::Start() >= 0) { | |||||
PaError err = Pa_StartStream(fStream); | |||||
if (err == paNoError) { | |||||
return 0; | |||||
} | |||||
JackAudioDriver::Stop(); | |||||
int JackPortAudioDriver::Start() | |||||
{ | |||||
jack_log("JackPortAudioDriver::Start"); | |||||
if (JackAudioDriver::Start() >= 0) { | |||||
PaError err = Pa_StartStream(fStream); | |||||
if (err == paNoError) { | |||||
return 0; | |||||
} | } | ||||
return -1; | |||||
JackAudioDriver::Stop(); | |||||
} | } | ||||
return -1; | |||||
} | |||||
int JackPortAudioDriver::Stop() | |||||
{ | |||||
jack_log("JackPortAudioDriver::Stop"); | |||||
PaError err = Pa_StopStream(fStream); | |||||
int res = (err == paNoError) ? 0 : -1; | |||||
if (JackAudioDriver::Stop() < 0) { | |||||
res = -1; | |||||
} | |||||
return res; | |||||
int JackPortAudioDriver::Stop() | |||||
{ | |||||
jack_log("JackPortAudioDriver::Stop"); | |||||
PaError err = Pa_StopStream(fStream); | |||||
int res = (err == paNoError) ? 0 : -1; | |||||
if (JackAudioDriver::Stop() < 0) { | |||||
res = -1; | |||||
} | } | ||||
return res; | |||||
} | |||||
int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | |||||
{ | |||||
PaError err; | |||||
int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | |||||
{ | |||||
PaError err; | |||||
if ((err = Pa_CloseStream(fStream)) != paNoError) { | |||||
jack_error("Pa_CloseStream error = %s", Pa_GetErrorText(err)); | |||||
return -1; | |||||
} | |||||
if ((err = Pa_CloseStream(fStream)) != paNoError) { | |||||
jack_error("Pa_CloseStream error = %s", Pa_GetErrorText(err)); | |||||
return -1; | |||||
} | |||||
err = OpenStream(buffer_size); | |||||
if (err != paNoError) { | |||||
jack_error("Pa_OpenStream error %d = %s", err, Pa_GetErrorText(err)); | |||||
return -1; | |||||
} else { | |||||
JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails | |||||
return 0; | |||||
} | |||||
err = OpenStream(buffer_size); | |||||
if (err != paNoError) { | |||||
jack_error("Pa_OpenStream error %d = %s", err, Pa_GetErrorText(err)); | |||||
return -1; | |||||
} else { | |||||
JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails | |||||
return 0; | |||||
} | } | ||||
} | |||||
} // end of namespace | } // end of namespace | ||||
@@ -49,8 +49,8 @@ class JackPortAudioDriver : public JackMMCSS, public JackAudioDriver | |||||
PaStreamCallbackFlags statusFlags, | PaStreamCallbackFlags statusFlags, | ||||
void* userData); | void* userData); | ||||
void UpdateLatencies(); | |||||
PaError OpenStream(jack_nframes_t buffer_size); | PaError OpenStream(jack_nframes_t buffer_size); | ||||
void UpdateLatencies(); | |||||
public: | public: | ||||