Conflicts: common/JackControlAPI.cpptags/1.9.9.5
@@ -0,0 +1,4 @@ | |||||
build/ | |||||
man/*.1 | |||||
.waf* | |||||
.lock* |
@@ -36,6 +36,88 @@ John Emmas | |||||
Jackdmp changes log | Jackdmp changes log | ||||
--------------------------- | --------------------------- | ||||
2012-03-15 Stephane Letz <letz@grame.fr> | |||||
* POST_PACKED_STRUCTURE used for jack_latency_range_t type. | |||||
2012-03-09 Stephane Letz <letz@grame.fr> | |||||
* Remove JACK_32_64 flag, so POST_PACKED_STRUCTURE now always used. | |||||
2012-02-10 Stephane Letz <letz@grame.fr> | |||||
* Improve libjacknet master mode. | |||||
2012-02-09 Stephane Letz <letz@grame.fr> | |||||
* In control API, UNIX like sigset_t replaced by more abstract jackctl_sigmask_t * opaque struct. | |||||
2012-02-01 Stephane Letz <letz@grame.fr> | |||||
* Check server API callback from notification thread. | |||||
* Use a time-out in notification channel write function. | |||||
* Fix lock management in JackEngine. | |||||
2012-01-29 Stephane Letz <letz@grame.fr> | |||||
* A bit more robust JackMessageBuffer implementation (in progress). | |||||
2012-01-27 Stephane Letz <letz@grame.fr> | |||||
* Rename JackProcessSync in JackPosixProcessSync. | |||||
2012-01-26 Stephane Letz <letz@grame.fr> | |||||
* Add EndTime function (especially for Windows). | |||||
2012-01-25 Stephane Letz <letz@grame.fr> | |||||
* Fix NetJack2 initialisation bug. | |||||
2012-01-24 Stephane Letz <letz@grame.fr> | |||||
* Improve ShutDown in NetManager. | |||||
* Correct ShutDown in JackInternalClient and JackLibClient. | |||||
2012-01-20 Stephane Letz <letz@grame.fr> | |||||
* Experimental system port alias use in WIndows JackRouter. | |||||
2012-01-19 Stephane Letz <letz@grame.fr> | |||||
* Implement shutdown for in server clients. | |||||
* Better time-out management in NetJack2. | |||||
2012-01-13 Stephane Letz <letz@grame.fr> | |||||
* More robust server/client protocol. | |||||
2012-01-11 Stephane Letz <letz@grame.fr> | |||||
* Factorize code the server/client request in JackRequestDecoder class. | |||||
2012-01-06 Stephane Letz <letz@grame.fr> | |||||
* Cleanup drivers and internals loading code. | |||||
* jackctl_driver_params_parse API moved in public control.h. | |||||
* More general drivers/internals loading model on Windows. | |||||
2012-01-06 Stephane Letz <letz@grame.fr> | |||||
* Fix for compilation on Solaris. | |||||
2012-01-04 Stephane Letz <letz@grame.fr> | |||||
* Fix library symbols export issue. | |||||
2012-01-02 Stephane Letz <letz@grame.fr> | |||||
* Adrian Knoth fix in midiseq.c. | |||||
2011-12-20 Stephane Letz <letz@grame.fr> | |||||
* Version 1.9.9 started. | |||||
2011-11-25 Stephane Letz <letz@grame.fr> | 2011-11-25 Stephane Letz <letz@grame.fr> | ||||
* More robust dynamic port management in JACK/CoreMidi bridge. | * More robust dynamic port management in JACK/CoreMidi bridge. | ||||
@@ -0,0 +1,317 @@ | |||||
/* | |||||
Copyright (C) 2006 Jesse Chappell <jesse@essej.net> (AC3Jack) | |||||
Copyright (C) 2012 Grame | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation; either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include "JackAC3Encoder.h" | |||||
#include "JackError.h" | |||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#include <stdio.h> | |||||
#define max(x,y) (((x)>(y)) ? (x) : (y)) | |||||
#define min(x,y) (((x)<(y)) ? (x) : (y)) | |||||
namespace Jack | |||||
{ | |||||
#ifndef __ppc__ | |||||
JackAC3Encoder::JackAC3Encoder(const JackAC3EncoderParams& params) | |||||
{ | |||||
aften_set_defaults(&fAftenContext); | |||||
fAftenContext.channels = params.channels; | |||||
fAftenContext.samplerate = params.sample_rate; | |||||
fAftenContext.params.bitrate = params.bitrate; | |||||
int acmod = A52_ACMOD_MONO; | |||||
int lfe = params.lfe; | |||||
switch (params.channels) { | |||||
case 1: acmod = A52_ACMOD_MONO; break; | |||||
case 2: acmod = A52_ACMOD_STEREO; break; | |||||
case 3: acmod = A52_ACMOD_3_0; break; | |||||
case 4: acmod = A52_ACMOD_2_2; break; | |||||
case 5: acmod = A52_ACMOD_3_2; break; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
if (lfe) { | |||||
fAftenContext.channels += 1; | |||||
} | |||||
fAftenContext.acmod = acmod; | |||||
fAftenContext.lfe = lfe; | |||||
fAftenContext.sample_format = A52_SAMPLE_FMT_FLT; | |||||
fAftenContext.verbose = 1; | |||||
fAftenContext.system.n_threads = 1; | |||||
// create interleaved framebuffer for MAX_AC3_CHANNELS | |||||
fSampleBuffer = new float[MAX_AC3_CHANNELS * A52_SAMPLES_PER_FRAME]; | |||||
// create AC3 buffer | |||||
fAC3Buffer = new unsigned char[A52_MAX_CODED_FRAME_SIZE]; | |||||
memset(fAC3Buffer, 0, A52_MAX_CODED_FRAME_SIZE); | |||||
fZeroBuffer = new unsigned char[SPDIF_FRAME_SIZE]; | |||||
memset(fZeroBuffer, 0, SPDIF_FRAME_SIZE); | |||||
fRingBuffer = jack_ringbuffer_create(32768); | |||||
fOutSizeByte = 0; | |||||
fFramePos = 0; | |||||
fSampleRate = 0; | |||||
fByteRate = 0; | |||||
} | |||||
bool JackAC3Encoder::Init(jack_nframes_t sample_rate) | |||||
{ | |||||
fSampleRate = sample_rate; | |||||
fByteRate = fSampleRate * sizeof(short) * 2; | |||||
return (aften_encode_init(&fAftenContext) == 0); | |||||
} | |||||
JackAC3Encoder::~JackAC3Encoder() | |||||
{ | |||||
aften_encode_close(&fAftenContext); | |||||
delete [] fSampleBuffer; | |||||
delete [] fAC3Buffer; | |||||
delete [] fZeroBuffer; | |||||
if (fRingBuffer) { | |||||
jack_ringbuffer_free(fRingBuffer); | |||||
} | |||||
} | |||||
void JackAC3Encoder::Process(float** inputs_buffer, float** outputs_buffer, int nframes) | |||||
{ | |||||
// fill and process frame buffers as appropriate | |||||
jack_nframes_t frames_left = A52_SAMPLES_PER_FRAME - fFramePos; | |||||
jack_nframes_t offset = 0; | |||||
while (offset < nframes) | |||||
{ | |||||
if ((nframes - offset) >= frames_left) { | |||||
// copy only frames_left more data | |||||
jack_nframes_t pos = fFramePos * fAftenContext.channels; | |||||
for (jack_nframes_t spos = offset; spos < offset + frames_left; ++spos) { | |||||
for (size_t i = 0; i < fAftenContext.channels; ++i) { | |||||
fSampleBuffer[pos + i] = inputs_buffer[i][spos]; | |||||
} | |||||
pos += fAftenContext.channels; | |||||
} | |||||
// use interleaved version | |||||
int res = aften_encode_frame(&fAftenContext, fAC3Buffer + SPDIF_HEADER_SIZE, fSampleBuffer); | |||||
if (res < 0) { | |||||
jack_error("aften_encode_frame error !!"); | |||||
return; | |||||
} | |||||
fOutSizeByte = res; | |||||
FillSpdifHeader(fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE); | |||||
// push AC3 output to SPDIF ring buffer | |||||
float calc_ac3byterate = (fOutSizeByte * fSampleRate / (float) A52_SAMPLES_PER_FRAME); | |||||
jack_nframes_t silencebytes = (jack_nframes_t) (fOutSizeByte * (fByteRate / calc_ac3byterate)) - fOutSizeByte - SPDIF_HEADER_SIZE; | |||||
jack_ringbuffer_write(fRingBuffer, (const char *)fAC3Buffer, fOutSizeByte + SPDIF_HEADER_SIZE); | |||||
// write the proper remainder of zero padding (inefficient, should be memsetting) | |||||
jack_ringbuffer_write(fRingBuffer, (const char *)fZeroBuffer, silencebytes); | |||||
offset += frames_left; | |||||
frames_left = A52_SAMPLES_PER_FRAME; | |||||
fFramePos = 0; | |||||
} else { | |||||
// copy incoming data into frame buffers without processing | |||||
jack_nframes_t pos = fFramePos * fAftenContext.channels; | |||||
for (jack_nframes_t spos = offset; spos < nframes; ++spos) { | |||||
for (size_t i = 0; i < fAftenContext.channels; ++i) { | |||||
fSampleBuffer[pos + i] = inputs_buffer[i][spos]; | |||||
} | |||||
pos += fAftenContext.channels; | |||||
} | |||||
fFramePos += (nframes - offset); | |||||
offset += (nframes-offset); | |||||
} | |||||
} | |||||
Output2Driver(outputs_buffer, nframes); | |||||
} | |||||
void JackAC3Encoder::FillSpdifHeader(unsigned char* buf, int outsize) | |||||
{ | |||||
// todo, use outsize and not assume the fixed frame size? | |||||
int ac3outsize = outsize - SPDIF_HEADER_SIZE; | |||||
buf[0] = 0x72; buf[1] = 0xf8; /* spdif syncword */ | |||||
buf[2] = 0x1f; buf[3] = 0x4e; /* .............. */ | |||||
buf[4] = 0x01; /* AC3 data */ | |||||
buf[5] = buf[13] & 7; /* bsmod, stream = 0 */ | |||||
buf[6] = (ac3outsize << 3) & 0xff; | |||||
buf[7] = (ac3outsize >> 5) & 0xff; | |||||
#if !IS_BIGENDIAN | |||||
swab(buf+SPDIF_HEADER_SIZE, buf + SPDIF_HEADER_SIZE, ac3outsize); | |||||
#endif | |||||
} | |||||
int JackAC3Encoder::Output2Driver(float** outputs, jack_nframes_t nframes) | |||||
{ | |||||
int wrotebytes = 0; | |||||
jack_nframes_t nframes_left = nframes; | |||||
if (jack_ringbuffer_read_space(fRingBuffer) == 0) { | |||||
// just write silence | |||||
memset(outputs[0], 0, nframes * sizeof(jack_default_audio_sample_t)); | |||||
memset(outputs[1], 0, nframes * sizeof(jack_default_audio_sample_t)); | |||||
} else { | |||||
jack_ringbuffer_data_t rb_data[2]; | |||||
jack_ringbuffer_get_read_vector(fRingBuffer, rb_data); | |||||
while (nframes_left > 0 && rb_data[0].len > 4) { | |||||
jack_nframes_t towrite_frames = (rb_data[0].len) / (sizeof(short) * 2); | |||||
towrite_frames = min(towrite_frames, nframes_left); | |||||
// write and deinterleave into the two channels | |||||
#if 1 | |||||
sample_move_dS_s16(outputs[0] + (nframes - nframes_left), (char *) rb_data[0].buf, towrite_frames, sizeof(short) * 2); | |||||
sample_move_dS_s16(outputs[1] + (nframes - nframes_left), (char *) rb_data[0].buf + sizeof(short), towrite_frames, sizeof(short) * 2); | |||||
#else | |||||
sample_move_dS_s16_24ph(outputs[0] + (nframes - nframes_left), (char *) rb_data[0].buf, towrite_frames, sizeof(short) * 2); | |||||
sample_move_dS_s16_24ph(outputs[1] + (nframes - nframes_left), (char *) rb_data[0].buf + sizeof(short), towrite_frames, sizeof(short) * 2); | |||||
#endif | |||||
wrotebytes = towrite_frames * sizeof(short) * 2; | |||||
nframes_left -= towrite_frames; | |||||
jack_ringbuffer_read_advance(fRingBuffer, wrotebytes); | |||||
jack_ringbuffer_get_read_vector(fRingBuffer, rb_data); | |||||
} | |||||
if (nframes_left > 0) { | |||||
// write silence | |||||
memset(outputs[0] + (nframes - nframes_left), 0, (nframes_left) * sizeof(jack_default_audio_sample_t)); | |||||
memset(outputs[1] + (nframes - nframes_left), 0, (nframes_left) * sizeof(jack_default_audio_sample_t)); | |||||
} | |||||
} | |||||
return wrotebytes; | |||||
} | |||||
void JackAC3Encoder::sample_move_dS_s16(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip) | |||||
{ | |||||
/* ALERT: signed sign-extension portability !!! */ | |||||
while (nsamples--) { | |||||
*dst = (*((short *) src)) / SAMPLE_MAX_16BIT; | |||||
dst++; | |||||
src += src_skip; | |||||
} | |||||
} | |||||
void JackAC3Encoder::sample_move_dS_s16_24ph(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip) | |||||
{ | |||||
/* ALERT: signed sign-extension portability !!! */ | |||||
while (nsamples--) { | |||||
*dst = (((int)(*((short *) src))) << 8) / SAMPLE_MAX_24BIT; | |||||
dst++; | |||||
src += src_skip; | |||||
} | |||||
} | |||||
void JackAC3Encoder::GetChannelName(const char* name, const char* alias, char* portname, int channel) | |||||
{ | |||||
/* | |||||
* 2 channels = L, R | |||||
* 3 channels = L, C, R | |||||
* 4 channels = L, R, LS, RS | |||||
* 5 ch = L, C, R, LS, RS | |||||
* 6 ch = L, C, R, LS, RS, LFE | |||||
*/ | |||||
const char* AC3_name = ""; | |||||
switch (channel) { | |||||
case 0: | |||||
AC3_name = "AC3_1_Left"; | |||||
break; | |||||
case 1: | |||||
if (fAftenContext.channels == 2 || fAftenContext.channels == 4) { | |||||
AC3_name = "AC3_2_Right"; | |||||
} else { | |||||
AC3_name = "AC3_2_Center"; | |||||
} | |||||
break; | |||||
case 2: | |||||
if (fAftenContext.channels == 4) { | |||||
AC3_name = "AC3_3_LeftSurround"; | |||||
} else { | |||||
AC3_name = "AC3_3_Right"; | |||||
} | |||||
break; | |||||
case 3: | |||||
if (fAftenContext.channels == 4) { | |||||
AC3_name = "AC3_4_RightSurround"; | |||||
} else { | |||||
AC3_name = "AC3_4_LeftSurround"; | |||||
} | |||||
break; | |||||
case 4: | |||||
if (fAftenContext.channels > 4) { | |||||
AC3_name = "AC3_5_RightSurround"; | |||||
} | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
// Last channel | |||||
if (fAftenContext.lfe && (channel == fAftenContext.channels - 1)) { | |||||
sprintf(portname, "%s:%s:AC3_%d_LFE", name, alias, fAftenContext.channels); | |||||
} else { | |||||
sprintf(portname, "%s:%s:%s", name, alias, AC3_name); | |||||
} | |||||
} | |||||
#endif | |||||
} // end of namespace |
@@ -0,0 +1,100 @@ | |||||
/* | |||||
Copyright (C) 2006 Jesse Chappell <jesse@essej.net> (AC3Jack) | |||||
Copyright (C) 2012 Grame | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation; either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __JackAC3Encoder__ | |||||
#define __JackAC3Encoder__ | |||||
#include <aften/aften.h> | |||||
#include <aften/aften-types.h> | |||||
#include "ringbuffer.h" | |||||
#include "types.h" | |||||
#define MAX_AC3_CHANNELS 6 | |||||
#define SPDIF_HEADER_SIZE 8 | |||||
#define SPDIF_FRAME_SIZE 6144 | |||||
#define SAMPLE_MAX_16BIT 32768.0f | |||||
#define SAMPLE_MAX_24BIT 8388608.0f | |||||
namespace Jack | |||||
{ | |||||
struct JackAC3EncoderParams | |||||
{ | |||||
int64_t duration; | |||||
unsigned int channels; | |||||
int bitdepth; | |||||
int bitrate; | |||||
unsigned int sample_rate; | |||||
bool lfe; | |||||
}; | |||||
class JackAC3Encoder | |||||
{ | |||||
private: | |||||
AftenContext fAftenContext; | |||||
jack_ringbuffer_t* fRingBuffer; | |||||
float* fSampleBuffer; | |||||
unsigned char* fAC3Buffer; | |||||
unsigned char* fZeroBuffer; | |||||
int fOutSizeByte; | |||||
jack_nframes_t fFramePos; | |||||
jack_nframes_t fSampleRate; | |||||
jack_nframes_t fByteRate; | |||||
void FillSpdifHeader(unsigned char* buf, int outsize); | |||||
int Output2Driver(float** outputs, jack_nframes_t nframes); | |||||
void sample_move_dS_s16(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip); | |||||
void sample_move_dS_s16_24ph(jack_default_audio_sample_t* dst, char *src, jack_nframes_t nsamples, unsigned long src_skip); | |||||
public: | |||||
#ifdef __ppc__ | |||||
JackAC3Encoder(const JackAC3EncoderParams& params) {} | |||||
virtual ~JackAC3Encoder() {} | |||||
bool Init(jack_nframes_t sample_rate) {return false;} | |||||
void Process(float** inputs, float** outputs, int nframes) {} | |||||
void GetChannelName(const char* name, const char* alias, char* portname, int channel) {} | |||||
#else | |||||
JackAC3Encoder(const JackAC3EncoderParams& params); | |||||
virtual ~JackAC3Encoder(); | |||||
bool Init(jack_nframes_t sample_rate); | |||||
void Process(float** inputs, float** outputs, int nframes); | |||||
void GetChannelName(const char* name, const char* alias, char* portname, int channel); | |||||
#endif | |||||
}; | |||||
typedef JackAC3Encoder * JackAC3EncoderPtr; | |||||
} // end of namespace | |||||
#endif |
@@ -35,20 +35,22 @@ namespace Jack | |||||
int JackAudioAdapter::Process(jack_nframes_t frames, void* arg) | int JackAudioAdapter::Process(jack_nframes_t frames, void* arg) | ||||
{ | { | ||||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(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()]; | |||||
return adapter->ProcessAux(frames); | |||||
} | |||||
int JackAudioAdapter::ProcessAux(jack_nframes_t frames) | |||||
{ | |||||
// Always clear output | // 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)); | |||||
for (int i = 0; i < fAudioAdapter->GetInputs(); i++) { | |||||
fInputBufferList[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(fCapturePortList[i], frames); | |||||
memset(fInputBufferList[i], 0, frames * sizeof(jack_default_audio_sample_t)); | |||||
} | } | ||||
for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { | |||||
outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames); | |||||
for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) { | |||||
fOutputBufferList[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(fPlaybackPortList[i], frames); | |||||
} | } | ||||
adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames); | |||||
fAudioAdapter->PullAndPush(fInputBufferList, fOutputBufferList, frames); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -126,6 +128,9 @@ void JackAudioAdapter::FreePorts() | |||||
delete[] fCapturePortList; | delete[] fCapturePortList; | ||||
delete[] fPlaybackPortList; | delete[] fPlaybackPortList; | ||||
delete[] fInputBufferList; | |||||
delete[] fOutputBufferList; | |||||
} | } | ||||
void JackAudioAdapter::ConnectPorts() | void JackAudioAdapter::ConnectPorts() | ||||
@@ -164,6 +169,9 @@ int JackAudioAdapter::Open() | |||||
fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()]; | fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()]; | ||||
fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()]; | fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()]; | ||||
fInputBufferList = new jack_default_audio_sample_t*[fAudioAdapter->GetInputs()]; | |||||
fOutputBufferList = new jack_default_audio_sample_t*[fAudioAdapter->GetOutputs()]; | |||||
for (int i = 0; i < fAudioAdapter->GetInputs(); i++) { | for (int i = 0; i < fAudioAdapter->GetInputs(); i++) { | ||||
snprintf(name, sizeof(name), "capture_%d", i + 1); | snprintf(name, sizeof(name), "capture_%d", i + 1); | ||||
if ((fCapturePortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, 0)) == NULL) { | if ((fCapturePortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, 0)) == NULL) { | ||||
@@ -42,6 +42,9 @@ namespace Jack | |||||
jack_port_t** fCapturePortList; | jack_port_t** fCapturePortList; | ||||
jack_port_t** fPlaybackPortList; | jack_port_t** fPlaybackPortList; | ||||
jack_default_audio_sample_t** fInputBufferList; | |||||
jack_default_audio_sample_t** fOutputBufferList; | |||||
jack_client_t* fClient; | jack_client_t* fClient; | ||||
JackAudioAdapterInterface* fAudioAdapter; | JackAudioAdapterInterface* fAudioAdapter; | ||||
bool fAutoConnect; | bool fAutoConnect; | ||||
@@ -49,6 +52,7 @@ namespace Jack | |||||
void FreePorts(); | void FreePorts(); | ||||
void ConnectPorts(); | void ConnectPorts(); | ||||
void Reset(); | void Reset(); | ||||
int ProcessAux(jack_nframes_t frames); | |||||
public: | public: | ||||
@@ -26,6 +26,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackLibSampleRateResampler.h" | #include "JackLibSampleRateResampler.h" | ||||
#endif | #endif | ||||
#include "JackTime.h" | #include "JackTime.h" | ||||
#include "JackError.h" | |||||
#include <stdio.h> | #include <stdio.h> | ||||
namespace Jack | namespace Jack | ||||
@@ -317,4 +318,75 @@ namespace Jack | |||||
return res; | return res; | ||||
} | } | ||||
int JackAudioAdapterInterface::SetHostBufferSize(jack_nframes_t buffer_size) | |||||
{ | |||||
fHostBufferSize = buffer_size; | |||||
if (fAdaptative) { | |||||
AdaptRingBufferSize(); | |||||
} | |||||
return 0; | |||||
} | |||||
int JackAudioAdapterInterface::SetAdaptedBufferSize(jack_nframes_t buffer_size) | |||||
{ | |||||
fAdaptedBufferSize = buffer_size; | |||||
if (fAdaptative) { | |||||
AdaptRingBufferSize(); | |||||
} | |||||
return 0; | |||||
} | |||||
int JackAudioAdapterInterface::SetBufferSize(jack_nframes_t buffer_size) | |||||
{ | |||||
SetHostBufferSize(buffer_size); | |||||
SetAdaptedBufferSize(buffer_size); | |||||
return 0; | |||||
} | |||||
int JackAudioAdapterInterface::SetHostSampleRate(jack_nframes_t sample_rate) | |||||
{ | |||||
fHostSampleRate = sample_rate; | |||||
fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate)); | |||||
return 0; | |||||
} | |||||
int JackAudioAdapterInterface::SetAdaptedSampleRate(jack_nframes_t sample_rate) | |||||
{ | |||||
fAdaptedSampleRate = sample_rate; | |||||
fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate)); | |||||
return 0; | |||||
} | |||||
int JackAudioAdapterInterface::SetSampleRate(jack_nframes_t sample_rate) | |||||
{ | |||||
SetHostSampleRate(sample_rate); | |||||
SetAdaptedSampleRate(sample_rate); | |||||
return 0; | |||||
} | |||||
void JackAudioAdapterInterface::SetInputs(int inputs) | |||||
{ | |||||
jack_log("JackAudioAdapterInterface::SetInputs %d", inputs); | |||||
fCaptureChannels = inputs; | |||||
} | |||||
void JackAudioAdapterInterface::SetOutputs(int outputs) | |||||
{ | |||||
jack_log("JackAudioAdapterInterface::SetOutputs %d", outputs); | |||||
fPlaybackChannels = outputs; | |||||
} | |||||
int JackAudioAdapterInterface::GetInputs() | |||||
{ | |||||
//jack_log("JackAudioAdapterInterface::GetInputs %d", fCaptureChannels); | |||||
return fCaptureChannels; | |||||
} | |||||
int JackAudioAdapterInterface::GetOutputs() | |||||
{ | |||||
//jack_log ("JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels); | |||||
return fPlaybackChannels; | |||||
} | |||||
} // namespace | } // namespace |
@@ -154,75 +154,16 @@ namespace Jack | |||||
return 0; | return 0; | ||||
} | } | ||||
virtual int SetHostBufferSize(jack_nframes_t buffer_size) | |||||
{ | |||||
fHostBufferSize = buffer_size; | |||||
if (fAdaptative) { | |||||
AdaptRingBufferSize(); | |||||
} | |||||
return 0; | |||||
} | |||||
virtual int SetAdaptedBufferSize(jack_nframes_t buffer_size) | |||||
{ | |||||
fAdaptedBufferSize = buffer_size; | |||||
if (fAdaptative) { | |||||
AdaptRingBufferSize(); | |||||
} | |||||
return 0; | |||||
} | |||||
virtual int SetBufferSize(jack_nframes_t buffer_size) | |||||
{ | |||||
SetHostBufferSize(buffer_size); | |||||
SetAdaptedBufferSize(buffer_size); | |||||
return 0; | |||||
} | |||||
virtual int SetHostSampleRate(jack_nframes_t sample_rate) | |||||
{ | |||||
fHostSampleRate = sample_rate; | |||||
fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate)); | |||||
return 0; | |||||
} | |||||
virtual int SetAdaptedSampleRate(jack_nframes_t sample_rate) | |||||
{ | |||||
fAdaptedSampleRate = sample_rate; | |||||
fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate)); | |||||
return 0; | |||||
} | |||||
virtual int SetSampleRate(jack_nframes_t sample_rate) | |||||
{ | |||||
SetHostSampleRate(sample_rate); | |||||
SetAdaptedSampleRate(sample_rate); | |||||
return 0; | |||||
} | |||||
void SetInputs(int inputs) | |||||
{ | |||||
jack_log("JackAudioAdapterInterface::SetInputs %d", inputs); | |||||
fCaptureChannels = inputs; | |||||
} | |||||
void SetOutputs(int outputs) | |||||
{ | |||||
jack_log("JackAudioAdapterInterface::SetOutputs %d", outputs); | |||||
fPlaybackChannels = outputs; | |||||
} | |||||
int GetInputs() | |||||
{ | |||||
//jack_log("JackAudioAdapterInterface::GetInputs %d", fCaptureChannels); | |||||
return fCaptureChannels; | |||||
} | |||||
int GetOutputs() | |||||
{ | |||||
//jack_log ("JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels); | |||||
return fPlaybackChannels; | |||||
} | |||||
virtual int SetHostBufferSize(jack_nframes_t buffer_size); | |||||
virtual int SetAdaptedBufferSize(jack_nframes_t buffer_size); | |||||
virtual int SetBufferSize(jack_nframes_t buffer_size); | |||||
virtual int SetHostSampleRate(jack_nframes_t sample_rate); | |||||
virtual int SetAdaptedSampleRate(jack_nframes_t sample_rate); | |||||
virtual int SetSampleRate(jack_nframes_t sample_rate); | |||||
void SetInputs(int inputs); | |||||
void SetOutputs(int outputs); | |||||
int GetInputs(); | |||||
int GetOutputs(); | |||||
virtual int GetInputLatency(int port_index) { return 0; } | virtual int GetInputLatency(int port_index) { return 0; } | ||||
virtual int GetOutputLatency(int port_index) { return 0; } | virtual int GetOutputLatency(int port_index) { return 0; } | ||||
@@ -46,25 +46,20 @@ int JackAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | |||||
// Update engine and graph manager state | // Update engine and graph manager state | ||||
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 | |||||
if (!fEngineControl->fTimeOut) { | |||||
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | |||||
} | |||||
fEngineControl->UpdateTimeOut(); | |||||
UpdateLatencies(); | UpdateLatencies(); | ||||
// Redirect on slaves drivers... | |||||
// Redirected on slaves drivers... | |||||
return JackDriver::SetBufferSize(buffer_size); | return JackDriver::SetBufferSize(buffer_size); | ||||
} | } | ||||
int JackAudioDriver::SetSampleRate(jack_nframes_t sample_rate) | 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 | |||||
if (!fEngineControl->fTimeOut) { | |||||
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | |||||
} | |||||
fEngineControl->UpdateTimeOut(); | |||||
// Redirected on slaves drivers... | |||||
return JackDriver::SetSampleRate(sample_rate); | return JackDriver::SetSampleRate(sample_rate); | ||||
} | } | ||||
@@ -35,6 +35,54 @@ class JackGraphManager; | |||||
namespace detail | namespace detail | ||||
{ | { | ||||
class JackChannelTransactionInterface | |||||
{ | |||||
public: | |||||
JackChannelTransactionInterface() | |||||
{} | |||||
virtual ~JackChannelTransactionInterface() | |||||
{} | |||||
virtual int Read(void* data, int len) = 0; | |||||
virtual int Write(void* data, int len) = 0; | |||||
}; | |||||
class JackRequestInterface | |||||
{ | |||||
public: | |||||
JackRequestInterface() | |||||
{} | |||||
virtual ~JackRequestInterface() | |||||
{} | |||||
virtual int Connect(const char* dir, const char* name, int which) = 0; | |||||
virtual int Close() = 0; | |||||
}; | |||||
class JackClientRequestInterface : public JackChannelTransactionInterface, public JackRequestInterface | |||||
{ | |||||
public: | |||||
JackClientRequestInterface() | |||||
{} | |||||
virtual ~JackClientRequestInterface() | |||||
{} | |||||
virtual int Read(void* data, int len) { return -1; } | |||||
virtual int Write(void* data, int len) { return -1; } | |||||
virtual int Connect(const char* dir, const char* name, int which) { return -1; } | |||||
virtual int Close() { return -1; } | |||||
}; | |||||
/*! | /*! | ||||
\brief Inter process channel for server/client bidirectionnal communication : request and (receiving) notifications. | \brief Inter process channel for server/client bidirectionnal communication : request and (receiving) notifications. | ||||
*/ | */ | ||||
@@ -88,6 +88,19 @@ JackClient::JackClient(JackSynchro* table):fThread(this) | |||||
JackClient::~JackClient() | JackClient::~JackClient() | ||||
{} | {} | ||||
void JackClient::ShutDown() | |||||
{ | |||||
jack_log("JackClient::ShutDown"); | |||||
if (fInfoShutdown) { | |||||
fInfoShutdown(JackFailure, "JACK server has been closed", fInfoShutdownArg); | |||||
fInfoShutdown = NULL; | |||||
} else if (fShutdown) { | |||||
fShutdown(fShutdownArg); | |||||
fShutdown = NULL; | |||||
} | |||||
} | |||||
int JackClient::Close() | int JackClient::Close() | ||||
{ | { | ||||
jack_log("JackClient::Close ref = %ld", GetClientControl()->fRefNum); | jack_log("JackClient::Close ref = %ld", GetClientControl()->fRefNum); | ||||
@@ -346,15 +359,18 @@ int JackClient::HandleLatencyCallback(int status) | |||||
if (port->GetFlags() & JackPortIsOutput) { | if (port->GetFlags() & JackPortIsOutput) { | ||||
jack_latency_range_t other_latency; | jack_latency_range_t other_latency; | ||||
port->GetLatencyRange(mode, &other_latency); | port->GetLatencyRange(mode, &other_latency); | ||||
if (other_latency.max > latency.max) | |||||
if (other_latency.max > latency.max) { | |||||
latency.max = other_latency.max; | latency.max = other_latency.max; | ||||
if (other_latency.min < latency.min) | |||||
} | |||||
if (other_latency.min < latency.min) { | |||||
latency.min = other_latency.min; | latency.min = other_latency.min; | ||||
} | |||||
} | } | ||||
} | } | ||||
if (latency.min == UINT32_MAX) | |||||
if (latency.min == UINT32_MAX) { | |||||
latency.min = 0; | latency.min = 0; | ||||
} | |||||
/* now set the found latency on all input ports | /* now set the found latency on all input ports | ||||
*/ | */ | ||||
@@ -373,15 +389,18 @@ int JackClient::HandleLatencyCallback(int status) | |||||
if (port->GetFlags() & JackPortIsInput) { | if (port->GetFlags() & JackPortIsInput) { | ||||
jack_latency_range_t other_latency; | jack_latency_range_t other_latency; | ||||
port->GetLatencyRange(mode, &other_latency); | port->GetLatencyRange(mode, &other_latency); | ||||
if (other_latency.max > latency.max) | |||||
if (other_latency.max > latency.max) { | |||||
latency.max = other_latency.max; | latency.max = other_latency.max; | ||||
if (other_latency.min < latency.min) | |||||
} | |||||
if (other_latency.min < latency.min) { | |||||
latency.min = other_latency.min; | latency.min = other_latency.min; | ||||
} | |||||
} | } | ||||
} | } | ||||
if (latency.min == UINT32_MAX) | |||||
if (latency.min == UINT32_MAX) { | |||||
latency.min = 0; | latency.min = 0; | ||||
} | |||||
/* now set the found latency on all output ports | /* now set the found latency on all output ports | ||||
*/ | */ | ||||
@@ -409,13 +428,15 @@ connected to the client may not be activated. | |||||
int JackClient::Activate() | int JackClient::Activate() | ||||
{ | { | ||||
jack_log("JackClient::Activate"); | jack_log("JackClient::Activate"); | ||||
if (IsActive()) | |||||
if (IsActive()) { | |||||
return 0; | return 0; | ||||
} | |||||
// RT thread is started only when needed... | // RT thread is started only when needed... | ||||
if (IsRealTime()) { | if (IsRealTime()) { | ||||
if (StartThread() < 0) | |||||
if (StartThread() < 0) { | |||||
return -1; | return -1; | ||||
} | |||||
} | } | ||||
/* | /* | ||||
@@ -440,8 +461,9 @@ int JackClient::Activate() | |||||
int JackClient::Deactivate() | int JackClient::Deactivate() | ||||
{ | { | ||||
jack_log("JackClient::Deactivate"); | jack_log("JackClient::Deactivate"); | ||||
if (!IsActive()) | |||||
if (!IsActive()) { | |||||
return 0; | return 0; | ||||
} | |||||
GetClientControl()->fActive = false; | GetClientControl()->fActive = false; | ||||
@@ -455,8 +477,9 @@ int JackClient::Deactivate() | |||||
jack_log("JackClient::Deactivate res = %ld", result); | jack_log("JackClient::Deactivate res = %ld", result); | ||||
// RT thread is stopped only when needed... | // RT thread is stopped only when needed... | ||||
if (IsRealTime()) | |||||
if (IsRealTime()) { | |||||
fThread.Kill(); | fThread.Kill(); | ||||
} | |||||
return result; | return result; | ||||
} | } | ||||
@@ -493,11 +516,13 @@ bool JackClient::Init() | |||||
InitAux(); | InitAux(); | ||||
// Setup context | // Setup context | ||||
if (!jack_tls_set(JackGlobals::fRealTime, this)) | |||||
jack_error("failed to set thread realtime key"); | |||||
if (!jack_tls_set(JackGlobals::fRealTimeThread, this)) { | |||||
jack_error("Failed to set thread realtime key"); | |||||
} | |||||
if (GetEngineControl()->fRealTime) | |||||
if (GetEngineControl()->fRealTime) { | |||||
set_threaded_log_function(); | set_threaded_log_function(); | ||||
} | |||||
// Setup RT | // Setup RT | ||||
if (GetEngineControl()->fRealTime) { | if (GetEngineControl()->fRealTime) { | ||||
@@ -560,19 +585,22 @@ inline void JackClient::ExecuteThread() | |||||
inline jack_nframes_t JackClient::CycleWaitAux() | inline jack_nframes_t JackClient::CycleWaitAux() | ||||
{ | { | ||||
if (!WaitSync()) | |||||
if (!WaitSync()) { | |||||
Error(); // Terminates the thread | Error(); // Terminates the thread | ||||
} | |||||
CallSyncCallbackAux(); | CallSyncCallbackAux(); | ||||
return GetEngineControl()->fBufferSize; | return GetEngineControl()->fBufferSize; | ||||
} | } | ||||
inline void JackClient::CycleSignalAux(int status) | inline void JackClient::CycleSignalAux(int status) | ||||
{ | { | ||||
if (status == 0) | |||||
if (status == 0) { | |||||
CallTimebaseCallbackAux(); | CallTimebaseCallbackAux(); | ||||
} | |||||
SignalSync(); | SignalSync(); | ||||
if (status != 0) | |||||
if (status != 0) { | |||||
End(); // Terminates the thread | End(); // Terminates the thread | ||||
} | |||||
} | } | ||||
jack_nframes_t JackClient::CycleWait() | jack_nframes_t JackClient::CycleWait() | ||||
@@ -747,27 +775,6 @@ int JackClient::ComputeTotalLatencies() | |||||
return result; | return result; | ||||
} | } | ||||
/* | |||||
ShutDown is called: | |||||
- from the RT thread when Execute method fails | |||||
- possibly from a "closed" notification channel | |||||
(Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown)) | |||||
*/ | |||||
void JackClient::ShutDown() | |||||
{ | |||||
jack_log("JackClient::ShutDown"); | |||||
JackGlobals::fServerRunning = false; | |||||
if (fInfoShutdown) { | |||||
fInfoShutdown(JackFailure, "JACK server has been closed", fInfoShutdownArg); | |||||
fInfoShutdown = NULL; | |||||
} else if (fShutdown) { | |||||
fShutdown(fShutdownArg); | |||||
fShutdown = NULL; | |||||
} | |||||
} | |||||
//---------------------- | //---------------------- | ||||
// Transport management | // Transport management | ||||
//---------------------- | //---------------------- | ||||
@@ -780,8 +787,9 @@ inline int JackClient::ActivateAux() | |||||
jack_log("JackClient::ActivateAux"); | jack_log("JackClient::ActivateAux"); | ||||
// RT thread is started | // RT thread is started | ||||
if (StartThread() < 0) | |||||
if (StartThread() < 0) { | |||||
return -1; | return -1; | ||||
} | |||||
int result = -1; | int result = -1; | ||||
GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime(); | GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime(); | ||||
@@ -1001,8 +1009,7 @@ int JackClient::SetInitCallback(JackThreadInitCallback callback, void *arg) | |||||
fInitArg = arg; | fInitArg = arg; | ||||
fInit = callback; | fInit = callback; | ||||
/* make sure that the message buffer thread is initialized too */ | /* make sure that the message buffer thread is initialized too */ | ||||
JackMessageBuffer::fInstance->SetInitCallback(callback, arg); | |||||
return 0; | |||||
return JackMessageBuffer::fInstance->SetInitCallback(callback, arg); | |||||
} | } | ||||
} | } | ||||
@@ -1042,8 +1049,9 @@ int JackClient::SetSampleRateCallback(JackSampleRateCallback callback, void *arg | |||||
fSampleRateArg = arg; | fSampleRateArg = arg; | ||||
fSampleRate = callback; | fSampleRate = callback; | ||||
// Now invoke it | // Now invoke it | ||||
if (callback) | |||||
if (callback) { | |||||
callback(GetEngineControl()->fSampleRate, arg); | callback(GetEngineControl()->fSampleRate, arg); | ||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
} | } | ||||
@@ -1122,7 +1130,7 @@ int JackClient::SetProcessThread(JackThreadCallback fun, void *arg) | |||||
jack_error("You cannot set callbacks on an active client"); | jack_error("You cannot set callbacks on an active client"); | ||||
return -1; | return -1; | ||||
} else if (fProcess) { | } else if (fProcess) { | ||||
jack_error ("A process callback has already been setup, both models cannot be used at the same time!"); | |||||
jack_error("A process callback has already been setup, both models cannot be used at the same time!"); | |||||
return -1; | return -1; | ||||
} else { | } else { | ||||
fThreadFun = fun; | fThreadFun = fun; | ||||
@@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#include "JackSynchro.h" | #include "JackSynchro.h" | ||||
#include "JackPlatformPlug.h" | #include "JackPlatformPlug.h" | ||||
#include "JackChannel.h" | #include "JackChannel.h" | ||||
#include "JackRequest.h" | |||||
#include "varargs.h" | #include "varargs.h" | ||||
#include <list> | #include <list> | ||||
@@ -86,7 +87,7 @@ class SERVER_EXPORT JackClient : public JackClientInterface, public JackRunnable | |||||
void* fThreadFunArg; | void* fThreadFunArg; | ||||
void* fSessionArg; | void* fSessionArg; | ||||
void* fLatencyArg; | void* fLatencyArg; | ||||
char fServerName[64]; | |||||
char fServerName[JACK_SERVER_CONTROL_NAME_SIZE]; | |||||
JackThread fThread; /*! Thread to execute the Process function */ | JackThread fThread; /*! Thread to execute the Process function */ | ||||
detail::JackClientChannelInterface* fChannel; | detail::JackClientChannelInterface* fChannel; | ||||
@@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | ||||
You should have received a copy of the GNU Lesser General Public License | You should have received a copy of the GNU Lesser General Public License | ||||
along with this program; if not, write to the Free Software | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | */ | ||||
@@ -36,12 +36,12 @@ class SERVER_EXPORT JackClientInterface | |||||
{ | { | ||||
public: | public: | ||||
JackClientInterface() | JackClientInterface() | ||||
{} | {} | ||||
virtual ~JackClientInterface() | virtual ~JackClientInterface() | ||||
{} | {} | ||||
virtual int Close() = 0; | virtual int Close() = 0; | ||||
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) = 0; | virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) = 0; | ||||
@@ -24,7 +24,7 @@ | |||||
#include "config.h" | #include "config.h" | ||||
#endif | #endif | ||||
#define VERSION "1.9.8" | |||||
#define VERSION "1.9.9" | |||||
#define BUFFER_SIZE_MAX 8192 | #define BUFFER_SIZE_MAX 8192 | ||||
@@ -71,7 +71,7 @@ | |||||
#define JACK_PROTOCOL_VERSION 8 | #define JACK_PROTOCOL_VERSION 8 | ||||
#define SOCKET_TIME_OUT 5 // in sec | |||||
#define SOCKET_TIME_OUT 2 // in sec | |||||
#define DRIVER_OPEN_TIMEOUT 5 // in sec | #define DRIVER_OPEN_TIMEOUT 5 // in sec | ||||
#define FREEWHEEL_DRIVER_TIMEOUT 10 // in sec | #define FREEWHEEL_DRIVER_TIMEOUT 10 // in sec | ||||
#define DRIVER_TIMEOUT_FACTOR 10 | #define DRIVER_TIMEOUT_FACTOR 10 | ||||
@@ -237,7 +237,7 @@ jackctl_add_driver_parameters( | |||||
jackctl_value.b = descriptor_ptr->value.i; | jackctl_value.b = descriptor_ptr->value.i; | ||||
break; | break; | ||||
default: | default: | ||||
jack_error("unknown driver parameter type %i", (int)descriptor_ptr->type); | |||||
jack_error("Unknown driver parameter type %i", (int)descriptor_ptr->type); | |||||
assert(0); | assert(0); | ||||
goto fail; | goto fail; | ||||
} | } | ||||
@@ -330,7 +330,7 @@ jackctl_create_param_list( | |||||
retparam_ptr->value.i = param_ptr->value_ptr->b; | retparam_ptr->value.i = param_ptr->value_ptr->b; | ||||
break; | break; | ||||
default: | default: | ||||
jack_error("unknown parameter type %i", (int)param_ptr->type); | |||||
jack_error("Unknown parameter type %i", (int)param_ptr->type); | |||||
assert(0); | assert(0); | ||||
goto free; | goto free; | ||||
} | } | ||||
@@ -361,7 +361,7 @@ jackctl_drivers_load( | |||||
descriptor_node_ptr = jack_drivers_load(NULL); | descriptor_node_ptr = jack_drivers_load(NULL); | ||||
if (descriptor_node_ptr == NULL) | if (descriptor_node_ptr == NULL) | ||||
{ | { | ||||
jack_error("could not find any drivers in driver directory!"); | |||||
jack_error("Could not find any drivers in driver directory!"); | |||||
return false; | return false; | ||||
} | } | ||||
@@ -370,7 +370,7 @@ jackctl_drivers_load( | |||||
driver_ptr = (struct jackctl_driver *)malloc(sizeof(struct jackctl_driver)); | driver_ptr = (struct jackctl_driver *)malloc(sizeof(struct jackctl_driver)); | ||||
if (driver_ptr == NULL) | if (driver_ptr == NULL) | ||||
{ | { | ||||
jack_error("memory allocation of jackctl_driver structure failed."); | |||||
jack_error("Memory allocation of jackctl_driver structure failed."); | |||||
goto next; | goto next; | ||||
} | } | ||||
@@ -430,7 +430,7 @@ jackctl_internals_load( | |||||
descriptor_node_ptr = jack_internals_load(NULL); | descriptor_node_ptr = jack_internals_load(NULL); | ||||
if (descriptor_node_ptr == NULL) | if (descriptor_node_ptr == NULL) | ||||
{ | { | ||||
jack_error("could not find any internals in driver directory!"); | |||||
jack_error("Could not find any internals in driver directory!"); | |||||
return false; | return false; | ||||
} | } | ||||
@@ -439,7 +439,7 @@ jackctl_internals_load( | |||||
internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal)); | internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal)); | ||||
if (internal_ptr == NULL) | if (internal_ptr == NULL) | ||||
{ | { | ||||
jack_error("memory allocation of jackctl_driver structure failed."); | |||||
jack_error("Memory allocation of jackctl_driver structure failed."); | |||||
goto next; | goto next; | ||||
} | } | ||||
@@ -506,57 +506,68 @@ jackctl_server_free_parameters( | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
static HANDLE waitEvent; | |||||
struct jackctl_sigmask | |||||
{ | |||||
HANDLE wait_event; | |||||
}; | |||||
static jackctl_sigmask sigmask; | |||||
static void do_nothing_handler(int signum) | |||||
static void signal_handler(int signum) | |||||
{ | { | ||||
printf("jack main caught signal %d\n", signum); | |||||
printf("Jack main caught signal %d\n", signum); | |||||
(void) signal(SIGINT, SIG_DFL); | (void) signal(SIGINT, SIG_DFL); | ||||
SetEvent(waitEvent); | |||||
SetEvent(sigmask.wait_event); | |||||
} | } | ||||
sigset_t | |||||
jackctl_sigmask_t * | |||||
jackctl_setup_signals( | jackctl_setup_signals( | ||||
unsigned int flags) | unsigned int flags) | ||||
{ | { | ||||
if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) { | |||||
if ((sigmask.wait_event = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) { | |||||
jack_error("CreateEvent fails err = %ld", GetLastError()); | jack_error("CreateEvent fails err = %ld", GetLastError()); | ||||
return 0; | return 0; | ||||
} | } | ||||
(void) signal(SIGINT, do_nothing_handler); | |||||
(void) signal(SIGABRT, do_nothing_handler); | |||||
(void) signal(SIGTERM, do_nothing_handler); | |||||
(void) signal(SIGINT, signal_handler); | |||||
(void) signal(SIGABRT, signal_handler); | |||||
(void) signal(SIGTERM, signal_handler); | |||||
return (sigset_t)waitEvent; | |||||
return &sigmask; | |||||
} | } | ||||
void jackctl_wait_signals(sigset_t signals) | |||||
void jackctl_wait_signals(jackctl_sigmask_t * signals) | |||||
{ | { | ||||
if (WaitForSingleObject(waitEvent, INFINITE) != WAIT_OBJECT_0) { | |||||
if (WaitForSingleObject(signals->wait_event, INFINITE) != WAIT_OBJECT_0) { | |||||
jack_error("WaitForSingleObject fails err = %ld", GetLastError()); | jack_error("WaitForSingleObject fails err = %ld", GetLastError()); | ||||
} | } | ||||
} | } | ||||
#else | #else | ||||
struct jackctl_sigmask | |||||
{ | |||||
sigset_t signals; | |||||
}; | |||||
static jackctl_sigmask sigmask; | |||||
static | static | ||||
void | void | ||||
do_nothing_handler(int sig) | |||||
signal_handler(int sig) | |||||
{ | { | ||||
/* this is used by the child (active) process, but it never | /* this is used by the child (active) process, but it never | ||||
gets called unless we are already shutting down after | gets called unless we are already shutting down after | ||||
another signal. | another signal. | ||||
*/ | */ | ||||
char buf[64]; | char buf[64]; | ||||
snprintf (buf, sizeof(buf), "received signal %d during shutdown (ignored)\n", sig); | |||||
snprintf(buf, sizeof(buf), "Received signal %d during shutdown (ignored)\n", sig); | |||||
} | } | ||||
SERVER_EXPORT sigset_t | |||||
SERVER_EXPORT jackctl_sigmask_t * | |||||
jackctl_setup_signals( | jackctl_setup_signals( | ||||
unsigned int flags) | unsigned int flags) | ||||
{ | { | ||||
sigset_t signals; | |||||
sigset_t allsignals; | sigset_t allsignals; | ||||
struct sigaction action; | struct sigaction action; | ||||
int i; | int i; | ||||
@@ -595,54 +606,54 @@ jackctl_setup_signals( | |||||
after a return from sigwait(). | after a return from sigwait(). | ||||
*/ | */ | ||||
sigemptyset(&signals); | |||||
sigaddset(&signals, SIGHUP); | |||||
sigaddset(&signals, SIGINT); | |||||
sigaddset(&signals, SIGQUIT); | |||||
sigaddset(&signals, SIGPIPE); | |||||
sigaddset(&signals, SIGTERM); | |||||
sigaddset(&signals, SIGUSR1); | |||||
sigaddset(&signals, SIGUSR2); | |||||
sigemptyset(&sigmask.signals); | |||||
sigaddset(&sigmask.signals, SIGHUP); | |||||
sigaddset(&sigmask.signals, SIGINT); | |||||
sigaddset(&sigmask.signals, SIGQUIT); | |||||
sigaddset(&sigmask.signals, SIGPIPE); | |||||
sigaddset(&sigmask.signals, SIGTERM); | |||||
sigaddset(&sigmask.signals, SIGUSR1); | |||||
sigaddset(&sigmask.signals, SIGUSR2); | |||||
/* all child threads will inherit this mask unless they | /* all child threads will inherit this mask unless they | ||||
* explicitly reset it | * explicitly reset it | ||||
*/ | */ | ||||
pthread_sigmask(SIG_BLOCK, &signals, 0); | |||||
pthread_sigmask(SIG_BLOCK, &sigmask.signals, 0); | |||||
/* install a do-nothing handler because otherwise pthreads | /* install a do-nothing handler because otherwise pthreads | ||||
behaviour is undefined when we enter sigwait. | behaviour is undefined when we enter sigwait. | ||||
*/ | */ | ||||
sigfillset(&allsignals); | sigfillset(&allsignals); | ||||
action.sa_handler = do_nothing_handler; | |||||
action.sa_handler = signal_handler; | |||||
action.sa_mask = allsignals; | action.sa_mask = allsignals; | ||||
action.sa_flags = SA_RESTART|SA_RESETHAND; | action.sa_flags = SA_RESTART|SA_RESETHAND; | ||||
for (i = 1; i < NSIG; i++) | for (i = 1; i < NSIG; i++) | ||||
{ | { | ||||
if (sigismember (&signals, i)) | |||||
if (sigismember (&sigmask.signals, i)) | |||||
{ | { | ||||
sigaction(i, &action, 0); | sigaction(i, &action, 0); | ||||
} | } | ||||
} | } | ||||
return signals; | |||||
return &sigmask; | |||||
} | } | ||||
SERVER_EXPORT void | SERVER_EXPORT void | ||||
jackctl_wait_signals(sigset_t signals) | |||||
jackctl_wait_signals(jackctl_sigmask_t * sigmask) | |||||
{ | { | ||||
int sig; | int sig; | ||||
bool waiting = true; | bool waiting = true; | ||||
while (waiting) { | while (waiting) { | ||||
#if defined(sun) && !defined(__sun__) // SUN compiler only, to check | #if defined(sun) && !defined(__sun__) // SUN compiler only, to check | ||||
sigwait(&signals); | |||||
sigwait(&sigmask->signals); | |||||
#else | #else | ||||
sigwait(&signals, &sig); | |||||
sigwait(&sigmask->signals, &sig); | |||||
#endif | #endif | ||||
fprintf(stderr, "jack main caught signal %d\n", sig); | |||||
fprintf(stderr, "Jack main caught signal %d\n", sig); | |||||
switch (sig) { | switch (sig) { | ||||
case SIGUSR1: | case SIGUSR1: | ||||
@@ -664,7 +675,7 @@ jackctl_wait_signals(sigset_t signals) | |||||
// unblock signals so we can see them during shutdown. | // unblock signals so we can see them during shutdown. | ||||
// this will help prod developers not to lose sight of | // this will help prod developers not to lose sight of | ||||
// bugs that cause segfaults etc. during shutdown. | // bugs that cause segfaults etc. during shutdown. | ||||
sigprocmask(SIG_UNBLOCK, &signals, 0); | |||||
sigprocmask(SIG_UNBLOCK, &sigmask->signals, 0); | |||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
@@ -911,15 +922,15 @@ SERVER_EXPORT bool jackctl_server_close(jackctl_server *server_ptr) | |||||
delete server_ptr->engine; | delete server_ptr->engine; | ||||
/* clean up shared memory and files from this server instance */ | /* clean up shared memory and files from this server instance */ | ||||
jack_log("cleaning up shared memory"); | |||||
jack_log("Cleaning up shared memory"); | |||||
jack_cleanup_shm(); | jack_cleanup_shm(); | ||||
jack_log("cleaning up files"); | |||||
jack_log("Cleaning up files"); | |||||
JackTools::CleanupFiles(server_ptr->name.str); | JackTools::CleanupFiles(server_ptr->name.str); | ||||
jack_log("unregistering server `%s'", server_ptr->name.str); | |||||
jack_log("Unregistering server `%s'", server_ptr->name.str); | |||||
jack_unregister_server(server_ptr->name.str); | jack_unregister_server(server_ptr->name.str); | ||||
@@ -956,14 +967,14 @@ jackctl_server_open( | |||||
jack_error("`%s' server already active", server_ptr->name.str); | jack_error("`%s' server already active", server_ptr->name.str); | ||||
goto fail; | goto fail; | ||||
case ENOSPC: | case ENOSPC: | ||||
jack_error("too many servers already active"); | |||||
jack_error("Too many servers already active"); | |||||
goto fail; | goto fail; | ||||
case ENOMEM: | case ENOMEM: | ||||
jack_error("no access to shm registry"); | |||||
jack_error("No access to shm registry"); | |||||
goto fail; | goto fail; | ||||
} | } | ||||
jack_log("server `%s' registered", server_ptr->name.str); | |||||
jack_log("Server `%s' registered", server_ptr->name.str); | |||||
/* clean up shared memory and files from any previous | /* clean up shared memory and files from any previous | ||||
* instance of this server name */ | * instance of this server name */ | ||||
@@ -976,7 +987,7 @@ jackctl_server_open( | |||||
/* check port max value before allocating server */ | /* check port max value before allocating server */ | ||||
if (server_ptr->port_max.ui > PORT_NUM_MAX) { | if (server_ptr->port_max.ui > PORT_NUM_MAX) { | ||||
jack_error("JACK server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX); | |||||
jack_error("Jack server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX); | |||||
goto fail; | goto fail; | ||||
} | } | ||||
@@ -1003,7 +1014,7 @@ jackctl_server_open( | |||||
jackctl_destroy_param_list(paramlist); | jackctl_destroy_param_list(paramlist); | ||||
if (rc < 0) | if (rc < 0) | ||||
{ | { | ||||
jack_error("JackServer::Open() failed with %d", rc); | |||||
jack_error("JackServer::Open failed with %d", rc); | |||||
goto fail_delete; | goto fail_delete; | ||||
} | } | ||||
@@ -1019,15 +1030,15 @@ fail_delete: | |||||
server_ptr->engine = NULL; | server_ptr->engine = NULL; | ||||
fail_unregister: | fail_unregister: | ||||
jack_log("cleaning up shared memory"); | |||||
jack_log("Cleaning up shared memory"); | |||||
jack_cleanup_shm(); | jack_cleanup_shm(); | ||||
jack_log("cleaning up files"); | |||||
jack_log("Cleaning up files"); | |||||
JackTools::CleanupFiles(server_ptr->name.str); | JackTools::CleanupFiles(server_ptr->name.str); | ||||
jack_log("unregistering server `%s'", server_ptr->name.str); | |||||
jack_log("Unregistering server `%s'", server_ptr->name.str); | |||||
jack_unregister_server(server_ptr->name.str); | jack_unregister_server(server_ptr->name.str); | ||||
@@ -1138,7 +1149,7 @@ SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constrain | |||||
strcpy(jackctl_value.str, value_ptr->str); | strcpy(jackctl_value.str, value_ptr->str); | ||||
break; | break; | ||||
default: | default: | ||||
jack_error("bad driver parameter type %i (enum constraint)", (int)parameter_ptr->type); | |||||
jack_error("Bad driver parameter type %i (enum constraint)", (int)parameter_ptr->type); | |||||
assert(0); | assert(0); | ||||
} | } | ||||
@@ -1167,7 +1178,7 @@ SERVER_EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *par | |||||
max_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.max.ui; | max_ptr->ui = parameter_ptr->constraint_ptr->constraint.range.max.ui; | ||||
return; | return; | ||||
default: | default: | ||||
jack_error("bad driver parameter type %i (range constraint)", (int)parameter_ptr->type); | |||||
jack_error("Bad driver parameter type %i (range constraint)", (int)parameter_ptr->type); | |||||
assert(0); | assert(0); | ||||
} | } | ||||
} | } | ||||
@@ -1307,7 +1318,7 @@ SERVER_EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl | |||||
{ | { | ||||
if (server_ptr && server_ptr->engine) { | if (server_ptr && server_ptr->engine) { | ||||
if (server_ptr->engine->IsRunning()) { | if (server_ptr->engine->IsRunning()) { | ||||
jack_error("cannot add a slave in a running server"); | |||||
jack_error("Cannot add a slave in a running server"); | |||||
return false; | return false; | ||||
} else { | } else { | ||||
JSList * paramlist = jackctl_create_param_list(driver_ptr->parameters); | JSList * paramlist = jackctl_create_param_list(driver_ptr->parameters); | ||||
@@ -1330,7 +1341,7 @@ SERVER_EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jack | |||||
{ | { | ||||
if (server_ptr && server_ptr->engine) { | if (server_ptr && server_ptr->engine) { | ||||
if (server_ptr->engine->IsRunning()) { | if (server_ptr->engine->IsRunning()) { | ||||
jack_error("cannot remove a slave from a running server"); | |||||
jack_error("Cannot remove a slave from a running server"); | |||||
return false; | return false; | ||||
} else { | } else { | ||||
if (driver_ptr->infos) { | if (driver_ptr->infos) { | ||||
@@ -25,15 +25,6 @@ | |||||
#include "jslist.h" | #include "jslist.h" | ||||
#include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
#ifdef WIN32 | |||||
#ifdef __MINGW32__ | |||||
#include <sys/types.h> | |||||
typedef _sigset_t sigset_t; | |||||
#else | |||||
typedef HANDLE sigset_t; | |||||
#endif | |||||
#endif | |||||
/** Parameter types, intentionally similar to jack_driver_param_type_t */ | /** Parameter types, intentionally similar to jack_driver_param_type_t */ | ||||
typedef enum | typedef enum | ||||
{ | { | ||||
@@ -80,6 +71,9 @@ typedef struct jackctl_internal jackctl_internal_t; | |||||
/** opaque type for parameter object */ | /** opaque type for parameter object */ | ||||
typedef struct jackctl_parameter jackctl_parameter_t; | typedef struct jackctl_parameter jackctl_parameter_t; | ||||
/** opaque type for sigmask object */ | |||||
typedef struct jackctl_sigmask jackctl_sigmask_t; | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
@@ -87,13 +81,13 @@ extern "C" { | |||||
} /* Adjust editor indent */ | } /* Adjust editor indent */ | ||||
#endif | #endif | ||||
SERVER_EXPORT sigset_t | |||||
SERVER_EXPORT jackctl_sigmask_t * | |||||
jackctl_setup_signals( | jackctl_setup_signals( | ||||
unsigned int flags); | unsigned int flags); | ||||
SERVER_EXPORT void | SERVER_EXPORT void | ||||
jackctl_wait_signals( | jackctl_wait_signals( | ||||
sigset_t signals); | |||||
jackctl_sigmask_t * signals); | |||||
SERVER_EXPORT jackctl_server_t * | SERVER_EXPORT jackctl_server_t * | ||||
jackctl_server_create( | jackctl_server_create( | ||||
@@ -252,6 +246,9 @@ SERVER_EXPORT bool | |||||
jackctl_server_switch_master(jackctl_server_t * server, | jackctl_server_switch_master(jackctl_server_t * server, | ||||
jackctl_driver_t * driver); | jackctl_driver_t * driver); | ||||
SERVER_EXPORT int | |||||
jackctl_parse_driver_params(jackctl_driver * driver_ptr, int argc, char* argv[]); | |||||
#if 0 | #if 0 | ||||
{ /* Adjust editor indent */ | { /* Adjust editor indent */ | ||||
#endif | #endif | ||||
@@ -115,7 +115,11 @@ int JackDebugClient::Close() | |||||
void JackDebugClient::CheckClient(const char* function_name) const | void JackDebugClient::CheckClient(const char* function_name) const | ||||
{ | { | ||||
#ifdef WIN32 | |||||
*fStream << "CheckClient : " << function_name << ", calling thread : " << GetCurrentThread() << endl; | |||||
#else | |||||
*fStream << "CheckClient : " << function_name << ", calling thread : " << pthread_self() << endl; | *fStream << "CheckClient : " << function_name << ", calling thread : " << pthread_self() << endl; | ||||
#endif | |||||
if (fIsClosed > 0) { | if (fIsClosed > 0) { | ||||
*fStream << "!!! ERROR !!! : Accessing a client '" << fClientName << "' already closed " << "from " << function_name << endl; | *fStream << "!!! ERROR !!! : Accessing a client '" << fClientName << "' already closed " << "from " << function_name << endl; | ||||
@@ -290,13 +294,13 @@ int JackDebugClient::PortDisconnect(jack_port_id_t src) | |||||
{ | { | ||||
CheckClient("PortDisconnect"); | CheckClient("PortDisconnect"); | ||||
if (!fIsActivated) | if (!fIsActivated) | ||||
*fStream << "!!! ERROR !!! : Trying to disconnect port " << src << " while that client has not been activated !" << endl; | |||||
*fStream << "!!! ERROR !!! : Trying to disconnect port " << src << " while that client has not been activated !" << endl; | |||||
int res = fClient->PortDisconnect(src); | int res = fClient->PortDisconnect(src); | ||||
int i; | int i; | ||||
for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history | for (i = (fTotalPortNumber - 1); i >= 0; i--) { // We search the record into the history | ||||
if (fPortList[i].idport == src) { // We found the record in sources | if (fPortList[i].idport == src) { // We found the record in sources | ||||
if (fPortList[i].IsUnregistered != 0) | if (fPortList[i].IsUnregistered != 0) | ||||
*fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl; | |||||
*fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl; | |||||
fPortList[i].IsConnected--; | fPortList[i].IsConnected--; | ||||
*fStream << "Disconnecting port " << src << ". " << endl; | *fStream << "Disconnecting port " << src << ". " << endl; | ||||
break; | break; | ||||
@@ -313,9 +317,17 @@ int JackDebugClient::PortDisconnect(jack_port_id_t src) | |||||
int JackDebugClient::PortIsMine(jack_port_id_t port_index) | int JackDebugClient::PortIsMine(jack_port_id_t port_index) | ||||
{ | { | ||||
CheckClient("PortIsMine"); | CheckClient("PortIsMine"); | ||||
*fStream << "JackClientDebug : PortIsMine port_index " << port_index << endl; | |||||
return fClient->PortIsMine(port_index); | return fClient->PortIsMine(port_index); | ||||
} | } | ||||
int JackDebugClient::PortRename(jack_port_id_t port_index, const char* name) | |||||
{ | |||||
CheckClient("PortRename"); | |||||
*fStream << "JackClientDebug : PortRename port_index " << port_index << "name" << name << endl; | |||||
return fClient->PortRename(port_index, name); | |||||
} | |||||
//-------------------- | //-------------------- | ||||
// Context management | // Context management | ||||
//-------------------- | //-------------------- | ||||
@@ -323,6 +335,7 @@ int JackDebugClient::PortIsMine(jack_port_id_t port_index) | |||||
int JackDebugClient::SetBufferSize(jack_nframes_t buffer_size) | int JackDebugClient::SetBufferSize(jack_nframes_t buffer_size) | ||||
{ | { | ||||
CheckClient("SetBufferSize"); | CheckClient("SetBufferSize"); | ||||
*fStream << "JackClientDebug : SetBufferSize buffer_size " << buffer_size << endl; | |||||
return fClient->SetBufferSize(buffer_size); | return fClient->SetBufferSize(buffer_size); | ||||
} | } | ||||
@@ -330,13 +343,19 @@ int JackDebugClient::SetFreeWheel(int onoff) | |||||
{ | { | ||||
CheckClient("SetFreeWheel"); | CheckClient("SetFreeWheel"); | ||||
if (onoff && fFreewheel) | if (onoff && fFreewheel) | ||||
*fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = ON while FW is already ON " << endl; | |||||
*fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = ON while FW is already ON " << endl; | |||||
if (!onoff && !fFreewheel) | if (!onoff && !fFreewheel) | ||||
*fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = OFF while FW is already OFF " << endl; | |||||
*fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = OFF while FW is already OFF " << endl; | |||||
fFreewheel = onoff ? true : false; | fFreewheel = onoff ? true : false; | ||||
return fClient->SetFreeWheel(onoff); | return fClient->SetFreeWheel(onoff); | ||||
} | } | ||||
int JackDebugClient::ComputeTotalLatencies() | |||||
{ | |||||
CheckClient("ComputeTotalLatencies"); | |||||
return fClient->ComputeTotalLatencies(); | |||||
} | |||||
/* | /* | ||||
ShutDown is called: | ShutDown is called: | ||||
- from the RT thread when Execute method fails | - from the RT thread when Execute method fails | ||||
@@ -346,6 +365,7 @@ ShutDown is called: | |||||
void JackDebugClient::ShutDown() | void JackDebugClient::ShutDown() | ||||
{ | { | ||||
CheckClient("ShutDown"); | |||||
fClient->ShutDown(); | fClient->ShutDown(); | ||||
} | } | ||||
@@ -368,6 +388,7 @@ int JackDebugClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg) | |||||
int JackDebugClient::SetSyncTimeout(jack_time_t timeout) | int JackDebugClient::SetSyncTimeout(jack_time_t timeout) | ||||
{ | { | ||||
CheckClient("SetSyncTimeout"); | CheckClient("SetSyncTimeout"); | ||||
*fStream << "JackClientDebug : SetSyncTimeout timeout " << timeout << endl; | |||||
return fClient->SetSyncTimeout(timeout); | return fClient->SetSyncTimeout(timeout); | ||||
} | } | ||||
@@ -380,6 +401,7 @@ int JackDebugClient::SetTimebaseCallback(int conditional, JackTimebaseCallback t | |||||
void JackDebugClient::TransportLocate(jack_nframes_t frame) | void JackDebugClient::TransportLocate(jack_nframes_t frame) | ||||
{ | { | ||||
CheckClient("TransportLocate"); | CheckClient("TransportLocate"); | ||||
*fStream << "JackClientDebug : TransportLocate frame " << frame << endl; | |||||
fClient->TransportLocate(frame); | fClient->TransportLocate(frame); | ||||
} | } | ||||
@@ -435,10 +457,11 @@ int JackDebugClient::TimeCallback(jack_nframes_t nframes, void *arg) | |||||
jack_time_t t1 = GetMicroSeconds(); | jack_time_t t1 = GetMicroSeconds(); | ||||
int res = client->fProcessTimeCallback(nframes, client->fProcessTimeCallbackArg); | int res = client->fProcessTimeCallback(nframes, client->fProcessTimeCallbackArg); | ||||
if (res == 0) { | if (res == 0) { | ||||
jack_time_t t2 = GetMicroSeconds(); | |||||
jack_time_t t2 = GetMicroSeconds(); | |||||
long delta = long((t2 - t1) - client->GetEngineControl()->fPeriodUsecs); | long delta = long((t2 - t1) - client->GetEngineControl()->fPeriodUsecs); | ||||
if (delta > 0 && !client->fFreewheel) | |||||
if (delta > 0 && !client->fFreewheel) { | |||||
*client->fStream << "!!! ERROR !!! : Process overload of " << delta << " us" << endl; | *client->fStream << "!!! ERROR !!! : Process overload of " << delta << " us" << endl; | ||||
} | |||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
@@ -446,9 +469,17 @@ int JackDebugClient::TimeCallback(jack_nframes_t nframes, void *arg) | |||||
int JackDebugClient::SetProcessCallback(JackProcessCallback callback, void *arg) | int JackDebugClient::SetProcessCallback(JackProcessCallback callback, void *arg) | ||||
{ | { | ||||
CheckClient("SetProcessCallback"); | CheckClient("SetProcessCallback"); | ||||
fProcessTimeCallback = callback; | fProcessTimeCallback = callback; | ||||
fProcessTimeCallbackArg = arg; | fProcessTimeCallbackArg = arg; | ||||
return fClient->SetProcessCallback(TimeCallback, this); | |||||
if (callback == NULL) { | |||||
// Clear the callback... | |||||
return fClient->SetProcessCallback(callback, arg); | |||||
} else { | |||||
// Setup the measuring version... | |||||
return fClient->SetProcessCallback(TimeCallback, this); | |||||
} | |||||
} | } | ||||
int JackDebugClient::SetXRunCallback(JackXRunCallback callback, void *arg) | int JackDebugClient::SetXRunCallback(JackXRunCallback callback, void *arg) | ||||
@@ -517,9 +548,16 @@ int JackDebugClient::SetLatencyCallback(JackLatencyCallback callback, void *arg) | |||||
return fClient->SetLatencyCallback(callback, arg); | return fClient->SetLatencyCallback(callback, arg); | ||||
} | } | ||||
int JackDebugClient::SetProcessThread(JackThreadCallback fun, void *arg) | |||||
{ | |||||
CheckClient("SetProcessThread"); | |||||
return fClient->SetProcessThread(fun, arg); | |||||
} | |||||
jack_session_command_t* JackDebugClient::SessionNotify(const char* target, jack_session_event_type_t type, const char* path) | jack_session_command_t* JackDebugClient::SessionNotify(const char* target, jack_session_event_type_t type, const char* path) | ||||
{ | { | ||||
CheckClient("SessionNotify"); | CheckClient("SessionNotify"); | ||||
*fStream << "JackClientDebug : SessionNotify target " << target << "type " << type << "path " << path << endl; | |||||
return fClient->SessionNotify(target, type, path); | return fClient->SessionNotify(target, type, path); | ||||
} | } | ||||
@@ -532,24 +570,28 @@ int JackDebugClient::SessionReply(jack_session_event_t* ev) | |||||
char* JackDebugClient::GetUUIDForClientName(const char* client_name) | char* JackDebugClient::GetUUIDForClientName(const char* client_name) | ||||
{ | { | ||||
CheckClient("GetUUIDForClientName"); | CheckClient("GetUUIDForClientName"); | ||||
*fStream << "JackClientDebug : GetUUIDForClientName client_name " << client_name << endl; | |||||
return fClient->GetUUIDForClientName(client_name); | return fClient->GetUUIDForClientName(client_name); | ||||
} | } | ||||
char* JackDebugClient::GetClientNameByUUID(const char* uuid) | char* JackDebugClient::GetClientNameByUUID(const char* uuid) | ||||
{ | { | ||||
CheckClient("GetClientNameByUUID"); | CheckClient("GetClientNameByUUID"); | ||||
*fStream << "JackClientDebug : GetClientNameByUUID uuid " << uuid << endl; | |||||
return fClient->GetClientNameByUUID(uuid); | return fClient->GetClientNameByUUID(uuid); | ||||
} | } | ||||
int JackDebugClient::ReserveClientName(const char* client_name, const char* uuid) | int JackDebugClient::ReserveClientName(const char* client_name, const char* uuid) | ||||
{ | { | ||||
CheckClient("ReserveClientName"); | CheckClient("ReserveClientName"); | ||||
*fStream << "JackClientDebug : ReserveClientName client_name " << client_name << "uuid " << uuid << endl; | |||||
return fClient->ReserveClientName(client_name, uuid); | return fClient->ReserveClientName(client_name, uuid); | ||||
} | } | ||||
int JackDebugClient::ClientHasSessionCallback(const char* client_name) | int JackDebugClient::ClientHasSessionCallback(const char* client_name) | ||||
{ | { | ||||
CheckClient("ClientHasSessionCallback"); | CheckClient("ClientHasSessionCallback"); | ||||
*fStream << "JackClientDebug : ClientHasSessionCallback client_name " << client_name << endl; | |||||
return fClient->ClientHasSessionCallback(client_name); | return fClient->ClientHasSessionCallback(client_name); | ||||
} | } | ||||
@@ -46,7 +46,7 @@ PortFollower; | |||||
\brief A "decorator" debug client to validate API use. | \brief A "decorator" debug client to validate API use. | ||||
*/ | */ | ||||
class LIB_EXPORT JackDebugClient : public JackClient | |||||
class JackDebugClient : public JackClient | |||||
{ | { | ||||
protected: | protected: | ||||
@@ -83,6 +83,7 @@ class LIB_EXPORT JackDebugClient : public JackClient | |||||
// Context | // Context | ||||
int SetBufferSize(jack_nframes_t buffer_size); | int SetBufferSize(jack_nframes_t buffer_size); | ||||
int SetFreeWheel(int onoff); | int SetFreeWheel(int onoff); | ||||
int ComputeTotalLatencies(); | |||||
void ShutDown(); | void ShutDown(); | ||||
jack_native_thread_t GetThreadID(); | jack_native_thread_t GetThreadID(); | ||||
@@ -95,6 +96,7 @@ class LIB_EXPORT JackDebugClient : public JackClient | |||||
int PortDisconnect(jack_port_id_t src); | int PortDisconnect(jack_port_id_t src); | ||||
int PortIsMine(jack_port_id_t port_index); | int PortIsMine(jack_port_id_t port_index); | ||||
int PortRename(jack_port_id_t port_index, const char* name); | |||||
// Transport | // Transport | ||||
int ReleaseTimebase(); | int ReleaseTimebase(); | ||||
@@ -129,6 +131,9 @@ class LIB_EXPORT JackDebugClient : public JackClient | |||||
int InternalClientHandle(const char* client_name, jack_status_t* status); | int InternalClientHandle(const char* client_name, jack_status_t* status); | ||||
int InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va); | int InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va); | ||||
void InternalClientUnload(int ref, jack_status_t* status); | void InternalClientUnload(int ref, jack_status_t* status); | ||||
// RT Thread | |||||
int SetProcessThread(JackThreadCallback fun, void *arg); | |||||
// Session API | // Session API | ||||
jack_session_command_t* SessionNotify(const char* target, jack_session_event_type_t type, const char* path); | jack_session_command_t* SessionNotify(const char* target, jack_session_event_type_t type, const char* path); | ||||
@@ -129,10 +129,7 @@ int JackDriver::Open(bool capturing, | |||||
strcpy(fCaptureDriverName, capture_driver_name); | strcpy(fCaptureDriverName, capture_driver_name); | ||||
strcpy(fPlaybackDriverName, playback_driver_name); | strcpy(fPlaybackDriverName, playback_driver_name); | ||||
fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | |||||
if (!fEngineControl->fTimeOut) { | |||||
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | |||||
} | |||||
fEngineControl->UpdateTimeOut(); | |||||
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); | ||||
@@ -183,10 +180,7 @@ int JackDriver::Open(jack_nframes_t buffer_size, | |||||
strcpy(fCaptureDriverName, capture_driver_name); | strcpy(fCaptureDriverName, capture_driver_name); | ||||
strcpy(fPlaybackDriverName, playback_driver_name); | strcpy(fPlaybackDriverName, playback_driver_name); | ||||
fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | |||||
if (!fEngineControl->fTimeOut) { | |||||
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | |||||
} | |||||
fEngineControl->UpdateTimeOut(); | |||||
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 | ||||
@@ -495,7 +489,7 @@ void JackDriver::SaveConnections() | |||||
fConnections.push_back(make_pair(aliases[0], connections[j])); | fConnections.push_back(make_pair(aliases[0], connections[j])); | ||||
jack_info("Save connection: %s %s", aliases[0], connections[j]); | jack_info("Save connection: %s %s", aliases[0], connections[j]); | ||||
*/ | */ | ||||
fConnections.push_back(make_pair(fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j])); | |||||
fConnections.push_back(make_pair(string(fGraphManager->GetPort(fCapturePortList[i])->GetName()), string(connections[j]))); | |||||
jack_info("Save connection: %s %s", fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j]); | jack_info("Save connection: %s %s", fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j]); | ||||
} | } | ||||
free(connections); | free(connections); | ||||
@@ -510,7 +504,7 @@ void JackDriver::SaveConnections() | |||||
fConnections.push_back(make_pair(connections[j], aliases[0])); | fConnections.push_back(make_pair(connections[j], aliases[0])); | ||||
jack_info("Save connection: %s %s", connections[j], aliases[0]); | jack_info("Save connection: %s %s", connections[j], aliases[0]); | ||||
*/ | */ | ||||
fConnections.push_back(make_pair(connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName())); | |||||
fConnections.push_back(make_pair(string(connections[j]), string(fGraphManager->GetPort(fPlaybackPortList[i])->GetName()))); | |||||
jack_info("Save connection: %s %s", connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName()); | jack_info("Save connection: %s %s", connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName()); | ||||
} | } | ||||
free(connections); | free(connections); | ||||
@@ -176,7 +176,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||||
void CycleTakeEndTime(); | void CycleTakeEndTime(); | ||||
void SetupDriverSync(int ref, bool freewheel); | void SetupDriverSync(int ref, bool freewheel); | ||||
void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); // XRun notification sent by the driver | void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); // XRun notification sent by the driver | ||||
void NotifyBufferSize(jack_nframes_t buffer_size); // BufferSize notification sent by the driver | void NotifyBufferSize(jack_nframes_t buffer_size); // BufferSize notification sent by the driver | ||||
void NotifySampleRate(jack_nframes_t sample_rate); // SampleRate notification sent by the driver | void NotifySampleRate(jack_nframes_t sample_rate); // SampleRate notification sent by the driver | ||||
@@ -0,0 +1,55 @@ | |||||
/* | |||||
Copyright (C) 2001-2005 Paul Davis | |||||
Copyright (C) 2004-2008 Grame | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation; either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#ifndef __JackDriverInfo__ | |||||
#define __JackDriverInfo__ | |||||
#include "driver_interface.h" | |||||
#include "JackDriver.h" | |||||
#include "JackSystemDeps.h" | |||||
typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | |||||
class SERVER_EXPORT JackDriverInfo | |||||
{ | |||||
private: | |||||
driverInitialize fInitialize; | |||||
DRIVER_HANDLE fHandle; | |||||
Jack::JackDriverClientInterface* fBackend; | |||||
public: | |||||
JackDriverInfo():fInitialize(NULL),fHandle(NULL),fBackend(NULL) | |||||
{} | |||||
~JackDriverInfo(); | |||||
Jack::JackDriverClientInterface* Open(jack_driver_desc_t* driver_desc, Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | |||||
Jack::JackDriverClientInterface* GetBackend() | |||||
{ | |||||
return fBackend; | |||||
} | |||||
}; | |||||
#endif | |||||
@@ -20,6 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackSystemDeps.h" | #include "JackSystemDeps.h" | ||||
#include "JackDriverLoader.h" | #include "JackDriverLoader.h" | ||||
#include "JackDriverInfo.h" | |||||
#include "JackConstants.h" | #include "JackConstants.h" | ||||
#include "JackError.h" | #include "JackError.h" | ||||
#include <getopt.h> | #include <getopt.h> | ||||
@@ -31,9 +32,57 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include <dirent.h> | #include <dirent.h> | ||||
#endif | #endif | ||||
#ifdef WIN32 | |||||
static char* locate_dll_driver_dir() | |||||
{ | |||||
#ifdef _WIN64 | |||||
HMODULE libjack_handle = LoadLibrary("libjackserver64.dll"); | |||||
#else | |||||
HMODULE libjack_handle = LoadLibrary("libjackserver.dll"); | |||||
#endif | |||||
// For WIN32 ADDON_DIR is defined in JackConstants.h as relative path | |||||
char driver_dir_storage[512]; | |||||
if (3 < GetModuleFileName(libjack_handle, driver_dir_storage, 512)) { | |||||
char *p = strrchr(driver_dir_storage, '\\'); | |||||
if (p && (p != driver_dir_storage)) { | |||||
*p = 0; | |||||
} | |||||
jack_info("Drivers/internals found in : %s", driver_dir_storage); | |||||
strcat(driver_dir_storage, "/"); | |||||
strcat(driver_dir_storage, ADDON_DIR); | |||||
FreeLibrary(libjack_handle); | |||||
return strdup(driver_dir_storage); | |||||
} else { | |||||
jack_error("Cannot get JACK dll directory : %d", GetLastError()); | |||||
FreeLibrary(libjack_handle); | |||||
return NULL; | |||||
} | |||||
} | |||||
static char* locate_driver_dir(HANDLE& file, WIN32_FIND_DATA& filedata) | |||||
{ | |||||
// Search drivers/internals iin the same folder of "libjackserver.dll" | |||||
char* driver_dir = locate_dll_driver_dir(); | |||||
char dll_filename[512]; | |||||
snprintf(dll_filename, sizeof(dll_filename), "%s/*.dll", driver_dir); | |||||
file = (HANDLE)FindFirstFile(dll_filename, &filedata); | |||||
if (file == INVALID_HANDLE_VALUE) { | |||||
jack_error("Drivers not found "); | |||||
free(driver_dir); | |||||
return NULL; | |||||
} else { | |||||
return driver_dir; | |||||
} | |||||
} | |||||
#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) | |||||
void jack_print_driver_options(jack_driver_desc_t* desc, FILE* file) | |||||
{ | { | ||||
unsigned long i; | unsigned long i; | ||||
char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1]; | char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1]; | ||||
@@ -69,15 +118,14 @@ SERVER_EXPORT void jack_print_driver_options(jack_driver_desc_t* desc, FILE* fil | |||||
} | } | ||||
} | } | ||||
static void | |||||
jack_print_driver_param_usage (jack_driver_desc_t* desc, unsigned long param, FILE *file) | |||||
static void 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); | ||||
fprintf (file, "%s\n", desc->params[param].long_desc); | fprintf (file, "%s\n", desc->params[param].long_desc); | ||||
} | } | ||||
SERVER_EXPORT void jack_free_driver_params(JSList * driver_params) | |||||
void jack_free_driver_params(JSList * driver_params) | |||||
{ | { | ||||
JSList*node_ptr = driver_params; | JSList*node_ptr = driver_params; | ||||
JSList*next_node_ptr; | JSList*next_node_ptr; | ||||
@@ -90,8 +138,7 @@ SERVER_EXPORT void jack_free_driver_params(JSList * driver_params) | |||||
} | } | ||||
} | } | ||||
SERVER_EXPORT int | |||||
jack_parse_driver_params(jack_driver_desc_t* desc, int argc, char* argv[], JSList** param_ptr) | |||||
int 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; | ||||
@@ -116,7 +163,7 @@ jack_parse_driver_params(jack_driver_desc_t* desc, int argc, char* argv[], JSLis | |||||
} | } | ||||
} | } | ||||
fprintf (stderr, "jackd: unknown option '%s' " | |||||
fprintf (stderr, "Jackd: unknown option '%s' " | |||||
"for driver '%s'\n", argv[2], | "for driver '%s'\n", argv[2], | ||||
desc->name); | desc->name); | ||||
} | } | ||||
@@ -218,8 +265,7 @@ jack_parse_driver_params(jack_driver_desc_t* desc, int argc, char* argv[], JSLis | |||||
return 0; | return 0; | ||||
} | } | ||||
SERVER_EXPORT int | |||||
jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[]) | |||||
SERVER_EXPORT int jackctl_driver_params_parse(jackctl_driver *driver_ptr, int argc, char* argv[]) | |||||
{ | { | ||||
struct option* long_options; | struct option* long_options; | ||||
char* options, * options_ptr; | char* options, * options_ptr; | ||||
@@ -250,7 +296,7 @@ jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[]) | |||||
} | } | ||||
} | } | ||||
fprintf (stderr, "jackd: unknown option '%s' " | |||||
fprintf (stderr, "Jackd: unknown option '%s' " | |||||
"for driver '%s'\n", argv[2], | "for driver '%s'\n", argv[2], | ||||
desc->name); | desc->name); | ||||
} | } | ||||
@@ -352,8 +398,7 @@ 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; | jack_driver_desc_t* desc = 0; | ||||
JSList* node; | JSList* node; | ||||
@@ -371,193 +416,87 @@ 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 void* check_symbol(const char* sofile, const char* symbol, const char* driver_dir, void** res_dllhandle = NULL) | |||||
{ | { | ||||
jack_driver_desc_t* descriptor, * other_descriptor; | |||||
JackDriverDescFunction so_get_descriptor = NULL; | |||||
JSList* node; | |||||
void * dlhandle; | |||||
char* filename; | |||||
void* dlhandle; | |||||
void* res = NULL; | |||||
char filename[1024]; | |||||
sprintf(filename, "%s/%s", driver_dir, sofile); | |||||
if ((dlhandle = LoadDriverModule(filename)) == NULL) { | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
int dlerr; | |||||
jack_error ("Could not open component .dll '%s': %ld", filename, GetLastError()); | |||||
#else | #else | ||||
const char* dlerr; | |||||
jack_error ("Could not open component .so '%s': %s", filename, dlerror()); | |||||
#endif | #endif | ||||
int err; | |||||
const char* driver_dir; | |||||
if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | |||||
// for WIN32 ADDON_DIR is defined in JackConstants.h as relative path | |||||
// for posix systems, it is absolute path of default driver dir | |||||
#ifdef WIN32 | |||||
char temp_driver_dir1[512]; | |||||
char temp_driver_dir2[512]; | |||||
if (3 < GetModuleFileName(NULL, temp_driver_dir1, 512)) { | |||||
char *p = strrchr(temp_driver_dir1, '\\'); | |||||
if (p && (p != temp_driver_dir1)) | |||||
*p = 0; | |||||
else | |||||
GetCurrentDirectory(512, temp_driver_dir1); | |||||
} else { | |||||
res = (void*)GetDriverProc(dlhandle, symbol); | |||||
if (res_dllhandle) { | |||||
*res_dllhandle = dlhandle; | |||||
} else { | } else { | ||||
GetCurrentDirectory(512, temp_driver_dir1); | |||||
UnloadDriverModule(dlhandle); | |||||
} | } | ||||
sprintf(temp_driver_dir2, "%s/%s", temp_driver_dir1, ADDON_DIR); | |||||
driver_dir = temp_driver_dir2; | |||||
#else | |||||
driver_dir = ADDON_DIR; | |||||
#endif | |||||
} | } | ||||
int len = strlen(driver_dir) + 1 + strlen(sofile) + 1; | |||||
filename = (char*)malloc(len); | |||||
snprintf(filename, len, "%s/%s", driver_dir, sofile); | |||||
if ((dlhandle = LoadDriverModule(filename)) == NULL) { | |||||
#ifdef WIN32 | |||||
jack_error ("could not open driver .dll '%s': %ld", filename, GetLastError()); | |||||
#else | |||||
jack_error ("could not open driver .so '%s': %s", filename, dlerror()); | |||||
#endif | |||||
free(filename); | |||||
return NULL; | |||||
} | |||||
return res; | |||||
} | |||||
so_get_descriptor = (JackDriverDescFunction)GetDriverProc(dlhandle, symbol); | |||||
static jack_driver_desc_t* jack_get_descriptor (JSList* drivers, const char* sofile, const char* symbol, const char* driver_dir) | |||||
{ | |||||
jack_driver_desc_t* descriptor = NULL; | |||||
jack_driver_desc_t* other_descriptor; | |||||
JackDriverDescFunction so_get_descriptor = NULL; | |||||
char filename[1024]; | |||||
JSList* node; | |||||
void* dlhandle; | |||||
#ifdef WIN32 | |||||
if ((so_get_descriptor == NULL) && (dlerr = GetLastError()) != 0) { | |||||
jack_error("jack_get_descriptor : dll is not a driver, err = %ld", dlerr); | |||||
#else | |||||
if ((so_get_descriptor == NULL) && (dlerr = dlerror ()) != NULL) { | |||||
jack_error("jack_get_descriptor err = %s", dlerr); | |||||
#endif | |||||
sprintf(filename, "%s/%s", driver_dir, sofile); | |||||
so_get_descriptor = (JackDriverDescFunction)check_symbol(sofile, symbol, driver_dir, &dlhandle); | |||||
UnloadDriverModule(dlhandle); | |||||
free(filename); | |||||
return NULL; | |||||
if (so_get_descriptor == NULL) { | |||||
jack_error("jack_get_descriptor : dll %s is not a driver", sofile); | |||||
goto error; | |||||
} | } | ||||
if ((descriptor = so_get_descriptor ()) == NULL) { | if ((descriptor = so_get_descriptor ()) == NULL) { | ||||
jack_error("driver from '%s' returned NULL descriptor", filename); | |||||
UnloadDriverModule(dlhandle); | |||||
free(filename); | |||||
return NULL; | |||||
jack_error("Driver from '%s' returned NULL descriptor", filename); | |||||
goto error; | |||||
} | } | ||||
#ifdef WIN32 | |||||
if ((err = UnloadDriverModule(dlhandle)) == 0) { | |||||
jack_error ("error closing driver .so '%s': %ld", filename, GetLastError ()); | |||||
} | |||||
#else | |||||
if ((err = UnloadDriverModule(dlhandle)) != 0) { | |||||
jack_error ("error closing driver .so '%s': %s", filename, dlerror ()); | |||||
} | |||||
#endif | |||||
/* 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", | |||||
other_descriptor->file, filename, other_descriptor->name); | other_descriptor->file, filename, other_descriptor->name); | ||||
/* FIXME: delete the descriptor */ | /* FIXME: delete the descriptor */ | ||||
free(filename); | |||||
return NULL; | |||||
goto error; | |||||
} | } | ||||
} | } | ||||
strncpy(descriptor->file, filename, JACK_PATH_MAX); | strncpy(descriptor->file, filename, JACK_PATH_MAX); | ||||
free(filename); | |||||
return descriptor; | |||||
} | |||||
static bool check_symbol(const char* sofile, const char* symbol) | |||||
{ | |||||
void * dlhandle; | |||||
bool res = false; | |||||
const char* driver_dir; | |||||
error: | |||||
if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | |||||
// for WIN32 ADDON_DIR is defined in JackConstants.h as relative path | |||||
// for posix systems, it is absolute path of default driver dir | |||||
#ifdef WIN32 | |||||
char temp_driver_dir1[512]; | |||||
char temp_driver_dir2[512]; | |||||
if (3 < GetModuleFileName(NULL, temp_driver_dir1, 512)) { | |||||
char *p = strrchr(temp_driver_dir1, '\\'); | |||||
if (p && (p != temp_driver_dir1)) | |||||
*p = 0; | |||||
else | |||||
GetCurrentDirectory(512, temp_driver_dir1); | |||||
} else { | |||||
GetCurrentDirectory(512, temp_driver_dir1); | |||||
} | |||||
snprintf(temp_driver_dir2, sizeof(temp_driver_dir2), "%s/%s", temp_driver_dir1, ADDON_DIR); | |||||
driver_dir = temp_driver_dir2; | |||||
#else | |||||
driver_dir = ADDON_DIR; | |||||
#endif | |||||
} | |||||
int len = strlen(driver_dir) + 1 + strlen(sofile) + 1; | |||||
char* filename = (char*)malloc(len); | |||||
snprintf(filename, len, "%s/%s", driver_dir, sofile); | |||||
if ((dlhandle = LoadDriverModule(filename)) == NULL) { | |||||
#ifdef WIN32 | |||||
jack_error ("could not open component .dll '%s': %ld", filename, GetLastError()); | |||||
#else | |||||
jack_error ("could not open component .so '%s': %s", filename, dlerror()); | |||||
#endif | |||||
} else { | |||||
res = (GetDriverProc(dlhandle, symbol)) ? true : false; | |||||
UnloadDriverModule(dlhandle); | |||||
} | |||||
free(filename); | |||||
return res; | |||||
UnloadDriverModule(dlhandle); | |||||
return descriptor; | |||||
} | } | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
JSList * | |||||
jack_drivers_load (JSList * drivers) { | |||||
char* driver_dir; | |||||
char driver_dir_storage[512]; | |||||
char dll_filename[512]; | |||||
JSList * jack_drivers_load(JSList * drivers) | |||||
{ | |||||
//char dll_filename[512]; | |||||
WIN32_FIND_DATA filedata; | WIN32_FIND_DATA filedata; | ||||
HANDLE file; | HANDLE file; | ||||
const char* ptr = NULL; | const char* ptr = NULL; | ||||
JSList* driver_list = NULL; | JSList* driver_list = NULL; | ||||
jack_driver_desc_t* desc = NULL; | jack_driver_desc_t* desc = NULL; | ||||
if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | |||||
// for WIN32 ADDON_DIR is defined in JackConstants.h as relative path | |||||
if (3 < GetModuleFileName(NULL, driver_dir_storage, 512)) { | |||||
char *p = strrchr(driver_dir_storage, '\\'); | |||||
if (p && (p != driver_dir_storage)) | |||||
*p = 0; | |||||
else | |||||
GetCurrentDirectory(512, driver_dir_storage); | |||||
} else { | |||||
GetCurrentDirectory(512, driver_dir_storage); | |||||
} | |||||
strcat(driver_dir_storage, "/"); | |||||
strcat(driver_dir_storage, ADDON_DIR); | |||||
driver_dir = driver_dir_storage; | |||||
} | |||||
snprintf(dll_filename, sizeof(dll_filename), "%s/*.dll", driver_dir); | |||||
file = (HANDLE )FindFirstFile(dll_filename, &filedata); | |||||
if (file == INVALID_HANDLE_VALUE) { | |||||
jack_error("error invalid handle"); | |||||
return NULL; | |||||
char* driver_dir = locate_driver_dir(file, filedata); | |||||
if (!driver_dir) { | |||||
jack_error("Driver folder not found"); | |||||
goto error; | |||||
} | } | ||||
do { | do { | ||||
@@ -570,17 +509,18 @@ jack_drivers_load (JSList * drivers) { | |||||
if (!ptr) { | if (!ptr) { | ||||
continue; | continue; | ||||
} | } | ||||
ptr++; | ptr++; | ||||
if (strncmp ("dll", ptr, 3) != 0) { | if (strncmp ("dll", ptr, 3) != 0) { | ||||
continue; | continue; | ||||
} | } | ||||
/* check if dll is an internal client */ | /* check if dll is an internal client */ | ||||
if (check_symbol(filedata.cFileName, "jack_internal_initialize")) { | |||||
continue; | |||||
if (check_symbol(filedata.cFileName, "jack_internal_initialize", driver_dir) != NULL) { | |||||
continue; | |||||
} | } | ||||
desc = jack_get_descriptor (drivers, filedata.cFileName, "driver_get_descriptor"); | |||||
desc = jack_get_descriptor (drivers, filedata.cFileName, "driver_get_descriptor", driver_dir); | |||||
if (desc) { | if (desc) { | ||||
driver_list = jack_slist_append (driver_list, desc); | driver_list = jack_slist_append (driver_list, desc); | ||||
} else { | } else { | ||||
@@ -590,17 +530,21 @@ jack_drivers_load (JSList * drivers) { | |||||
} while (FindNextFile(file, &filedata)); | } while (FindNextFile(file, &filedata)); | ||||
if (!driver_list) { | if (!driver_list) { | ||||
jack_error ("could not find any drivers in %s!", driver_dir); | |||||
return NULL; | |||||
jack_error ("Could not find any drivers in %s!", driver_dir); | |||||
} | } | ||||
error: | |||||
if (driver_dir) { | |||||
free(driver_dir); | |||||
} | |||||
FindClose(file); | |||||
return driver_list; | return driver_list; | ||||
} | } | ||||
#else | #else | ||||
JSList * | |||||
jack_drivers_load (JSList * drivers) { | |||||
JSList* 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; | ||||
@@ -617,7 +561,7 @@ jack_drivers_load (JSList * drivers) { | |||||
from the .so files in it */ | from the .so files in it */ | ||||
dir_stream = opendir (driver_dir); | dir_stream = opendir (driver_dir); | ||||
if (!dir_stream) { | if (!dir_stream) { | ||||
jack_error ("could not open driver directory %s: %s", | |||||
jack_error ("Could not open driver directory %s: %s", | |||||
driver_dir, strerror (errno)); | driver_dir, strerror (errno)); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -639,11 +583,11 @@ jack_drivers_load (JSList * drivers) { | |||||
} | } | ||||
/* check if dll is an internal client */ | /* check if dll is an internal client */ | ||||
if (check_symbol(dir_entry->d_name, "jack_internal_initialize")) { | |||||
continue; | |||||
if (check_symbol(dir_entry->d_name, "jack_internal_initialize", driver_dir) != NULL) { | |||||
continue; | |||||
} | } | ||||
desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor"); | |||||
desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor", driver_dir); | |||||
if (desc) { | if (desc) { | ||||
driver_list = jack_slist_append (driver_list, desc); | driver_list = jack_slist_append (driver_list, desc); | ||||
} else { | } else { | ||||
@@ -653,12 +597,12 @@ jack_drivers_load (JSList * drivers) { | |||||
err = closedir (dir_stream); | err = closedir (dir_stream); | ||||
if (err) { | if (err) { | ||||
jack_error ("error closing driver directory %s: %s", | |||||
jack_error ("Error closing driver directory %s: %s", | |||||
driver_dir, strerror (errno)); | driver_dir, strerror (errno)); | ||||
} | } | ||||
if (!driver_list) { | if (!driver_list) { | ||||
jack_error ("could not find any drivers in %s!", driver_dir); | |||||
jack_error ("Could not find any drivers in %s!", driver_dir); | |||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -669,40 +613,19 @@ jack_drivers_load (JSList * drivers) { | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
JSList * | |||||
jack_internals_load (JSList * internals) { | |||||
char* driver_dir; | |||||
char driver_dir_storage[512]; | |||||
char dll_filename[512]; | |||||
JSList* jack_internals_load(JSList * internals) | |||||
{ | |||||
///char dll_filename[512]; | |||||
WIN32_FIND_DATA filedata; | WIN32_FIND_DATA filedata; | ||||
HANDLE file; | HANDLE file; | ||||
const char* ptr = NULL; | const char* ptr = NULL; | ||||
JSList* driver_list = NULL; | JSList* driver_list = NULL; | ||||
jack_driver_desc_t* desc; | jack_driver_desc_t* desc; | ||||
if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) { | |||||
// for WIN32 ADDON_DIR is defined in JackConstants.h as relative path | |||||
if (3 < GetModuleFileName(NULL, driver_dir_storage, 512)) { | |||||
char *p = strrchr(driver_dir_storage, '\\'); | |||||
if (p && (p != driver_dir_storage)) | |||||
*p = 0; | |||||
else | |||||
GetCurrentDirectory(512, driver_dir_storage); | |||||
} else { | |||||
GetCurrentDirectory(512, driver_dir_storage); | |||||
} | |||||
strcat(driver_dir_storage, "/"); | |||||
strcat(driver_dir_storage, ADDON_DIR); | |||||
driver_dir = driver_dir_storage; | |||||
} | |||||
snprintf(dll_filename, sizeof(dll_filename), "%s/*.dll", driver_dir); | |||||
file = (HANDLE )FindFirstFile(dll_filename, &filedata); | |||||
if (file == INVALID_HANDLE_VALUE) { | |||||
jack_error("could not open driver directory %s", driver_dir); | |||||
return NULL; | |||||
char* driver_dir = locate_driver_dir(file, filedata); | |||||
if (!driver_dir) { | |||||
jack_error("Driver folder not found"); | |||||
goto error; | |||||
} | } | ||||
do { | do { | ||||
@@ -711,17 +634,18 @@ jack_internals_load (JSList * internals) { | |||||
if (!ptr) { | if (!ptr) { | ||||
continue; | continue; | ||||
} | } | ||||
ptr++; | ptr++; | ||||
if (strncmp ("dll", ptr, 3) != 0) { | if (strncmp ("dll", ptr, 3) != 0) { | ||||
continue; | continue; | ||||
} | } | ||||
/* check if dll is an internal client */ | /* check if dll is an internal client */ | ||||
if (!check_symbol(filedata.cFileName, "jack_internal_initialize")) { | |||||
continue; | |||||
if (check_symbol(filedata.cFileName, "jack_internal_initialize", driver_dir) == NULL) { | |||||
continue; | |||||
} | } | ||||
desc = jack_get_descriptor (internals, filedata.cFileName, "jack_get_descriptor"); | |||||
desc = jack_get_descriptor (internals, filedata.cFileName, "jack_get_descriptor", driver_dir); | |||||
if (desc) { | if (desc) { | ||||
driver_list = jack_slist_append (driver_list, desc); | driver_list = jack_slist_append (driver_list, desc); | ||||
} else { | } else { | ||||
@@ -731,17 +655,21 @@ jack_internals_load (JSList * internals) { | |||||
} while (FindNextFile(file, &filedata)); | } while (FindNextFile(file, &filedata)); | ||||
if (!driver_list) { | if (!driver_list) { | ||||
jack_error ("could not find any internals in %s!", driver_dir); | |||||
return NULL; | |||||
jack_error ("Could not find any internals in %s!", driver_dir); | |||||
} | } | ||||
error: | |||||
if (driver_dir) { | |||||
free(driver_dir); | |||||
} | |||||
FindClose(file); | |||||
return driver_list; | return driver_list; | ||||
} | } | ||||
#else | #else | ||||
JSList * | |||||
jack_internals_load (JSList * internals) { | |||||
JSList* 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; | ||||
@@ -758,7 +686,7 @@ jack_internals_load (JSList * internals) { | |||||
from the .so files in it */ | from the .so files in it */ | ||||
dir_stream = opendir (driver_dir); | dir_stream = opendir (driver_dir); | ||||
if (!dir_stream) { | if (!dir_stream) { | ||||
jack_error ("could not open driver directory %s: %s\n", | |||||
jack_error ("Could not open driver directory %s: %s\n", | |||||
driver_dir, strerror (errno)); | driver_dir, strerror (errno)); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -769,17 +697,18 @@ jack_internals_load (JSList * internals) { | |||||
if (!ptr) { | if (!ptr) { | ||||
continue; | continue; | ||||
} | } | ||||
ptr++; | ptr++; | ||||
if (strncmp ("so", ptr, 2) != 0) { | if (strncmp ("so", ptr, 2) != 0) { | ||||
continue; | continue; | ||||
} | } | ||||
/* check if dll is an internal client */ | /* check if dll is an internal client */ | ||||
if (!check_symbol(dir_entry->d_name, "jack_internal_initialize")) { | |||||
continue; | |||||
if (check_symbol(dir_entry->d_name, "jack_internal_initialize", driver_dir) == NULL) { | |||||
continue; | |||||
} | } | ||||
desc = jack_get_descriptor (internals, dir_entry->d_name, "jack_get_descriptor"); | |||||
desc = jack_get_descriptor (internals, dir_entry->d_name, "jack_get_descriptor", driver_dir); | |||||
if (desc) { | if (desc) { | ||||
driver_list = jack_slist_append (driver_list, desc); | driver_list = jack_slist_append (driver_list, desc); | ||||
} else { | } else { | ||||
@@ -789,12 +718,12 @@ jack_internals_load (JSList * internals) { | |||||
err = closedir (dir_stream); | err = closedir (dir_stream); | ||||
if (err) { | if (err) { | ||||
jack_error ("error closing internal directory %s: %s\n", | |||||
jack_error ("Error closing internal directory %s: %s\n", | |||||
driver_dir, strerror (errno)); | driver_dir, strerror (errno)); | ||||
} | } | ||||
if (!driver_list) { | if (!driver_list) { | ||||
jack_error ("could not find any internals in %s!", driver_dir); | |||||
jack_error ("Could not find any internals in %s!", driver_dir); | |||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -819,14 +748,14 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||||
if (fHandle == NULL) { | if (fHandle == NULL) { | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
if ((errstr = GetLastError ()) != 0) { | if ((errstr = GetLastError ()) != 0) { | ||||
jack_error ("can't load \"%s\": %ld", driver_desc->file, errstr); | |||||
jack_error ("Can't load \"%s\": %ld", driver_desc->file, errstr); | |||||
#else | #else | ||||
if ((errstr = dlerror ()) != 0) { | if ((errstr = dlerror ()) != 0) { | ||||
jack_error ("can't load \"%s\": %s", driver_desc->file, errstr); | |||||
jack_error ("Can't load \"%s\": %s", driver_desc->file, errstr); | |||||
#endif | #endif | ||||
} else { | } else { | ||||
jack_error ("bizarre error loading driver shared object %s", driver_desc->file); | |||||
jack_error ("Error loading driver shared object %s", driver_desc->file); | |||||
} | } | ||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -838,7 +767,7 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||||
#else | #else | ||||
if ((fInitialize == NULL) && (errstr = dlerror ()) != 0) { | if ((fInitialize == NULL) && (errstr = dlerror ()) != 0) { | ||||
#endif | #endif | ||||
jack_error("no initialize function in shared object %s\n", driver_desc->file); | |||||
jack_error("No initialize function in shared object %s\n", driver_desc->file); | |||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -849,13 +778,12 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||||
JackDriverInfo::~JackDriverInfo() | JackDriverInfo::~JackDriverInfo() | ||||
{ | { | ||||
delete fBackend; | delete fBackend; | ||||
if (fHandle) | |||||
if (fHandle) { | |||||
UnloadDriverModule(fHandle); | UnloadDriverModule(fHandle); | ||||
} | |||||
} | } | ||||
SERVER_EXPORT | |||||
jack_driver_desc_t* | |||||
jack_driver_descriptor_construct( | |||||
SERVER_EXPORT jack_driver_desc_t* jack_driver_descriptor_construct( | |||||
const char * name, | const char * name, | ||||
jack_driver_type_t type, | jack_driver_type_t type, | ||||
const char * description, | const char * description, | ||||
@@ -876,7 +804,7 @@ jack_driver_descriptor_construct( | |||||
desc_ptr = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t)); | desc_ptr = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t)); | ||||
if (desc_ptr == NULL) { | if (desc_ptr == NULL) { | ||||
jack_error("calloc() failed to allocate memory for driver descriptor struct"); | |||||
jack_error("Error calloc() failed to allocate memory for driver descriptor struct"); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -893,9 +821,7 @@ jack_driver_descriptor_construct( | |||||
return desc_ptr; | return desc_ptr; | ||||
} | } | ||||
SERVER_EXPORT | |||||
int | |||||
jack_driver_descriptor_add_parameter( | |||||
SERVER_EXPORT int 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, | ||||
@@ -933,7 +859,7 @@ jack_driver_descriptor_add_parameter( | |||||
newsize = filler_ptr->size + 20; // most drivers have less than 20 parameters | newsize = filler_ptr->size + 20; // most drivers have less than 20 parameters | ||||
param_ptr = (jack_driver_param_desc_t*)realloc (desc_ptr->params, newsize * sizeof (jack_driver_param_desc_t)); | param_ptr = (jack_driver_param_desc_t*)realloc (desc_ptr->params, newsize * sizeof (jack_driver_param_desc_t)); | ||||
if (param_ptr == NULL) { | if (param_ptr == NULL) { | ||||
jack_error("realloc() failed for parameter array of %zu elements", newsize); | |||||
jack_error("Error realloc() failed for parameter array of %zu elements", newsize); | |||||
return false; | return false; | ||||
} | } | ||||
filler_ptr->size = newsize; | filler_ptr->size = newsize; | ||||
@@ -952,6 +878,5 @@ jack_driver_descriptor_add_parameter( | |||||
memcpy(param_ptr->long_desc, long_desc, long_desc_len + 1); | memcpy(param_ptr->long_desc, long_desc, long_desc_len + 1); | ||||
desc_ptr->nparams++; | desc_ptr->nparams++; | ||||
return true; | return true; | ||||
} | } |
@@ -24,53 +24,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "driver_interface.h" | #include "driver_interface.h" | ||||
#include "JackControlAPI.h" | #include "JackControlAPI.h" | ||||
#include "JackPlatformPlug.h" | #include "JackPlatformPlug.h" | ||||
#include "JackDriver.h" | |||||
#include "JackSystemDeps.h" | |||||
typedef jack_driver_desc_t* (*JackDriverDescFunction) (); | |||||
typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | |||||
class SERVER_EXPORT JackDriverInfo | |||||
{ | |||||
private: | |||||
driverInitialize fInitialize; | |||||
DRIVER_HANDLE fHandle; | |||||
Jack::JackDriverClientInterface* fBackend; | |||||
public: | |||||
JackDriverInfo():fInitialize(NULL),fHandle(NULL),fBackend(NULL) | |||||
{} | |||||
~JackDriverInfo(); | |||||
Jack::JackDriverClientInterface* Open(jack_driver_desc_t* driver_desc, Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | |||||
Jack::JackDriverClientInterface* GetBackend() | |||||
{ | |||||
return fBackend; | |||||
} | |||||
}; | |||||
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_drivers_load(JSList* drivers); | ||||
JSList* jack_internals_load(JSList* internals); | JSList* jack_internals_load(JSList* internals); | ||||
void jack_free_driver_params(JSList * param_ptr); | |||||
void jack_print_driver_options(jack_driver_desc_t* desc, FILE* file); | |||||
#ifdef __cplusplus | |||||
extern "C" | |||||
{ | |||||
#endif | |||||
SERVER_EXPORT int jackctl_parse_driver_params(jackctl_driver * driver_ptr, int argc, char* argv[]); | |||||
SERVER_EXPORT void jack_free_driver_params(JSList * param_ptr); | |||||
SERVER_EXPORT void jack_print_driver_options(jack_driver_desc_t* desc, FILE* file); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
// External control.h API | |||||
extern "C" SERVER_EXPORT int jackctl_driver_params_parse(jackctl_driver * driver, int argc, char* argv[]); | |||||
#endif | #endif | ||||
@@ -38,13 +38,16 @@ namespace Jack | |||||
JackEngine::JackEngine(JackGraphManager* manager, | JackEngine::JackEngine(JackGraphManager* manager, | ||||
JackSynchro* table, | JackSynchro* table, | ||||
JackEngineControl* control) | |||||
JackEngineControl* control) | |||||
: JackLockAble(control->fServerName), | |||||
fSignal(control->fServerName) | |||||
{ | { | ||||
fGraphManager = manager; | fGraphManager = manager; | ||||
fSynchroTable = table; | fSynchroTable = table; | ||||
fEngineControl = control; | fEngineControl = control; | ||||
for (int i = 0; i < CLIENT_NUM; i++) | |||||
for (int i = 0; i < CLIENT_NUM; i++) { | |||||
fClientTable[i] = NULL; | fClientTable[i] = NULL; | ||||
} | |||||
fLastSwitchUsecs = 0; | fLastSwitchUsecs = 0; | ||||
fMaxUUID = 0; | fMaxUUID = 0; | ||||
fSessionPendingReplies = 0; | fSessionPendingReplies = 0; | ||||
@@ -78,20 +81,33 @@ int JackEngine::Close() | |||||
if (JackLoadableInternalClient* loadable_client = dynamic_cast<JackLoadableInternalClient*>(fClientTable[i])) { | if (JackLoadableInternalClient* loadable_client = dynamic_cast<JackLoadableInternalClient*>(fClientTable[i])) { | ||||
jack_log("JackEngine::Close loadable client = %s", loadable_client->GetClientControl()->fName); | jack_log("JackEngine::Close loadable client = %s", loadable_client->GetClientControl()->fName); | ||||
loadable_client->Close(); | loadable_client->Close(); | ||||
// Close does not delete the pointer for internal clients | |||||
fClientTable[i] = NULL; | fClientTable[i] = NULL; | ||||
delete loadable_client; | delete loadable_client; | ||||
} else if (JackExternalClient* external_client = dynamic_cast<JackExternalClient*>(fClientTable[i])) { | } else if (JackExternalClient* external_client = dynamic_cast<JackExternalClient*>(fClientTable[i])) { | ||||
jack_log("JackEngine::Close external client = %s", external_client->GetClientControl()->fName); | jack_log("JackEngine::Close external client = %s", external_client->GetClientControl()->fName); | ||||
external_client->Close(); | external_client->Close(); | ||||
// Close deletes the pointer for external clients | |||||
fClientTable[i] = NULL; | fClientTable[i] = NULL; | ||||
delete external_client; | |||||
} | } | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
void JackEngine::ShutDown() | |||||
{ | |||||
jack_log("JackEngine::ShutDown"); | |||||
// Shutdown remaining clients (RT is stopped) | |||||
for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) { | |||||
if (JackLoadableInternalClient* loadable_client = dynamic_cast<JackLoadableInternalClient*>(fClientTable[i])) { | |||||
jack_log("JackEngine::ShutDown loadable client = %s", loadable_client->GetClientControl()->fName); | |||||
loadable_client->ShutDown(); | |||||
} | |||||
} | |||||
} | |||||
void JackEngine::NotifyQuit() | void JackEngine::NotifyQuit() | ||||
{ | { | ||||
fChannel.NotifyQuit(); | fChannel.NotifyQuit(); | ||||
@@ -119,8 +135,9 @@ void JackEngine::ReleaseRefnum(int ref) | |||||
if (fEngineControl->fTemporary) { | if (fEngineControl->fTemporary) { | ||||
int i; | int i; | ||||
for (i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) { | for (i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) { | ||||
if (fClientTable[i]) | |||||
if (fClientTable[i]) { | |||||
break; | break; | ||||
} | |||||
} | } | ||||
if (i == CLIENT_NUM) { | if (i == CLIENT_NUM) { | ||||
// last client and temporay case: quit the server | // last client and temporay case: quit the server | ||||
@@ -146,8 +163,9 @@ void JackEngine::ProcessNext(jack_time_t cur_cycle_begin) | |||||
void JackEngine::ProcessCurrent(jack_time_t cur_cycle_begin) | void JackEngine::ProcessCurrent(jack_time_t cur_cycle_begin) | ||||
{ | { | ||||
if (cur_cycle_begin < fLastSwitchUsecs + 2 * fEngineControl->fPeriodUsecs) // Signal XRun only for the first failing cycle | |||||
if (cur_cycle_begin < fLastSwitchUsecs + 2 * fEngineControl->fPeriodUsecs) { // Signal XRun only for the first failing cycle | |||||
CheckXRun(cur_cycle_begin); | CheckXRun(cur_cycle_begin); | ||||
} | |||||
fGraphManager->RunCurrentGraph(); | fGraphManager->RunCurrentGraph(); | ||||
} | } | ||||
@@ -157,7 +175,7 @@ bool JackEngine::Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end | |||||
// Cycle begin | // Cycle begin | ||||
fEngineControl->CycleBegin(fClientTable, fGraphManager, cur_cycle_begin, prev_cycle_end); | fEngineControl->CycleBegin(fClientTable, fGraphManager, cur_cycle_begin, prev_cycle_end); | ||||
// Graph | // Graph | ||||
if (fGraphManager->IsFinishedGraph()) { | if (fGraphManager->IsFinishedGraph()) { | ||||
ProcessNext(cur_cycle_begin); | ProcessNext(cur_cycle_begin); | ||||
@@ -236,26 +254,42 @@ int JackEngine::ComputeTotalLatencies() | |||||
// Notifications | // Notifications | ||||
//--------------- | //--------------- | ||||
int JackEngine::ClientNotify(JackClientInterface* client, int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) | |||||
{ | |||||
if (!client) { | |||||
return 0; | |||||
} | |||||
if (!client->GetClientControl()->fCallback[notify]) { | |||||
jack_log("JackEngine::ClientNotify: no callback for notification = %ld", notify); | |||||
return 0; | |||||
} | |||||
int ret; | |||||
// External client | |||||
if (dynamic_cast<JackExternalClient*>(client)) { | |||||
ret = client->ClientNotify(refnum, name, notify, sync, message, value1, value2); | |||||
// Important for internal client : unlock before calling the notification callbacks | |||||
} else { | |||||
bool res = Unlock(); | |||||
ret = client->ClientNotify(refnum, name, notify, sync, message, value1, value2); | |||||
if (res) { | |||||
Lock(); | |||||
} | |||||
} | |||||
if (ret < 0) { | |||||
jack_error("NotifyClient fails name = %s notification = %ld val1 = %ld val2 = %ld", name, notify, value1, value2); | |||||
} | |||||
return ret; | |||||
} | |||||
void JackEngine::NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2) | void JackEngine::NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2) | ||||
{ | { | ||||
JackClientInterface* client = fClientTable[refnum]; | JackClientInterface* client = fClientTable[refnum]; | ||||
// The client may be notified by the RT thread while closing | |||||
if (client) { | if (client) { | ||||
if (client->GetClientControl()->fCallback[event]) { | |||||
/* | |||||
Important for internal clients : unlock before calling the notification callbacks. | |||||
*/ | |||||
bool res = Unlock(); | |||||
if (client->ClientNotify(refnum, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0) | |||||
jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2); | |||||
if (res) | |||||
Lock(); | |||||
} else { | |||||
jack_log("JackEngine::NotifyClient: no callback for event = %ld", event); | |||||
} | |||||
ClientNotify(client, refnum, client->GetClientControl()->fName, event, sync, message, value1, value2); | |||||
} | } | ||||
} | } | ||||
@@ -266,19 +300,21 @@ void JackEngine::NotifyClients(int event, int sync, const char* message, int val | |||||
} | } | ||||
} | } | ||||
int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* name, int refnum) | |||||
int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* new_name, int refnum) | |||||
{ | { | ||||
jack_log("JackEngine::NotifyAddClient: name = %s", name); | |||||
jack_log("JackEngine::NotifyAddClient: name = %s", new_name); | |||||
// Notify existing clients of the new client and new client of existing clients. | // Notify existing clients of the new client and new client of existing clients. | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* old_client = fClientTable[i]; | JackClientInterface* old_client = fClientTable[i]; | ||||
if (old_client && old_client != new_client) { | if (old_client && old_client != new_client) { | ||||
if (old_client->ClientNotify(refnum, name, kAddClient, false, "", 0, 0) < 0) { | |||||
jack_error("NotifyAddClient old_client fails name = %s", old_client->GetClientControl()->fName); | |||||
char* old_name = old_client->GetClientControl()->fName; | |||||
if (ClientNotify(old_client, refnum, new_name, kAddClient, false, "", 0, 0) < 0) { | |||||
jack_error("NotifyAddClient old_client fails name = %s", old_name); | |||||
// Not considered as a failure... | // Not considered as a failure... | ||||
} | } | ||||
if (new_client->ClientNotify(i, old_client->GetClientControl()->fName, kAddClient, true, "", 0, 0) < 0) { | |||||
jack_error("NotifyAddClient new_client fails name = %s", name); | |||||
if (ClientNotify(new_client, i, old_name, kAddClient, true, "", 0, 0) < 0) { | |||||
jack_error("NotifyAddClient new_client fails name = %s", new_name); | |||||
return -1; | return -1; | ||||
} | } | ||||
} | } | ||||
@@ -291,10 +327,7 @@ void JackEngine::NotifyRemoveClient(const char* name, int refnum) | |||||
{ | { | ||||
// Notify existing clients (including the one beeing suppressed) of the removed client | // Notify existing clients (including the one beeing suppressed) of the removed client | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | |||||
if (client) { | |||||
client->ClientNotify(refnum, name, kRemoveClient, false, "", 0, 0); | |||||
} | |||||
ClientNotify(fClientTable[i], refnum, name, kRemoveClient, false, "", 0, 0); | |||||
} | } | ||||
} | } | ||||
@@ -491,13 +524,15 @@ bool JackEngine::ClientCheckName(const char* name) | |||||
{ | { | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | JackClientInterface* client = fClientTable[i]; | ||||
if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) | |||||
if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) { | |||||
return true; | return true; | ||||
} | |||||
} | } | ||||
for (std::map<int,std::string>::iterator i = fReservationMap.begin(); i != fReservationMap.end(); i++) { | for (std::map<int,std::string>::iterator i = fReservationMap.begin(); i != fReservationMap.end(); i++) { | ||||
if (i->second == name) | |||||
if (i->second == name) { | |||||
return true; | return true; | ||||
} | |||||
} | } | ||||
return false; | return false; | ||||
@@ -510,8 +545,9 @@ int JackEngine::GetNewUUID() | |||||
void JackEngine::EnsureUUID(int uuid) | void JackEngine::EnsureUUID(int uuid) | ||||
{ | { | ||||
if (uuid > fMaxUUID) | |||||
fMaxUUID = uuid+1; | |||||
if (uuid > fMaxUUID) { | |||||
fMaxUUID = uuid + 1; | |||||
} | |||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | JackClientInterface* client = fClientTable[i]; | ||||
@@ -525,8 +561,9 @@ int JackEngine::GetClientPID(const char* name) | |||||
{ | { | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | JackClientInterface* client = fClientTable[i]; | ||||
if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) | |||||
if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) { | |||||
return client->GetClientControl()->fPID; | return client->GetClientControl()->fPID; | ||||
} | |||||
} | } | ||||
return 0; | return 0; | ||||
@@ -536,8 +573,9 @@ int JackEngine::GetClientRefNum(const char* name) | |||||
{ | { | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | JackClientInterface* client = fClientTable[i]; | ||||
if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) | |||||
if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) { | |||||
return client->GetClientControl()->fRefNum; | return client->GetClientControl()->fRefNum; | ||||
} | |||||
} | } | ||||
return -1; | return -1; | ||||
@@ -657,9 +695,9 @@ error: | |||||
// Used for external clients | // Used for external clients | ||||
int JackEngine::ClientExternalClose(int refnum) | int JackEngine::ClientExternalClose(int refnum) | ||||
{ | { | ||||
jack_log("JackEngine::ClientExternalClose ref = %ld", refnum); | |||||
JackClientInterface* client = fClientTable[refnum]; | JackClientInterface* client = fClientTable[refnum]; | ||||
fEngineControl->fTransport.ResetTimebase(refnum); | |||||
int res = ClientCloseAux(refnum, client, true); | |||||
int res = ClientCloseAux(refnum, true); | |||||
client->Close(); | client->Close(); | ||||
delete client; | delete client; | ||||
return res; | return res; | ||||
@@ -668,13 +706,16 @@ int JackEngine::ClientExternalClose(int refnum) | |||||
// Used for server internal clients or drivers when the RT thread is stopped | // Used for server internal clients or drivers when the RT thread is stopped | ||||
int JackEngine::ClientInternalClose(int refnum, bool wait) | int JackEngine::ClientInternalClose(int refnum, bool wait) | ||||
{ | { | ||||
JackClientInterface* client = fClientTable[refnum]; | |||||
return ClientCloseAux(refnum, client, wait); | |||||
jack_log("JackEngine::ClientInternalClose ref = %ld", refnum); | |||||
return ClientCloseAux(refnum, wait); | |||||
} | } | ||||
int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wait) | |||||
int JackEngine::ClientCloseAux(int refnum, bool wait) | |||||
{ | { | ||||
jack_log("JackEngine::ClientCloseAux ref = %ld", refnum); | jack_log("JackEngine::ClientCloseAux ref = %ld", refnum); | ||||
JackClientInterface* client = fClientTable[refnum]; | |||||
fEngineControl->fTransport.ResetTimebase(refnum); | |||||
// Unregister all ports ==> notifications are sent | // Unregister all ports ==> notifications are sent | ||||
jack_int_t ports[PORT_NUM_FOR_CLIENT]; | jack_int_t ports[PORT_NUM_FOR_CLIENT]; | ||||
@@ -717,8 +758,9 @@ int JackEngine::ClientActivate(int refnum, bool is_real_time) | |||||
JackClientInterface* client = fClientTable[refnum]; | JackClientInterface* client = fClientTable[refnum]; | ||||
jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName); | jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName); | ||||
if (is_real_time) | |||||
if (is_real_time) { | |||||
fGraphManager->Activate(refnum); | fGraphManager->Activate(refnum); | ||||
} | |||||
// Wait for graph state change to be effective | // Wait for graph state change to be effective | ||||
if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) { | if (!fSignal.LockedTimedWait(fEngineControl->fTimeOutUsecs * 10)) { | ||||
@@ -802,8 +844,9 @@ int JackEngine::PortRegister(int refnum, const char* name, const char *type, uns | |||||
// buffer_size is actually ignored... | // buffer_size is actually ignored... | ||||
*port_index = fGraphManager->AllocatePort(refnum, name, type, (JackPortFlags)flags, fEngineControl->fBufferSize); | *port_index = fGraphManager->AllocatePort(refnum, name, type, (JackPortFlags)flags, fEngineControl->fBufferSize); | ||||
if (*port_index != NO_PORT) { | if (*port_index != NO_PORT) { | ||||
if (client->GetClientControl()->fActive) | |||||
if (client->GetClientControl()->fActive) { | |||||
NotifyPortRegistation(*port_index, true); | NotifyPortRegistation(*port_index, true); | ||||
} | |||||
return 0; | return 0; | ||||
} else { | } else { | ||||
return -1; | return -1; | ||||
@@ -819,8 +862,9 @@ int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index) | |||||
PortDisconnect(refnum, port_index, ALL_PORTS); | PortDisconnect(refnum, port_index, ALL_PORTS); | ||||
if (fGraphManager->ReleasePort(refnum, port_index) == 0) { | if (fGraphManager->ReleasePort(refnum, port_index) == 0) { | ||||
if (client->GetClientControl()->fActive) | |||||
if (client->GetClientControl()->fActive) { | |||||
NotifyPortRegistation(port_index, false); | NotifyPortRegistation(port_index, false); | ||||
} | |||||
return 0; | return 0; | ||||
} else { | } else { | ||||
return -1; | return -1; | ||||
@@ -843,8 +887,9 @@ int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst) | |||||
JackClientInterface* client; | JackClientInterface* client; | ||||
int ref; | int ref; | ||||
if (fGraphManager->CheckPorts(src, dst) < 0) | |||||
if (fGraphManager->CheckPorts(src, dst) < 0) { | |||||
return -1; | return -1; | ||||
} | |||||
ref = fGraphManager->GetOutputRefNum(src); | ref = fGraphManager->GetOutputRefNum(src); | ||||
assert(ref >= 0); | assert(ref >= 0); | ||||
@@ -867,8 +912,9 @@ int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst) | |||||
} | } | ||||
int res = fGraphManager->Connect(src, dst); | int res = fGraphManager->Connect(src, dst); | ||||
if (res == 0) | |||||
if (res == 0) { | |||||
NotifyPortConnect(src, dst, true); | NotifyPortConnect(src, dst, true); | ||||
} | |||||
return res; | return res; | ||||
} | } | ||||
@@ -932,7 +978,7 @@ int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name) | |||||
// Session management | // Session management | ||||
//-------------------- | //-------------------- | ||||
void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket, JackSessionNotifyResult** result) | |||||
void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, detail::JackChannelTransactionInterface *socket, JackSessionNotifyResult** result) | |||||
{ | { | ||||
if (fSessionPendingReplies != 0) { | if (fSessionPendingReplies != 0) { | ||||
JackSessionNotifyResult res(-1); | JackSessionNotifyResult res(-1); | ||||
@@ -967,8 +1013,9 @@ void JackEngine::SessionNotify(int refnum, const char *target, jack_session_even | |||||
snprintf(path_buf, sizeof(path_buf), "%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR); | snprintf(path_buf, sizeof(path_buf), "%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR); | ||||
int res = JackTools::MkDir(path_buf); | int res = JackTools::MkDir(path_buf); | ||||
if (res) | |||||
if (res) { | |||||
jack_error("JackEngine::SessionNotify: can not create session directory '%s'", path_buf); | jack_error("JackEngine::SessionNotify: can not create session directory '%s'", path_buf); | ||||
} | |||||
int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, true, path_buf, (int)type, 0); | int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, true, path_buf, (int)type, 0); | ||||
@@ -1000,7 +1047,7 @@ void JackEngine::SessionNotify(int refnum, const char *target, jack_session_even | |||||
} | } | ||||
} | } | ||||
void JackEngine::SessionReply(int refnum) | |||||
int JackEngine::SessionReply(int refnum) | |||||
{ | { | ||||
JackClientInterface* client = fClientTable[refnum]; | JackClientInterface* client = fClientTable[refnum]; | ||||
char uuid_buf[JACK_UUID_SIZE]; | char uuid_buf[JACK_UUID_SIZE]; | ||||
@@ -1013,78 +1060,78 @@ void JackEngine::SessionReply(int refnum) | |||||
if (fSessionPendingReplies == 0) { | if (fSessionPendingReplies == 0) { | ||||
fSessionResult->Write(fSessionTransaction); | fSessionResult->Write(fSessionTransaction); | ||||
if (fSessionTransaction != NULL) | |||||
{ | |||||
if (fSessionTransaction != NULL) { | |||||
delete fSessionResult; | delete fSessionResult; | ||||
} | } | ||||
fSessionResult = NULL; | fSessionResult = NULL; | ||||
} | } | ||||
return 0; | |||||
} | } | ||||
void JackEngine::GetUUIDForClientName(const char *client_name, char *uuid_res, int *result) | |||||
int JackEngine::GetUUIDForClientName(const char *client_name, char *uuid_res) | |||||
{ | { | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | JackClientInterface* client = fClientTable[i]; | ||||
if (client && (strcmp(client_name, client->GetClientControl()->fName) == 0)) { | if (client && (strcmp(client_name, client->GetClientControl()->fName) == 0)) { | ||||
snprintf(uuid_res, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); | snprintf(uuid_res, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); | ||||
*result = 0; | |||||
return; | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
// Did not find name. | // Did not find name. | ||||
*result = -1; | |||||
return -1; | |||||
} | } | ||||
void JackEngine::GetClientNameForUUID(const char *uuid, char *name_res, int *result) | |||||
int JackEngine::GetClientNameForUUID(const char *uuid, char *name_res) | |||||
{ | { | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | JackClientInterface* client = fClientTable[i]; | ||||
if (!client) | |||||
if (!client) { | |||||
continue; | continue; | ||||
} | |||||
char uuid_buf[JACK_UUID_SIZE]; | char uuid_buf[JACK_UUID_SIZE]; | ||||
snprintf(uuid_buf, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); | snprintf(uuid_buf, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); | ||||
if (strcmp(uuid,uuid_buf) == 0) { | if (strcmp(uuid,uuid_buf) == 0) { | ||||
strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE); | strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE); | ||||
*result = 0; | |||||
return; | |||||
return 0; | |||||
} | } | ||||
} | } | ||||
// Did not find uuid. | // Did not find uuid. | ||||
*result = -1; | |||||
return -1; | |||||
} | } | ||||
void JackEngine::ReserveClientName(const char *name, const char *uuid, int *result) | |||||
int JackEngine::ReserveClientName(const char *name, const char *uuid) | |||||
{ | { | ||||
jack_log("JackEngine::ReserveClientName ( name = %s, uuid = %s )", name, uuid); | jack_log("JackEngine::ReserveClientName ( name = %s, uuid = %s )", name, uuid); | ||||
if (ClientCheckName(name)) { | if (ClientCheckName(name)) { | ||||
*result = -1; | |||||
jack_log("name already taken"); | jack_log("name already taken"); | ||||
return; | |||||
return -1; | |||||
} | } | ||||
EnsureUUID(atoi(uuid)); | EnsureUUID(atoi(uuid)); | ||||
fReservationMap[atoi(uuid)] = name; | fReservationMap[atoi(uuid)] = name; | ||||
*result = 0; | |||||
return 0; | |||||
} | } | ||||
void JackEngine::ClientHasSessionCallback(const char *name, int *result) | |||||
int JackEngine::ClientHasSessionCallback(const char *name) | |||||
{ | { | ||||
JackClientInterface* client = NULL; | JackClientInterface* client = NULL; | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
client = fClientTable[i]; | client = fClientTable[i]; | ||||
if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) | |||||
if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) { | |||||
break; | break; | ||||
} | |||||
} | } | ||||
if (client) { | if (client) { | ||||
*result = client->GetClientControl()->fCallback[kSessionCallback]; | |||||
return client->GetClientControl()->fCallback[kSessionCallback]; | |||||
} else { | } else { | ||||
*result = -1; | |||||
return -1; | |||||
} | } | ||||
} | } | ||||
@@ -26,6 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackMutex.h" | #include "JackMutex.h" | ||||
#include "JackTransportEngine.h" | #include "JackTransportEngine.h" | ||||
#include "JackPlatformPlug.h" | #include "JackPlatformPlug.h" | ||||
#include "JackRequest.h" | |||||
#include "JackChannel.h" | |||||
#include <map> | #include <map> | ||||
namespace Jack | namespace Jack | ||||
@@ -54,15 +56,15 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||||
jack_time_t fLastSwitchUsecs; | jack_time_t fLastSwitchUsecs; | ||||
int fSessionPendingReplies; | int fSessionPendingReplies; | ||||
JackChannelTransaction* fSessionTransaction; | |||||
detail::JackChannelTransactionInterface* fSessionTransaction; | |||||
JackSessionNotifyResult* fSessionResult; | JackSessionNotifyResult* fSessionResult; | ||||
std::map<int,std::string> fReservationMap; | std::map<int,std::string> fReservationMap; | ||||
int fMaxUUID; | int fMaxUUID; | ||||
int ClientCloseAux(int refnum, JackClientInterface* client, bool wait); | |||||
int ClientCloseAux(int refnum, bool wait); | |||||
void CheckXRun(jack_time_t callback_usecs); | void CheckXRun(jack_time_t callback_usecs); | ||||
int NotifyAddClient(JackClientInterface* new_client, const char* name, int refnum); | |||||
int NotifyAddClient(JackClientInterface* new_client, const char* new_name, int refnum); | |||||
void NotifyRemoveClient(const char* name, int refnum); | void NotifyRemoveClient(const char* name, int refnum); | ||||
void ProcessNext(jack_time_t callback_usecs); | void ProcessNext(jack_time_t callback_usecs); | ||||
@@ -74,6 +76,8 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||||
int AllocateRefnum(); | int AllocateRefnum(); | ||||
void ReleaseRefnum(int ref); | void ReleaseRefnum(int ref); | ||||
int ClientNotify(JackClientInterface* client, int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); | |||||
void NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2); | void NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2); | ||||
void NotifyClients(int event, int sync, const char* message, int value1, int value2); | void NotifyClients(int event, int sync, const char* message, int value1, int value2); | ||||
@@ -97,6 +101,8 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||||
int Open(); | int Open(); | ||||
int Close(); | int Close(); | ||||
void ShutDown(); | |||||
// Client management | // Client management | ||||
int ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status); | int ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status); | ||||
@@ -145,13 +151,13 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||||
void NotifyQuit(); | void NotifyQuit(); | ||||
// Session management | // Session management | ||||
void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket, JackSessionNotifyResult** result); | |||||
void SessionReply(int refnum); | |||||
void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, detail::JackChannelTransactionInterface *socket, JackSessionNotifyResult** result); | |||||
int SessionReply(int refnum); | |||||
void GetUUIDForClientName(const char *client_name, char *uuid_res, int *result); | |||||
void GetClientNameForUUID(const char *uuid, char *name_res, int *result); | |||||
void ReserveClientName(const char *name, const char *uuid, int *result); | |||||
void ClientHasSessionCallback(const char *name, int *result); | |||||
int GetUUIDForClientName(const char *client_name, char *uuid_res); | |||||
int GetClientNameForUUID(const char *uuid, char *name_res); | |||||
int ReserveClientName(const char *name, const char *uuid); | |||||
int ClientHasSessionCallback(const char *name); | |||||
}; | }; | ||||
@@ -97,10 +97,11 @@ void JackEngineControl::ResetRollingUsecs() | |||||
void JackEngineControl::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) | void JackEngineControl::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs) | ||||
{ | { | ||||
ResetFrameTime(callback_usecs); | |||||
ResetFrameTime(callback_usecs); | |||||
fXrunDelayedUsecs = delayed_usecs; | fXrunDelayedUsecs = delayed_usecs; | ||||
if (delayed_usecs > fMaxDelayedUsecs) | |||||
if (delayed_usecs > fMaxDelayedUsecs) { | |||||
fMaxDelayedUsecs = delayed_usecs; | fMaxDelayedUsecs = delayed_usecs; | ||||
} | |||||
} | } | ||||
} // end of namespace | } // end of namespace |
@@ -124,6 +124,14 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem | |||||
~JackEngineControl() | ~JackEngineControl() | ||||
{} | {} | ||||
void UpdateTimeOut() | |||||
{ | |||||
fPeriodUsecs = jack_time_t(1000000.f / fSampleRate * fBufferSize); // In microsec | |||||
if (!(fTimeOut && fTimeOutUsecs > 2 * fPeriodUsecs)) { | |||||
fTimeOutUsecs = 2 * fPeriodUsecs; | |||||
} | |||||
} | |||||
// Cycle | // Cycle | ||||
void CycleIncTime(jack_time_t callback_usecs) | void CycleIncTime(jack_time_t callback_usecs) | ||||
@@ -154,7 +162,7 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem | |||||
void ResetFrameTime(jack_time_t callback_usecs) | void ResetFrameTime(jack_time_t callback_usecs) | ||||
{ | { | ||||
fFrameTimer.ResetFrameTime(fSampleRate, callback_usecs, fPeriodUsecs); | |||||
fFrameTimer.ResetFrameTime(callback_usecs); | |||||
} | } | ||||
void ReadFrameTime(JackTimer* timer) | void ReadFrameTime(JackTimer* timer) | ||||
@@ -2,21 +2,21 @@ | |||||
Copyright (C) 2001 Paul Davis | Copyright (C) 2001 Paul Davis | ||||
Copyright (C) 2004-2008 Grame | Copyright (C) 2004-2008 Grame | ||||
Copyright (C) 2008 Nedko Arnaudov | Copyright (C) 2008 Nedko Arnaudov | ||||
This program is free software; you can redistribute it and/or modify | This program is free software; you can redistribute it and/or modify | ||||
it under the terms of the GNU Lesser General Public License as published by | it under the terms of the GNU Lesser General Public License as published by | ||||
the Free Software Foundation; either version 2.1 of the License, or | the Free Software Foundation; either version 2.1 of the License, or | ||||
(at your option) any later version. | (at your option) any later version. | ||||
This program is distributed in the hope that it will be useful, | This program is distributed in the hope that it will be useful, | ||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | ||||
You should have received a copy of the GNU Lesser General Public License | You should have received a copy of the GNU Lesser General Public License | ||||
along with this program; if not, write to the Free Software | along with this program; if not, write to the Free Software | ||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | */ | ||||
#include <stdarg.h> | #include <stdarg.h> | ||||
@@ -29,7 +29,7 @@ using namespace Jack; | |||||
static bool change_thread_log_function(jack_log_function_t log_function) | static bool change_thread_log_function(jack_log_function_t log_function) | ||||
{ | { | ||||
return (jack_tls_get(JackGlobals::fKeyLogFunction) == NULL | |||||
return (jack_tls_get(JackGlobals::fKeyLogFunction) == NULL | |||||
&& jack_tls_set(JackGlobals::fKeyLogFunction, (void*)log_function)); | && jack_tls_set(JackGlobals::fKeyLogFunction, (void*)log_function)); | ||||
} | } | ||||
@@ -31,14 +31,8 @@ extern "C" | |||||
{ | { | ||||
#endif | #endif | ||||
#define LOG_LEVEL_INFO 1 | |||||
#define LOG_LEVEL_ERROR 2 | |||||
SERVER_EXPORT void jack_error(const char *fmt, ...); | SERVER_EXPORT void jack_error(const char *fmt, ...); | ||||
SERVER_EXPORT void jack_info(const char *fmt, ...); | SERVER_EXPORT void jack_info(const char *fmt, ...); | ||||
// like jack_info() but only if verbose mode is enabled | |||||
SERVER_EXPORT void jack_log(const char *fmt, ...); | SERVER_EXPORT void jack_log(const char *fmt, ...); | ||||
SERVER_EXPORT extern void (*jack_error_callback)(const char *desc); | SERVER_EXPORT extern void (*jack_error_callback)(const char *desc); | ||||
@@ -47,14 +41,16 @@ extern "C" | |||||
SERVER_EXPORT extern void default_jack_error_callback(const char *desc); | SERVER_EXPORT extern void default_jack_error_callback(const char *desc); | ||||
SERVER_EXPORT extern void default_jack_info_callback(const char *desc); | SERVER_EXPORT extern void default_jack_info_callback(const char *desc); | ||||
SERVER_EXPORT extern void silent_jack_error_callback(const char *desc); | |||||
SERVER_EXPORT extern void silent_jack_info_callback(const char *desc); | |||||
SERVER_EXPORT void silent_jack_error_callback(const char *desc); | |||||
SERVER_EXPORT void silent_jack_info_callback(const char *desc); | |||||
typedef void (* jack_log_function_t)(int level, const char *message); | |||||
SERVER_EXPORT int set_threaded_log_function(); | |||||
void jack_log_function(int level, const char *message); | |||||
#define LOG_LEVEL_INFO 1 | |||||
#define LOG_LEVEL_ERROR 2 | |||||
SERVER_EXPORT int set_threaded_log_function(); | |||||
void jack_log_function(int level, const char *message); | |||||
typedef void (* jack_log_function_t)(int level, const char *message); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
@@ -0,0 +1,34 @@ | |||||
/* | |||||
Copyright (C) 2008 Grame | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation; either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | |||||
#include "JackException.h" | |||||
#include "JackError.h" | |||||
namespace Jack | |||||
{ | |||||
void JackException::PrintMessage() | |||||
{ | |||||
std::string str = what(); | |||||
if (str != "") { | |||||
jack_info(str.c_str()); | |||||
} | |||||
} | |||||
} |
@@ -20,10 +20,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#ifndef __JackException__ | #ifndef __JackException__ | ||||
#define __JackException__ | #define __JackException__ | ||||
#include "JackCompilerDeps.h" | |||||
#include <stdexcept> | #include <stdexcept> | ||||
#include <iostream> | #include <iostream> | ||||
#include <string> | #include <string> | ||||
#include "JackError.h" | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -55,14 +56,9 @@ class SERVER_EXPORT JackException : public std::runtime_error { | |||||
return what(); | return what(); | ||||
} | } | ||||
void PrintMessage() | |||||
{ | |||||
std::string str = what(); | |||||
if (str != "") { | |||||
jack_info(str.c_str()); | |||||
} | |||||
} | |||||
}; | |||||
void PrintMessage(); | |||||
}; | |||||
/*! | /*! | ||||
\brief Exception thrown by JackEngine in temporary mode. | \brief Exception thrown by JackEngine in temporary mode. | ||||
@@ -43,14 +43,26 @@ JackTimer::JackTimer() | |||||
fCurrentWakeup = 0; | fCurrentWakeup = 0; | ||||
fCurrentCallback = 0; | fCurrentCallback = 0; | ||||
fNextWakeUp = 0; | fNextWakeUp = 0; | ||||
fFilterCoefficient = 0.01f; | |||||
fSecondOrderIntegrator = 0.0f; | |||||
fPeriodUsecs = 0.0f; | |||||
fFilterOmega = 0.0f; /* Initialised later */ | |||||
} | } | ||||
jack_nframes_t JackTimer::Time2Frames(jack_time_t time, jack_nframes_t buffer_size) | |||||
jack_nframes_t JackTimer::Time2Frames(jack_time_t usecs, jack_nframes_t buffer_size) | |||||
{ | { | ||||
if (fInitialized) { | if (fInitialized) { | ||||
return fFrames + (long)rint(((double) ((long long)(time - fCurrentWakeup)) / ((long long)(fNextWakeUp - fCurrentWakeup))) * buffer_size); | |||||
/* | |||||
Make sure we have signed differences. It would make a lot of sense | |||||
to use the standard signed intNN_t types everywhere instead of e.g. | |||||
jack_nframes_t and jack_time_t. This would at least ensure that the | |||||
types used below are the correct ones. There is no way to get a type | |||||
that would be 'a signed version of jack_time_t' for example - the | |||||
types below are inherently fragile and there is no automatic way to | |||||
check they are the correct ones. The only way is to check manually | |||||
against jack/types.h. FA - 16/02/2012 | |||||
*/ | |||||
int64_t du = usecs - fCurrentWakeup; | |||||
int64_t dp = fNextWakeUp - fCurrentWakeup; | |||||
return fFrames + (int32_t)rint((double)du / (double)dp * buffer_size); | |||||
} else { | } else { | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -59,12 +71,37 @@ jack_nframes_t JackTimer::Time2Frames(jack_time_t time, jack_nframes_t buffer_si | |||||
jack_time_t JackTimer::Frames2Time(jack_nframes_t frames, jack_nframes_t buffer_size) | jack_time_t JackTimer::Frames2Time(jack_nframes_t frames, jack_nframes_t buffer_size) | ||||
{ | { | ||||
if (fInitialized) { | if (fInitialized) { | ||||
return fCurrentWakeup + (long)rint(((double) ((long long)(frames - fFrames)) * ((long long)(fNextWakeUp - fCurrentWakeup))) / buffer_size); | |||||
/* | |||||
Make sure we have signed differences. It would make a lot of sense | |||||
to use the standard signed intNN_t types everywhere instead of e.g. | |||||
jack_nframes_t and jack_time_t. This would at least ensure that the | |||||
types used below are the correct ones. There is no way to get a type | |||||
that would be 'a signed version of jack_time_t' for example - the | |||||
types below are inherently fragile and there is no automatic way to | |||||
check they are the correct ones. The only way is to check manually | |||||
against jack/types.h. FA - 16/02/2012 | |||||
*/ | |||||
int32_t df = frames - fFrames; | |||||
int64_t dp = fNextWakeUp - fCurrentWakeup; | |||||
return fCurrentWakeup + (int64_t)rint((double) df * (double) dp / buffer_size); | |||||
} else { | } else { | ||||
return 0; | return 0; | ||||
} | } | ||||
} | } | ||||
int JackTimer::GetCycleTimes(jack_nframes_t* current_frames, jack_time_t* current_usecs, jack_time_t* next_usecs, float* period_usecs) | |||||
{ | |||||
if (fInitialized) { | |||||
*current_frames = fFrames; | |||||
*current_usecs = fCurrentWakeup; | |||||
*next_usecs = fNextWakeUp; | |||||
*period_usecs = fPeriodUsecs; | |||||
return 0; | |||||
} else { | |||||
return -1; | |||||
} | |||||
} | |||||
jack_nframes_t JackTimer::FramesSinceCycleStart(jack_time_t cur_time, jack_nframes_t frames_rate) | jack_nframes_t JackTimer::FramesSinceCycleStart(jack_time_t cur_time, jack_nframes_t frames_rate) | ||||
{ | { | ||||
return (jack_nframes_t) floor((((float)frames_rate) / 1000000.0f) * (cur_time - fCurrentCallback)); | return (jack_nframes_t) floor((((float)frames_rate) / 1000000.0f) * (cur_time - fCurrentCallback)); | ||||
@@ -80,20 +117,17 @@ void JackFrameTimer::IncFrameTime(jack_nframes_t buffer_size, jack_time_t callba | |||||
if (fFirstWakeUp) { | if (fFirstWakeUp) { | ||||
InitFrameTimeAux(callback_usecs, period_usecs); | InitFrameTimeAux(callback_usecs, period_usecs); | ||||
fFirstWakeUp = false; | fFirstWakeUp = false; | ||||
} else { | |||||
IncFrameTimeAux(buffer_size, callback_usecs, period_usecs); | |||||
} | } | ||||
IncFrameTimeAux(buffer_size, callback_usecs, period_usecs); | |||||
} | } | ||||
void JackFrameTimer::ResetFrameTime(jack_nframes_t frames_rate, jack_time_t callback_usecs, jack_time_t period_usecs) | |||||
void JackFrameTimer::ResetFrameTime(jack_time_t callback_usecs) | |||||
{ | { | ||||
if (!fFirstWakeUp) { // ResetFrameTime may be called by a xrun/delayed wakeup on the first cycle | if (!fFirstWakeUp) { // ResetFrameTime may be called by a xrun/delayed wakeup on the first cycle | ||||
JackTimer* timer = WriteNextStateStart(); | JackTimer* timer = WriteNextStateStart(); | ||||
jack_nframes_t period_size_guess = (jack_nframes_t)(frames_rate * ((timer->fNextWakeUp - timer->fCurrentWakeup) / 1000000.0)); | |||||
timer->fFrames += ((callback_usecs - timer->fNextWakeUp) / period_size_guess) * period_size_guess; | |||||
timer->fCurrentWakeup = callback_usecs; | timer->fCurrentWakeup = callback_usecs; | ||||
timer->fCurrentCallback = callback_usecs; | timer->fCurrentCallback = callback_usecs; | ||||
timer->fNextWakeUp = callback_usecs + period_usecs; | |||||
WriteNextStateStop(); | WriteNextStateStop(); | ||||
TrySwitchState(); // always succeed since there is only one writer | TrySwitchState(); // always succeed since there is only one writer | ||||
} | } | ||||
@@ -119,10 +153,44 @@ void JackFrameTimer::ReadFrameTime(JackTimer* timer) | |||||
void JackFrameTimer::InitFrameTimeAux(jack_time_t callback_usecs, jack_time_t period_usecs) | void JackFrameTimer::InitFrameTimeAux(jack_time_t callback_usecs, jack_time_t period_usecs) | ||||
{ | { | ||||
/* the first wakeup or post-freewheeling or post-xrun */ | |||||
/* There seems to be no significant difference between | |||||
the two conditions OR-ed above. Incrementing the | |||||
frame_time after an xrun shouldn't harm, as there | |||||
will be a discontinuity anyway. So the two are | |||||
combined in this version. | |||||
FA 16/03/2012 | |||||
*/ | |||||
/* Since the DLL *will* be run, next_wakeup should be the | |||||
current wakeup time *without* adding the period time, as | |||||
if it were computed in the previous period. | |||||
FA 16/03/2012 | |||||
*/ | |||||
/* Added initialisation of timer->period_usecs, required | |||||
due to the modified implementation of the DLL itself. | |||||
OTOH, this should maybe not be repeated after e.g. | |||||
freewheeling or an xrun, as the current value would be | |||||
more accurate than the nominal one. But it doesn't really | |||||
harm either. Implementing this would require a new flag | |||||
in the engine structure, to be used after freewheeling | |||||
or an xrun instead of first_wakeup. I don't know if this | |||||
can be done without breaking compatibility, so I did not | |||||
add this | |||||
FA 13/02/2012 | |||||
*/ | |||||
/* Added initialisation of timer->filter_omega. This makes | |||||
the DLL bandwidth independent of the actual period time. | |||||
The bandwidth is now 1/8 Hz in all cases. The value of | |||||
timer->filter_omega is 2 * pi * BW * Tperiod. | |||||
FA 13/02/2012 | |||||
*/ | |||||
JackTimer* timer = WriteNextStateStart(); | JackTimer* timer = WriteNextStateStart(); | ||||
timer->fSecondOrderIntegrator = 0.0f; | |||||
timer->fPeriodUsecs = (float)period_usecs; | |||||
timer->fCurrentCallback = callback_usecs; | timer->fCurrentCallback = callback_usecs; | ||||
timer->fNextWakeUp = callback_usecs + period_usecs; | |||||
timer->fNextWakeUp = callback_usecs; | |||||
timer->fFilterOmega = period_usecs * 7.854e-7f; | |||||
WriteNextStateStop(); | WriteNextStateStop(); | ||||
TrySwitchState(); // always succeed since there is only one writer | TrySwitchState(); // always succeed since there is only one writer | ||||
} | } | ||||
@@ -130,13 +198,38 @@ void JackFrameTimer::InitFrameTimeAux(jack_time_t callback_usecs, jack_time_t pe | |||||
void JackFrameTimer::IncFrameTimeAux(jack_nframes_t buffer_size, jack_time_t callback_usecs, jack_time_t period_usecs) | void JackFrameTimer::IncFrameTimeAux(jack_nframes_t buffer_size, jack_time_t callback_usecs, jack_time_t period_usecs) | ||||
{ | { | ||||
JackTimer* timer = WriteNextStateStart(); | JackTimer* timer = WriteNextStateStart(); | ||||
float delta = (int64_t)callback_usecs - (int64_t)timer->fNextWakeUp; | |||||
/* Modified implementation (the actual result is the same). | |||||
'fSecondOrderIntegrator' is renamed to 'fPeriodUsecs' | |||||
and now represents the DLL's best estimate of the | |||||
period time in microseconds (before it was a scaled | |||||
version of the difference w.r.t. the nominal value). | |||||
This allows this value to be made available to clients | |||||
that are interested in it (see jack_get_cycle_times). | |||||
This change also means that 'fPeriodUsecs' must be | |||||
initialised to the nominal period time instead of zero. | |||||
This is done in the first cycle in jack_run_cycle(). | |||||
'fFilterCoefficient' is renamed to 'fFilterOmega'. It | |||||
is now equal to the 'omega' value as defined in the | |||||
'Using a DLL to filter time' paper (before it was a | |||||
scaled version of this value). It is computed once in | |||||
jack_run_cycle() rather than set to a fixed value. This | |||||
makes the DLL bandwidth independent of the period time. | |||||
FA 13/02/2012 | |||||
*/ | |||||
float delta = (float)((int64_t)callback_usecs - (int64_t)timer->fNextWakeUp); | |||||
delta *= timer->fFilterOmega; | |||||
timer->fCurrentWakeup = timer->fNextWakeUp; | timer->fCurrentWakeup = timer->fNextWakeUp; | ||||
timer->fCurrentCallback = callback_usecs; | timer->fCurrentCallback = callback_usecs; | ||||
timer->fFrames += buffer_size; | timer->fFrames += buffer_size; | ||||
timer->fSecondOrderIntegrator += 0.5f * timer->fFilterCoefficient * delta; | |||||
timer->fNextWakeUp = timer->fCurrentWakeup + period_usecs + (int64_t) floorf((timer->fFilterCoefficient * (delta + timer->fSecondOrderIntegrator))); | |||||
timer->fPeriodUsecs += timer->fFilterOmega * delta; | |||||
timer->fNextWakeUp += (int64_t)floorf(timer->fPeriodUsecs + 1.41f * delta + 0.5f); | |||||
timer->fInitialized = true; | timer->fInitialized = true; | ||||
WriteNextStateStop(); | WriteNextStateStop(); | ||||
TrySwitchState(); // always succeed since there is only one writer | TrySwitchState(); // always succeed since there is only one writer | ||||
} | } | ||||
@@ -44,8 +44,8 @@ class SERVER_EXPORT JackTimer | |||||
jack_time_t fCurrentWakeup; | jack_time_t fCurrentWakeup; | ||||
jack_time_t fCurrentCallback; | jack_time_t fCurrentCallback; | ||||
jack_time_t fNextWakeUp; | jack_time_t fNextWakeUp; | ||||
float fSecondOrderIntegrator; | |||||
float fFilterCoefficient; /* set once, never altered */ | |||||
float fPeriodUsecs; | |||||
float fFilterOmega; /* set once, never altered */ | |||||
bool fInitialized; | bool fInitialized; | ||||
public: | public: | ||||
@@ -57,6 +57,7 @@ class SERVER_EXPORT JackTimer | |||||
jack_nframes_t Time2Frames(jack_time_t time, jack_nframes_t buffer_size); | jack_nframes_t Time2Frames(jack_time_t time, jack_nframes_t buffer_size); | ||||
jack_time_t Frames2Time(jack_nframes_t frames, jack_nframes_t buffer_size); | jack_time_t Frames2Time(jack_nframes_t frames, jack_nframes_t buffer_size); | ||||
jack_nframes_t FramesSinceCycleStart(jack_time_t cur_time, jack_nframes_t frames_rate); | jack_nframes_t FramesSinceCycleStart(jack_time_t cur_time, jack_nframes_t frames_rate); | ||||
int GetCycleTimes(jack_nframes_t* current_frames, jack_time_t* current_usecs, jack_time_t* next_usecs, float* period_usecs); | |||||
jack_nframes_t CurFrame() | jack_nframes_t CurFrame() | ||||
{ | { | ||||
@@ -92,7 +93,7 @@ class SERVER_EXPORT JackFrameTimer : public JackAtomicState<JackTimer> | |||||
{} | {} | ||||
void InitFrameTime(); | void InitFrameTime(); | ||||
void ResetFrameTime(jack_nframes_t frames_rate, jack_time_t callback_usecs, jack_time_t period_usecs); | |||||
void ResetFrameTime(jack_time_t callback_usecs); | |||||
void IncFrameTime(jack_nframes_t buffer_size, jack_time_t callback_usecs, jack_time_t period_usecs); | void IncFrameTime(jack_nframes_t buffer_size, jack_time_t callback_usecs, jack_time_t period_usecs); | ||||
void ReadFrameTime(JackTimer* timer); | void ReadFrameTime(JackTimer* timer); | ||||
@@ -37,7 +37,8 @@ int JackFreewheelDriver::Process() | |||||
if (fEngine->Process(fBeginDateUst, fEndDateUst)) { | if (fEngine->Process(fBeginDateUst, fEndDateUst)) { | ||||
if (ResumeRefNum()) { // Signal all clients | |||||
// Resume connected clients in the graph | |||||
if (ResumeRefNum()) { | |||||
jack_error("JackFreewheelDriver::Process: ResumeRefNum error"); | jack_error("JackFreewheelDriver::Process: ResumeRefNum error"); | ||||
res = -1; | res = -1; | ||||
} | } | ||||
@@ -61,6 +62,7 @@ int JackFreewheelDriver::Process() | |||||
int JackFreewheelDriver::ProcessReadSync() | int JackFreewheelDriver::ProcessReadSync() | ||||
{ | { | ||||
// Resume connected clients in the graph | |||||
if (ResumeRefNum() < 0) { // Signal all clients | if (ResumeRefNum() < 0) { // Signal all clients | ||||
jack_error("JackFreewheelDriver::ProcessReadSync: ResumeRefNum error"); | jack_error("JackFreewheelDriver::ProcessReadSync: ResumeRefNum error"); | ||||
return -1; | return -1; | ||||
@@ -80,6 +82,7 @@ int JackFreewheelDriver::ProcessWriteSync() | |||||
int JackFreewheelDriver::ProcessReadAsync() | int JackFreewheelDriver::ProcessReadAsync() | ||||
{ | { | ||||
// Resume connected clients in the graph | |||||
if (ResumeRefNum() < 0) { // Signal all clients | if (ResumeRefNum() < 0) { // Signal all clients | ||||
jack_error("JackFreewheelDriver::ProcessReadAsync: ResumeRefNum error"); | jack_error("JackFreewheelDriver::ProcessReadAsync: ResumeRefNum error"); | ||||
return -1; | return -1; | ||||
@@ -0,0 +1,298 @@ | |||||
/* | |||||
Copyright (C) 2004-2008 Grame | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#include "JackGenericClientChannel.h" | |||||
#include "JackClient.h" | |||||
#include "JackGlobals.h" | |||||
#include "JackError.h" | |||||
namespace Jack | |||||
{ | |||||
JackGenericClientChannel::JackGenericClientChannel() | |||||
{} | |||||
JackGenericClientChannel::~JackGenericClientChannel() | |||||
{} | |||||
int JackGenericClientChannel::ServerCheck(const char* server_name) | |||||
{ | |||||
jack_log("JackGenericClientChannel::ServerCheck = %s", server_name); | |||||
// Connect to server | |||||
if (fRequest->Connect(jack_server_dir, server_name, 0) < 0) { | |||||
jack_error("Cannot connect to server request channel"); | |||||
return -1; | |||||
} else { | |||||
return 0; | |||||
} | |||||
} | |||||
void JackGenericClientChannel::ServerSyncCall(JackRequest* req, JackResult* res, int* result) | |||||
{ | |||||
// Check call context | |||||
if (jack_tls_get(JackGlobals::fNotificationThread)) { | |||||
jack_error("Cannot callback the server in notification thread!"); | |||||
*result = -1; | |||||
return; | |||||
} | |||||
if (req->Write(fRequest) < 0) { | |||||
jack_error("Could not write request type = %ld", req->fType); | |||||
*result = -1; | |||||
return; | |||||
} | |||||
if (res->Read(fRequest) < 0) { | |||||
jack_error("Could not read result type = %ld", req->fType); | |||||
*result = -1; | |||||
return; | |||||
} | |||||
*result = res->fResult; | |||||
} | |||||
void JackGenericClientChannel::ServerAsyncCall(JackRequest* req, JackResult* res, int* result) | |||||
{ | |||||
// Check call context | |||||
if (jack_tls_get(JackGlobals::fNotificationThread)) { | |||||
jack_error("Cannot callback the server in notification thread!"); | |||||
*result = -1; | |||||
return; | |||||
} | |||||
if (req->Write(fRequest) < 0) { | |||||
jack_error("Could not write request type = %ld", req->fType); | |||||
*result = -1; | |||||
} else { | |||||
*result = 0; | |||||
} | |||||
} | |||||
void JackGenericClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) | |||||
{ | |||||
JackClientCheckRequest req(name, protocol, options, uuid, open); | |||||
JackClientCheckResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
*status = res.fStatus; | |||||
strcpy(name_res, res.fName); | |||||
} | |||||
void JackGenericClientChannel::ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result) | |||||
{ | |||||
JackClientOpenRequest req(name, pid, uuid); | |||||
JackClientOpenResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
*shared_engine = res.fSharedEngine; | |||||
*shared_client = res.fSharedClient; | |||||
*shared_graph = res.fSharedGraph; | |||||
} | |||||
void JackGenericClientChannel::ClientClose(int refnum, int* result) | |||||
{ | |||||
JackClientCloseRequest req(refnum); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::ClientActivate(int refnum, int is_real_time, int* result) | |||||
{ | |||||
JackActivateRequest req(refnum, is_real_time); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::ClientDeactivate(int refnum, int* result) | |||||
{ | |||||
JackDeactivateRequest req(refnum); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result) | |||||
{ | |||||
JackPortRegisterRequest req(refnum, name, type, flags, buffer_size); | |||||
JackPortRegisterResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
*port_index = res.fPortIndex; | |||||
} | |||||
void JackGenericClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result) | |||||
{ | |||||
JackPortUnRegisterRequest req(refnum, port_index); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result) | |||||
{ | |||||
JackPortConnectNameRequest req(refnum, src, dst); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result) | |||||
{ | |||||
JackPortDisconnectNameRequest req(refnum, src, dst); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result) | |||||
{ | |||||
JackPortConnectRequest req(refnum, src, dst); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result) | |||||
{ | |||||
JackPortDisconnectRequest req(refnum, src, dst); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result) | |||||
{ | |||||
JackPortRenameRequest req(refnum, port, name); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result) | |||||
{ | |||||
JackSetBufferSizeRequest req(buffer_size); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::SetFreewheel(int onoff, int* result) | |||||
{ | |||||
JackSetFreeWheelRequest req(onoff); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::ComputeTotalLatencies(int* result) | |||||
{ | |||||
JackComputeTotalLatenciesRequest req; | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result) | |||||
{ | |||||
JackSessionNotifyRequest req(refnum, path, type, target); | |||||
JackSessionNotifyResult res; | |||||
int intresult; | |||||
ServerSyncCall(&req, &res, &intresult); | |||||
*result = res.GetCommands(); | |||||
} | |||||
void JackGenericClientChannel::SessionReply(int refnum, int* result) | |||||
{ | |||||
JackSessionReplyRequest req(refnum); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result) | |||||
{ | |||||
JackGetUUIDRequest req(client_name); | |||||
JackUUIDResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
strncpy(uuid_res, res.fUUID, JACK_UUID_SIZE); | |||||
} | |||||
void JackGenericClientChannel::GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result) | |||||
{ | |||||
JackGetClientNameRequest req(uuid); | |||||
JackClientNameResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
strncpy(name_res, res.fName, JACK_CLIENT_NAME_SIZE); | |||||
} | |||||
void JackGenericClientChannel::ClientHasSessionCallback(const char* client_name, int* result) | |||||
{ | |||||
JackClientHasSessionCallbackRequest req(client_name); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::ReserveClientName(int refnum, const char* client_name, const char* uuid, int* result) | |||||
{ | |||||
JackReserveNameRequest req(refnum, client_name, uuid); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::ReleaseTimebase(int refnum, int* result) | |||||
{ | |||||
JackReleaseTimebaseRequest req(refnum); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result) | |||||
{ | |||||
JackSetTimebaseCallbackRequest req(refnum, conditional); | |||||
JackResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
} | |||||
void JackGenericClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result) | |||||
{ | |||||
JackGetInternalClientNameRequest req(refnum, int_ref); | |||||
JackGetInternalClientNameResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
strcpy(name_res, res.fName); | |||||
} | |||||
void JackGenericClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result) | |||||
{ | |||||
JackInternalClientHandleRequest req(refnum, client_name); | |||||
JackInternalClientHandleResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
*int_ref = res.fIntRefNum; | |||||
*status = res.fStatus; | |||||
} | |||||
void JackGenericClientChannel::InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int uuid, int* result) | |||||
{ | |||||
JackInternalClientLoadRequest req(refnum, client_name, so_name, objet_data, options, uuid); | |||||
JackInternalClientLoadResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
*int_ref = res.fIntRefNum; | |||||
*status = res.fStatus; | |||||
} | |||||
void JackGenericClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result) | |||||
{ | |||||
JackInternalClientUnloadRequest req(refnum, int_ref); | |||||
JackInternalClientUnloadResult res; | |||||
ServerSyncCall(&req, &res, result); | |||||
*status = res.fStatus; | |||||
} | |||||
} // end of namespace | |||||
@@ -0,0 +1,103 @@ | |||||
/* | |||||
Copyright (C) 2004-2008 Grame | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __JackGenericClientChannel__ | |||||
#define __JackGenericClientChannel__ | |||||
#include "JackChannel.h" | |||||
namespace Jack | |||||
{ | |||||
struct JackRequest; | |||||
struct JackResult; | |||||
/*! | |||||
\brief Generic JackClientChannel class. | |||||
*/ | |||||
class JackGenericClientChannel : public detail::JackClientChannelInterface | |||||
{ | |||||
protected: | |||||
detail::JackClientRequestInterface* fRequest; | |||||
void ServerSyncCall(JackRequest* req, JackResult* res, int* result); | |||||
void ServerAsyncCall(JackRequest* req, JackResult* res, int* result); | |||||
public: | |||||
JackGenericClientChannel(); | |||||
virtual ~JackGenericClientChannel(); | |||||
virtual int Open(const char* server_name, const char* name, int uuid, char* name_res, JackClient* obj, jack_options_t options, jack_status_t* status) { return -1; } | |||||
virtual void Close() {} | |||||
virtual int Start() { return -1; } | |||||
virtual void Stop() {} | |||||
int ServerCheck(const char* server_name); | |||||
void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open); | |||||
void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result); | |||||
void ClientOpen(const char* name, int* ref, int uuid, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, int* result) | |||||
{} | |||||
void ClientClose(int refnum, int* result); | |||||
void ClientActivate(int refnum, int is_real_time, int* result); | |||||
void ClientDeactivate(int refnum, int* result); | |||||
void PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result); | |||||
void PortUnRegister(int refnum, jack_port_id_t port_index, int* result); | |||||
void PortConnect(int refnum, const char* src, const char* dst, int* result); | |||||
void PortDisconnect(int refnum, const char* src, const char* dst, int* result); | |||||
void PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result); | |||||
void PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result); | |||||
void PortRename(int refnum, jack_port_id_t port, const char* name, int* result); | |||||
void SetBufferSize(jack_nframes_t buffer_size, int* result); | |||||
void SetFreewheel(int onoff, int* result); | |||||
void ComputeTotalLatencies(int* result); | |||||
void ReleaseTimebase(int refnum, int* result); | |||||
void SetTimebaseCallback(int refnum, int conditional, int* result); | |||||
void GetInternalClientName(int refnum, int int_ref, char* name_res, int* result); | |||||
void InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result); | |||||
void InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int uuid, int* result); | |||||
void InternalClientUnload(int refnum, int int_ref, int* status, int* result); | |||||
// Session API | |||||
void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char* path, jack_session_command_t** result); | |||||
void SessionReply(int refnum, int* result); | |||||
void GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result); | |||||
void GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result); | |||||
void ReserveClientName(int refnum, const char* client_name, const char *uuid, int* result); | |||||
void ClientHasSessionCallback(const char* client_name, int* result); | |||||
}; | |||||
} // end of namespace | |||||
#endif | |||||
@@ -24,8 +24,11 @@ namespace Jack | |||||
bool JackGlobals::fVerbose = 0; | bool JackGlobals::fVerbose = 0; | ||||
jack_tls_key JackGlobals::fRealTime; | |||||
static bool gKeyRealtimeInitialized = jack_tls_allocate_key(&JackGlobals::fRealTime); | |||||
jack_tls_key JackGlobals::fRealTimeThread; | |||||
static bool gKeyRealtimeThreadInitialized = jack_tls_allocate_key(&JackGlobals::fRealTimeThread); | |||||
jack_tls_key JackGlobals::fNotificationThread; | |||||
static bool gKeyNotificationThreadInitialized = jack_tls_allocate_key(&JackGlobals::fNotificationThread); | |||||
jack_tls_key JackGlobals::fKeyLogFunction; | jack_tls_key JackGlobals::fKeyLogFunction; | ||||
static bool fKeyLogFunctionInitialized = jack_tls_allocate_key(&JackGlobals::fKeyLogFunction); | static bool fKeyLogFunctionInitialized = jack_tls_allocate_key(&JackGlobals::fKeyLogFunction); | ||||
@@ -39,6 +42,7 @@ jack_thread_creator_t JackGlobals::fJackThreadCreator = pthread_create; | |||||
#endif | #endif | ||||
#ifdef __CLIENTDEBUG__ | #ifdef __CLIENTDEBUG__ | ||||
std::ofstream* JackGlobals::fStream = NULL; | std::ofstream* JackGlobals::fStream = NULL; | ||||
void JackGlobals::CheckContext(const char* name) | void JackGlobals::CheckContext(const char* name) | ||||
@@ -59,6 +63,12 @@ void JackGlobals::CheckContext(const char* name) | |||||
} | } | ||||
(*fStream) << "JACK API call : " << name << ", calling thread : " << pthread_self() << std::endl; | (*fStream) << "JACK API call : " << name << ", calling thread : " << pthread_self() << std::endl; | ||||
} | } | ||||
#else | |||||
void JackGlobals::CheckContext(const char* name) | |||||
{} | |||||
#endif | #endif | ||||
} // end of namespace | } // end of namespace |
@@ -37,7 +37,8 @@ namespace Jack | |||||
// Globals used for client management on server or library side. | // Globals used for client management on server or library side. | ||||
struct JackGlobals { | struct JackGlobals { | ||||
static jack_tls_key fRealTime; | |||||
static jack_tls_key fRealTimeThread; | |||||
static jack_tls_key fNotificationThread; | |||||
static jack_tls_key fKeyLogFunction; | static jack_tls_key fKeyLogFunction; | ||||
static JackMutex* fOpenMutex; | static JackMutex* fOpenMutex; | ||||
static volatile bool fServerRunning; | static volatile bool fServerRunning; | ||||
@@ -49,8 +50,8 @@ struct JackGlobals { | |||||
#ifdef __CLIENTDEBUG__ | #ifdef __CLIENTDEBUG__ | ||||
static std::ofstream* fStream; | static std::ofstream* fStream; | ||||
static void CheckContext(const char* name); | |||||
#endif | #endif | ||||
static void CheckContext(const char* name); | |||||
}; | }; | ||||
// Each "side" server and client will implement this to get the shared graph manager, engine control and inter-process synchro table. | // Each "side" server and client will implement this to get the shared graph manager, engine control and inter-process synchro table. | ||||
@@ -344,7 +344,7 @@ void JackGraphManager::RecalculateLatency(jack_port_id_t port_index, jack_latenc | |||||
next_index = GetCurrentIndex(); | next_index = GetCurrentIndex(); | ||||
} while (cur_index != next_index); // Until a coherent state has been read | } while (cur_index != next_index); // Until a coherent state has been read | ||||
jack_log("JackGraphManager::RecalculateLatency port_index = %ld", port_index); | |||||
//jack_log("JackGraphManager::RecalculateLatency port_index = %ld", port_index); | |||||
} | } | ||||
// Server | // Server | ||||
@@ -27,7 +27,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackServer.h" | #include "JackServer.h" | ||||
#include "JackEngineControl.h" | #include "JackEngineControl.h" | ||||
#include "JackClientControl.h" | #include "JackClientControl.h" | ||||
#include "JackInternalClientChannel.h" | #include "JackInternalClientChannel.h" | ||||
#include "JackGenericClientChannel.h" | |||||
#include "JackTools.h" | #include "JackTools.h" | ||||
#include <assert.h> | #include <assert.h> | ||||
@@ -98,11 +101,16 @@ int JackInternalClient::Open(const char* server_name, const char* name, int uuid | |||||
return 0; | return 0; | ||||
error: | error: | ||||
fChannel->Stop(); | |||||
fChannel->Close(); | fChannel->Close(); | ||||
return -1; | return -1; | ||||
} | } | ||||
void JackInternalClient::ShutDown() | |||||
{ | |||||
jack_log("JackInternalClient::ShutDown"); | |||||
JackClient::ShutDown(); | |||||
} | |||||
JackGraphManager* JackInternalClient::GetGraphManager() const | JackGraphManager* JackInternalClient::GetGraphManager() const | ||||
{ | { | ||||
assert(fGraphManager); | assert(fGraphManager); | ||||
@@ -193,10 +201,12 @@ JackLoadableInternalClient2::JackLoadableInternalClient2(JackServer* server, Jac | |||||
JackLoadableInternalClient::~JackLoadableInternalClient() | JackLoadableInternalClient::~JackLoadableInternalClient() | ||||
{ | { | ||||
if (fFinish != NULL) | |||||
if (fFinish != NULL) { | |||||
fFinish(fProcessArg); | fFinish(fProcessArg); | ||||
if (fHandle != NULL) | |||||
} | |||||
if (fHandle != NULL) { | |||||
UnloadJackModule(fHandle); | UnloadJackModule(fHandle); | ||||
} | |||||
} | } | ||||
int JackLoadableInternalClient1::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status) | int JackLoadableInternalClient1::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status) | ||||
@@ -47,6 +47,7 @@ class JackInternalClient : public JackClient | |||||
virtual ~JackInternalClient(); | virtual ~JackInternalClient(); | ||||
int Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status); | int Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status); | ||||
void ShutDown(); | |||||
JackGraphManager* GetGraphManager() const; | JackGraphManager* GetGraphManager() const; | ||||
JackEngineControl* GetEngineControl() const; | JackEngineControl* GetEngineControl() const; | ||||
@@ -63,7 +64,6 @@ class JackInternalClient : public JackClient | |||||
typedef int (*InitializeCallback)(jack_client_t*, const char*); | typedef int (*InitializeCallback)(jack_client_t*, const char*); | ||||
typedef int (*InternalInitializeCallback)(jack_client_t*, const JSList* params); | typedef int (*InternalInitializeCallback)(jack_client_t*, const JSList* params); | ||||
typedef void (*FinishCallback)(void *); | typedef void (*FinishCallback)(void *); | ||||
typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | |||||
class JackLoadableInternalClient : public JackInternalClient | class JackLoadableInternalClient : public JackInternalClient | ||||
{ | { | ||||
@@ -92,7 +92,7 @@ class JackLoadableInternalClient1 : public JackLoadableInternalClient | |||||
InitializeCallback fInitialize; | InitializeCallback fInitialize; | ||||
char fObjectData[JACK_LOAD_INIT_LIMIT]; | char fObjectData[JACK_LOAD_INIT_LIMIT]; | ||||
public: | public: | ||||
JackLoadableInternalClient1(JackServer* server, JackSynchro* table, const char* object_data); | JackLoadableInternalClient1(JackServer* server, JackSynchro* table, const char* object_data); | ||||
@@ -111,7 +111,7 @@ class JackLoadableInternalClient2 : public JackLoadableInternalClient | |||||
InternalInitializeCallback fInitialize; | InternalInitializeCallback fInitialize; | ||||
const JSList* fParameters; | const JSList* fParameters; | ||||
public: | public: | ||||
JackLoadableInternalClient2(JackServer* server, JackSynchro* table, const JSList* parameters); | JackLoadableInternalClient2(JackServer* server, JackSynchro* table, const JSList* parameters); | ||||
@@ -44,12 +44,6 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||||
virtual ~JackInternalClientChannel() | virtual ~JackInternalClientChannel() | ||||
{} | {} | ||||
// Open the Server/Client connection | |||||
virtual int Open(const char* name, char* name_res, JackClient* obj, jack_options_t options, jack_status_t* status) | |||||
{ | |||||
return 0; | |||||
} | |||||
void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) | void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open) | ||||
{ | { | ||||
*result = fEngine->ClientCheck(name, uuid, name_res, protocol, options, status); | *result = fEngine->ClientCheck(name, uuid, name_res, protocol, options, status); | ||||
@@ -148,8 +142,7 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||||
{ | { | ||||
JackSessionNotifyResult* res; | JackSessionNotifyResult* res; | ||||
fEngine->SessionNotify(refnum, target, type, path, NULL, &res); | fEngine->SessionNotify(refnum, target, type, path, NULL, &res); | ||||
if (res == NULL) | |||||
{ | |||||
if (res == NULL) { | |||||
*result = NULL; | *result = NULL; | ||||
return; | return; | ||||
} | } | ||||
@@ -160,28 +153,27 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||||
void SessionReply(int refnum, int* result) | void SessionReply(int refnum, int* result) | ||||
{ | { | ||||
fEngine->SessionReply(refnum); | |||||
*result = 0; | |||||
*result = fEngine->SessionReply(refnum); | |||||
} | } | ||||
void GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result) | void GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result) | ||||
{ | { | ||||
fEngine->GetUUIDForClientName(client_name, uuid_res, result); | |||||
*result = fEngine->GetUUIDForClientName(client_name, uuid_res); | |||||
} | } | ||||
void GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result) | void GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result) | ||||
{ | { | ||||
fEngine->GetClientNameForUUID(uuid, name_res, result); | |||||
*result = fEngine->GetClientNameForUUID(uuid, name_res); | |||||
} | } | ||||
void ReserveClientName(int refnum, const char* client_name, const char *uuid, int* result) | void ReserveClientName(int refnum, const char* client_name, const char *uuid, int* result) | ||||
{ | { | ||||
fEngine->ReserveClientName(client_name, uuid, result); | |||||
*result = fEngine->ReserveClientName(client_name, uuid); | |||||
} | } | ||||
void ClientHasSessionCallback(const char* client_name, int* result) | void ClientHasSessionCallback(const char* client_name, int* result) | ||||
{ | { | ||||
fEngine->ClientHasSessionCallback(client_name, result); | |||||
*result = fEngine->ClientHasSessionCallback(client_name); | |||||
} | } | ||||
@@ -166,9 +166,8 @@ static jack_client_t* jack_client_open_aux(const char* client_name, jack_options | |||||
LIB_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | LIB_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | ||||
{ | { | ||||
#ifdef __CLIENTDEBUG__ | |||||
JackGlobals::CheckContext("jack_client_open"); | JackGlobals::CheckContext("jack_client_open"); | ||||
#endif | |||||
try { | try { | ||||
assert(JackGlobals::fOpenMutex); | assert(JackGlobals::fOpenMutex); | ||||
JackGlobals::fOpenMutex->Lock(); | JackGlobals::fOpenMutex->Lock(); | ||||
@@ -189,9 +188,8 @@ LIB_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_opt | |||||
LIB_EXPORT int jack_client_close(jack_client_t* ext_client) | LIB_EXPORT int jack_client_close(jack_client_t* ext_client) | ||||
{ | { | ||||
#ifdef __CLIENTDEBUG__ | |||||
JackGlobals::CheckContext("jack_client_close"); | JackGlobals::CheckContext("jack_client_close"); | ||||
#endif | |||||
assert(JackGlobals::fOpenMutex); | assert(JackGlobals::fOpenMutex); | ||||
JackGlobals::fOpenMutex->Lock(); | JackGlobals::fOpenMutex->Lock(); | ||||
int res = -1; | int res = -1; | ||||
@@ -55,6 +55,20 @@ JackSynchro* GetSynchroTable() | |||||
// Client management | // Client management | ||||
//------------------- | //------------------- | ||||
/* | |||||
ShutDown is called: | |||||
- from the RT thread when Execute method fails | |||||
- possibly from a "closed" notification channel | |||||
(Not needed since the synch object used (Sema of Fifo will fails when server quits... see ShutDown)) | |||||
*/ | |||||
void JackLibClient::ShutDown() | |||||
{ | |||||
jack_log("JackLibClient::ShutDown"); | |||||
JackGlobals::fServerRunning = false; | |||||
JackClient::ShutDown(); | |||||
} | |||||
JackLibClient::JackLibClient(JackSynchro* table): JackClient(table) | JackLibClient::JackLibClient(JackSynchro* table): JackClient(table) | ||||
{ | { | ||||
jack_log("JackLibClient::JackLibClient table = %x", table); | jack_log("JackLibClient::JackLibClient table = %x", table); | ||||
@@ -32,7 +32,7 @@ namespace Jack | |||||
\brief Client on the library side. | \brief Client on the library side. | ||||
*/ | */ | ||||
class LIB_EXPORT JackLibClient : public JackClient | |||||
class JackLibClient : public JackClient | |||||
{ | { | ||||
private: | private: | ||||
@@ -45,6 +45,7 @@ class LIB_EXPORT JackLibClient : public JackClient | |||||
virtual ~JackLibClient(); | virtual ~JackLibClient(); | ||||
int Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status); | int Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status); | ||||
void ShutDown(); | |||||
int ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); | int ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); | ||||
@@ -50,7 +50,7 @@ class JackClient; | |||||
\brief Global library static structure: singleton kind of pattern. | \brief Global library static structure: singleton kind of pattern. | ||||
*/ | */ | ||||
struct LIB_EXPORT JackLibGlobals | |||||
struct JackLibGlobals | |||||
{ | { | ||||
JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */ | JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */ | ||||
JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable | JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable | ||||
@@ -63,7 +63,9 @@ struct LIB_EXPORT JackLibGlobals | |||||
JackLibGlobals() | JackLibGlobals() | ||||
{ | { | ||||
jack_log("JackLibGlobals"); | jack_log("JackLibGlobals"); | ||||
JackMessageBuffer::Create(); | |||||
if (!JackMessageBuffer::Create()) { | |||||
jack_error("Cannot create message buffer"); | |||||
} | |||||
fGraphManager = -1; | fGraphManager = -1; | ||||
fEngineControl = -1; | fEngineControl = -1; | ||||
@@ -127,6 +129,7 @@ struct LIB_EXPORT JackLibGlobals | |||||
{ | { | ||||
if (--fClientCount == 0 && fGlobals) { | if (--fClientCount == 0 && fGlobals) { | ||||
jack_log("JackLibGlobals Destroy %x", fGlobals); | jack_log("JackLibGlobals Destroy %x", fGlobals); | ||||
EndTime(); | |||||
delete fGlobals; | delete fGlobals; | ||||
fGlobals = NULL; | fGlobals = NULL; | ||||
} | } | ||||
@@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | */ | ||||
#include "JackLibSampleRateResampler.h" | #include "JackLibSampleRateResampler.h" | ||||
#include "JackError.h" | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -103,6 +103,14 @@ class SERVER_EXPORT JackLockedEngine | |||||
return fEngine.Close(); | return fEngine.Close(); | ||||
CATCH_EXCEPTION_RETURN | CATCH_EXCEPTION_RETURN | ||||
} | } | ||||
void ShutDown() | |||||
{ | |||||
// No lock needed | |||||
TRY_CALL | |||||
fEngine.ShutDown(); | |||||
CATCH_EXCEPTION | |||||
} | |||||
// Client management | // Client management | ||||
int ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status) | int ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status) | ||||
@@ -325,7 +333,7 @@ class SERVER_EXPORT JackLockedEngine | |||||
CATCH_EXCEPTION | CATCH_EXCEPTION | ||||
} | } | ||||
void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket, JackSessionNotifyResult** result) | |||||
void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, detail::JackChannelTransactionInterface *socket, JackSessionNotifyResult** result) | |||||
{ | { | ||||
TRY_CALL | TRY_CALL | ||||
JackLock lock(&fEngine); | JackLock lock(&fEngine); | ||||
@@ -333,42 +341,42 @@ class SERVER_EXPORT JackLockedEngine | |||||
CATCH_EXCEPTION | CATCH_EXCEPTION | ||||
} | } | ||||
void SessionReply(int refnum) | |||||
int SessionReply(int refnum) | |||||
{ | { | ||||
TRY_CALL | TRY_CALL | ||||
JackLock lock(&fEngine); | JackLock lock(&fEngine); | ||||
fEngine.SessionReply(refnum); | |||||
CATCH_EXCEPTION | |||||
return fEngine.SessionReply(refnum); | |||||
CATCH_EXCEPTION_RETURN | |||||
} | } | ||||
void GetUUIDForClientName(const char *client_name, char *uuid_res, int *result) | |||||
int GetUUIDForClientName(const char *client_name, char *uuid_res) | |||||
{ | { | ||||
TRY_CALL | TRY_CALL | ||||
JackLock lock(&fEngine); | JackLock lock(&fEngine); | ||||
fEngine.GetUUIDForClientName(client_name, uuid_res, result); | |||||
CATCH_EXCEPTION | |||||
return fEngine.GetUUIDForClientName(client_name, uuid_res); | |||||
CATCH_EXCEPTION_RETURN | |||||
} | } | ||||
void GetClientNameForUUID(const char *uuid, char *name_res, int *result) | |||||
int GetClientNameForUUID(const char *uuid, char *name_res) | |||||
{ | { | ||||
TRY_CALL | TRY_CALL | ||||
JackLock lock(&fEngine); | JackLock lock(&fEngine); | ||||
fEngine.GetClientNameForUUID(uuid, name_res, result); | |||||
CATCH_EXCEPTION | |||||
return fEngine.GetClientNameForUUID(uuid, name_res); | |||||
CATCH_EXCEPTION_RETURN | |||||
} | } | ||||
void ReserveClientName(const char *name, const char *uuid, int *result) | |||||
int ReserveClientName(const char *name, const char *uuid) | |||||
{ | { | ||||
TRY_CALL | TRY_CALL | ||||
JackLock lock(&fEngine); | JackLock lock(&fEngine); | ||||
fEngine.ReserveClientName(name, uuid, result); | |||||
CATCH_EXCEPTION | |||||
return fEngine.ReserveClientName(name, uuid); | |||||
CATCH_EXCEPTION_RETURN | |||||
} | } | ||||
void ClientHasSessionCallback(const char *name, int *result) | |||||
int ClientHasSessionCallback(const char *name) | |||||
{ | { | ||||
TRY_CALL | TRY_CALL | ||||
JackLock lock(&fEngine); | JackLock lock(&fEngine); | ||||
fEngine.ClientHasSessionCallback(name, result); | |||||
CATCH_EXCEPTION | |||||
return fEngine.ClientHasSessionCallback(name); | |||||
CATCH_EXCEPTION_RETURN | |||||
} | } | ||||
}; | }; | ||||
@@ -41,6 +41,7 @@ int JackLoopbackDriver::ProcessReadSync() | |||||
memcpy(GetInputBuffer(i), GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | memcpy(GetInputBuffer(i), GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | ||||
} | } | ||||
// Resume connected clients in the graph | |||||
if (ResumeRefNum() < 0) { | if (ResumeRefNum() < 0) { | ||||
jack_error("JackLoopbackDriver::ProcessReadSync - ResumeRefNum error"); | jack_error("JackLoopbackDriver::ProcessReadSync - ResumeRefNum error"); | ||||
res = -1; | res = -1; | ||||
@@ -51,6 +52,7 @@ int JackLoopbackDriver::ProcessReadSync() | |||||
int JackLoopbackDriver::ProcessWriteSync() | int JackLoopbackDriver::ProcessWriteSync() | ||||
{ | { | ||||
// Suspend on connected clients in the graph | |||||
if (SuspendRefNum() < 0) { | if (SuspendRefNum() < 0) { | ||||
jack_error("JackLoopbackDriver::ProcessWriteSync SuspendRefNum error"); | jack_error("JackLoopbackDriver::ProcessWriteSync SuspendRefNum error"); | ||||
return -1; | return -1; | ||||
@@ -67,6 +69,7 @@ int JackLoopbackDriver::ProcessReadAsync() | |||||
memcpy(GetInputBuffer(i), GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | memcpy(GetInputBuffer(i), GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | ||||
} | } | ||||
// Resume connected clients in the graph | |||||
if (ResumeRefNum() < 0) { | if (ResumeRefNum() < 0) { | ||||
jack_error("JackLoopbackDriver::ProcessReadAsync - ResumeRefNum error"); | jack_error("JackLoopbackDriver::ProcessReadAsync - ResumeRefNum error"); | ||||
res = -1; | res = -1; | ||||
@@ -22,6 +22,7 @@ | |||||
#include "JackMessageBuffer.h" | #include "JackMessageBuffer.h" | ||||
#include "JackGlobals.h" | #include "JackGlobals.h" | ||||
#include "JackError.h" | #include "JackError.h" | ||||
#include "JackTime.h" | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -29,19 +30,32 @@ namespace Jack | |||||
JackMessageBuffer* JackMessageBuffer::fInstance = NULL; | JackMessageBuffer* JackMessageBuffer::fInstance = NULL; | ||||
JackMessageBuffer::JackMessageBuffer() | JackMessageBuffer::JackMessageBuffer() | ||||
:fInit(NULL),fInitArg(NULL),fThread(this),fInBuffer(0),fOutBuffer(0),fOverruns(0),fRunning(false) | |||||
:fInit(NULL), | |||||
fInitArg(NULL), | |||||
fThread(this), | |||||
fGuard(), | |||||
fInBuffer(0), | |||||
fOutBuffer(0), | |||||
fOverruns(0), | |||||
fRunning(false) | |||||
{} | {} | ||||
JackMessageBuffer::~JackMessageBuffer() | JackMessageBuffer::~JackMessageBuffer() | ||||
{} | {} | ||||
void JackMessageBuffer::Start() | |||||
bool JackMessageBuffer::Start() | |||||
{ | { | ||||
// Before StartSync()... | |||||
fRunning = true; | fRunning = true; | ||||
fThread.StartSync(); | |||||
if (fThread.StartSync() == 0) { | |||||
return true; | |||||
} else { | |||||
fRunning = false; | |||||
return false; | |||||
} | |||||
} | } | ||||
void JackMessageBuffer::Stop() | |||||
bool JackMessageBuffer::Stop() | |||||
{ | { | ||||
if (fOverruns > 0) { | if (fOverruns > 0) { | ||||
jack_error("WARNING: %d message buffer overruns!", fOverruns); | jack_error("WARNING: %d message buffer overruns!", fOverruns); | ||||
@@ -59,6 +73,7 @@ void JackMessageBuffer::Stop() | |||||
} | } | ||||
Flush(); | Flush(); | ||||
return true; | |||||
} | } | ||||
void JackMessageBuffer::Flush() | void JackMessageBuffer::Flush() | ||||
@@ -96,7 +111,7 @@ bool JackMessageBuffer::Execute() | |||||
/* and we're done */ | /* and we're done */ | ||||
fGuard.Signal(); | fGuard.Signal(); | ||||
} | } | ||||
/* releasing the mutex reduces contention */ | /* releasing the mutex reduces contention */ | ||||
fGuard.Unlock(); | fGuard.Unlock(); | ||||
Flush(); | Flush(); | ||||
@@ -110,20 +125,30 @@ bool JackMessageBuffer::Execute() | |||||
return false; | return false; | ||||
} | } | ||||
void JackMessageBuffer::Create() | |||||
bool JackMessageBuffer::Create() | |||||
{ | { | ||||
if (fInstance == NULL) { | if (fInstance == NULL) { | ||||
fInstance = new JackMessageBuffer(); | fInstance = new JackMessageBuffer(); | ||||
fInstance->Start(); | |||||
if (!fInstance->Start()) { | |||||
jack_error("JackMessageBuffer::Create cannot start thread"); | |||||
delete fInstance; | |||||
fInstance = NULL; | |||||
return false; | |||||
} | |||||
} | } | ||||
return true; | |||||
} | } | ||||
void JackMessageBuffer::Destroy() | |||||
bool JackMessageBuffer::Destroy() | |||||
{ | { | ||||
if (fInstance != NULL) { | if (fInstance != NULL) { | ||||
fInstance->Stop(); | fInstance->Stop(); | ||||
delete fInstance; | delete fInstance; | ||||
fInstance = NULL; | fInstance = NULL; | ||||
return true; | |||||
} else { | |||||
return false; | |||||
} | } | ||||
} | } | ||||
@@ -137,21 +162,42 @@ void JackMessageBufferAdd(int level, const char *message) | |||||
} | } | ||||
} | } | ||||
void JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *arg) | |||||
int JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *arg) | |||||
{ | { | ||||
if (fGuard.Lock()) { | |||||
if (fInstance && callback && fRunning && fGuard.Lock()) { | |||||
/* set up the callback */ | /* set up the callback */ | ||||
fInitArg = arg; | fInitArg = arg; | ||||
fInit = callback; | fInit = callback; | ||||
/* wake msg buffer thread */ | |||||
#ifndef WIN32 | |||||
// wake msg buffer thread | |||||
fGuard.Signal(); | fGuard.Signal(); | ||||
/* wait for it to be done */ | |||||
// wait for it to be done | |||||
fGuard.Wait(); | fGuard.Wait(); | ||||
/* and we're done */ | |||||
// and we're done | |||||
fGuard.Unlock(); | fGuard.Unlock(); | ||||
} else { | |||||
jack_error("JackMessageBuffer::SetInitCallback lock cannot be taken"); | |||||
#else | |||||
/* | |||||
The condition variable emulation code does not work reliably on Windows (lost signal). | |||||
So use a "hackish" way to signal/wait for the result. | |||||
Probaly better in the long term : use pthread-win32 (http://sourceware.org/pthreads-win32/` | |||||
*/ | |||||
fGuard.Unlock(); | |||||
int count = 0; | |||||
while (fInit && ++count < 1000) { | |||||
/* wake msg buffer thread */ | |||||
fGuard.Signal(); | |||||
JackSleep(1000); | |||||
} | |||||
if (count == 1000) goto error; | |||||
#endif | |||||
return 0; | |||||
} | } | ||||
error: | |||||
jack_error("JackMessageBuffer::SetInitCallback : callback cannot be executed"); | |||||
return -1; | |||||
} | } | ||||
}; | }; | ||||
@@ -57,7 +57,7 @@ class JackMessageBuffer : public JackRunnableInterface | |||||
private: | private: | ||||
JackThreadInitCallback fInit; | |||||
volatile JackThreadInitCallback fInit; | |||||
void* fInitArg; | void* fInitArg; | ||||
JackMessage fBuffers[MB_BUFFERS]; | JackMessage fBuffers[MB_BUFFERS]; | ||||
JackThread fThread; | JackThread fThread; | ||||
@@ -69,8 +69,8 @@ class JackMessageBuffer : public JackRunnableInterface | |||||
void Flush(); | void Flush(); | ||||
void Start(); | |||||
void Stop(); | |||||
bool Start(); | |||||
bool Stop(); | |||||
public: | public: | ||||
@@ -80,11 +80,11 @@ class JackMessageBuffer : public JackRunnableInterface | |||||
// JackRunnableInterface interface | // JackRunnableInterface interface | ||||
bool Execute(); | bool Execute(); | ||||
void static Create(); | |||||
void static Destroy(); | |||||
bool static Create(); | |||||
bool static Destroy(); | |||||
void AddMessage(int level, const char *message); | void AddMessage(int level, const char *message); | ||||
void SetInitCallback(JackThreadInitCallback callback, void *arg); | |||||
int SetInitCallback(JackThreadInitCallback callback, void *arg); | |||||
static JackMessageBuffer* fInstance; | static JackMessageBuffer* fInstance; | ||||
}; | }; | ||||
@@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#include "JackMidiBufferReadQueue.h" | #include "JackMidiBufferReadQueue.h" | ||||
#include "JackMidiUtil.h" | #include "JackMidiUtil.h" | ||||
#include "JackError.h" | |||||
using Jack::JackMidiBufferReadQueue; | using Jack::JackMidiBufferReadQueue; | ||||
@@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#include "JackMidiBufferWriteQueue.h" | #include "JackMidiBufferWriteQueue.h" | ||||
#include "JackMidiUtil.h" | #include "JackMidiUtil.h" | ||||
#include "JackError.h" | |||||
using Jack::JackMidiBufferWriteQueue; | using Jack::JackMidiBufferWriteQueue; | ||||
@@ -136,6 +136,8 @@ int JackMidiDriver::SetBufferSize(jack_nframes_t buffer_size) | |||||
int JackMidiDriver::ProcessReadSync() | int JackMidiDriver::ProcessReadSync() | ||||
{ | { | ||||
int res = 0; | int res = 0; | ||||
jack_log("JackMidiDriver::ProcessReadSync"); | |||||
// Read input buffers for the current cycle | // Read input buffers for the current cycle | ||||
if (Read() < 0) { | if (Read() < 0) { | ||||
@@ -154,6 +156,8 @@ int JackMidiDriver::ProcessReadSync() | |||||
int JackMidiDriver::ProcessWriteSync() | int JackMidiDriver::ProcessWriteSync() | ||||
{ | { | ||||
int res = 0; | int res = 0; | ||||
jack_log("JackMidiDriver::ProcessWriteSync"); | |||||
if (SuspendRefNum() < 0) { | if (SuspendRefNum() < 0) { | ||||
jack_error("JackMidiDriver::ProcessWriteSync: SuspendRefNum error"); | jack_error("JackMidiDriver::ProcessWriteSync: SuspendRefNum error"); | ||||
@@ -172,6 +176,8 @@ int JackMidiDriver::ProcessWriteSync() | |||||
int JackMidiDriver::ProcessReadAsync() | int JackMidiDriver::ProcessReadAsync() | ||||
{ | { | ||||
int res = 0; | int res = 0; | ||||
jack_log("JackMidiDriver::ProcessReadAsync"); | |||||
// Read input buffers for the current cycle | // Read input buffers for the current cycle | ||||
if (Read() < 0) { | if (Read() < 0) { | ||||
@@ -195,6 +201,7 @@ int JackMidiDriver::ProcessReadAsync() | |||||
int JackMidiDriver::ProcessWriteAsync() | int JackMidiDriver::ProcessWriteAsync() | ||||
{ | { | ||||
jack_log("JackMidiDriver::ProcessWriteAsync"); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#include <new> | #include <new> | ||||
#include "JackMidiRawInputWriteQueue.h" | #include "JackMidiRawInputWriteQueue.h" | ||||
#include "JackError.h" | |||||
using Jack::JackMidiRawInputWriteQueue; | using Jack::JackMidiRawInputWriteQueue; | ||||
@@ -40,7 +40,8 @@ class JackLockAble | |||||
JackMutex fMutex; | JackMutex fMutex; | ||||
JackLockAble() | |||||
JackLockAble(const char* name = NULL) | |||||
:fMutex(name) | |||||
{} | {} | ||||
~JackLockAble() | ~JackLockAble() | ||||
{} | {} | ||||
@@ -19,9 +19,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#include <assert.h> | #include <assert.h> | ||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#include "JackNetInterface.h" | #include "JackNetInterface.h" | ||||
#include "JackError.h" | |||||
#include "JackException.h" | |||||
#include "JackAudioAdapterInterface.h" | #include "JackAudioAdapterInterface.h" | ||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
@@ -86,41 +85,48 @@ extern "C" | |||||
typedef int (*JackNetSlaveSampleRateCallback) (jack_nframes_t nframes, void *arg); | typedef int (*JackNetSlaveSampleRateCallback) (jack_nframes_t nframes, void *arg); | ||||
typedef void (*JackNetSlaveShutdownCallback) (void* data); | typedef void (*JackNetSlaveShutdownCallback) (void* data); | ||||
SERVER_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result); | |||||
SERVER_EXPORT int jack_net_slave_close(jack_net_slave_t* net); | |||||
LIB_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result); | |||||
LIB_EXPORT int jack_net_slave_close(jack_net_slave_t* net); | |||||
SERVER_EXPORT int jack_net_slave_activate(jack_net_slave_t* net); | |||||
SERVER_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net); | |||||
LIB_EXPORT int jack_net_slave_activate(jack_net_slave_t* net); | |||||
LIB_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net); | |||||
SERVER_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg); | |||||
SERVER_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t* net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg); | |||||
SERVER_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t* net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg); | |||||
SERVER_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t* net, JackNetSlaveShutdownCallback shutdown_callback, void *arg); | |||||
LIB_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg); | |||||
LIB_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t* net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg); | |||||
LIB_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t* net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg); | |||||
LIB_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t* net, JackNetSlaveShutdownCallback shutdown_callback, void *arg); | |||||
// NetJack master API | // NetJack master API | ||||
typedef struct _jack_net_master jack_net_master_t; | typedef struct _jack_net_master jack_net_master_t; | ||||
SERVER_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result); | |||||
SERVER_EXPORT int jack_net_master_close(jack_net_master_t* net); | |||||
LIB_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result); | |||||
LIB_EXPORT int jack_net_master_close(jack_net_master_t* net); | |||||
SERVER_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer); | |||||
SERVER_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer); | |||||
LIB_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer); | |||||
LIB_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer); | |||||
// NetJack adapter API | // NetJack adapter API | ||||
typedef struct _jack_adapter jack_adapter_t; | typedef struct _jack_adapter jack_adapter_t; | ||||
SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, | |||||
LIB_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, | |||||
jack_nframes_t host_buffer_size, | 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); | ||||
SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter); | |||||
SERVER_EXPORT void jack_flush_adapter(jack_adapter_t* adapter); | |||||
LIB_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter); | |||||
LIB_EXPORT void jack_flush_adapter(jack_adapter_t* adapter); | |||||
LIB_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); | |||||
LIB_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); | |||||
SERVER_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); | |||||
SERVER_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames); | |||||
#define LOG_LEVEL_INFO 1 | |||||
#define LOG_LEVEL_ERROR 2 | |||||
LIB_EXPORT void jack_error(const char *fmt, ...); | |||||
LIB_EXPORT void jack_info(const char *fmt, ...); | |||||
LIB_EXPORT void jack_log(const char *fmt, ...); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
@@ -151,6 +157,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
fSocket.SetPort(port); | fSocket.SetPort(port); | ||||
fRequest.buffer_size = request->buffer_size; | fRequest.buffer_size = request->buffer_size; | ||||
fRequest.sample_rate = request->sample_rate; | fRequest.sample_rate = request->sample_rate; | ||||
fRequest.audio_input = request->audio_input; | |||||
fRequest.audio_output = request->audio_output; | |||||
fAudioCaptureBuffer = NULL; | fAudioCaptureBuffer = NULL; | ||||
fAudioPlaybackBuffer = NULL; | fAudioPlaybackBuffer = NULL; | ||||
fMidiCaptureBuffer = NULL; | fMidiCaptureBuffer = NULL; | ||||
@@ -215,11 +223,10 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
} | } | ||||
if (rx_bytes == sizeof(session_params_t )) { | if (rx_bytes == sizeof(session_params_t )) { | ||||
switch (GetPacketType(&fParams)) { | switch (GetPacketType(&fParams)) { | ||||
case SLAVE_AVAILABLE: | case SLAVE_AVAILABLE: | ||||
if (MasterInit() == 0) { | |||||
if (InitMaster(result) == 0) { | |||||
SessionParamsDisplay(&fParams); | SessionParamsDisplay(&fParams); | ||||
fRunning = false; | fRunning = false; | ||||
} else { | } else { | ||||
@@ -238,8 +245,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
} | } | ||||
} | } | ||||
while (fRunning); | while (fRunning); | ||||
// Set result paramaters | |||||
// Set result parameters | |||||
result->audio_input = fParams.fSendAudioChannels; | result->audio_input = fParams.fSendAudioChannels; | ||||
result->audio_output = fParams.fReturnAudioChannels; | result->audio_output = fParams.fReturnAudioChannels; | ||||
result->midi_input = fParams.fSendMidiChannels; | result->midi_input = fParams.fSendMidiChannels; | ||||
@@ -253,7 +260,7 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
return -1; | return -1; | ||||
} | } | ||||
int MasterInit() | |||||
int InitMaster(jack_slave_t* result) | |||||
{ | { | ||||
// Check MASTER <==> SLAVE network protocol coherency | // Check MASTER <==> SLAVE network protocol coherency | ||||
if (fParams.fProtocolVersion != MASTER_PROTOCOL) { | if (fParams.fProtocolVersion != MASTER_PROTOCOL) { | ||||
@@ -264,14 +271,45 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
// Settings | // Settings | ||||
fSocket.GetName(fParams.fMasterNetName); | fSocket.GetName(fParams.fMasterNetName); | ||||
fParams.fID = 1; | fParams.fID = 1; | ||||
fParams.fSampleEncoder = JackFloatEncoder; | |||||
fParams.fPeriodSize = fRequest.buffer_size; | fParams.fPeriodSize = fRequest.buffer_size; | ||||
fParams.fSampleRate = fRequest.sample_rate; | fParams.fSampleRate = fRequest.sample_rate; | ||||
if (fRequest.audio_input == -1) { | |||||
if (fParams.fSendAudioChannels == -1) { | |||||
jack_error("Error : master and slave use -1 for wanted inputs..."); | |||||
return -1; | |||||
} else { | |||||
result->audio_input = fParams.fSendAudioChannels; | |||||
jack_info("Takes slave %d inputs", fParams.fSendAudioChannels); | |||||
} | |||||
} else if (fParams.fSendAudioChannels == -1) { | |||||
fParams.fSendAudioChannels = fRequest.audio_input; | |||||
jack_info("Takes master %d inputs", fRequest.audio_input); | |||||
} else if (fParams.fSendAudioChannels != fRequest.audio_input) { | |||||
jack_error("Error : master wants %d inputs and slave wants %d inputs...", fRequest.audio_input, fParams.fSendAudioChannels); | |||||
return -1; | |||||
} | |||||
if (fRequest.audio_output == -1) { | |||||
if (fParams.fReturnAudioChannels == -1) { | |||||
jack_error("Error : master and slave use -1 for wanted outputs..."); | |||||
return -1; | |||||
} else { | |||||
result->audio_output = fParams.fReturnAudioChannels; | |||||
jack_info("Takes slave %d outputs", fParams.fReturnAudioChannels); | |||||
} | |||||
} else if (fParams.fReturnAudioChannels == -1) { | |||||
fParams.fReturnAudioChannels = fRequest.audio_output; | |||||
jack_info("Takes master %d outputs", fRequest.audio_output); | |||||
} else if (fParams.fReturnAudioChannels != fRequest.audio_output) { | |||||
jack_error("Error : master wants %d outputs and slave wants %d outputs...", fRequest.audio_output, fParams.fReturnAudioChannels); | |||||
return -1; | |||||
} | |||||
// Close request socket | // Close request socket | ||||
fSocket.Close(); | fSocket.Close(); | ||||
// Network slave init | |||||
/// Network init | |||||
if (!JackNetMasterInterface::Init()) { | if (!JackNetMasterInterface::Init()) { | ||||
return -1; | return -1; | ||||
} | } | ||||
@@ -361,7 +399,9 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) | int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) | ||||
{ | { | ||||
try { | try { | ||||
assert(audio_input == fParams.fReturnAudioChannels); | assert(audio_input == fParams.fReturnAudioChannels); | ||||
for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) { | for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) { | ||||
@@ -371,11 +411,13 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
for (int midi_port_index = 0; midi_port_index < midi_input; midi_port_index++) { | for (int midi_port_index = 0; midi_port_index < midi_input; midi_port_index++) { | ||||
fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]); | fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]); | ||||
} | } | ||||
if (SyncRecv() == SOCKET_ERROR) { | |||||
return 0; | |||||
//receive sync | |||||
int res = SyncRecv(); | |||||
if ((res == 0) || (res == SOCKET_ERROR)) { | |||||
return res; | |||||
} | } | ||||
DecodeSyncPacket(); | DecodeSyncPacket(); | ||||
return DataRecv(); | return DataRecv(); | ||||
@@ -388,6 +430,7 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) | int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) | ||||
{ | { | ||||
try { | try { | ||||
assert(audio_output == fParams.fSendAudioChannels); | assert(audio_output == fParams.fSendAudioChannels); | ||||
for (int audio_port_index = 0; audio_port_index < audio_output; audio_port_index++) { | for (int audio_port_index = 0; audio_port_index < audio_output; audio_port_index++) { | ||||
@@ -397,20 +440,32 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
for (int midi_port_index = 0; midi_port_index < midi_output; midi_port_index++) { | for (int midi_port_index = 0; midi_port_index < midi_output; midi_port_index++) { | ||||
fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); | fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); | ||||
} | } | ||||
if (IsSynched()) { // only send if connection is "synched" | |||||
EncodeSyncPacket(); | |||||
if (SyncSend() == SOCKET_ERROR) { | |||||
return SOCKET_ERROR; | |||||
} | |||||
EncodeSyncPacket(); | |||||
if (SyncSend() == SOCKET_ERROR) { | |||||
return SOCKET_ERROR; | |||||
//send data | |||||
if (DataSend() == SOCKET_ERROR) { | |||||
return SOCKET_ERROR; | |||||
} | |||||
} else { | |||||
jack_info("Connection is not synched, skip cycle..."); | |||||
} | } | ||||
return DataSend(); | |||||
return 0; | |||||
} catch (JackNetException& e) { | } catch (JackNetException& e) { | ||||
jack_error("Connection lost."); | jack_error("Connection lost."); | ||||
return -1; | return -1; | ||||
} | } | ||||
} | |||||
} | |||||
// Transport | // Transport | ||||
void EncodeTransportData() | void EncodeTransportData() | ||||
@@ -490,6 +545,13 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
int Open(jack_master_t* result) | int Open(jack_master_t* result) | ||||
{ | { | ||||
// Check CELT encoder parameters | |||||
if ((fParams.fSampleEncoder == JackCeltEncoder) && (fParams.fKBps == 0)) { | |||||
jack_error("CELT encoder with 0 for kps..."); | |||||
return -1; | |||||
} | |||||
// Check latency | |||||
if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) { | if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) { | ||||
jack_error("Error : network latency is limited to %d", NETWORK_MAX_LATENCY); | jack_error("Error : network latency is limited to %d", NETWORK_MAX_LATENCY); | ||||
return -1; | return -1; | ||||
@@ -541,7 +603,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
return -1; | return -1; | ||||
} | } | ||||
// Finish connection... | |||||
// Finish connection | |||||
if (!JackNetSlaveInterface::InitRendering()) { | if (!JackNetSlaveInterface::InitRendering()) { | ||||
jack_error("Starting network fails..."); | jack_error("Starting network fails..."); | ||||
return -1; | return -1; | ||||
@@ -604,29 +666,33 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
void FreePorts() | void FreePorts() | ||||
{ | { | ||||
if (fAudioCaptureBuffer) { | if (fAudioCaptureBuffer) { | ||||
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++) { | |||||
delete[] fAudioCaptureBuffer[audio_port_index]; | delete[] fAudioCaptureBuffer[audio_port_index]; | ||||
} | |||||
delete[] fAudioCaptureBuffer; | delete[] fAudioCaptureBuffer; | ||||
fAudioCaptureBuffer = NULL; | fAudioCaptureBuffer = NULL; | ||||
} | } | ||||
if (fMidiCaptureBuffer) { | if (fMidiCaptureBuffer) { | ||||
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++) { | |||||
delete[] (fMidiCaptureBuffer[midi_port_index]); | delete[] (fMidiCaptureBuffer[midi_port_index]); | ||||
} | |||||
delete[] fMidiCaptureBuffer; | delete[] fMidiCaptureBuffer; | ||||
fMidiCaptureBuffer = NULL; | fMidiCaptureBuffer = NULL; | ||||
} | } | ||||
if (fAudioPlaybackBuffer) { | if (fAudioPlaybackBuffer) { | ||||
for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) | |||||
for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) { | |||||
delete[] fAudioPlaybackBuffer[audio_port_index]; | delete[] fAudioPlaybackBuffer[audio_port_index]; | ||||
} | |||||
delete[] fAudioPlaybackBuffer; | delete[] fAudioPlaybackBuffer; | ||||
fAudioPlaybackBuffer = NULL; | fAudioPlaybackBuffer = NULL; | ||||
} | } | ||||
if (fMidiPlaybackBuffer) { | if (fMidiPlaybackBuffer) { | ||||
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++) { | |||||
delete[] fMidiPlaybackBuffer[midi_port_index]; | delete[] fMidiPlaybackBuffer[midi_port_index]; | ||||
} | |||||
delete[] fMidiPlaybackBuffer; | delete[] fMidiPlaybackBuffer; | ||||
fMidiPlaybackBuffer = NULL; | fMidiPlaybackBuffer = NULL; | ||||
} | } | ||||
@@ -661,9 +727,9 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
} | } | ||||
return false; | return false; | ||||
} catch (JackNetException& e) { | } catch (JackNetException& e) { | ||||
// Otherwise just restart... | // Otherwise just restart... | ||||
e.PrintMessage(); | e.PrintMessage(); | ||||
jack_info("NetSlave is restarted"); | |||||
fThread.DropRealTime(); | fThread.DropRealTime(); | ||||
fThread.SetStatus(JackThread::kIniting); | fThread.SetStatus(JackThread::kIniting); | ||||
FreePorts(); | FreePorts(); | ||||
@@ -855,7 +921,7 @@ struct JackNetAdapter : public JackAudioAdapterInterface { | |||||
using namespace Jack; | using namespace Jack; | ||||
SERVER_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result) | |||||
LIB_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result) | |||||
{ | { | ||||
JackNetExtSlave* slave = new JackNetExtSlave(ip, port, name, request); | JackNetExtSlave* slave = new JackNetExtSlave(ip, port, name, request); | ||||
if (slave->Open(result) == 0) { | if (slave->Open(result) == 0) { | ||||
@@ -866,7 +932,7 @@ SERVER_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, co | |||||
} | } | ||||
} | } | ||||
SERVER_EXPORT int jack_net_slave_close(jack_net_slave_t* net) | |||||
LIB_EXPORT int jack_net_slave_close(jack_net_slave_t* net) | |||||
{ | { | ||||
JackNetExtSlave* slave = (JackNetExtSlave*)net; | JackNetExtSlave* slave = (JackNetExtSlave*)net; | ||||
slave->Close(); | slave->Close(); | ||||
@@ -874,37 +940,37 @@ SERVER_EXPORT int jack_net_slave_close(jack_net_slave_t* net) | |||||
return 0; | return 0; | ||||
} | } | ||||
SERVER_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg) | |||||
LIB_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg) | |||||
{ | { | ||||
JackNetExtSlave* slave = (JackNetExtSlave*)net; | JackNetExtSlave* slave = (JackNetExtSlave*)net; | ||||
return slave->SetProcessCallback(net_callback, arg); | return slave->SetProcessCallback(net_callback, arg); | ||||
} | } | ||||
SERVER_EXPORT int jack_net_slave_activate(jack_net_slave_t* net) | |||||
LIB_EXPORT int jack_net_slave_activate(jack_net_slave_t* net) | |||||
{ | { | ||||
JackNetExtSlave* slave = (JackNetExtSlave*)net; | JackNetExtSlave* slave = (JackNetExtSlave*)net; | ||||
return slave->Start(); | return slave->Start(); | ||||
} | } | ||||
SERVER_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net) | |||||
LIB_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net) | |||||
{ | { | ||||
JackNetExtSlave* slave = (JackNetExtSlave*)net; | JackNetExtSlave* slave = (JackNetExtSlave*)net; | ||||
return slave->Stop(); | return slave->Stop(); | ||||
} | } | ||||
SERVER_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg) | |||||
LIB_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg) | |||||
{ | { | ||||
JackNetExtSlave* slave = (JackNetExtSlave*)net; | JackNetExtSlave* slave = (JackNetExtSlave*)net; | ||||
return slave->SetBufferSizeCallback(bufsize_callback, arg); | return slave->SetBufferSizeCallback(bufsize_callback, arg); | ||||
} | } | ||||
SERVER_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg) | |||||
LIB_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg) | |||||
{ | { | ||||
JackNetExtSlave* slave = (JackNetExtSlave*)net; | JackNetExtSlave* slave = (JackNetExtSlave*)net; | ||||
return slave->SetSampleRateCallback(samplerate_callback, arg); | return slave->SetSampleRateCallback(samplerate_callback, arg); | ||||
} | } | ||||
SERVER_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg) | |||||
LIB_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg) | |||||
{ | { | ||||
JackNetExtSlave* slave = (JackNetExtSlave*)net; | JackNetExtSlave* slave = (JackNetExtSlave*)net; | ||||
return slave->SetShutdownCallback(shutdown_callback, arg); | return slave->SetShutdownCallback(shutdown_callback, arg); | ||||
@@ -912,7 +978,7 @@ SERVER_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, Ja | |||||
// Master API | // Master API | ||||
SERVER_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result) | |||||
LIB_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result) | |||||
{ | { | ||||
JackNetExtMaster* master = new JackNetExtMaster(ip, port, name, request); | JackNetExtMaster* master = new JackNetExtMaster(ip, port, name, request); | ||||
if (master->Open(result) == 0) { | if (master->Open(result) == 0) { | ||||
@@ -923,20 +989,21 @@ SERVER_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, | |||||
} | } | ||||
} | } | ||||
SERVER_EXPORT int jack_net_master_close(jack_net_master_t* net) | |||||
LIB_EXPORT int jack_net_master_close(jack_net_master_t* net) | |||||
{ | { | ||||
JackNetExtMaster* master = (JackNetExtMaster*)net; | JackNetExtMaster* master = (JackNetExtMaster*)net; | ||||
master->Close(); | master->Close(); | ||||
delete master; | delete master; | ||||
return 0; | return 0; | ||||
} | } | ||||
SERVER_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) | |||||
LIB_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) | |||||
{ | { | ||||
JackNetExtMaster* master = (JackNetExtMaster*)net; | JackNetExtMaster* master = (JackNetExtMaster*)net; | ||||
return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer); | return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer); | ||||
} | } | ||||
SERVER_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) | |||||
LIB_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) | |||||
{ | { | ||||
JackNetExtMaster* master = (JackNetExtMaster*)net; | JackNetExtMaster* master = (JackNetExtMaster*)net; | ||||
return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer); | return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer); | ||||
@@ -944,7 +1011,7 @@ SERVER_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, | |||||
// Adapter API | // Adapter API | ||||
SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, | |||||
LIB_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, | |||||
jack_nframes_t host_buffer_size, | 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, | ||||
@@ -957,52 +1024,53 @@ SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, | |||||
} | } | ||||
} | } | ||||
SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter) | |||||
LIB_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter) | |||||
{ | { | ||||
delete((JackNetAdapter*)adapter); | delete((JackNetAdapter*)adapter); | ||||
return 0; | return 0; | ||||
} | } | ||||
SERVER_EXPORT void jack_flush_adapter(jack_adapter_t* adapter) | |||||
LIB_EXPORT void jack_flush_adapter(jack_adapter_t* adapter) | |||||
{ | { | ||||
JackNetAdapter* slave = (JackNetAdapter*)adapter; | JackNetAdapter* slave = (JackNetAdapter*)adapter; | ||||
slave->Flush(); | slave->Flush(); | ||||
} | } | ||||
SERVER_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) | |||||
LIB_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) | |||||
{ | { | ||||
JackNetAdapter* slave = (JackNetAdapter*)adapter; | JackNetAdapter* slave = (JackNetAdapter*)adapter; | ||||
return slave->PushAndPull(input, output, frames); | return slave->PushAndPull(input, output, frames); | ||||
} | } | ||||
SERVER_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) | |||||
LIB_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) | |||||
{ | { | ||||
JackNetAdapter* slave = (JackNetAdapter*)adapter; | JackNetAdapter* slave = (JackNetAdapter*)adapter; | ||||
return slave->PullAndPush(input, output, frames); | return slave->PullAndPush(input, output, frames); | ||||
} | } | ||||
//#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) | ||||
{ | { | ||||
char buffer[300]; | |||||
size_t len; | |||||
static const char* netjack_log = getenv("JACK_NETJACK_LOG"); | |||||
static bool is_netjack_log = (netjack_log) ? atoi(netjack_log) : 0; | |||||
if (prefix != NULL) { | |||||
len = strlen(prefix); | |||||
memcpy(buffer, prefix, len); | |||||
} else { | |||||
len = 0; | |||||
} | |||||
if (is_netjack_log) { | |||||
char buffer[300]; | |||||
size_t len; | |||||
if (prefix != NULL) { | |||||
len = strlen(prefix); | |||||
memcpy(buffer, prefix, len); | |||||
} else { | |||||
len = 0; | |||||
} | |||||
vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap); | |||||
printf("%s", buffer); | |||||
printf("\n"); | |||||
vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap); | |||||
printf("%s", buffer); | |||||
printf("\n"); | |||||
} | |||||
} | } | ||||
SERVER_EXPORT void jack_error(const char *fmt, ...) | |||||
LIB_EXPORT void jack_error(const char *fmt, ...) | |||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
va_start(ap, fmt); | va_start(ap, fmt); | ||||
@@ -1010,7 +1078,7 @@ SERVER_EXPORT void jack_error(const char *fmt, ...) | |||||
va_end(ap); | va_end(ap); | ||||
} | } | ||||
SERVER_EXPORT void jack_info(const char *fmt, ...) | |||||
LIB_EXPORT void jack_info(const char *fmt, ...) | |||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
va_start(ap, fmt); | va_start(ap, fmt); | ||||
@@ -1018,26 +1086,10 @@ SERVER_EXPORT void jack_info(const char *fmt, ...) | |||||
va_end(ap); | va_end(ap); | ||||
} | } | ||||
SERVER_EXPORT void jack_log(const char *fmt, ...) | |||||
LIB_EXPORT void jack_log(const char *fmt, ...) | |||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
va_start(ap, fmt); | va_start(ap, fmt); | ||||
jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap); | jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap); | ||||
va_end(ap); | va_end(ap); | ||||
} | } | ||||
#else | |||||
// Empty code for now.. | |||||
SERVER_EXPORT void jack_error(const char *fmt, ...) | |||||
{} | |||||
SERVER_EXPORT void jack_info(const char *fmt, ...) | |||||
{} | |||||
SERVER_EXPORT void jack_log(const char *fmt, ...) | |||||
{} | |||||
#endif | |||||
@@ -260,6 +260,7 @@ namespace Jack | |||||
} | } | ||||
return false; | return false; | ||||
} catch (JackNetException& e) { | } catch (JackNetException& e) { | ||||
// Otherwise just restart... | |||||
e.PrintMessage(); | e.PrintMessage(); | ||||
jack_info("NetAdapter is restarted"); | jack_info("NetAdapter is restarted"); | ||||
Reset(); | Reset(); | ||||
@@ -413,7 +414,7 @@ extern "C" | |||||
value.i = 2; | value.i = 2; | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", NULL); | jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", NULL); | ||||
jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio output ports", NULL); | |||||
jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'P', JackDriverParamInt, &value, NULL, "Number of audio output ports", NULL); | |||||
#if HAVE_CELT | #if HAVE_CELT | ||||
value.i = -1; | value.i = -1; | ||||
@@ -16,6 +16,8 @@ along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
*/ | */ | ||||
#include "JackCompilerDeps.h" | |||||
#include "driver_interface.h" | |||||
#include "JackNetDriver.h" | #include "JackNetDriver.h" | ||||
#include "JackEngineControl.h" | #include "JackEngineControl.h" | ||||
#include "JackLockedEngine.h" | #include "JackLockedEngine.h" | ||||
@@ -509,7 +511,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(); | ||||
@@ -524,7 +526,7 @@ namespace Jack | |||||
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; | ||||
@@ -555,7 +557,7 @@ namespace Jack | |||||
} | } | ||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
fNetTimeMon->AddLast((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||||
fNetTimeMon->AddLast(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||||
#endif | #endif | ||||
//sync | //sync | ||||
@@ -588,6 +590,7 @@ namespace Jack | |||||
extern "C" | extern "C" | ||||
{ | { | ||||
#endif | #endif | ||||
SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() | SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() | ||||
{ | { | ||||
jack_driver_desc_t * desc; | jack_driver_desc_t * desc; | ||||
@@ -620,8 +623,11 @@ namespace Jack | |||||
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); | ||||
/* | |||||
Deactivated for now.. | |||||
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); | ||||
@@ -696,9 +702,12 @@ namespace Jack | |||||
case 'n' : | case 'n' : | ||||
strncpy(net_name, param->value.str, JACK_CLIENT_NAME_SIZE); | strncpy(net_name, param->value.str, JACK_CLIENT_NAME_SIZE); | ||||
break; | break; | ||||
/* | |||||
Deactivated for now.. | |||||
case 't' : | case 't' : | ||||
transport_sync = param->value.ui; | transport_sync = param->value.ui; | ||||
break; | break; | ||||
*/ | |||||
case 'l' : | case 'l' : | ||||
network_latency = param->value.ui; | network_latency = param->value.ui; | ||||
if (network_latency > NETWORK_MAX_LATENCY) { | if (network_latency > NETWORK_MAX_LATENCY) { | ||||
@@ -18,6 +18,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackNetInterface.h" | #include "JackNetInterface.h" | ||||
#include "JackException.h" | #include "JackException.h" | ||||
#include "JackError.h" | |||||
#include <assert.h> | #include <assert.h> | ||||
using namespace std; | using namespace std; | ||||
@@ -52,6 +54,7 @@ namespace Jack | |||||
void JackNetInterface::Initialize() | void JackNetInterface::Initialize() | ||||
{ | { | ||||
fSetTimeOut = false; | |||||
fTxBuffer = NULL; | fTxBuffer = NULL; | ||||
fRxBuffer = NULL; | fRxBuffer = NULL; | ||||
fNetAudioCaptureBuffer = NULL; | fNetAudioCaptureBuffer = NULL; | ||||
@@ -196,6 +199,7 @@ namespace Jack | |||||
fRxHeader.fCycle = rx_head->fCycle; | fRxHeader.fCycle = rx_head->fCycle; | ||||
fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | ||||
buffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); | buffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); | ||||
// Last midi packet is received, so finish rendering... | // Last midi packet is received, so finish rendering... | ||||
if (++recvd_midi_pckt == rx_head->fNumPacket) { | if (++recvd_midi_pckt == rx_head->fNumPacket) { | ||||
buffer->RenderToJackPorts(); | buffer->RenderToJackPorts(); | ||||
@@ -211,6 +215,7 @@ namespace Jack | |||||
fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | ||||
fRxHeader.fActivePorts = rx_head->fActivePorts; | fRxHeader.fActivePorts = rx_head->fActivePorts; | ||||
rx_bytes = buffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, fRxHeader.fActivePorts); | rx_bytes = buffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, fRxHeader.fActivePorts); | ||||
// Last audio packet is received, so finish rendering... | // Last audio packet is received, so finish rendering... | ||||
if (fRxHeader.fIsLastPckt) { | if (fRxHeader.fIsLastPckt) { | ||||
buffer->RenderToJackPorts(); | buffer->RenderToJackPorts(); | ||||
@@ -220,7 +225,6 @@ namespace Jack | |||||
int JackNetInterface::FinishRecv(NetAudioBuffer* buffer) | int JackNetInterface::FinishRecv(NetAudioBuffer* buffer) | ||||
{ | { | ||||
// TODO : finish midi and audio rendering ? | |||||
buffer->RenderToJackPorts(); | buffer->RenderToJackPorts(); | ||||
return NET_PACKET_ERROR; | return NET_PACKET_ERROR; | ||||
} | } | ||||
@@ -242,12 +246,23 @@ namespace Jack | |||||
} | } | ||||
return NULL; | return NULL; | ||||
} | } | ||||
void JackNetInterface::SetRcvTimeOut() | |||||
{ | |||||
if (!fSetTimeOut) { | |||||
if (fSocket.SetTimeOut(PACKET_TIMEOUT) == SOCKET_ERROR) { | |||||
jack_error("Can't set rx timeout : %s", StrError(NET_ERROR_CODE)); | |||||
return; | |||||
} | |||||
fSetTimeOut = true; | |||||
} | |||||
} | |||||
// JackNetMasterInterface ************************************************************************************ | // JackNetMasterInterface ************************************************************************************ | ||||
bool JackNetMasterInterface::Init() | bool JackNetMasterInterface::Init() | ||||
{ | { | ||||
jack_log("JackNetMasterInterface::Init, ID %u", fParams.fID); | |||||
jack_log("JackNetMasterInterface::Init : ID %u", fParams.fID); | |||||
session_params_t host_params; | session_params_t host_params; | ||||
uint attempt = 0; | uint attempt = 0; | ||||
@@ -260,8 +275,9 @@ namespace Jack | |||||
} | } | ||||
// timeout on receive (for init) | // timeout on receive (for init) | ||||
if (fSocket.SetTimeOut(MASTER_INIT_TIMEOUT) < 0) | |||||
jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE)); | |||||
if (fSocket.SetTimeOut(MASTER_INIT_TIMEOUT) < 0) { | |||||
jack_error("Can't set init timeout : %s", StrError(NET_ERROR_CODE)); | |||||
} | |||||
// connect | // connect | ||||
if (fSocket.Connect() == SOCKET_ERROR) { | if (fSocket.Connect() == SOCKET_ERROR) { | ||||
@@ -291,6 +307,7 @@ namespace Jack | |||||
SessionParamsNToH(&net_params, &host_params); | SessionParamsNToH(&net_params, &host_params); | ||||
} | } | ||||
while ((GetPacketType(&host_params) != START_MASTER) && (++attempt < SLAVE_SETUP_RETRY)); | while ((GetPacketType(&host_params) != START_MASTER) && (++attempt < SLAVE_SETUP_RETRY)); | ||||
if (attempt == SLAVE_SETUP_RETRY) { | if (attempt == SLAVE_SETUP_RETRY) { | ||||
jack_error("Slave doesn't respond, exiting"); | jack_error("Slave doesn't respond, exiting"); | ||||
return false; | return false; | ||||
@@ -299,13 +316,6 @@ namespace Jack | |||||
return true; | return true; | ||||
} | } | ||||
int JackNetMasterInterface::SetRxTimeout() | |||||
{ | |||||
jack_log("JackNetMasterInterface::SetRxTimeout"); | |||||
float time = 3 * 1000000.f * (static_cast<float>(fParams.fPeriodSize) / static_cast<float>(fParams.fSampleRate)); | |||||
return fSocket.SetTimeOut(static_cast<int>(time)); | |||||
} | |||||
bool JackNetMasterInterface::SetParams() | bool JackNetMasterInterface::SetParams() | ||||
{ | { | ||||
jack_log("JackNetMasterInterface::SetParams audio in = %d audio out = %d MIDI in = %d MIDI out = %d", | jack_log("JackNetMasterInterface::SetParams audio in = %d audio out = %d MIDI in = %d MIDI out = %d", | ||||
@@ -346,14 +356,6 @@ namespace Jack | |||||
return false; | return false; | ||||
} | } | ||||
// set the new timeout for the socket | |||||
/* | |||||
if (SetRxTimeout() == SOCKET_ERROR) { | |||||
jack_error("Can't set rx timeout : %s", StrError(NET_ERROR_CODE)); | |||||
goto error; | |||||
} | |||||
*/ | |||||
// set the new rx buffer size | // set the new rx buffer size | ||||
if (SetNetBufferSize() == SOCKET_ERROR) { | if (SetNetBufferSize() == SOCKET_ERROR) { | ||||
jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE)); | jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE)); | ||||
@@ -418,19 +420,6 @@ namespace Jack | |||||
int rx_bytes; | int rx_bytes; | ||||
if (((rx_bytes = fSocket.Recv(fRxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) { | if (((rx_bytes = fSocket.Recv(fRxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) { | ||||
/* | |||||
net_error_t error = fSocket.GetError(); | |||||
// no data isn't really a network error, so just return 0 available read bytes | |||||
if (error == NET_NO_DATA) { | |||||
return 0; | |||||
} else if (error == NET_CONN_ERROR) { | |||||
FatalRecvError(); | |||||
} else { | |||||
jack_error("Error in master receive : %s", StrError(NET_ERROR_CODE)); | |||||
} | |||||
*/ | |||||
FatalRecvError(); | FatalRecvError(); | ||||
} | } | ||||
@@ -446,14 +435,6 @@ namespace Jack | |||||
PacketHeaderHToN(header, header); | PacketHeaderHToN(header, header); | ||||
if (((tx_bytes = fSocket.Send(fTxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) { | if (((tx_bytes = fSocket.Send(fTxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) { | ||||
/* | |||||
net_error_t error = fSocket.GetError(); | |||||
if (error == NET_CONN_ERROR) { | |||||
FatalSendError(); | |||||
} else { | |||||
jack_error("Error in master send : %s", StrError(NET_ERROR_CODE)); | |||||
} | |||||
*/ | |||||
FatalSendError(); | FatalSendError(); | ||||
} | } | ||||
return tx_bytes; | return tx_bytes; | ||||
@@ -466,6 +447,8 @@ namespace Jack | |||||
int JackNetMasterInterface::SyncSend() | int JackNetMasterInterface::SyncSend() | ||||
{ | { | ||||
SetRcvTimeOut(); | |||||
fTxHeader.fCycle++; | fTxHeader.fCycle++; | ||||
fTxHeader.fSubCycle = 0; | fTxHeader.fSubCycle = 0; | ||||
fTxHeader.fDataType = 's'; | fTxHeader.fDataType = 's'; | ||||
@@ -490,17 +473,6 @@ namespace Jack | |||||
int rx_bytes = 0; | int rx_bytes = 0; | ||||
packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); | packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); | ||||
/* | |||||
int rx_bytes = Recv(fParams.fMtu, MSG_PEEK); | |||||
if ((rx_bytes == 0) || (rx_bytes == SOCKET_ERROR)) { | |||||
// 0 bytes considered an error (lost connection) | |||||
return SOCKET_ERROR; | |||||
} | |||||
fCurrentCycleOffset = fTxHeader.fCycle - rx_head->fCycle; | |||||
*/ | |||||
// receive sync (launch the cycle) | // receive sync (launch the cycle) | ||||
do { | do { | ||||
rx_bytes = Recv(fParams.fMtu, MSG_PEEK); | rx_bytes = Recv(fParams.fMtu, MSG_PEEK); | ||||
@@ -532,7 +504,7 @@ namespace Jack | |||||
while (!fRxHeader.fIsLastPckt) { | while (!fRxHeader.fIsLastPckt) { | ||||
// how much data is queued on the rx buffer ? | // how much data is queued on the rx buffer ? | ||||
rx_bytes = Recv(fParams.fMtu, MSG_PEEK); | rx_bytes = Recv(fParams.fMtu, MSG_PEEK); | ||||
// error here, problem with recv, just skip the cycle (return -1) | // error here, problem with recv, just skip the cycle (return -1) | ||||
if (rx_bytes == SOCKET_ERROR) { | if (rx_bytes == SOCKET_ERROR) { | ||||
return rx_bytes; | return rx_bytes; | ||||
@@ -556,7 +528,7 @@ namespace Jack | |||||
} | } | ||||
} | } | ||||
} | } | ||||
return rx_bytes; | return rx_bytes; | ||||
} | } | ||||
@@ -608,6 +580,17 @@ namespace Jack | |||||
uint JackNetSlaveInterface::fSlaveCounter = 0; | uint JackNetSlaveInterface::fSlaveCounter = 0; | ||||
void JackNetSlaveInterface::InitAPI() | |||||
{ | |||||
// open Socket API with the first slave | |||||
if (fSlaveCounter++ == 0) { | |||||
if (SocketAPIInit() < 0) { | |||||
jack_error("Can't init Socket API, exiting..."); | |||||
throw std::bad_alloc(); | |||||
} | |||||
} | |||||
} | |||||
bool JackNetSlaveInterface::Init() | bool JackNetSlaveInterface::Init() | ||||
{ | { | ||||
jack_log("JackNetSlaveInterface::Init()"); | jack_log("JackNetSlaveInterface::Init()"); | ||||
@@ -674,8 +657,9 @@ namespace Jack | |||||
// then tell the master we are ready | // then tell the master we are ready | ||||
jack_info("Initializing connection with %s...", fParams.fMasterNetName); | jack_info("Initializing connection with %s...", fParams.fMasterNetName); | ||||
status = SendStartToMaster(); | status = SendStartToMaster(); | ||||
if (status == NET_ERROR) | |||||
if (status == NET_ERROR) { | |||||
return false; | return false; | ||||
} | |||||
} | } | ||||
while (status != NET_ROLLING); | while (status != NET_ROLLING); | ||||
@@ -705,13 +689,15 @@ namespace Jack | |||||
} | } | ||||
} | } | ||||
// timeout on receive | |||||
if (fSocket.SetTimeOut(SLAVE_INIT_TIMEOUT) == SOCKET_ERROR) | |||||
jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE)); | |||||
// timeout on receive (for init) | |||||
if (fSocket.SetTimeOut(SLAVE_INIT_TIMEOUT) == SOCKET_ERROR) { | |||||
jack_error("Can't set init timeout : %s", StrError(NET_ERROR_CODE)); | |||||
} | |||||
// disable local loop | // disable local loop | ||||
if (fSocket.SetLocalLoop() == SOCKET_ERROR) | |||||
if (fSocket.SetLocalLoop() == SOCKET_ERROR) { | |||||
jack_error("Can't disable multicast loop : %s", StrError(NET_ERROR_CODE)); | jack_error("Can't disable multicast loop : %s", StrError(NET_ERROR_CODE)); | ||||
} | |||||
// send 'AVAILABLE' until 'SLAVE_SETUP' received | // send 'AVAILABLE' until 'SLAVE_SETUP' received | ||||
jack_info("Waiting for a master..."); | jack_info("Waiting for a master..."); | ||||
@@ -720,8 +706,9 @@ namespace Jack | |||||
session_params_t net_params; | session_params_t net_params; | ||||
memset(&net_params, 0, sizeof(session_params_t)); | memset(&net_params, 0, sizeof(session_params_t)); | ||||
SessionParamsHToN(&fParams, &net_params); | SessionParamsHToN(&fParams, &net_params); | ||||
if (fSocket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR) | |||||
if (fSocket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR) { | |||||
jack_error("Error in data send : %s", StrError(NET_ERROR_CODE)); | jack_error("Error in data send : %s", StrError(NET_ERROR_CODE)); | ||||
} | |||||
// filter incoming packets : don't exit while no error is detected | // filter incoming packets : don't exit while no error is detected | ||||
memset(&net_params, 0, sizeof(session_params_t)); | memset(&net_params, 0, sizeof(session_params_t)); | ||||
@@ -833,20 +820,9 @@ namespace Jack | |||||
int JackNetSlaveInterface::Recv(size_t size, int flags) | int JackNetSlaveInterface::Recv(size_t size, int flags) | ||||
{ | { | ||||
int rx_bytes = fSocket.Recv(fRxBuffer, size, flags); | int rx_bytes = fSocket.Recv(fRxBuffer, size, flags); | ||||
// handle errors | // handle errors | ||||
if (rx_bytes == SOCKET_ERROR) { | if (rx_bytes == SOCKET_ERROR) { | ||||
/* | |||||
net_error_t error = fSocket.GetError(); | |||||
// no data isn't really an error in realtime processing, so just return 0 | |||||
if (error == NET_NO_DATA) { | |||||
jack_error("No data, is the master still running ?"); | |||||
// if a network error occurs, this exception will restart the driver | |||||
} else if (error == NET_CONN_ERROR) { | |||||
FatalRecvError(); | |||||
} else { | |||||
jack_error("Fatal error in slave receive : %s", StrError(NET_ERROR_CODE)); | |||||
} | |||||
*/ | |||||
FatalRecvError(); | FatalRecvError(); | ||||
} | } | ||||
@@ -863,17 +839,9 @@ namespace Jack | |||||
// handle errors | // handle errors | ||||
if (tx_bytes == SOCKET_ERROR) { | if (tx_bytes == SOCKET_ERROR) { | ||||
/* | |||||
net_error_t error = fSocket.GetError(); | |||||
// if a network error occurs, this exception will restart the driver | |||||
if (error == NET_CONN_ERROR) { | |||||
FatalSendError(); | |||||
} else { | |||||
jack_error("Fatal error in slave send : %s", StrError(NET_ERROR_CODE)); | |||||
} | |||||
*/ | |||||
FatalSendError(); | FatalSendError(); | ||||
} | } | ||||
return tx_bytes; | return tx_bytes; | ||||
} | } | ||||
@@ -881,7 +849,7 @@ namespace Jack | |||||
{ | { | ||||
int rx_bytes = 0; | int rx_bytes = 0; | ||||
packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); | packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); | ||||
// receive sync (launch the cycle) | // receive sync (launch the cycle) | ||||
do { | do { | ||||
rx_bytes = Recv(fParams.fMtu, 0); | rx_bytes = Recv(fParams.fMtu, 0); | ||||
@@ -893,6 +861,8 @@ namespace Jack | |||||
while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's')); | while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's')); | ||||
fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | ||||
SetRcvTimeOut(); | |||||
return rx_bytes; | return rx_bytes; | ||||
} | } | ||||
@@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#define __JackNetInterface__ | #define __JackNetInterface__ | ||||
#include "JackNetTool.h" | #include "JackNetTool.h" | ||||
#include <limits.h> | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -31,9 +32,10 @@ namespace Jack | |||||
#define SLAVE_SETUP_RETRY 5 | #define SLAVE_SETUP_RETRY 5 | ||||
#define MANAGER_INIT_TIMEOUT 2000000 // in usec | |||||
#define MASTER_INIT_TIMEOUT 1000000 // in usec | |||||
#define SLAVE_INIT_TIMEOUT 1000000 // in usec | |||||
#define MANAGER_INIT_TIMEOUT 2000000 // in usec | |||||
#define MASTER_INIT_TIMEOUT 1000000 * 10 // in usec | |||||
#define SLAVE_INIT_TIMEOUT 1000000 * 10 // in usec | |||||
#define PACKET_TIMEOUT 500000 // in usec | |||||
#define NETWORK_MAX_LATENCY 20 | #define NETWORK_MAX_LATENCY 20 | ||||
@@ -45,6 +47,8 @@ namespace Jack | |||||
{ | { | ||||
protected: | protected: | ||||
bool fSetTimeOut; | |||||
void Initialize(); | void Initialize(); | ||||
@@ -106,6 +110,8 @@ namespace Jack | |||||
int AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer); | int AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer); | ||||
int FinishRecv(NetAudioBuffer* buffer); | int FinishRecv(NetAudioBuffer* buffer); | ||||
void SetRcvTimeOut(); | |||||
NetAudioBuffer* AudioBufferFactory(int nports, char* buffer); | NetAudioBuffer* AudioBufferFactory(int nports, char* buffer); | ||||
@@ -129,13 +135,10 @@ namespace Jack | |||||
protected: | protected: | ||||
bool fRunning; | bool fRunning; | ||||
int fCurrentCycleOffset; | int fCurrentCycleOffset; | ||||
int fMaxCycleOffset; | int fMaxCycleOffset; | ||||
int fLastfCycleOffset; | |||||
bool Init(); | bool Init(); | ||||
int SetRxTimeout(); | |||||
bool SetParams(); | bool SetParams(); | ||||
void Exit(); | void Exit(); | ||||
@@ -160,10 +163,10 @@ namespace Jack | |||||
public: | public: | ||||
JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCurrentCycleOffset(0), fMaxCycleOffset(0), fLastfCycleOffset(0) | |||||
JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCurrentCycleOffset(0), fMaxCycleOffset(0) | |||||
{} | {} | ||||
JackNetMasterInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip) | JackNetMasterInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip) | ||||
: JackNetInterface(params, socket, multicast_ip) | |||||
: JackNetInterface(params, socket, multicast_ip), fRunning(false), fCurrentCycleOffset(0), fMaxCycleOffset(0) | |||||
{} | {} | ||||
virtual~JackNetMasterInterface() | virtual~JackNetMasterInterface() | ||||
@@ -206,16 +209,7 @@ namespace Jack | |||||
void FatalRecvError(); | void FatalRecvError(); | ||||
void FatalSendError(); | void FatalSendError(); | ||||
void InitAPI() | |||||
{ | |||||
// open Socket API with the first slave | |||||
if (fSlaveCounter++ == 0) { | |||||
if (SocketAPIInit() < 0) { | |||||
jack_error("Can't init Socket API, exiting..."); | |||||
throw std::bad_alloc(); | |||||
} | |||||
} | |||||
} | |||||
void InitAPI(); | |||||
public: | public: | ||||
@@ -33,8 +33,8 @@ namespace Jack | |||||
jack_log("JackNetMaster::JackNetMaster"); | jack_log("JackNetMaster::JackNetMaster"); | ||||
//settings | //settings | ||||
fClientName = const_cast<char*>(fParams.fName); | |||||
fJackClient = NULL; | |||||
fName = const_cast<char*>(fParams.fName); | |||||
fClient = NULL; | |||||
fSendTransportData.fState = -1; | fSendTransportData.fState = -1; | ||||
fReturnTransportData.fState = -1; | fReturnTransportData.fState = -1; | ||||
fLastTransportState = -1; | fLastTransportState = -1; | ||||
@@ -91,10 +91,10 @@ namespace Jack | |||||
{ | { | ||||
jack_log("JackNetMaster::~JackNetMaster ID = %u", fParams.fID); | jack_log("JackNetMaster::~JackNetMaster ID = %u", fParams.fID); | ||||
if (fJackClient) { | |||||
jack_deactivate(fJackClient); | |||||
if (fClient) { | |||||
jack_deactivate(fClient); | |||||
FreePorts(); | FreePorts(); | ||||
jack_client_close(fJackClient); | |||||
jack_client_close(fClient); | |||||
} | } | ||||
delete[] fAudioCapturePorts; | delete[] fAudioCapturePorts; | ||||
delete[] fAudioPlaybackPorts; | delete[] fAudioPlaybackPorts; | ||||
@@ -122,18 +122,24 @@ namespace Jack | |||||
//jack client and process | //jack client and process | ||||
jack_status_t status; | jack_status_t status; | ||||
if ((fJackClient = jack_client_open(fClientName, JackNullOption, &status, NULL)) == NULL) { | |||||
if ((fClient = jack_client_open(fName, JackNullOption, &status, NULL)) == NULL) { | |||||
jack_error("Can't open a new JACK client"); | jack_error("Can't open a new JACK client"); | ||||
return false; | return false; | ||||
} | } | ||||
if (jack_set_process_callback(fJackClient, SetProcess, this) < 0) { | |||||
if (jack_set_process_callback(fClient, SetProcess, this) < 0) { | |||||
goto fail; | goto fail; | ||||
} | } | ||||
if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0) { | |||||
if (jack_set_buffer_size_callback(fClient, SetBufferSize, this) < 0) { | |||||
goto fail; | |||||
} | |||||
/* | |||||
if (jack_set_port_connect_callback(fClient, SetConnectCallback, this) < 0) { | |||||
goto fail; | goto fail; | ||||
} | } | ||||
*/ | |||||
if (AllocPorts() != 0) { | if (AllocPorts() != 0) { | ||||
jack_error("Can't allocate JACK ports"); | jack_error("Can't allocate JACK ports"); | ||||
@@ -144,7 +150,7 @@ namespace Jack | |||||
fRunning = true; | fRunning = true; | ||||
//finally activate jack client | //finally activate jack client | ||||
if (jack_activate(fJackClient) != 0) { | |||||
if (jack_activate(fClient) != 0) { | |||||
jack_error("Can't activate JACK client"); | jack_error("Can't activate JACK client"); | ||||
goto fail; | goto fail; | ||||
} | } | ||||
@@ -157,8 +163,8 @@ namespace Jack | |||||
fail: | fail: | ||||
FreePorts(); | FreePorts(); | ||||
jack_client_close(fJackClient); | |||||
fJackClient = NULL; | |||||
jack_client_close(fClient); | |||||
fClient = NULL; | |||||
return false; | return false; | ||||
} | } | ||||
@@ -167,7 +173,7 @@ namespace Jack | |||||
{ | { | ||||
int i; | int i; | ||||
char name[24]; | char name[24]; | ||||
jack_nframes_t port_latency = jack_get_buffer_size(fJackClient); | |||||
jack_nframes_t port_latency = jack_get_buffer_size(fClient); | |||||
jack_latency_range_t range; | jack_latency_range_t range; | ||||
jack_log("JackNetMaster::AllocPorts"); | jack_log("JackNetMaster::AllocPorts"); | ||||
@@ -175,7 +181,7 @@ namespace Jack | |||||
//audio | //audio | ||||
for (i = 0; i < fParams.fSendAudioChannels; i++) { | for (i = 0; i < fParams.fSendAudioChannels; i++) { | ||||
snprintf(name, sizeof(name), "to_slave_%d", i+1); | snprintf(name, sizeof(name), "to_slave_%d", i+1); | ||||
if ((fAudioCapturePorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) | |||||
if ((fAudioCapturePorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) | |||||
return -1; | return -1; | ||||
//port latency | //port latency | ||||
range.min = range.max = 0; | range.min = range.max = 0; | ||||
@@ -184,7 +190,7 @@ namespace Jack | |||||
for (i = 0; i < fParams.fReturnAudioChannels; i++) { | for (i = 0; i < fParams.fReturnAudioChannels; i++) { | ||||
snprintf(name, sizeof(name), "from_slave_%d", i+1); | snprintf(name, sizeof(name), "from_slave_%d", i+1); | ||||
if ((fAudioPlaybackPorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) | |||||
if ((fAudioPlaybackPorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) | |||||
return -1; | return -1; | ||||
//port latency | //port latency | ||||
range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; | range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; | ||||
@@ -194,7 +200,7 @@ namespace Jack | |||||
//midi | //midi | ||||
for (i = 0; i < fParams.fSendMidiChannels; i++) { | for (i = 0; i < fParams.fSendMidiChannels; i++) { | ||||
snprintf(name, sizeof(name), "midi_to_slave_%d", i+1); | snprintf(name, sizeof(name), "midi_to_slave_%d", i+1); | ||||
if ((fMidiCapturePorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) | |||||
if ((fMidiCapturePorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) | |||||
return -1; | return -1; | ||||
//port latency | //port latency | ||||
range.min = range.max = 0; | range.min = range.max = 0; | ||||
@@ -203,7 +209,7 @@ namespace Jack | |||||
for (i = 0; i < fParams.fReturnMidiChannels; i++) { | for (i = 0; i < fParams.fReturnMidiChannels; i++) { | ||||
snprintf(name, sizeof(name), "midi_from_slave_%d", i+1); | snprintf(name, sizeof(name), "midi_from_slave_%d", i+1); | ||||
if ((fMidiPlaybackPorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) | |||||
if ((fMidiPlaybackPorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) | |||||
return -1; | return -1; | ||||
//port latency | //port latency | ||||
range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; | range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; | ||||
@@ -216,18 +222,18 @@ namespace Jack | |||||
{ | { | ||||
const char **ports; | const char **ports; | ||||
ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); | |||||
ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); | |||||
if (ports != NULL) { | if (ports != NULL) { | ||||
for (int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) { | for (int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) { | ||||
jack_connect(fJackClient, ports[i], jack_port_name(fAudioCapturePorts[i])); | |||||
jack_connect(fClient, ports[i], jack_port_name(fAudioCapturePorts[i])); | |||||
} | } | ||||
free(ports); | free(ports); | ||||
} | } | ||||
ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); | |||||
ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); | |||||
if (ports != NULL) { | if (ports != NULL) { | ||||
for (int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) { | for (int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) { | ||||
jack_connect(fJackClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]); | |||||
jack_connect(fClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]); | |||||
} | } | ||||
free(ports); | free(ports); | ||||
} | } | ||||
@@ -240,22 +246,22 @@ namespace Jack | |||||
int port_index; | int port_index; | ||||
for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) { | for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) { | ||||
if (fAudioCapturePorts[port_index]) { | if (fAudioCapturePorts[port_index]) { | ||||
jack_port_unregister(fJackClient, fAudioCapturePorts[port_index]); | |||||
jack_port_unregister(fClient, fAudioCapturePorts[port_index]); | |||||
} | } | ||||
} | } | ||||
for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) { | for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) { | ||||
if (fAudioPlaybackPorts[port_index]) { | if (fAudioPlaybackPorts[port_index]) { | ||||
jack_port_unregister(fJackClient, fAudioPlaybackPorts[port_index]); | |||||
jack_port_unregister(fClient, fAudioPlaybackPorts[port_index]); | |||||
} | } | ||||
} | } | ||||
for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) { | for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) { | ||||
if (fMidiCapturePorts[port_index]) { | if (fMidiCapturePorts[port_index]) { | ||||
jack_port_unregister(fJackClient, fMidiCapturePorts[port_index]); | |||||
jack_port_unregister(fClient, fMidiCapturePorts[port_index]); | |||||
} | } | ||||
} | } | ||||
for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) { | for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) { | ||||
if (fMidiPlaybackPorts[port_index]) { | if (fMidiPlaybackPorts[port_index]) { | ||||
jack_port_unregister(fJackClient, fMidiPlaybackPorts[port_index]); | |||||
jack_port_unregister(fClient, fMidiPlaybackPorts[port_index]); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -268,7 +274,7 @@ namespace Jack | |||||
fSendTransportData.fTimebaseMaster = NO_CHANGE; | fSendTransportData.fTimebaseMaster = NO_CHANGE; | ||||
//update state and position | //update state and position | ||||
fSendTransportData.fState = static_cast<uint>(jack_transport_query(fJackClient, &fSendTransportData.fPosition)); | |||||
fSendTransportData.fState = static_cast<uint>(jack_transport_query(fClient, &fSendTransportData.fPosition)); | |||||
//is it a new state ? | //is it a new state ? | ||||
fSendTransportData.fNewState = ((fSendTransportData.fState != fLastTransportState) && (fSendTransportData.fState != fReturnTransportData.fState)); | fSendTransportData.fNewState = ((fSendTransportData.fState != fLastTransportState) && (fSendTransportData.fState != fReturnTransportData.fState)); | ||||
@@ -287,7 +293,7 @@ namespace Jack | |||||
switch (fReturnTransportData.fTimebaseMaster) | switch (fReturnTransportData.fTimebaseMaster) | ||||
{ | { | ||||
case RELEASE_TIMEBASEMASTER : | case RELEASE_TIMEBASEMASTER : | ||||
timebase = jack_release_timebase(fJackClient); | |||||
timebase = jack_release_timebase(fClient); | |||||
if (timebase < 0) { | if (timebase < 0) { | ||||
jack_error("Can't release timebase master"); | jack_error("Can't release timebase master"); | ||||
} else { | } else { | ||||
@@ -296,7 +302,7 @@ namespace Jack | |||||
break; | break; | ||||
case TIMEBASEMASTER : | case TIMEBASEMASTER : | ||||
timebase = jack_set_timebase_callback(fJackClient, 0, SetTimebaseCallback, this); | |||||
timebase = jack_set_timebase_callback(fClient, 0, SetTimebaseCallback, this); | |||||
if (timebase < 0) { | if (timebase < 0) { | ||||
jack_error("Can't set a new timebase master"); | jack_error("Can't set a new timebase master"); | ||||
} else { | } else { | ||||
@@ -305,7 +311,7 @@ namespace Jack | |||||
break; | break; | ||||
case CONDITIONAL_TIMEBASEMASTER : | case CONDITIONAL_TIMEBASEMASTER : | ||||
timebase = jack_set_timebase_callback(fJackClient, 1, SetTimebaseCallback, this); | |||||
timebase = jack_set_timebase_callback(fClient, 1, SetTimebaseCallback, this); | |||||
if (timebase != EBUSY) { | if (timebase != EBUSY) { | ||||
if (timebase < 0) | if (timebase < 0) | ||||
jack_error("Can't set a new timebase master"); | jack_error("Can't set a new timebase master"); | ||||
@@ -317,19 +323,19 @@ namespace Jack | |||||
} | } | ||||
//is the slave in a new transport state and is this state different from master's ? | //is the slave in a new transport state and is this state different from master's ? | ||||
if (fReturnTransportData.fNewState && (fReturnTransportData.fState != jack_transport_query(fJackClient, NULL))) { | |||||
if (fReturnTransportData.fNewState && (fReturnTransportData.fState != jack_transport_query(fClient, NULL))) { | |||||
switch (fReturnTransportData.fState) | switch (fReturnTransportData.fState) | ||||
{ | { | ||||
case JackTransportStopped : | case JackTransportStopped : | ||||
jack_transport_stop(fJackClient); | |||||
jack_transport_stop(fClient); | |||||
jack_info("'%s' stops transport", fParams.fName); | jack_info("'%s' stops transport", fParams.fName); | ||||
break; | break; | ||||
case JackTransportStarting : | case JackTransportStarting : | ||||
if (jack_transport_reposition(fJackClient, &fReturnTransportData.fPosition) == EINVAL) | |||||
if (jack_transport_reposition(fClient, &fReturnTransportData.fPosition) == EINVAL) | |||||
jack_error("Can't set new position"); | jack_error("Can't set new position"); | ||||
jack_transport_start(fJackClient); | |||||
jack_transport_start(fClient); | |||||
jack_info("'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame); | jack_info("'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame); | ||||
break; | break; | ||||
@@ -387,11 +393,22 @@ namespace Jack | |||||
return 0; | return 0; | ||||
} | } | ||||
} | } | ||||
void JackNetMaster::SetConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg) | |||||
{ | |||||
static_cast<JackNetMaster*>(arg)->ConnectCallback(a, b, connect); | |||||
} | |||||
void JackNetMaster::ConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect) | |||||
{ | |||||
jack_info("JackNetMaster::ConnectCallback a = %d b = %d connect = %d", a, b, connect); | |||||
if (connect) { | |||||
jack_connect(fClient, jack_port_name(jack_port_by_id(fClient, a)), "system:playback_1"); | |||||
} | |||||
} | |||||
int JackNetMaster::Process() | int JackNetMaster::Process() | ||||
{ | { | ||||
int res; | |||||
if (!fRunning) { | if (!fRunning) { | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -474,35 +491,15 @@ namespace Jack | |||||
#endif | #endif | ||||
} else { | } else { | ||||
jack_error("Connection is not synched, skip cycle..."); | |||||
jack_info("Connection is not synched, skip cycle..."); | |||||
} | } | ||||
//receive sync | //receive sync | ||||
res = SyncRecv(); | |||||
int res = SyncRecv(); | |||||
if ((res == 0) || (res == SOCKET_ERROR)) { | if ((res == 0) || (res == SOCKET_ERROR)) { | ||||
return res; | return res; | ||||
} | } | ||||
/* | |||||
switch (SyncRecv()) { | |||||
case 0: | |||||
jack_error("Connection is not yet synched, skip cycle..."); | |||||
return 0; | |||||
case SOCKET_ERROR: | |||||
jack_error("Connection is lost, quit master..."); | |||||
//ask to the manager to properly remove the master | |||||
Exit(); | |||||
//UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine. | |||||
ThreadExit(); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
*/ | |||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | ||||
#endif | #endif | ||||
@@ -519,26 +516,6 @@ namespace Jack | |||||
JackServerGlobals::fInstance->GetEngine()->NotifyXRun(GetMicroSeconds(), 0); | JackServerGlobals::fInstance->GetEngine()->NotifyXRun(GetMicroSeconds(), 0); | ||||
} | } | ||||
/* | |||||
switch (DataRecv()) { | |||||
case 0: | |||||
jack_error("Connection is not yet synched, skip cycle..."); | |||||
return 0; | |||||
case SOCKET_ERROR: | |||||
jack_error("Connection is lost, quit master..."); | |||||
//ask to the manager to properly remove the master | |||||
Exit(); | |||||
//UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine. | |||||
ThreadExit(); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
*/ | |||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
fNetTimeMon->AddLast((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | fNetTimeMon->AddLast((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | ||||
#endif | #endif | ||||
@@ -551,15 +528,17 @@ namespace Jack | |||||
{ | { | ||||
jack_log("JackNetMasterManager::JackNetMasterManager"); | jack_log("JackNetMasterManager::JackNetMasterManager"); | ||||
fManagerClient = client; | |||||
fManagerName = jack_get_client_name(fManagerClient); | |||||
fClient = client; | |||||
fName = jack_get_client_name(fClient); | |||||
fGlobalID = 0; | fGlobalID = 0; | ||||
fRunning = true; | fRunning = true; | ||||
fAutoConnect = false; | fAutoConnect = false; | ||||
const JSList* node; | const JSList* node; | ||||
const jack_driver_param_t* param; | const jack_driver_param_t* param; | ||||
jack_on_shutdown(fClient, SetShutDown, this); | |||||
// Possibly use env variable | // Possibly use env variable | ||||
const char* default_udp_port = getenv("JACK_NETJACK_PORT"); | const char* default_udp_port = getenv("JACK_NETJACK_PORT"); | ||||
fSocket.SetPort((default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT); | fSocket.SetPort((default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT); | ||||
@@ -595,15 +574,15 @@ namespace Jack | |||||
} | } | ||||
//set sync callback | //set sync callback | ||||
jack_set_sync_callback(fManagerClient, SetSyncCallback, this); | |||||
jack_set_sync_callback(fClient, SetSyncCallback, this); | |||||
//activate the client (for sync callback) | //activate the client (for sync callback) | ||||
if (jack_activate(fManagerClient) != 0) { | |||||
if (jack_activate(fClient) != 0) { | |||||
jack_error("Can't activate the NetManager client, transport disabled"); | jack_error("Can't activate the NetManager client, transport disabled"); | ||||
} | } | ||||
//launch the manager thread | //launch the manager thread | ||||
if (jack_client_create_thread(fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this)) { | |||||
if (jack_client_create_thread(fClient, &fThread, 0, 0, NetManagerThread, this)) { | |||||
jack_error("Can't create the NetManager control thread"); | jack_error("Can't create the NetManager control thread"); | ||||
} | } | ||||
} | } | ||||
@@ -611,15 +590,7 @@ namespace Jack | |||||
JackNetMasterManager::~JackNetMasterManager() | JackNetMasterManager::~JackNetMasterManager() | ||||
{ | { | ||||
jack_log("JackNetMasterManager::~JackNetMasterManager"); | jack_log("JackNetMasterManager::~JackNetMasterManager"); | ||||
jack_info("Exiting NetManager..."); | |||||
fRunning = false; | |||||
jack_client_kill_thread(fManagerClient, fManagerThread); | |||||
master_list_t::iterator it; | |||||
for (it = fMasterList.begin(); it != fMasterList.end(); it++) { | |||||
delete(*it); | |||||
} | |||||
fSocket.Close(); | |||||
SocketAPIEnd(); | |||||
ShutDown(); | |||||
} | } | ||||
int JackNetMasterManager::CountIO(int flags) | int JackNetMasterManager::CountIO(int flags) | ||||
@@ -628,10 +599,10 @@ namespace Jack | |||||
int count = 0; | int count = 0; | ||||
jack_port_t* port; | jack_port_t* port; | ||||
ports = jack_get_ports(fManagerClient, NULL, NULL, flags); | |||||
ports = jack_get_ports(fClient, NULL, NULL, flags); | |||||
if (ports != NULL) { | if (ports != NULL) { | ||||
while (ports[count] | while (ports[count] | ||||
&& (port = jack_port_by_name(fManagerClient, ports[count])) | |||||
&& (port = jack_port_by_name(fClient, ports[count])) | |||||
&& (strcmp(jack_port_type(port), JACK_DEFAULT_AUDIO_TYPE) == 0)) { | && (strcmp(jack_port_type(port), JACK_DEFAULT_AUDIO_TYPE) == 0)) { | ||||
count++; | count++; | ||||
} | } | ||||
@@ -639,6 +610,27 @@ namespace Jack | |||||
} | } | ||||
return count; | return count; | ||||
} | } | ||||
void JackNetMasterManager::SetShutDown(void* arg) | |||||
{ | |||||
static_cast<JackNetMasterManager*>(arg)->ShutDown(); | |||||
} | |||||
void JackNetMasterManager::ShutDown() | |||||
{ | |||||
jack_log("JackNetMasterManager::ShutDown"); | |||||
if (fRunning) { | |||||
jack_client_kill_thread(fClient, fThread); | |||||
fRunning = false; | |||||
} | |||||
master_list_t::iterator it; | |||||
for (it = fMasterList.begin(); it != fMasterList.end(); it++) { | |||||
delete(*it); | |||||
} | |||||
fMasterList.clear(); | |||||
fSocket.Close(); | |||||
SocketAPIEnd(); | |||||
} | |||||
int JackNetMasterManager::SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg) | int JackNetMasterManager::SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg) | ||||
{ | { | ||||
@@ -719,6 +711,7 @@ namespace Jack | |||||
session_params_t net_params; | session_params_t net_params; | ||||
rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0); | rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0); | ||||
SessionParamsNToH(&net_params, &host_params); | SessionParamsNToH(&net_params, &host_params); | ||||
if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) { | if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) { | ||||
jack_error("Error in receive : %s", StrError(NET_ERROR_CODE)); | jack_error("Error in receive : %s", StrError(NET_ERROR_CODE)); | ||||
if (++attempt == 10) { | if (++attempt == 10) { | ||||
@@ -728,7 +721,7 @@ namespace Jack | |||||
} | } | ||||
if (rx_bytes == sizeof(session_params_t)) { | if (rx_bytes == sizeof(session_params_t)) { | ||||
switch (GetPacketType (&host_params)) | |||||
switch (GetPacketType(&host_params)) | |||||
{ | { | ||||
case SLAVE_AVAILABLE: | case SLAVE_AVAILABLE: | ||||
if ((net_master = InitMaster(host_params))) { | if ((net_master = InitMaster(host_params))) { | ||||
@@ -764,8 +757,8 @@ namespace Jack | |||||
//settings | //settings | ||||
fSocket.GetName(params.fMasterNetName); | fSocket.GetName(params.fMasterNetName); | ||||
params.fID = ++fGlobalID; | params.fID = ++fGlobalID; | ||||
params.fSampleRate = jack_get_sample_rate(fManagerClient); | |||||
params.fPeriodSize = jack_get_buffer_size(fManagerClient); | |||||
params.fSampleRate = jack_get_sample_rate(fClient); | |||||
params.fPeriodSize = jack_get_buffer_size(fClient); | |||||
if (params.fSendAudioChannels == -1) { | if (params.fSendAudioChannels == -1) { | ||||
params.fSendAudioChannels = CountIO(JackPortIsPhysical | JackPortIsOutput); | params.fSendAudioChannels = CountIO(JackPortIsPhysical | JackPortIsOutput); | ||||
@@ -875,7 +868,7 @@ extern "C" | |||||
SERVER_EXPORT void jack_finish(void* arg) | SERVER_EXPORT void jack_finish(void* arg) | ||||
{ | { | ||||
if (master_manager) { | if (master_manager) { | ||||
jack_log ("Unloading Master Manager"); | |||||
jack_log("Unloading Master Manager"); | |||||
delete master_manager; | delete master_manager; | ||||
master_manager = NULL; | master_manager = NULL; | ||||
} | } | ||||
@@ -39,14 +39,15 @@ namespace Jack | |||||
friend class JackNetMasterManager; | friend class JackNetMasterManager; | ||||
private: | private: | ||||
static int SetProcess(jack_nframes_t nframes, void* arg); | static int SetProcess(jack_nframes_t nframes, void* arg); | ||||
static int SetBufferSize(jack_nframes_t nframes, void* arg); | static int SetBufferSize(jack_nframes_t nframes, void* arg); | ||||
static void SetTimebaseCallback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg); | static void SetTimebaseCallback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg); | ||||
static void SetConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg); | |||||
//jack client | //jack client | ||||
jack_client_t* fJackClient; | |||||
const char* fClientName; | |||||
jack_client_t* fClient; | |||||
const char* fName; | |||||
//jack ports | //jack ports | ||||
jack_port_t** fAudioCapturePorts; | jack_port_t** fAudioCapturePorts; | ||||
@@ -74,6 +75,7 @@ namespace Jack | |||||
int Process(); | int Process(); | ||||
void TimebaseCallback(jack_position_t* pos); | void TimebaseCallback(jack_position_t* pos); | ||||
void ConnectPorts(); | void ConnectPorts(); | ||||
void ConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect); | |||||
public: | public: | ||||
@@ -96,14 +98,15 @@ namespace Jack | |||||
private: | private: | ||||
static void SetShutDown(void* arg); | |||||
static int SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg); | static int SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg); | ||||
static void* NetManagerThread(void* arg); | static void* NetManagerThread(void* arg); | ||||
jack_client_t* fManagerClient; | |||||
const char* fManagerName; | |||||
jack_client_t* fClient; | |||||
const char* fName; | |||||
char fMulticastIP[32]; | char fMulticastIP[32]; | ||||
JackNetSocket fSocket; | JackNetSocket fSocket; | ||||
jack_native_thread_t fManagerThread; | |||||
jack_native_thread_t fThread; | |||||
master_list_t fMasterList; | master_list_t fMasterList; | ||||
uint32_t fGlobalID; | uint32_t fGlobalID; | ||||
bool fRunning; | bool fRunning; | ||||
@@ -115,6 +118,7 @@ namespace Jack | |||||
int KillMaster(session_params_t* params); | int KillMaster(session_params_t* params); | ||||
int SyncCallback(jack_transport_state_t state, jack_position_t* pos); | int SyncCallback(jack_transport_state_t state, jack_position_t* pos); | ||||
int CountIO(int flags); | int CountIO(int flags); | ||||
void ShutDown(); | |||||
public: | public: | ||||
@@ -56,7 +56,7 @@ JackNetOneDriver::JackNetOneDriver(const char* name, const char* alias, JackLock | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
WSADATA wsa; | WSADATA wsa; | ||||
int rc = WSAStartup(MAKEWORD(2, 0), &wsa); | |||||
WSAStartup(MAKEWORD(2, 0), &wsa); | |||||
#endif | #endif | ||||
netjack_init(& (this->netj), | netjack_init(& (this->netj), | ||||
@@ -753,6 +753,7 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p | |||||
extern "C" | extern "C" | ||||
{ | { | ||||
#endif | #endif | ||||
SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor () | SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor () | ||||
{ | { | ||||
jack_driver_desc_t * desc; | jack_driver_desc_t * desc; | ||||
@@ -20,7 +20,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#ifndef __JackNetSocket__ | #ifndef __JackNetSocket__ | ||||
#define __JackNetSocket__ | #define __JackNetSocket__ | ||||
#include "JackError.h" | |||||
#include "JackCompilerDeps.h" | |||||
#include <cstdlib> | #include <cstdlib> | ||||
#include <cstdio> | #include <cstdio> | ||||
#include <iostream> | #include <iostream> | ||||
@@ -29,7 +30,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
//get host name********************************* | //get host name********************************* | ||||
SERVER_EXPORT int GetHostName ( char * name, int size ); | |||||
SERVER_EXPORT int GetHostName(char * name, int size); | |||||
//net errors *********************************** | //net errors *********************************** | ||||
enum _net_error | enum _net_error | ||||
@@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | */ | ||||
#include "JackNetTool.h" | #include "JackNetTool.h" | ||||
#include "JackError.h" | |||||
#ifdef __APPLE__ | #ifdef __APPLE__ | ||||
@@ -274,7 +275,7 @@ namespace Jack | |||||
*active_port_address = htonl(port_index); | *active_port_address = htonl(port_index); | ||||
active_port_address++; | active_port_address++; | ||||
active_ports++; | active_ports++; | ||||
assert(active_ports < 256); | |||||
assert(active_ports < 256); | |||||
} | } | ||||
} | } | ||||
@@ -306,7 +307,6 @@ namespace Jack | |||||
// Count active ports | // Count active ports | ||||
int active_ports = 0; | int active_ports = 0; | ||||
for (int port_index = 0; port_index < fNPorts; port_index++) { | for (int port_index = 0; port_index < fNPorts; port_index++) { | ||||
if (fPortBuffer[port_index]) { | if (fPortBuffer[port_index]) { | ||||
active_ports++; | active_ports++; | ||||
} | } | ||||
@@ -627,7 +627,7 @@ namespace Jack | |||||
int NetCeltAudioBuffer::RenderFromJackPorts() | int NetCeltAudioBuffer::RenderFromJackPorts() | ||||
{ | { | ||||
float buffer[fPeriodSize]; | |||||
float buffer[BUFFER_SIZE_MAX]; | |||||
for (int port_index = 0; port_index < fNPorts; port_index++) { | for (int port_index = 0; port_index < fNPorts; port_index++) { | ||||
if (fPortBuffer[port_index]) { | if (fPortBuffer[port_index]) { | ||||
@@ -49,6 +49,8 @@ bool JackPort::Allocate(int refnum, const char* port_name, const char* port_type | |||||
fPlaybackLatency.min = fPlaybackLatency.max = 0; | fPlaybackLatency.min = fPlaybackLatency.max = 0; | ||||
fCaptureLatency.min = fCaptureLatency.max = 0; | fCaptureLatency.min = fCaptureLatency.max = 0; | ||||
fTied = NO_PORT; | fTied = NO_PORT; | ||||
fAlias1[0] = '\0'; | |||||
fAlias2[0] = '\0'; | |||||
// DB: At this point we do not know current buffer size in frames, | // DB: At this point we do not know current buffer size in frames, | ||||
// but every time buffer will be returned to any user, | // but every time buffer will be returned to any user, | ||||
// it will be called with either ClearBuffer or MixBuffers | // it will be called with either ClearBuffer or MixBuffers | ||||
@@ -58,7 +58,7 @@ class SERVER_EXPORT JackPort | |||||
bool fInUse; | bool fInUse; | ||||
jack_port_id_t fTied; // Locally tied source port | jack_port_id_t fTied; // Locally tied source port | ||||
jack_default_audio_sample_t fBuffer[BUFFER_SIZE_MAX + 4]; | |||||
jack_default_audio_sample_t fBuffer[BUFFER_SIZE_MAX + 8]; | |||||
bool IsUsed() const | bool IsUsed() const | ||||
{ | { | ||||
@@ -108,7 +108,7 @@ class SERVER_EXPORT JackPort | |||||
// Since we are in shared memory, the resulting pointer cannot be cached, so align it here... | // Since we are in shared memory, the resulting pointer cannot be cached, so align it here... | ||||
jack_default_audio_sample_t* GetBuffer() | jack_default_audio_sample_t* GetBuffer() | ||||
{ | { | ||||
return (jack_default_audio_sample_t*)((uintptr_t)fBuffer & ~15L) + 4; | |||||
return (jack_default_audio_sample_t*)((uintptr_t)fBuffer & ~31L) + 8; | |||||
} | } | ||||
int GetRefNum() const; | int GetRefNum() const; | ||||
@@ -0,0 +1,351 @@ | |||||
/* | |||||
Copyright (C) 2012 Grame | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#include "JackRequestDecoder.h" | |||||
#include "JackServer.h" | |||||
#include "JackLockedEngine.h" | |||||
#include "JackChannel.h" | |||||
#include <assert.h> | |||||
#include <signal.h> | |||||
using namespace std; | |||||
namespace Jack | |||||
{ | |||||
#define CheckRead(req, socket) { if (req.Read(socket) < 0) { jack_error("CheckRead error"); return -1; } } | |||||
#define CheckWriteName(error, socket) { if (res.Write(socket) < 0) { jack_error("%s write error name = %s", error, req.fName); } } | |||||
#define CheckWriteRefNum(error, socket) { if (res.Write(socket) < 0) { jack_error("%s write error ref = %d", error, req.fRefNum); } } | |||||
#define CheckWrite(error, socket) { if (res.Write(socket) < 0) { jack_error("%s write error", error); } } | |||||
JackRequestDecoder::JackRequestDecoder(JackServer* server, JackClientHandlerInterface* handler) | |||||
:fServer(server), fHandler(handler) | |||||
{} | |||||
JackRequestDecoder::~JackRequestDecoder() | |||||
{} | |||||
int JackRequestDecoder::HandleRequest(detail::JackChannelTransactionInterface* socket, int type_aux) | |||||
{ | |||||
JackRequest::RequestType type = (JackRequest::RequestType)type_aux; | |||||
// Read data | |||||
switch (type) { | |||||
case JackRequest::kClientCheck: { | |||||
jack_log("JackRequest::ClientCheck"); | |||||
JackClientCheckRequest req; | |||||
JackClientCheckResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus); | |||||
CheckWriteName("JackRequest::ClientCheck", socket); | |||||
// Atomic ClientCheck followed by ClientOpen on same socket | |||||
if (req.fOpen) { | |||||
JackRequest header; | |||||
header.Read(socket); | |||||
return HandleRequest(socket, header.fType); | |||||
} | |||||
break; | |||||
} | |||||
case JackRequest::kClientOpen: { | |||||
jack_log("JackRequest::ClientOpen"); | |||||
JackClientOpenRequest req; | |||||
JackClientOpenResult res; | |||||
CheckRead(req, socket); | |||||
fHandler->ClientAdd(socket, &req, &res); | |||||
CheckWriteName("JackRequest::ClientOpen", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kClientClose: { | |||||
jack_log("JackRequest::ClientClose"); | |||||
JackClientCloseRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum); | |||||
CheckWriteRefNum("JackRequest::ClientClose", socket); | |||||
fHandler->ClientRemove(socket, req.fRefNum); | |||||
// Will cause the wrapping thread to stop | |||||
return -1; | |||||
} | |||||
case JackRequest::kActivateClient: { | |||||
JackActivateRequest req; | |||||
JackResult res; | |||||
jack_log("JackRequest::ActivateClient"); | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum, req.fIsRealTime); | |||||
CheckWriteRefNum("JackRequest::ActivateClient", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kDeactivateClient: { | |||||
jack_log("JackRequest::DeactivateClient"); | |||||
JackDeactivateRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum); | |||||
CheckWriteRefNum("JackRequest::DeactivateClient", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kRegisterPort: { | |||||
jack_log("JackRequest::RegisterPort"); | |||||
JackPortRegisterRequest req; | |||||
JackPortRegisterResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fPortType, req.fFlags, req.fBufferSize, &res.fPortIndex); | |||||
CheckWriteRefNum("JackRequest::RegisterPort", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kUnRegisterPort: { | |||||
jack_log("JackRequest::UnRegisterPort"); | |||||
JackPortUnRegisterRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex); | |||||
CheckWriteRefNum("JackRequest::UnRegisterPort", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kConnectNamePorts: { | |||||
jack_log("JackRequest::ConnectNamePorts"); | |||||
JackPortConnectNameRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); | |||||
CheckWriteRefNum("JackRequest::ConnectNamePorts", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kDisconnectNamePorts: { | |||||
jack_log("JackRequest::DisconnectNamePorts"); | |||||
JackPortDisconnectNameRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); | |||||
CheckWriteRefNum("JackRequest::DisconnectNamePorts", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kConnectPorts: { | |||||
jack_log("JackRequest::ConnectPorts"); | |||||
JackPortConnectRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); | |||||
CheckWriteRefNum("JackRequest::ConnectPorts", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kDisconnectPorts: { | |||||
jack_log("JackRequest::DisconnectPorts"); | |||||
JackPortDisconnectRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); | |||||
CheckWriteRefNum("JackRequest::DisconnectPorts", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kPortRename: { | |||||
jack_log("JackRequest::PortRename"); | |||||
JackPortRenameRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->PortRename(req.fRefNum, req.fPort, req.fName); | |||||
CheckWriteRefNum("JackRequest::PortRename", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kSetBufferSize: { | |||||
jack_log("JackRequest::SetBufferSize"); | |||||
JackSetBufferSizeRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->SetBufferSize(req.fBufferSize); | |||||
CheckWrite("JackRequest::SetBufferSize", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kSetFreeWheel: { | |||||
jack_log("JackRequest::SetFreeWheel"); | |||||
JackSetFreeWheelRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->SetFreewheel(req.fOnOff); | |||||
CheckWrite("JackRequest::SetFreeWheel", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kComputeTotalLatencies: { | |||||
jack_log("JackRequest::ComputeTotalLatencies"); | |||||
JackComputeTotalLatenciesRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->ComputeTotalLatencies(); | |||||
CheckWrite("JackRequest::ComputeTotalLatencies", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kReleaseTimebase: { | |||||
jack_log("JackRequest::ReleaseTimebase"); | |||||
JackReleaseTimebaseRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->ReleaseTimebase(req.fRefNum); | |||||
CheckWriteRefNum("JackRequest::ReleaseTimebase", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kSetTimebaseCallback: { | |||||
jack_log("JackRequest::SetTimebaseCallback"); | |||||
JackSetTimebaseCallbackRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal); | |||||
CheckWriteRefNum("JackRequest::SetTimebaseCallback", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kGetInternalClientName: { | |||||
jack_log("JackRequest::GetInternalClientName"); | |||||
JackGetInternalClientNameRequest req; | |||||
JackGetInternalClientNameResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName); | |||||
CheckWriteRefNum("JackRequest::GetInternalClientName", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kInternalClientHandle: { | |||||
jack_log("JackRequest::InternalClientHandle"); | |||||
JackInternalClientHandleRequest req; | |||||
JackInternalClientHandleResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum); | |||||
CheckWriteRefNum("JackRequest::InternalClientHandle", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kInternalClientLoad: { | |||||
jack_log("JackRequest::InternalClientLoad"); | |||||
JackInternalClientLoadRequest req; | |||||
JackInternalClientLoadResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus); | |||||
CheckWriteName("JackRequest::InternalClientLoad", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kInternalClientUnload: { | |||||
jack_log("JackRequest::InternalClientUnload"); | |||||
JackInternalClientUnloadRequest req; | |||||
JackInternalClientUnloadResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus); | |||||
CheckWriteRefNum("JackRequest::InternalClientUnload", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kNotification: { | |||||
jack_log("JackRequest::Notification"); | |||||
JackClientNotificationRequest req; | |||||
CheckRead(req, socket); | |||||
if (req.fNotify == kQUIT) { | |||||
jack_log("JackRequest::Notification kQUIT"); | |||||
throw JackQuitException(); | |||||
} else { | |||||
fServer->Notify(req.fRefNum, req.fNotify, req.fValue); | |||||
} | |||||
break; | |||||
} | |||||
case JackRequest::kSessionNotify: { | |||||
jack_log("JackRequest::SessionNotify"); | |||||
JackSessionNotifyRequest req; | |||||
CheckRead(req, socket); | |||||
fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, socket, NULL); | |||||
break; | |||||
} | |||||
case JackRequest::kSessionReply: { | |||||
jack_log("JackRequest::SessionReply"); | |||||
JackSessionReplyRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->SessionReply(req.fRefNum); | |||||
CheckWrite("JackRequest::SessionReply", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kGetClientByUUID: { | |||||
jack_log("JackRequest::GetClientByUUID"); | |||||
JackGetClientNameRequest req; | |||||
JackClientNameResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->GetClientNameForUUID(req.fUUID, res.fName); | |||||
CheckWrite("JackRequest::GetClientByUUID", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kGetUUIDByClient: { | |||||
jack_log("JackRequest::GetUUIDByClient"); | |||||
JackGetUUIDRequest req; | |||||
JackUUIDResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->GetUUIDForClientName(req.fName, res.fUUID); | |||||
CheckWrite("JackRequest::GetUUIDByClient", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kReserveClientName: { | |||||
jack_log("JackRequest::ReserveClientName"); | |||||
JackReserveNameRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->ReserveClientName(req.fName, req.fUUID); | |||||
CheckWrite("JackRequest::ReserveClientName", socket); | |||||
break; | |||||
} | |||||
case JackRequest::kClientHasSessionCallback: { | |||||
jack_log("JackRequest::ClientHasSessionCallback"); | |||||
JackClientHasSessionCallbackRequest req; | |||||
JackResult res; | |||||
CheckRead(req, socket); | |||||
res.fResult = fServer->GetEngine()->ClientHasSessionCallback(req.fName); | |||||
CheckWrite("JackRequest::ClientHasSessionCallback", socket); | |||||
break; | |||||
} | |||||
default: | |||||
jack_error("Unknown request %ld", type); | |||||
return -1; | |||||
} | |||||
return 0; | |||||
} | |||||
} // end of namespace | |||||
@@ -0,0 +1,63 @@ | |||||
/* | |||||
Copyright (C) 2012 Grame | |||||
This program is free software; you can redistribute it and/or modify | |||||
it under the terms of the GNU Lesser General Public License as published by | |||||
the Free Software Foundation; either version 2.1 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | |||||
You should have received a copy of the GNU Lesser General Public License | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
*/ | |||||
#ifndef __JackRequestDecoder__ | |||||
#define __JackRequestDecoder__ | |||||
#include "JackChannel.h" | |||||
namespace Jack | |||||
{ | |||||
class JackServer; | |||||
struct JackClientOpenRequest; | |||||
struct JackClientOpenResult; | |||||
struct JackClientHandlerInterface { | |||||
virtual void ClientAdd(detail::JackChannelTransactionInterface* socket, JackClientOpenRequest* req, JackClientOpenResult* res) = 0; | |||||
virtual void ClientRemove(detail::JackChannelTransactionInterface* socket, int refnum) = 0; | |||||
virtual ~JackClientHandlerInterface() | |||||
{} | |||||
}; | |||||
/*! | |||||
\brief Request decoder | |||||
*/ | |||||
class JackRequestDecoder | |||||
{ | |||||
private: | |||||
JackServer* fServer; | |||||
JackClientHandlerInterface* fHandler; | |||||
public: | |||||
JackRequestDecoder(JackServer* server, JackClientHandlerInterface* handler); | |||||
virtual ~JackRequestDecoder(); | |||||
int HandleRequest(detail::JackChannelTransactionInterface* socket, int type); | |||||
}; | |||||
} // end of namespace | |||||
#endif |
@@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | */ | ||||
#include "JackResampler.h" | #include "JackResampler.h" | ||||
#include "JackError.h" | |||||
#include <stdio.h> | #include <stdio.h> | ||||
namespace Jack | namespace Jack | ||||
@@ -22,7 +22,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "ringbuffer.h" | #include "ringbuffer.h" | ||||
#include "types.h" | #include "types.h" | ||||
#include "JackError.h" | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -78,7 +78,9 @@ JackServer::~JackServer() | |||||
int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) | int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) | ||||
{ | { | ||||
// TODO: move that in reworked JackServerGlobals::Init() | // TODO: move that in reworked JackServerGlobals::Init() | ||||
JackMessageBuffer::Create(); | |||||
if (!JackMessageBuffer::Create()) { | |||||
jack_error("Cannot create message buffer"); | |||||
} | |||||
if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) { | if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) { | ||||
jack_error("Cannot initialize driver"); | jack_error("Cannot initialize driver"); | ||||
@@ -140,6 +142,7 @@ int JackServer::Close() | |||||
fEngine->Close(); | fEngine->Close(); | ||||
// TODO: move that in reworked JackServerGlobals::Destroy() | // TODO: move that in reworked JackServerGlobals::Destroy() | ||||
JackMessageBuffer::Destroy(); | JackMessageBuffer::Destroy(); | ||||
EndTime(); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -188,6 +191,8 @@ int JackServer::Stop() | |||||
{ | { | ||||
jack_log("JackServer::Stop"); | jack_log("JackServer::Stop"); | ||||
fChannel.Stop(); | fChannel.Stop(); | ||||
fEngine->ShutDown(); | |||||
if (fFreewheel) { | if (fFreewheel) { | ||||
return fThreadedFreewheelDriver->Stop(); | return fThreadedFreewheelDriver->Stop(); | ||||
@@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
#include "driver_interface.h" | #include "driver_interface.h" | ||||
#include "JackDriverLoader.h" | #include "JackDriverLoader.h" | ||||
#include "JackDriverInfo.h" | |||||
#include "JackConnectionManager.h" | #include "JackConnectionManager.h" | ||||
#include "JackGlobals.h" | #include "JackGlobals.h" | ||||
#include "JackPlatformPlug.h" | #include "JackPlatformPlug.h" | ||||
@@ -47,10 +47,6 @@ extern "C" | |||||
using namespace Jack; | using namespace Jack; | ||||
static jack_client_t * jack_client_open_aux (const char *client_name, | |||||
jack_options_t options, | |||||
jack_status_t *status, va_list ap); | |||||
jack_client_t* jack_client_new_aux(const char* client_name, jack_options_t options, jack_status_t* status) | jack_client_t* jack_client_new_aux(const char* client_name, jack_options_t options, jack_status_t* status) | ||||
{ | { | ||||
jack_varargs_t va; /* variable arguments */ | jack_varargs_t va; /* variable arguments */ | ||||
@@ -155,9 +151,8 @@ jack_client_t* jack_client_open_aux(const char* client_name, jack_options_t opti | |||||
SERVER_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | SERVER_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...) | ||||
{ | { | ||||
#ifdef __CLIENTDEBUG__ | |||||
JackGlobals::CheckContext("jack_client_open"); | JackGlobals::CheckContext("jack_client_open"); | ||||
#endif | |||||
try { | try { | ||||
assert(JackGlobals::fOpenMutex); | assert(JackGlobals::fOpenMutex); | ||||
JackGlobals::fOpenMutex->Lock(); | JackGlobals::fOpenMutex->Lock(); | ||||
@@ -178,9 +173,8 @@ SERVER_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_ | |||||
SERVER_EXPORT int jack_client_close(jack_client_t* ext_client) | SERVER_EXPORT int jack_client_close(jack_client_t* ext_client) | ||||
{ | { | ||||
#ifdef __CLIENTDEBUG__ | |||||
JackGlobals::CheckContext("jack_client_close"); | JackGlobals::CheckContext("jack_client_close"); | ||||
#endif | |||||
assert(JackGlobals::fOpenMutex); | assert(JackGlobals::fOpenMutex); | ||||
JackGlobals::fOpenMutex->Lock(); | JackGlobals::fOpenMutex->Lock(); | ||||
int res = -1; | int res = -1; | ||||
@@ -33,11 +33,11 @@ | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
SERVER_EXPORT void LockMemoryImp(void* ptr, size_t size); | |||||
SERVER_EXPORT void InitLockMemoryImp(void* ptr, size_t size); | |||||
SERVER_EXPORT void UnlockMemoryImp(void* ptr, size_t size); | |||||
SERVER_EXPORT void LockAllMemory(); | |||||
SERVER_EXPORT void UnlockAllMemory(); | |||||
void LockMemoryImp(void* ptr, size_t size); | |||||
void InitLockMemoryImp(void* ptr, size_t size); | |||||
void UnlockMemoryImp(void* ptr, size_t size); | |||||
void LockAllMemory(); | |||||
void UnlockAllMemory(); | |||||
class JackMem | class JackMem | ||||
{ | { | ||||
@@ -30,10 +30,12 @@ extern "C" | |||||
#endif | #endif | ||||
SERVER_EXPORT void InitTime(); | SERVER_EXPORT void InitTime(); | ||||
SERVER_EXPORT void EndTime(); | |||||
SERVER_EXPORT jack_time_t GetMicroSeconds(void); | SERVER_EXPORT jack_time_t GetMicroSeconds(void); | ||||
SERVER_EXPORT void JackSleep(long usec); | SERVER_EXPORT void JackSleep(long usec); | ||||
SERVER_EXPORT void SetClockSource(jack_timer_type_t source); | |||||
SERVER_EXPORT const char* ClockSourceName(jack_timer_type_t source); | |||||
void SetClockSource(jack_timer_type_t source); | |||||
const char* ClockSourceName(jack_timer_type_t source); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
@@ -24,6 +24,7 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <signal.h> | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
#include <process.h> | #include <process.h> | ||||
@@ -36,11 +37,7 @@ namespace Jack { | |||||
void JackTools::KillServer() | void JackTools::KillServer() | ||||
{ | { | ||||
#ifdef WIN32 | |||||
exit(1); | |||||
#else | |||||
kill(GetPID(), SIGINT); | |||||
#endif | |||||
raise(SIGINT); | |||||
} | } | ||||
void JackTools::ThrowJackNetException() | void JackTools::ThrowJackNetException() | ||||
@@ -294,5 +291,6 @@ void BuildClientPath(char* path_to_so, int path_len, const char* so_name) | |||||
#endif | #endif | ||||
} // end of namespace | } // end of namespace | ||||
@@ -36,10 +36,8 @@ | |||||
#endif | #endif | ||||
#include "jslist.h" | #include "jslist.h" | ||||
#include "driver_interface.h" | |||||
#include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
#include "JackError.h" | #include "JackError.h" | ||||
#include "JackException.h" | |||||
#include <string> | #include <string> | ||||
#include <algorithm> | #include <algorithm> | ||||
@@ -112,114 +110,115 @@ namespace Jack | |||||
std::string fName; | std::string fName; | ||||
public: | public: | ||||
JackGnuPlotMonitor ( uint32_t measure_cnt = 512, uint32_t measure_points = 5, std::string name = std::string ( "default" ) ) | |||||
{ | |||||
jack_log ( "JackGnuPlotMonitor::JackGnuPlotMonitor %u measure points - %u measures", measure_points, measure_cnt ); | |||||
fMeasureCnt = measure_cnt; | |||||
fMeasurePoints = measure_points; | |||||
fTablePos = 0; | |||||
fName = name; | |||||
fCurrentMeasure = new T[fMeasurePoints]; | |||||
fMeasureTable = new T*[fMeasureCnt]; | |||||
for ( uint32_t cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||||
{ | |||||
fMeasureTable[cnt] = new T[fMeasurePoints]; | |||||
fill_n ( fMeasureTable[cnt], fMeasurePoints, 0 ); | |||||
} | |||||
} | |||||
~JackGnuPlotMonitor() | |||||
{ | |||||
jack_log ( "JackGnuPlotMonitor::~JackGnuPlotMonitor" ); | |||||
for ( uint32_t cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||||
delete[] fMeasureTable[cnt]; | |||||
delete[] fMeasureTable; | |||||
delete[] fCurrentMeasure; | |||||
} | |||||
T AddNew ( T measure_point ) | |||||
{ | |||||
fMeasureId = 0; | |||||
return fCurrentMeasure[fMeasureId++] = measure_point; | |||||
} | |||||
uint32_t New() | |||||
{ | |||||
return fMeasureId = 0; | |||||
} | |||||
T Add ( T measure_point ) | |||||
{ | |||||
return fCurrentMeasure[fMeasureId++] = measure_point; | |||||
} | |||||
uint32_t AddLast ( T measure_point ) | |||||
{ | |||||
fCurrentMeasure[fMeasureId] = measure_point; | |||||
fMeasureId = 0; | |||||
return Write(); | |||||
} | |||||
uint32_t Write() | |||||
{ | |||||
for ( uint32_t point = 0; point < fMeasurePoints; point++ ) | |||||
fMeasureTable[fTablePos][point] = fCurrentMeasure[point]; | |||||
if ( ++fTablePos == fMeasureCnt ) | |||||
fTablePos = 0; | |||||
return fTablePos; | |||||
} | |||||
JackGnuPlotMonitor(uint32_t measure_cnt, uint32_t measure_points, std::string name) | |||||
{ | |||||
jack_log ( "JackGnuPlotMonitor::JackGnuPlotMonitor %u measure points - %u measures", measure_points, measure_cnt ); | |||||
fMeasureCnt = measure_cnt; | |||||
fMeasurePoints = measure_points; | |||||
fTablePos = 0; | |||||
fName = name; | |||||
fCurrentMeasure = new T[fMeasurePoints]; | |||||
fMeasureTable = new T*[fMeasureCnt]; | |||||
for ( uint32_t cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||||
{ | |||||
fMeasureTable[cnt] = new T[fMeasurePoints]; | |||||
std::fill_n ( fMeasureTable[cnt], fMeasurePoints, 0 ); | |||||
} | |||||
} | |||||
~JackGnuPlotMonitor() | |||||
{ | |||||
jack_log ( "JackGnuPlotMonitor::~JackGnuPlotMonitor" ); | |||||
for ( uint32_t cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||||
delete[] fMeasureTable[cnt]; | |||||
delete[] fMeasureTable; | |||||
delete[] fCurrentMeasure; | |||||
} | |||||
T AddNew(T measure_point) | |||||
{ | |||||
fMeasureId = 0; | |||||
return fCurrentMeasure[fMeasureId++] = measure_point; | |||||
} | |||||
uint32_t New() | |||||
{ | |||||
return fMeasureId = 0; | |||||
} | |||||
T Add(T measure_point) | |||||
{ | |||||
return fCurrentMeasure[fMeasureId++] = measure_point; | |||||
} | |||||
uint32_t AddLast(T measure_point) | |||||
{ | |||||
fCurrentMeasure[fMeasureId] = measure_point; | |||||
fMeasureId = 0; | |||||
return Write(); | |||||
} | |||||
uint32_t Write() | |||||
{ | |||||
for ( uint32_t point = 0; point < fMeasurePoints; point++ ) | |||||
fMeasureTable[fTablePos][point] = fCurrentMeasure[point]; | |||||
if ( ++fTablePos == fMeasureCnt ) | |||||
fTablePos = 0; | |||||
return fTablePos; | |||||
} | |||||
int Save(std::string name = std::string ( "" )) | |||||
{ | |||||
std::string filename = ( name.empty() ) ? fName : name; | |||||
filename += ".log"; | |||||
jack_log ( "JackGnuPlotMonitor::Save filename %s", filename.c_str() ); | |||||
std::ofstream file ( filename.c_str() ); | |||||
for ( uint32_t cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||||
{ | |||||
for ( uint32_t point = 0; point < fMeasurePoints; point++ ) | |||||
file << fMeasureTable[cnt][point] << " \t"; | |||||
file << std::endl; | |||||
} | |||||
file.close(); | |||||
return 0; | |||||
} | |||||
int SetPlotFile(std::string* options_list, uint32_t options_number, | |||||
std::string* field_names, uint32_t field_number, | |||||
std::string name = std::string ( "" )) | |||||
{ | |||||
std::string title = ( name.empty() ) ? fName : name; | |||||
std::string plot_filename = title + ".plt"; | |||||
std::string data_filename = title + ".log"; | |||||
std::ofstream file ( plot_filename.c_str() ); | |||||
file << "set multiplot" << std::endl; | |||||
file << "set grid" << std::endl; | |||||
file << "set title \"" << title << "\"" << std::endl; | |||||
for ( uint32_t i = 0; i < options_number; i++ ) | |||||
file << options_list[i] << std::endl; | |||||
file << "plot "; | |||||
for ( uint32_t row = 1; row <= field_number; row++ ) | |||||
{ | |||||
file << "\"" << data_filename << "\" using " << row << " title \"" << field_names[row-1] << "\" with lines"; | |||||
file << ( ( row < field_number ) ? ", " : "\n" ); | |||||
} | |||||
jack_log ( "JackGnuPlotMonitor::SetPlotFile - Save GnuPlot file to '%s'", plot_filename.c_str() ); | |||||
file.close(); | |||||
return 0; | |||||
} | |||||
int Save ( std::string name = std::string ( "" ) ) | |||||
{ | |||||
std::string filename = ( name.empty() ) ? fName : name; | |||||
filename += ".log"; | |||||
jack_log ( "JackGnuPlotMonitor::Save filename %s", filename.c_str() ); | |||||
std::ofstream file ( filename.c_str() ); | |||||
for ( uint32_t cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||||
{ | |||||
for ( uint32_t point = 0; point < fMeasurePoints; point++ ) | |||||
file << fMeasureTable[cnt][point] << " \t"; | |||||
file << std::endl; | |||||
} | |||||
file.close(); | |||||
return 0; | |||||
} | |||||
int SetPlotFile ( std::string* options_list = NULL, uint32_t options_number = 0, | |||||
std::string* field_names = NULL, uint32_t field_number = 0, | |||||
std::string name = std::string ( "" ) ) | |||||
{ | |||||
std::string title = ( name.empty() ) ? fName : name; | |||||
std::string plot_filename = title + ".plt"; | |||||
std::string data_filename = title + ".log"; | |||||
std::ofstream file ( plot_filename.c_str() ); | |||||
file << "set multiplot" << std::endl; | |||||
file << "set grid" << std::endl; | |||||
file << "set title \"" << title << "\"" << std::endl; | |||||
for ( uint32_t i = 0; i < options_number; i++ ) | |||||
file << options_list[i] << std::endl; | |||||
file << "plot "; | |||||
for ( uint32_t row = 1; row <= field_number; row++ ) | |||||
{ | |||||
file << "\"" << data_filename << "\" using " << row << " title \"" << field_names[row-1] << "\" with lines"; | |||||
file << ( ( row < field_number ) ? ", " : "\n" ); | |||||
} | |||||
jack_log ( "JackGnuPlotMonitor::SetPlotFile - Save GnuPlot file to '%s'", plot_filename.c_str() ); | |||||
file.close(); | |||||
return 0; | |||||
} | |||||
}; | }; | ||||
void BuildClientPath(char* path_to_so, int path_len, const char* so_name); | void BuildClientPath(char* path_to_so, int path_len, const char* so_name); | ||||
@@ -44,8 +44,11 @@ static HMODULE libjack_handle = 0; | |||||
#else | #else | ||||
static void *libjack_handle = 0; | static void *libjack_handle = 0; | ||||
#endif | #endif | ||||
#ifndef WIN32 | |||||
static void __attribute__((constructor)) tryload_libjack() | static void __attribute__((constructor)) tryload_libjack() | ||||
#else | |||||
void tryload_libjack() | |||||
#endif | |||||
{ | { | ||||
if (getenv("SKIP_LIBJACK") == 0) { // just in case libjack is causing troubles.. | if (getenv("SKIP_LIBJACK") == 0) { // just in case libjack is causing troubles.. | ||||
#ifdef __APPLE__ | #ifdef __APPLE__ | ||||
@@ -30,8 +30,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "types.h" | #include "types.h" | ||||
#include "jack.h" | #include "jack.h" | ||||
#include "control.h" | |||||
#include "JackConstants.h" | #include "JackConstants.h" | ||||
#include "JackDriverLoader.h" | |||||
#include "JackPlatformPlug.h" | |||||
#if defined(JACK_DBUS) && defined(__linux__) | #if defined(JACK_DBUS) && defined(__linux__) | ||||
#include <dbus/dbus.h> | #include <dbus/dbus.h> | ||||
@@ -86,7 +88,7 @@ static void copyright(FILE* file) | |||||
{ | { | ||||
fprintf(file, "jackdmp " VERSION "\n" | fprintf(file, "jackdmp " VERSION "\n" | ||||
"Copyright 2001-2005 Paul Davis and others.\n" | "Copyright 2001-2005 Paul Davis and others.\n" | ||||
"Copyright 2004-2011 Grame.\n" | |||||
"Copyright 2004-2012 Grame.\n" | |||||
"jackdmp comes with ABSOLUTELY NO WARRANTY\n" | "jackdmp comes with ABSOLUTELY NO WARRANTY\n" | ||||
"This is free software, and you are welcome to redistribute it\n" | "This is free software, and you are welcome to redistribute it\n" | ||||
"under certain conditions; see the file COPYING for details\n"); | "under certain conditions; see the file COPYING for details\n"); | ||||
@@ -130,23 +132,15 @@ static void usage(FILE* file) | |||||
" to display options for each master backend\n\n"); | " to display options for each master backend\n\n"); | ||||
} | } | ||||
// To put in the control.h interface?? | |||||
static jackctl_driver_t * | |||||
jackctl_server_get_driver( | |||||
jackctl_server_t *server, | |||||
const char *driver_name) | |||||
// To put in the control.h interface ?? | |||||
static jackctl_driver_t * jackctl_server_get_driver(jackctl_server_t *server, const char *driver_name) | |||||
{ | { | ||||
const JSList * node_ptr; | |||||
node_ptr = jackctl_server_get_drivers_list(server); | |||||
const JSList * node_ptr = jackctl_server_get_drivers_list(server); | |||||
while (node_ptr) | |||||
{ | |||||
if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0) | |||||
{ | |||||
while (node_ptr) { | |||||
if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0) { | |||||
return (jackctl_driver_t *)node_ptr->data; | return (jackctl_driver_t *)node_ptr->data; | ||||
} | } | ||||
node_ptr = jack_slist_next(node_ptr); | node_ptr = jack_slist_next(node_ptr); | ||||
} | } | ||||
@@ -167,24 +161,21 @@ static jackctl_internal_t * jackctl_server_get_internal(jackctl_server_t *server | |||||
return NULL; | return NULL; | ||||
} | } | ||||
static jackctl_parameter_t * | |||||
jackctl_get_parameter( | |||||
const JSList * parameters_list, | |||||
const char * parameter_name) | |||||
static jackctl_parameter_t * jackctl_get_parameter(const JSList * parameters_list, const char * parameter_name) | |||||
{ | { | ||||
while (parameters_list) | |||||
{ | |||||
if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0) | |||||
{ | |||||
while (parameters_list) { | |||||
if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0) { | |||||
return (jackctl_parameter_t *)parameters_list->data; | return (jackctl_parameter_t *)parameters_list->data; | ||||
} | } | ||||
parameters_list = jack_slist_next(parameters_list); | parameters_list = jack_slist_next(parameters_list); | ||||
} | } | ||||
return NULL; | return NULL; | ||||
} | } | ||||
// Prototype to be found in libjackserver | |||||
extern "C" void silent_jack_error_callback(const char *desc); | |||||
int main(int argc, char** argv) | int main(int argc, char** argv) | ||||
{ | { | ||||
jackctl_server_t * server_ctl; | jackctl_server_t * server_ctl; | ||||
@@ -236,7 +227,7 @@ int main(int argc, char** argv) | |||||
int do_unlock = 0; | int do_unlock = 0; | ||||
int loopback = 0; | int loopback = 0; | ||||
bool show_version = false; | bool show_version = false; | ||||
sigset_t signals; | |||||
jackctl_sigmask_t * sigmask; | |||||
jackctl_parameter_t* param; | jackctl_parameter_t* param; | ||||
union jackctl_parameter_value value; | union jackctl_parameter_value value; | ||||
@@ -454,12 +445,12 @@ int main(int argc, char** argv) | |||||
master_driver_args[i] = argv[optind++]; | master_driver_args[i] = argv[optind++]; | ||||
} | } | ||||
if (jackctl_parse_driver_params(master_driver_ctl, master_driver_nargs, master_driver_args)) { | |||||
if (jackctl_driver_params_parse(master_driver_ctl, master_driver_nargs, master_driver_args)) { | |||||
goto destroy_server; | goto destroy_server; | ||||
} | } | ||||
// Setup signals | // Setup signals | ||||
signals = jackctl_setup_signals(0); | |||||
sigmask = jackctl_setup_signals(0); | |||||
// Open server | // Open server | ||||
if (! jackctl_server_open(server_ctl, master_driver_ctl)) { | if (! jackctl_server_open(server_ctl, master_driver_ctl)) { | ||||
@@ -529,7 +520,7 @@ int main(int argc, char** argv) | |||||
return_value = 0; | return_value = 0; | ||||
// Waits for signal | // Waits for signal | ||||
jackctl_wait_signals(signals); | |||||
jackctl_wait_signals(sigmask); | |||||
stop_server: | stop_server: | ||||
if (!jackctl_server_stop(server_ctl)) { | if (!jackctl_server_stop(server_ctl)) { | ||||
@@ -28,6 +28,7 @@ extern "C" | |||||
#include <limits.h> | #include <limits.h> | ||||
#include "jslist.h" | #include "jslist.h" | ||||
#include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
#include "JackSystemDeps.h" | #include "JackSystemDeps.h" | ||||
@@ -75,7 +76,6 @@ typedef struct { | |||||
typedef struct { | typedef struct { | ||||
uint32_t flags; /**< JACK_CONSTRAINT_FLAG_XXX */ | uint32_t flags; /**< JACK_CONSTRAINT_FLAG_XXX */ | ||||
union { | union { | ||||
struct { | struct { | ||||
jack_driver_param_value_t min; | jack_driver_param_value_t min; | ||||
@@ -124,28 +124,32 @@ typedef struct { | |||||
} | } | ||||
jack_driver_desc_filler_t; | jack_driver_desc_filler_t; | ||||
SERVER_EXPORT int jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr); | |||||
int jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr); | |||||
SERVER_EXPORT jack_driver_desc_t * /* newlly allocated driver descriptor, NULL on failure */ | |||||
// To be used by drivers | |||||
SERVER_EXPORT jack_driver_desc_t * /* Newly allocated driver descriptor, NULL on failure */ | |||||
jack_driver_descriptor_construct( | jack_driver_descriptor_construct( | ||||
const char * name, /* driver name */ | |||||
jack_driver_type_t type, /* driver type */ | |||||
const char * description, /* driver description */ | |||||
const char * name, /* Driver name */ | |||||
jack_driver_type_t type, /* Driver type */ | |||||
const char * description, /* Driver description */ | |||||
jack_driver_desc_filler_t * filler); /* Pointer to stack var to be supplied to jack_driver_descriptor_add_parameter() as well. | jack_driver_desc_filler_t * filler); /* Pointer to stack var to be supplied to jack_driver_descriptor_add_parameter() as well. | ||||
Can be NULL for drivers that have no parameters. */ | Can be NULL for drivers that have no parameters. */ | ||||
SERVER_EXPORT int /* 0 on failure */ | SERVER_EXPORT int /* 0 on failure */ | ||||
jack_driver_descriptor_add_parameter( | jack_driver_descriptor_add_parameter( | ||||
jack_driver_desc_t * driver_descr, /* pointer to driver descriptor as returned by jack_driver_descriptor_construct() */ | |||||
jack_driver_desc_t * driver_descr, /* Pointer to driver descriptor as returned by jack_driver_descriptor_construct() */ | |||||
jack_driver_desc_filler_t * filler, /* Pointer to the stack var that was supplied to jack_driver_descriptor_add_parameter(). */ | jack_driver_desc_filler_t * filler, /* Pointer to the stack var that was supplied to jack_driver_descriptor_add_parameter(). */ | ||||
const char * name, /* parameter's name */ | |||||
char character, /* parameter's character (for getopt, etc) */ | |||||
const char * name, /* Parameter's name */ | |||||
char character, /* Parameter's character (for getopt, etc) */ | |||||
jack_driver_param_type_t type, /* The parameter's type */ | jack_driver_param_type_t type, /* The parameter's type */ | ||||
const jack_driver_param_value_t * value_ptr, /* Pointer to parameter's (default) value */ | const jack_driver_param_value_t * value_ptr, /* Pointer to parameter's (default) value */ | ||||
jack_driver_param_constraint_desc_t * constraint, /* Pointer to parameter constraint descriptor. NULL if there is no constraint */ | jack_driver_param_constraint_desc_t * constraint, /* Pointer to parameter constraint descriptor. NULL if there is no constraint */ | ||||
const char * short_desc, /* A short (~30 chars) description for the user */ | const char * short_desc, /* A short (~30 chars) description for the user */ | ||||
const char * long_desc); /* A longer description for the user, if NULL short_desc will be used */ | const char * long_desc); /* A longer description for the user, if NULL short_desc will be used */ | ||||
typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif | ||||
@@ -29,9 +29,10 @@ | |||||
#ifndef JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED | #ifndef JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED | ||||
#define JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED | #define JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED | ||||
#include <jack/types.h> | |||||
#include <jack/jslist.h> | #include <jack/jslist.h> | ||||
#include <jack/systemdeps.h> | #include <jack/systemdeps.h> | ||||
#if !defined (__sun__) | |||||
#if !defined(sun) && !defined(__sun__) | |||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#endif | #endif | ||||
@@ -81,6 +82,9 @@ typedef struct jackctl_internal jackctl_internal_t; | |||||
/** opaque type for parameter object */ | /** opaque type for parameter object */ | ||||
typedef struct jackctl_parameter jackctl_parameter_t; | typedef struct jackctl_parameter jackctl_parameter_t; | ||||
/** opaque type for sigmask object */ | |||||
typedef struct jackctl_sigmask jackctl_sigmask_t; | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
@@ -102,7 +106,7 @@ extern "C" { | |||||
* | * | ||||
* @return the configurated signal set. | * @return the configurated signal set. | ||||
*/ | */ | ||||
sigset_t | |||||
jackctl_sigmask_t * | |||||
jackctl_setup_signals( | jackctl_setup_signals( | ||||
unsigned int flags); | unsigned int flags); | ||||
@@ -113,7 +117,7 @@ jackctl_setup_signals( | |||||
*/ | */ | ||||
void | void | ||||
jackctl_wait_signals( | jackctl_wait_signals( | ||||
sigset_t signals); | |||||
jackctl_sigmask_t * signals); | |||||
/** | /** | ||||
* Call this function to create server object. | * Call this function to create server object. | ||||
@@ -330,6 +334,21 @@ const JSList * | |||||
jackctl_driver_get_parameters( | jackctl_driver_get_parameters( | ||||
jackctl_driver_t * driver); | jackctl_driver_t * driver); | ||||
/** | |||||
* Call this function to parse parameters for a driver. | |||||
* | |||||
* @param driver driver object handle | |||||
* @param argc parameter list len | |||||
* @param argv parameter list, as an array of char* | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
int | |||||
jackctl_driver_params_parse( | |||||
jackctl_driver_t * driver, | |||||
int argc, | |||||
char* argv[]); | |||||
/** | /** | ||||
* Call this function to get name of internal client. | * Call this function to get name of internal client. | ||||
* | * | ||||
@@ -76,6 +76,11 @@ jack_get_version( | |||||
const char * | const char * | ||||
jack_get_version_string() JACK_OPTIONAL_WEAK_EXPORT; | jack_get_version_string() JACK_OPTIONAL_WEAK_EXPORT; | ||||
/** | |||||
* @defgroup ClientFunctions Creating & manipulating clients | |||||
* @{ | |||||
*/ | |||||
/** | /** | ||||
* Open an external client session with a JACK server. This interface | * Open an external client session with a JACK server. This interface | ||||
* is more complex but more powerful than jack_client_new(). With it, | * is more complex but more powerful than jack_client_new(). With it, | ||||
@@ -170,7 +175,7 @@ int jack_internal_client_new (const char *client_name, | |||||
/** | /** | ||||
* Remove an internal client from a JACK server. | * Remove an internal client from a JACK server. | ||||
* | * | ||||
* @deprecated Please use jack_internal_client_load(). | |||||
* @deprecated Please use jack_internal_client_unload(). | |||||
*/ | */ | ||||
void jack_internal_client_close (const char *client_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; | void jack_internal_client_close (const char *client_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; | ||||
@@ -198,9 +203,9 @@ int jack_get_client_pid (const char *name) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* @return the pthread ID of the thread running the JACK client side | * @return the pthread ID of the thread running the JACK client side | ||||
* code. | |||||
* real-time code. | |||||
*/ | */ | ||||
jack_native_thread_t jack_client_thread_id (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; | |||||
jack_native_thread_t jack_client_thread_id (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/*@}*/ | /*@}*/ | ||||
@@ -224,7 +229,7 @@ int jack_is_realtime (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; | |||||
* | * | ||||
* @deprecated Please use jack_cycle_wait() and jack_cycle_signal() functions. | * @deprecated Please use jack_cycle_wait() and jack_cycle_signal() functions. | ||||
*/ | */ | ||||
jack_nframes_t jack_thread_wait (jack_client_t*, int status) JACK_OPTIONAL_WEAK_EXPORT; | |||||
jack_nframes_t jack_thread_wait (jack_client_t *client, int status) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* Wait until this JACK client should process data. | * Wait until this JACK client should process data. | ||||
@@ -432,9 +437,9 @@ int jack_set_sample_rate_callback (jack_client_t *client, | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_set_client_registration_callback (jack_client_t *, | |||||
JackClientRegistrationCallback | |||||
registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | |||||
int jack_set_client_registration_callback (jack_client_t *client, | |||||
JackClientRegistrationCallback | |||||
registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* Tell the JACK server to call @a registration_callback whenever a | * Tell the JACK server to call @a registration_callback whenever a | ||||
@@ -449,7 +454,7 @@ int jack_set_client_registration_callback (jack_client_t *, | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_set_port_registration_callback (jack_client_t *, | |||||
int jack_set_port_registration_callback (jack_client_t *client, | |||||
JackPortRegistrationCallback | JackPortRegistrationCallback | ||||
registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | ||||
@@ -466,7 +471,7 @@ int jack_set_client_registration_callback (jack_client_t *, | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_set_port_connect_callback (jack_client_t *, | |||||
int jack_set_port_connect_callback (jack_client_t *client, | |||||
JackPortConnectCallback | JackPortConnectCallback | ||||
connect_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | connect_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | ||||
@@ -483,7 +488,7 @@ int jack_set_port_connect_callback (jack_client_t *, | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_set_port_rename_callback (jack_client_t *, | |||||
int jack_set_port_rename_callback (jack_client_t *client, | |||||
JackPortRenameCallback | JackPortRenameCallback | ||||
rename_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | rename_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | ||||
@@ -500,7 +505,7 @@ int jack_set_port_rename_callback (jack_client_t *, | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_set_graph_order_callback (jack_client_t *, | |||||
int jack_set_graph_order_callback (jack_client_t *client, | |||||
JackGraphOrderCallback graph_callback, | JackGraphOrderCallback graph_callback, | ||||
void *) JACK_OPTIONAL_WEAK_EXPORT; | void *) JACK_OPTIONAL_WEAK_EXPORT; | ||||
@@ -517,7 +522,7 @@ int jack_set_graph_order_callback (jack_client_t *, | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_set_xrun_callback (jack_client_t *, | |||||
int jack_set_xrun_callback (jack_client_t *client, | |||||
JackXRunCallback xrun_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | JackXRunCallback xrun_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; | ||||
/*@}*/ | /*@}*/ | ||||
@@ -575,7 +580,7 @@ int jack_set_xrun_callback (jack_client_t *, | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_set_latency_callback (jack_client_t *, | |||||
int jack_set_latency_callback (jack_client_t *client, | |||||
JackLatencyCallback latency_callback, | JackLatencyCallback latency_callback, | ||||
void *) JACK_WEAK_EXPORT; | void *) JACK_WEAK_EXPORT; | ||||
/*@}*/ | /*@}*/ | ||||
@@ -713,7 +718,7 @@ jack_port_t * jack_port_register (jack_client_t *client, | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_port_unregister (jack_client_t *, jack_port_t *) JACK_OPTIONAL_WEAK_EXPORT; | |||||
int jack_port_unregister (jack_client_t *client, jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* This returns a pointer to the memory area associated with the | * This returns a pointer to the memory area associated with the | ||||
@@ -734,7 +739,7 @@ int jack_port_unregister (jack_client_t *, jack_port_t *) JACK_OPTIONAL_WEAK_EXP | |||||
* Caching output ports is DEPRECATED in Jack 2.0, due to some new optimization (like "pipelining"). | * Caching output ports is DEPRECATED in Jack 2.0, due to some new optimization (like "pipelining"). | ||||
* Port buffers have to be retrieved in each callback for proper functionning. | * Port buffers have to be retrieved in each callback for proper functionning. | ||||
*/ | */ | ||||
void * jack_port_get_buffer (jack_port_t *, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; | |||||
void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* @return the full name of the jack_port_t (including the @a | * @return the full name of the jack_port_t (including the @a | ||||
@@ -771,7 +776,7 @@ jack_port_type_id_t jack_port_type_id (const jack_port_t *port) JACK_OPTIONAL_WE | |||||
/** | /** | ||||
* @return TRUE if the jack_port_t belongs to the jack_client_t. | * @return TRUE if the jack_port_t belongs to the jack_client_t. | ||||
*/ | */ | ||||
int jack_port_is_mine (const jack_client_t *, const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; | |||||
int jack_port_is_mine (const jack_client_t *client, const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* @return number of connections to or from @a port. | * @return number of connections to or from @a port. | ||||
@@ -931,7 +936,7 @@ int jack_port_monitoring_input (jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; | |||||
* @return 0 on success, EEXIST if the connection is already made, | * @return 0 on success, EEXIST if the connection is already made, | ||||
* otherwise a non-zero error code | * otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_connect (jack_client_t *, | |||||
int jack_connect (jack_client_t *client, | |||||
const char *source_port, | const char *source_port, | ||||
const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; | const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; | ||||
@@ -948,7 +953,7 @@ int jack_connect (jack_client_t *, | |||||
* | * | ||||
* @return 0 on success, otherwise a non-zero error code | * @return 0 on success, otherwise a non-zero error code | ||||
*/ | */ | ||||
int jack_disconnect (jack_client_t *, | |||||
int jack_disconnect (jack_client_t *client, | |||||
const char *source_port, | const char *source_port, | ||||
const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; | const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; | ||||
@@ -961,7 +966,7 @@ int jack_disconnect (jack_client_t *, | |||||
* while generic connection clients (e.g. patchbays) would use | * while generic connection clients (e.g. patchbays) would use | ||||
* jack_disconnect(). | * jack_disconnect(). | ||||
*/ | */ | ||||
int jack_port_disconnect (jack_client_t *, jack_port_t *) JACK_OPTIONAL_WEAK_EXPORT; | |||||
int jack_port_disconnect (jack_client_t *client, jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* @return the maximum number of characters in a full JACK port name | * @return the maximum number of characters in a full JACK port name | ||||
@@ -1052,7 +1057,7 @@ size_t jack_port_type_get_buffer_size (jack_client_t *client, const char *port_t | |||||
* be replaced by a latency callback that calls @ref | * be replaced by a latency callback that calls @ref | ||||
* jack_port_set_latency_range(). | * jack_port_set_latency_range(). | ||||
*/ | */ | ||||
void jack_port_set_latency (jack_port_t *, jack_nframes_t) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; | |||||
void jack_port_set_latency (jack_port_t *port, jack_nframes_t) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; | |||||
/** | /** | ||||
* return the latency range defined by @a mode for | * return the latency range defined by @a mode for | ||||
@@ -1147,7 +1152,7 @@ void jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_ | |||||
* @return zero for successful execution of the request. non-zero | * @return zero for successful execution of the request. non-zero | ||||
* otherwise. | * otherwise. | ||||
*/ | */ | ||||
int jack_recompute_total_latencies (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; | |||||
int jack_recompute_total_latencies (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* @return the time (in frames) between data being available or | * @return the time (in frames) between data being available or | ||||
@@ -1176,7 +1181,7 @@ jack_nframes_t jack_port_get_latency (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPR | |||||
* be replaced by jack_port_get_latency_range() in any existing | * be replaced by jack_port_get_latency_range() in any existing | ||||
* use cases. | * use cases. | ||||
*/ | */ | ||||
jack_nframes_t jack_port_get_total_latency (jack_client_t *, | |||||
jack_nframes_t jack_port_get_total_latency (jack_client_t *client, | |||||
jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; | jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; | ||||
/** | /** | ||||
@@ -1220,7 +1225,7 @@ int jack_recompute_total_latency (jack_client_t*, jack_port_t* port) JACK_OPTION | |||||
* | * | ||||
* @see jack_port_name_size(), jack_port_type_size() | * @see jack_port_name_size(), jack_port_type_size() | ||||
*/ | */ | ||||
const char ** jack_get_ports (jack_client_t *, | |||||
const char ** jack_get_ports (jack_client_t *client, | |||||
const char *port_name_pattern, | const char *port_name_pattern, | ||||
const char *type_name_pattern, | const char *type_name_pattern, | ||||
unsigned long flags) JACK_OPTIONAL_WEAK_EXPORT; | unsigned long flags) JACK_OPTIONAL_WEAK_EXPORT; | ||||
@@ -1230,7 +1235,7 @@ const char ** jack_get_ports (jack_client_t *, | |||||
* | * | ||||
* @see jack_port_name_size() | * @see jack_port_name_size() | ||||
*/ | */ | ||||
jack_port_t * jack_port_by_name (jack_client_t *, const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; | |||||
jack_port_t * jack_port_by_name (jack_client_t *client, const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* @return address of the jack_port_t of a @a port_id. | * @return address of the jack_port_t of a @a port_id. | ||||
@@ -1279,6 +1284,55 @@ jack_nframes_t jack_frame_time (const jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT | |||||
*/ | */ | ||||
jack_nframes_t jack_last_frame_time (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; | jack_nframes_t jack_last_frame_time (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; | ||||
/** | |||||
* This function may only be used from the process callback. | |||||
* It provides the internal cycle timing information as used by | |||||
* most of the other time related functions. This allows the | |||||
* caller to map between frame counts and microseconds with full | |||||
* precision (i.e. without rounding frame times to integers), | |||||
* and also provides e.g. the microseconds time of the start of | |||||
* the current cycle directly (it has to be computed otherwise). | |||||
* | |||||
* If the return value is zero, the following information is | |||||
* provided in the variables pointed to by the arguments: | |||||
* | |||||
* current_frames: the frame time counter at the start of the | |||||
* current cycle, same as jack_last_frame_time(). | |||||
* current_usecs: the microseconds time at the start of the | |||||
* current cycle. | |||||
* next_usecs: the microseconds time of the start of the next | |||||
* next cycle as computed by the DLL. | |||||
* period_usecs: the current best estimate of the period time in | |||||
* microseconds. | |||||
* | |||||
* NOTES: | |||||
* | |||||
* Because of the types used, all the returned values except period_usecs | |||||
* are unsigned. In computations mapping between frames and microseconds | |||||
* *signed* differences are required. The easiest way is to compute those | |||||
* separately and assign them to the appropriate signed variables, | |||||
* int32_t for frames and int64_t for usecs. See the implementation of | |||||
* jack_frames_to_time() and Jack_time_to_frames() for an example. | |||||
* | |||||
* Unless there was an xrun, skipped cycles, or the current cycle is the | |||||
* first after freewheeling or starting Jack, the value of current_usecs | |||||
* will always be the value of next_usecs of the previous cycle. | |||||
* | |||||
* The value of period_usecs will in general NOT be exactly equal to | |||||
* the difference of next_usecs and current_usecs. This is because to | |||||
* ensure stability of the DLL and continuity of the mapping, a fraction | |||||
* of the loop error must be included in next_usecs. For an accurate | |||||
* mapping between frames and microseconds, the difference of next_usecs | |||||
* and current_usecs should be used, and not period_usecs. | |||||
* | |||||
* @return zero if OK, non-zero otherwise. | |||||
*/ | |||||
int jack_get_cycle_times(const jack_client_t *client, | |||||
jack_nframes_t *current_frames, | |||||
jack_time_t *current_usecs, | |||||
jack_time_t *next_usecs, | |||||
float *period_usecs) JACK_OPTIONAL_WEAK_EXPORT; | |||||
/** | /** | ||||
* @return the estimated time in microseconds of the specified frame time | * @return the estimated time in microseconds of the specified frame time | ||||
*/ | */ | ||||
@@ -44,10 +44,10 @@ enum JackNetEncoder { | |||||
typedef struct { | typedef struct { | ||||
int audio_input; // from master or to slave (-1 for get master audio physical outputs) | |||||
int audio_output; // to master or from slave (-1 for get master audio physical inputs) | |||||
int midi_input; // from master or to slave (-1 for get master MIDI physical outputs) | |||||
int midi_output; // to master or from slave (-1 for get master MIDI physical inputs) | |||||
int audio_input; // from master or to slave (-1 to take master audio physical inputs) | |||||
int audio_output; // to master or from slave (-1 to take master audio physical outputs) | |||||
int midi_input; // from master or to slave (-1 to take master MIDI physical inputs) | |||||
int midi_output; // to master or from slave (-1 to take master MIDI physical outputs) | |||||
int mtu; // network Maximum Transmission Unit | int mtu; // network Maximum Transmission Unit | ||||
int time_out; // in second, -1 means in infinite | int time_out; // in second, -1 means in infinite | ||||
int encoder; // encoder type (one of JackNetEncoder) | int encoder; // encoder type (one of JackNetEncoder) | ||||
@@ -58,10 +58,10 @@ typedef struct { | |||||
typedef struct { | typedef struct { | ||||
int audio_input; // master audio physical outputs | |||||
int audio_output; // master audio physical inputs | |||||
int midi_input; // master MIDI physical outputs | |||||
int midi_output; // master MIDI physical inputs | |||||
int audio_input; // master audio physical outputs (-1 to take slave wanted audio inputs) | |||||
int audio_output; // master audio physical inputs (-1 to take slave wanted audio outputs) | |||||
int midi_input; // master MIDI physical outputs (-1 to take slave wanted MIDI inputs) | |||||
int midi_output; // master MIDI physical inputs (-1 to take slave wanted MIDI outputs) | |||||
jack_nframes_t buffer_size; // mater buffer size | jack_nframes_t buffer_size; // mater buffer size | ||||
jack_nframes_t sample_rate; // mater sample rate | jack_nframes_t sample_rate; // mater sample rate | ||||
char master_name[MASTER_NAME_SIZE]; // master machine name | char master_name[MASTER_NAME_SIZE]; // master machine name | ||||
@@ -1,5 +1,5 @@ | |||||
/* | /* | ||||
Copyright (C) 2004-2009 Grame | |||||
Copyright (C) 2004-2012 Grame | |||||
This program is free software; you can redistribute it and/or modify | This program is free software; you can redistribute it and/or modify | ||||
it under the terms of the GNU Lesser General Public License as published by | it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -20,66 +20,104 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#ifndef __jack_systemdeps_h__ | #ifndef __jack_systemdeps_h__ | ||||
#define __jack_systemdeps_h__ | #define __jack_systemdeps_h__ | ||||
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(GNU_WIN32) | |||||
#ifndef POST_PACKED_STRUCTURE | |||||
#ifdef __GNUC__ | |||||
/* POST_PACKED_STRUCTURE needs to be a macro which | |||||
expands into a compiler directive. The directive must | |||||
tell the compiler to arrange the preceding structure | |||||
declaration so that it is packed on byte-boundaries rather | |||||
than use the natural alignment of the processor and/or | |||||
compiler. | |||||
*/ | |||||
#define PRE_PACKED_STRUCTURE | |||||
#define POST_PACKED_STRUCTURE __attribute__((__packed__)) | |||||
#else | |||||
#ifdef _MSC_VER | |||||
#define PRE_PACKED_STRUCTURE1 __pragma(pack(push,1)) | |||||
#define PRE_PACKED_STRUCTURE PRE_PACKED_STRUCTURE1 | |||||
/* PRE_PACKED_STRUCTURE needs to be a macro which | |||||
expands into a compiler directive. The directive must | |||||
tell the compiler to arrange the following structure | |||||
declaration so that it is packed on byte-boundaries rather | |||||
than use the natural alignment of the processor and/or | |||||
compiler. | |||||
*/ | |||||
#define POST_PACKED_STRUCTURE ;__pragma(pack(pop)) | |||||
/* and POST_PACKED_STRUCTURE needs to be a macro which | |||||
restores the packing to its previous setting */ | |||||
#else | |||||
#define PRE_PACKED_STRUCTURE | |||||
#define POST_PACKED_STRUCTURE | |||||
#endif | |||||
#include <windows.h> | |||||
#ifdef _MSC_VER /* Microsoft compiler */ | |||||
#define __inline__ inline | |||||
#if (!defined(int8_t) && !defined(_STDINT_H)) | |||||
#define __int8_t_defined | |||||
typedef char int8_t; | |||||
typedef unsigned char uint8_t; | |||||
typedef short int16_t; | |||||
typedef unsigned short uint16_t; | |||||
typedef long int32_t; | |||||
typedef unsigned long uint32_t; | |||||
typedef LONGLONG int64_t; | |||||
typedef ULONGLONG uint64_t; | |||||
#endif | #endif | ||||
#elif __MINGW32__ /* MINGW */ | |||||
#include <stdint.h> | |||||
#include <sys/types.h> | |||||
#else /* other compilers ...*/ | |||||
#include <inttypes.h> | |||||
#include <pthread.h> | |||||
#include <sys/types.h> | |||||
#endif | #endif | ||||
#if !defined(_PTHREAD_H) && !defined(PTHREAD_WIN32) | |||||
/** | |||||
* to make jack API independent of different thread implementations, | |||||
* we define jack_native_thread_t to HANDLE here. | |||||
*/ | |||||
typedef HANDLE jack_native_thread_t; | |||||
#else | |||||
#ifdef PTHREAD_WIN32 // Added by JE - 10-10-2011 | |||||
#include <ptw32/pthread.h> // Makes sure we #include the ptw32 version ! | |||||
#if defined(WIN32) && !defined(__CYGWIN__) && !defined(GNU_WIN32) | |||||
#include <windows.h> | |||||
#ifdef _MSC_VER /* Microsoft compiler */ | |||||
#define __inline__ inline | |||||
#if (!defined(int8_t) && !defined(_STDINT_H)) | |||||
#define __int8_t_defined | |||||
typedef char int8_t; | |||||
typedef unsigned char uint8_t; | |||||
typedef short int16_t; | |||||
typedef unsigned short uint16_t; | |||||
typedef long int32_t; | |||||
typedef unsigned long uint32_t; | |||||
typedef LONGLONG int64_t; | |||||
typedef ULONGLONG uint64_t; | |||||
#endif | |||||
#elif __MINGW32__ /* MINGW */ | |||||
#include <stdint.h> | |||||
#include <sys/types.h> | |||||
#else /* other compilers ...*/ | |||||
#include <inttypes.h> | |||||
#include <pthread.h> | |||||
#include <sys/types.h> | |||||
#endif | |||||
#if !defined(_PTHREAD_H) && !defined(PTHREAD_WIN32) | |||||
/** | |||||
* to make jack API independent of different thread implementations, | |||||
* we define jack_native_thread_t to HANDLE here. | |||||
*/ | |||||
typedef HANDLE jack_native_thread_t; | |||||
#else | |||||
#ifdef PTHREAD_WIN32 // Added by JE - 10-10-2011 | |||||
#include <ptw32/pthread.h> // Makes sure we #include the ptw32 version ! | |||||
#endif | |||||
/** | |||||
* to make jack API independent of different thread implementations, | |||||
* we define jack_native_thread_t to pthread_t here. | |||||
*/ | |||||
typedef pthread_t jack_native_thread_t; | |||||
#endif | #endif | ||||
/** | |||||
* to make jack API independent of different thread implementations, | |||||
* we define jack_native_thread_t to pthread_t here. | |||||
*/ | |||||
typedef pthread_t jack_native_thread_t; | |||||
#endif | |||||
#endif // WIN32 && !__CYGWIN__ && !GNU_WIN32 */ | #endif // WIN32 && !__CYGWIN__ && !GNU_WIN32 */ | ||||
#if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32) | #if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32) | ||||
#if defined(__CYGWIN__) || defined(GNU_WIN32) | |||||
#include <stdint.h> | |||||
#endif | |||||
#include <inttypes.h> | |||||
#include <pthread.h> | |||||
#include <sys/types.h> | |||||
#if defined(__CYGWIN__) || defined(GNU_WIN32) | |||||
#include <stdint.h> | |||||
#endif | |||||
#include <inttypes.h> | |||||
#include <pthread.h> | |||||
#include <sys/types.h> | |||||
/** | |||||
* to make jack API independent of different thread implementations, | |||||
* we define jack_native_thread_t to pthread_t here. | |||||
*/ | |||||
typedef pthread_t jack_native_thread_t; | |||||
/** | |||||
* to make jack API independent of different thread implementations, | |||||
* we define jack_native_thread_t to pthread_t here. | |||||
*/ | |||||
typedef pthread_t jack_native_thread_t; | |||||
#endif /* __APPLE__ || __linux__ || __sun__ || sun */ | |||||
#endif /* __APPLE__ || __linux__ || __sun__ || sun */ | |||||
#endif | #endif |
@@ -259,6 +259,7 @@ typedef void (*JackLatencyCallback)(jack_latency_callback_mode_t mode, void *arg | |||||
/** | /** | ||||
* the new latency API operates on Ranges. | * the new latency API operates on Ranges. | ||||
*/ | */ | ||||
PRE_PACKED_STRUCTURE | |||||
struct _jack_latency_range | struct _jack_latency_range | ||||
{ | { | ||||
/** | /** | ||||
@@ -269,7 +270,7 @@ struct _jack_latency_range | |||||
* maximum latency | * maximum latency | ||||
*/ | */ | ||||
jack_nframes_t max; | jack_nframes_t max; | ||||
}; | |||||
} POST_PACKED_STRUCTURE; | |||||
typedef struct _jack_latency_range jack_latency_range_t; | typedef struct _jack_latency_range jack_latency_range_t; | ||||
@@ -548,7 +549,8 @@ typedef enum { | |||||
#define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode) | #define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode) | ||||
#define EXTENDED_TIME_INFO | #define EXTENDED_TIME_INFO | ||||
typedef struct { | |||||
PRE_PACKED_STRUCTURE | |||||
struct _jack_position { | |||||
/* these four cannot be set from clients: the server sets them */ | /* these four cannot be set from clients: the server sets them */ | ||||
jack_unique_t unique_1; /**< unique ID */ | jack_unique_t unique_1; /**< unique ID */ | ||||
@@ -614,7 +616,9 @@ typedef struct { | |||||
/* When (unique_1 == unique_2) the contents are consistent. */ | /* When (unique_1 == unique_2) the contents are consistent. */ | ||||
jack_unique_t unique_2; /**< unique ID */ | jack_unique_t unique_2; /**< unique ID */ | ||||
} jack_position_t; | |||||
} POST_PACKED_STRUCTURE; | |||||
typedef struct _jack_position jack_position_t; | |||||
/** | /** | ||||
* Prototype for the @a sync_callback defined by slow-sync clients. | * Prototype for the @a sync_callback defined by slow-sync clients. | ||||
@@ -67,6 +67,10 @@ | |||||
#endif | #endif | ||||
#endif | #endif | ||||
#ifndef JACK_WEAK_EXPORT | |||||
#define JACK_WEAK_EXPORT | |||||
#endif | |||||
#ifndef JACK_OPTIONAL_WEAK_EXPORT | #ifndef JACK_OPTIONAL_WEAK_EXPORT | ||||
#define JACK_OPTIONAL_WEAK_EXPORT | #define JACK_OPTIONAL_WEAK_EXPORT | ||||
#endif | #endif | ||||
@@ -82,6 +86,11 @@ | |||||
#endif | #endif | ||||
#endif /* __GNUC__ */ | #endif /* __GNUC__ */ | ||||
#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT | |||||
#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT | |||||
#endif | |||||
#endif | #endif | ||||
#endif /* __weakmacros_h__ */ | #endif /* __weakmacros_h__ */ | ||||
@@ -47,7 +47,7 @@ $Id: net_driver.c,v 1.17 2006/04/16 20:16:10 torbenh Exp $ | |||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#endif | #endif | ||||
#ifdef __linux__ | |||||
#if defined(HAVE_CONFIG_H) | |||||
#include "config.h" | #include "config.h" | ||||
#endif | #endif | ||||
@@ -26,7 +26,7 @@ | |||||
* | * | ||||
*/ | */ | ||||
#ifdef __linux__ | |||||
#if defined(HAVE_CONFIG_H) | |||||
#include "config.h" | #include "config.h" | ||||
#endif | #endif | ||||
@@ -75,7 +75,7 @@ | |||||
#include "netjack_packet.h" | #include "netjack_packet.h" | ||||
#include "JackError.h" | #include "JackError.h" | ||||
#ifdef NO_JACK_ERROR | |||||
#ifdef NO_JACK_ERROR | |||||
#define jack_error printf | #define jack_error printf | ||||
#endif | #endif | ||||
@@ -505,11 +505,11 @@ packet_cache_drain_socket( packet_cache *pcache, int sockfd ) | |||||
cache_packet *cpack; | cache_packet *cpack; | ||||
struct sockaddr_in sender_address; | struct sockaddr_in sender_address; | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
size_t senderlen = sizeof( struct sockaddr_in ); | |||||
int senderlen = sizeof( struct sockaddr_in ); | |||||
u_long parm = 1; | u_long parm = 1; | ||||
ioctlsocket( sockfd, FIONBIO, &parm ); | ioctlsocket( sockfd, FIONBIO, &parm ); | ||||
#else | #else | ||||
socklen_t senderlen = sizeof( struct sockaddr_in ); | |||||
int senderlen = sizeof( struct sockaddr_in ); | |||||
#endif | #endif | ||||
while (1) { | while (1) { | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
@@ -117,20 +117,17 @@ extern "C" | |||||
*/ | */ | ||||
PRE_PACKED_STRUCTURE | PRE_PACKED_STRUCTURE | ||||
typedef struct _jack_shm_info { | |||||
struct _jack_shm_info { | |||||
jack_shm_registry_index_t index; /* offset into the registry */ | jack_shm_registry_index_t index; /* offset into the registry */ | ||||
uint32_t size; | uint32_t size; | ||||
union { | union { | ||||
void *attached_at; /* address where attached */ | void *attached_at; /* address where attached */ | ||||
char ptr_size[8]; | char ptr_size[8]; | ||||
} ptr; /* a "pointer" that has the same 8 bytes size when compling in 32 or 64 bits */ | } ptr; /* a "pointer" that has the same 8 bytes size when compling in 32 or 64 bits */ | ||||
} | |||||
#ifdef _MSC_VER | |||||
jack_shm_info_t; POST_PACKED_STRUCTURE | |||||
#else | |||||
POST_PACKED_STRUCTURE jack_shm_info_t; | |||||
#endif | |||||
} POST_PACKED_STRUCTURE; | |||||
typedef struct _jack_shm_info jack_shm_info_t; | |||||
/* utility functions used only within JACK */ | /* utility functions used only within JACK */ | ||||
void jack_shm_copy_from_registry (jack_shm_info_t*, | void jack_shm_copy_from_registry (jack_shm_info_t*, | ||||
@@ -15,13 +15,13 @@ def configure(conf): | |||||
conf.env['BUILD_ADAPTER'] = conf.is_defined('HAVE_SAMPLERATE') | conf.env['BUILD_ADAPTER'] = conf.is_defined('HAVE_SAMPLERATE') | ||||
def create_jack_process_obj(bld, target, sources, uselib = None): | def create_jack_process_obj(bld, target, sources, uselib = None): | ||||
process = bld.new_task_gen('cxx', 'shlib') | |||||
process.env['shlib_PATTERN'] = '%s.so' | |||||
process = bld(features = ['cxx', 'cxxshlib']) | |||||
process.env['cxxshlib_PATTERN'] = '%s.so' | |||||
process.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | process.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | ||||
if bld.env['IS_MACOSX']: | if bld.env['IS_MACOSX']: | ||||
env_includes = ['../macosx', '../posix', '../macosx/coreaudio'] | env_includes = ['../macosx', '../posix', '../macosx/coreaudio'] | ||||
if bld.env['IS_LINUX']: | if bld.env['IS_LINUX']: | ||||
env_includes = ['../linux', '../posix', '../linux/alsa'] | |||||
env_includes = ['../linux', '../posix', '../linux/alsa'] | |||||
if bld.env['IS_SUN']: | if bld.env['IS_SUN']: | ||||
env_includes = ['../solaris', '../posix', '../solaris/oss'] | env_includes = ['../solaris', '../posix', '../solaris/oss'] | ||||
process.includes = ['.'] + env_includes + ['jack', '..'] | process.includes = ['.'] + env_includes + ['jack', '..'] | ||||
@@ -35,7 +35,7 @@ def create_jack_process_obj(bld, target, sources, uselib = None): | |||||
#process.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | #process.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | ||||
process.env.append_value("CPPFLAGS", "-fvisibility=hidden") | process.env.append_value("CPPFLAGS", "-fvisibility=hidden") | ||||
process.install_path = '${ADDON_DIR}/' | process.install_path = '${ADDON_DIR}/' | ||||
process.uselib_local = uselib.name | |||||
process.use = [uselib.name] | |||||
return process | return process | ||||
def build(bld): | def build(bld): | ||||
@@ -46,6 +46,7 @@ def build(bld): | |||||
'JackConnectionManager.cpp', | 'JackConnectionManager.cpp', | ||||
'ringbuffer.c', | 'ringbuffer.c', | ||||
'JackError.cpp', | 'JackError.cpp', | ||||
'JackException.cpp', | |||||
'JackFrameTimer.cpp', | 'JackFrameTimer.cpp', | ||||
'JackGraphManager.cpp', | 'JackGraphManager.cpp', | ||||
'JackPort.cpp', | 'JackPort.cpp', | ||||
@@ -55,6 +56,7 @@ def build(bld): | |||||
'JackMidiAPI.cpp', | 'JackMidiAPI.cpp', | ||||
'JackEngineControl.cpp', | 'JackEngineControl.cpp', | ||||
'JackShmMem.cpp', | 'JackShmMem.cpp', | ||||
'JackGenericClientChannel.cpp', | |||||
'shm.c', | 'shm.c', | ||||
'JackGlobals.cpp', | 'JackGlobals.cpp', | ||||
'JackDebugClient.cpp', | 'JackDebugClient.cpp', | ||||
@@ -72,8 +74,8 @@ def build(bld): | |||||
common_libsources += [ | common_libsources += [ | ||||
'../posix/JackPosixThread.cpp', | '../posix/JackPosixThread.cpp', | ||||
'../posix/JackPosixSemaphore.cpp', | '../posix/JackPosixSemaphore.cpp', | ||||
'../posix/JackFifo.cpp', | |||||
'../posix/JackProcessSync.cpp', | |||||
'../posix/JackPosixProcessSync.cpp', | |||||
'../posix/JackPosixMutex.cpp', | |||||
'../posix/JackSocket.cpp', | '../posix/JackSocket.cpp', | ||||
'../linux/JackLinuxTime.c', | '../linux/JackLinuxTime.c', | ||||
] | ] | ||||
@@ -85,7 +87,8 @@ def build(bld): | |||||
common_libsources += [ | common_libsources += [ | ||||
'../posix/JackPosixThread.cpp', | '../posix/JackPosixThread.cpp', | ||||
'../posix/JackFifo.cpp', | '../posix/JackFifo.cpp', | ||||
'../posix/JackProcessSync.cpp', | |||||
'../posix/JackPosixProcessSync.cpp', | |||||
'../posix/JackPosixMutex.cpp', | |||||
'../posix/JackSocket.cpp', | '../posix/JackSocket.cpp', | ||||
'../solaris/JackSolarisTime.c', | '../solaris/JackSolarisTime.c', | ||||
] | ] | ||||
@@ -94,7 +97,7 @@ def build(bld): | |||||
if bld.env['IS_MACOSX']: | if bld.env['IS_MACOSX']: | ||||
common_libsources += [ | common_libsources += [ | ||||
'../posix/JackProcessSync.cpp', | |||||
'../posix/JackPosixProcessSync.cpp', | |||||
'../posix/JackPosixThread.cpp', | '../posix/JackPosixThread.cpp', | ||||
'../macosx/JackMachThread.cpp', | '../macosx/JackMachThread.cpp', | ||||
'../macosx/JackMachSemaphore.cpp', | '../macosx/JackMachSemaphore.cpp', | ||||
@@ -103,18 +106,17 @@ def build(bld): | |||||
] | ] | ||||
includes = ['../macosx', '../macosx/RPC', '../posix'] + includes | includes = ['../macosx', '../macosx/RPC', '../posix'] + includes | ||||
serverlib = bld.new_task_gen('cxx', 'shlib') | |||||
serverlib.features.append('cc') | |||||
serverlib = bld(features = ['c', 'cxx', 'cxxshlib', 'cshlib']) | |||||
serverlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | serverlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | ||||
serverlib.includes = includes | serverlib.includes = includes | ||||
serverlib.name = 'serverlib' | serverlib.name = 'serverlib' | ||||
serverlib.target = 'jackserver' | serverlib.target = 'jackserver' | ||||
serverlib.uselib = uselib | |||||
serverlib.use = uselib | |||||
serverlib.install_path = '${LIBDIR}' | serverlib.install_path = '${LIBDIR}' | ||||
serverlib.source = [] + common_libsources | serverlib.source = [] + common_libsources | ||||
serverlib.source += [ | serverlib.source += [ | ||||
'JackAudioDriver.cpp', | 'JackAudioDriver.cpp', | ||||
'JackTimedDriver.cpp', | |||||
'JackTimedDriver.cpp', | |||||
'JackMidiDriver.cpp', | 'JackMidiDriver.cpp', | ||||
'JackDriver.cpp', | 'JackDriver.cpp', | ||||
'JackEngine.cpp', | 'JackEngine.cpp', | ||||
@@ -132,6 +134,7 @@ def build(bld): | |||||
'JackNetTool.cpp', | 'JackNetTool.cpp', | ||||
'JackNetInterface.cpp', | 'JackNetInterface.cpp', | ||||
'JackArgParser.cpp', | 'JackArgParser.cpp', | ||||
'JackRequestDecoder.cpp', | |||||
'JackMidiAsyncQueue.cpp', | 'JackMidiAsyncQueue.cpp', | ||||
'JackMidiAsyncWaitQueue.cpp', | 'JackMidiAsyncWaitQueue.cpp', | ||||
'JackMidiBufferReadQueue.cpp', | 'JackMidiBufferReadQueue.cpp', | ||||
@@ -185,22 +188,23 @@ def build(bld): | |||||
serverlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") | serverlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") | ||||
if bld.env['BUILD_NETLIB'] == True: | if bld.env['BUILD_NETLIB'] == True: | ||||
netlib = bld.new_task_gen('cxx', 'shlib') | |||||
netlib.features.append('cc') | |||||
netlib = bld(features = ['c', 'cxx', 'cxxshlib', 'cshlib']) | |||||
netlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | netlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | ||||
netlib.includes = includes | netlib.includes = includes | ||||
netlib.name = 'netlib' | netlib.name = 'netlib' | ||||
netlib.target = 'jacknet' | netlib.target = 'jacknet' | ||||
netlib.uselib = ['SAMPLERATE', 'CELT', 'PTHREAD' , 'RT'] | |||||
netlib.use = ['SAMPLERATE', 'CELT', 'PTHREAD' , 'RT'] | |||||
netlib.install_path = '${LIBDIR}' | netlib.install_path = '${LIBDIR}' | ||||
netlib.source = [ | netlib.source = [ | ||||
'JackNetAPI.cpp', | 'JackNetAPI.cpp', | ||||
'JackNetInterface.cpp', | 'JackNetInterface.cpp', | ||||
'JackNetTool.cpp', | 'JackNetTool.cpp', | ||||
'JackException.cpp', | |||||
'JackAudioAdapterInterface.cpp', | 'JackAudioAdapterInterface.cpp', | ||||
'JackLibSampleRateResampler.cpp', | 'JackLibSampleRateResampler.cpp', | ||||
'JackResampler.cpp', | 'JackResampler.cpp', | ||||
'JackGlobals.cpp', | 'JackGlobals.cpp', | ||||
'../posix/JackPosixMutex.cpp', | |||||
'ringbuffer.c'] | 'ringbuffer.c'] | ||||
if bld.env['IS_LINUX']: | if bld.env['IS_LINUX']: | ||||
@@ -218,13 +222,12 @@ def build(bld): | |||||
netlib.vnum = bld.env['JACK_API_VERSION'] | netlib.vnum = bld.env['JACK_API_VERSION'] | ||||
clientlib = bld.new_task_gen('cxx', 'shlib') | |||||
clientlib.features.append('cc') | |||||
clientlib = bld(features = ['c', 'cxx', 'cxxshlib', 'cshlib']) | |||||
clientlib.defines = 'HAVE_CONFIG_H' | clientlib.defines = 'HAVE_CONFIG_H' | ||||
clientlib.uselib = uselib | |||||
clientlib.use = uselib | |||||
clientlib.install_path = '${LIBDIR}' | clientlib.install_path = '${LIBDIR}' | ||||
if bld.env['BUILD_JACKDBUS'] == True and bld.env['BUILD_JACKD'] == False: | if bld.env['BUILD_JACKDBUS'] == True and bld.env['BUILD_JACKD'] == False: | ||||
clientlib.uselib.append('DBUS-1') | |||||
clientlib.use.append('DBUS-1') | |||||
clientlib.includes = includes | clientlib.includes = includes | ||||
clientlib.name = 'clientlib' | clientlib.name = 'clientlib' | ||||
clientlib.target = 'jack' | clientlib.target = 'jack' | ||||
@@ -268,7 +271,7 @@ def build(bld): | |||||
clientlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") | clientlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") | ||||
if bld.env['BUILD_WITH_32_64']: | if bld.env['BUILD_WITH_32_64']: | ||||
print "create 32bit lib..." | |||||
print("create 32bit lib...") | |||||
clientlib32bit = clientlib.clone('lib32') | clientlib32bit = clientlib.clone('lib32') | ||||
create_jack_process_obj(bld, 'netmanager', 'JackNetManager.cpp', serverlib) | create_jack_process_obj(bld, 'netmanager', 'JackNetManager.cpp', serverlib) | ||||
@@ -285,7 +288,7 @@ def build(bld): | |||||
if bld.env['BUILD_ADAPTER'] == True: | if bld.env['BUILD_ADAPTER'] == True: | ||||
process = create_jack_process_obj(bld, 'netadapter', net_adapter_sources, serverlib) | process = create_jack_process_obj(bld, 'netadapter', net_adapter_sources, serverlib) | ||||
process.uselib = 'SAMPLERATE' | |||||
process.use = 'SAMPLERATE' | |||||
audio_adapter_sources = [ | audio_adapter_sources = [ | ||||
'JackResampler.cpp', | 'JackResampler.cpp', | ||||
@@ -299,33 +302,29 @@ def build(bld): | |||||
audio_adapter_sources += ['../macosx/coreaudio/JackCoreAudioAdapter.cpp'] | audio_adapter_sources += ['../macosx/coreaudio/JackCoreAudioAdapter.cpp'] | ||||
process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | ||||
process.env.append_value("LINKFLAGS", "-framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework CoreServices") | process.env.append_value("LINKFLAGS", "-framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework CoreServices") | ||||
process.uselib = 'SAMPLERATE' | |||||
process.use = 'SAMPLERATE' | |||||
if bld.env['BUILD_ADAPTER'] and bld.env['IS_LINUX'] and bld.env['BUILD_DRIVER_ALSA']: | if bld.env['BUILD_ADAPTER'] and bld.env['IS_LINUX'] and bld.env['BUILD_DRIVER_ALSA']: | ||||
audio_adapter_sources += ['../linux/alsa/JackAlsaAdapter.cpp'] | audio_adapter_sources += ['../linux/alsa/JackAlsaAdapter.cpp'] | ||||
process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | ||||
process.uselib = ['ALSA', 'SAMPLERATE'] | |||||
process.use = ['ALSA', 'SAMPLERATE'] | |||||
if bld.env['BUILD_ADAPTER'] and bld.env['IS_SUN']: | if bld.env['BUILD_ADAPTER'] and bld.env['IS_SUN']: | ||||
audio_adapter_sources += ['../solaris/oss/JackOSSAdapter.cpp', 'memops.c'] | audio_adapter_sources += ['../solaris/oss/JackOSSAdapter.cpp', 'memops.c'] | ||||
process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | ||||
process.uselib = 'SAMPLERATE' | |||||
process.use = 'SAMPLERATE' | |||||
#audio_adapter_sources += ['../windows/JackPortAudioAdapter.cpp'] | #audio_adapter_sources += ['../windows/JackPortAudioAdapter.cpp'] | ||||
#process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | #process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | ||||
bld.install_files('${PREFIX}/include/jack', 'jack/*.h') | |||||
bld.install_files('${PREFIX}/include/jack', bld.path.ant_glob('jack/*.h')) | |||||
# process jack.pc.in -> jack.pc | # process jack.pc.in -> jack.pc | ||||
import misc | |||||
obj = bld.new_task_gen('subst') | |||||
obj.source = '../jack.pc.in' | |||||
obj.target = 'jack.pc' | |||||
obj.dict = {'PREFIX': bld.env['PREFIX'], | |||||
'LIBDIR': bld.env['LIBDIR'], | |||||
'INCLUDEDIR': os.path.normpath(bld.env['PREFIX'] + '/include'), | |||||
'SERVERLIB': serverlib.target, | |||||
'JACK_VERSION': bld.env['JACK_VERSION'], | |||||
} | |||||
obj.install_path = '${LIBDIR}/pkgconfig/' | |||||
obj.fun = misc.subst_func | |||||
obj = bld( | |||||
features = 'subst_pc', | |||||
source = '../jack.pc.in', | |||||
target = 'jack.pc', | |||||
install_path = '${LIBDIR}/pkgconfig/', | |||||
INCLUDEDIR = os.path.normpath(bld.env['PREFIX'] + '/include'), | |||||
SERVERLIB = serverlib.target, | |||||
) |
@@ -26,7 +26,7 @@ | |||||
#include "reserve.h" | #include "reserve.h" | ||||
#include "audio_reserve.h" | #include "audio_reserve.h" | ||||
#include "JackError.h" | |||||
#include "jack/control.h" | |||||
#define DEVICE_MAX 2 | #define DEVICE_MAX 2 | ||||
@@ -782,7 +782,7 @@ jack_controller_patchbay_disconnect( | |||||
ret = jack_disconnect(controller_ptr->client, port1_name, port2_name); | ret = jack_disconnect(controller_ptr->client, port1_name, port2_name); | ||||
if (ret != 0) | if (ret != 0) | ||||
{ | { | ||||
jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret); | |||||
jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_disconnect() failed with %d", ret); | |||||
return false; | return false; | ||||
} | } | ||||
@@ -30,7 +30,7 @@ | |||||
#include "jackdbus.h" | #include "jackdbus.h" | ||||
#include "controller_internal.h" | #include "controller_internal.h" | ||||
#include "jack/session.h" | #include "jack/session.h" | ||||
#include "common/JackError.h" | |||||
#include "jack/control.h" | |||||
#define JACK_DBUS_IFACE_NAME "org.jackaudio.SessionManager" | #define JACK_DBUS_IFACE_NAME "org.jackaudio.SessionManager" | ||||
@@ -33,7 +33,7 @@ | |||||
char * __cxa_demangle(const char * __mangled_name, char * __output_buffer, size_t * __length, int * __status); | char * __cxa_demangle(const char * __mangled_name, char * __output_buffer, size_t * __length, int * __status); | ||||
#endif | #endif | ||||
#include "JackError.h" | |||||
#include "jack/control.h" | |||||
#if defined(REG_RIP) | #if defined(REG_RIP) | ||||
# define SIGSEGV_STACK_IA64 | # define SIGSEGV_STACK_IA64 | ||||
@@ -60,6 +60,7 @@ static void signal_segv(int signum, siginfo_t* info, void*ptr) { | |||||
static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"}; | static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"}; | ||||
size_t i; | size_t i; | ||||
const char *si_code_str; | |||||
ucontext_t *ucontext = (ucontext_t*)ptr; | ucontext_t *ucontext = (ucontext_t*)ptr; | ||||
#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) | #if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) | ||||
@@ -94,9 +95,14 @@ static void signal_segv(int signum, siginfo_t* info, void*ptr) { | |||||
jack_error("Unknown bad signal catched!"); | jack_error("Unknown bad signal catched!"); | ||||
} | } | ||||
if (info->si_code >= 0 && info->si_code < 3) | |||||
si_code_str = si_codes[info->si_code]; | |||||
else | |||||
si_code_str = "unknown"; | |||||
jack_error("info.si_signo = %d", signum); | jack_error("info.si_signo = %d", signum); | ||||
jack_error("info.si_errno = %d", info->si_errno); | jack_error("info.si_errno = %d", info->si_errno); | ||||
jack_error("info.si_code = %d (%s)", info->si_code, si_codes[info->si_code]); | |||||
jack_error("info.si_code = %d (%s)", info->si_code, si_code_str); | |||||
jack_error("info.si_addr = %p", info->si_addr); | jack_error("info.si_addr = %p", info->si_addr); | ||||
#if !defined(__alpha__) && !defined(__ia64__) && !defined(__FreeBSD_kernel__) && !defined(__arm__) && !defined(__hppa__) && !defined(__sh__) | #if !defined(__alpha__) && !defined(__ia64__) && !defined(__FreeBSD_kernel__) && !defined(__arm__) && !defined(__hppa__) && !defined(__sh__) | ||||
for(i = 0; i < NGREG; i++) | for(i = 0; i < NGREG; i++) | ||||
@@ -171,7 +177,9 @@ int setup_sigsegv() { | |||||
memset(&action, 0, sizeof(action)); | memset(&action, 0, sizeof(action)); | ||||
action.sa_sigaction = signal_segv; | action.sa_sigaction = signal_segv; | ||||
#ifdef SA_SIGINFO | |||||
action.sa_flags = SA_SIGINFO; | action.sa_flags = SA_SIGINFO; | ||||
#endif | |||||
if(sigaction(SIGSEGV, &action, NULL) < 0) { | if(sigaction(SIGSEGV, &action, NULL) < 0) { | ||||
jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno)); | jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno)); | ||||
return 0; | return 0; | ||||
@@ -6,19 +6,19 @@ import Options | |||||
import re # subst_func | import re # subst_func | ||||
import Logs | import Logs | ||||
def set_options(opt): | |||||
def options(opt): | |||||
opt.add_option('--enable-pkg-config-dbus-service-dir', action='store_true', default=False, help='force D-Bus service install dir to be one returned by pkg-config') | opt.add_option('--enable-pkg-config-dbus-service-dir', action='store_true', default=False, help='force D-Bus service install dir to be one returned by pkg-config') | ||||
def configure(conf): | def configure(conf): | ||||
conf.env['BUILD_JACKDBUS'] = False | conf.env['BUILD_JACKDBUS'] = False | ||||
if not conf.check_cfg(package='dbus-1', atleast_version='1.0.0', args='--cflags --libs') or not conf.is_defined('HAVE_DBUS_1'): | if not conf.check_cfg(package='dbus-1', atleast_version='1.0.0', args='--cflags --libs') or not conf.is_defined('HAVE_DBUS_1'): | ||||
print Logs.colors.RED + 'WARNING !! jackdbus will not be built because libdbus-dev is missing' + Logs.colors.NORMAL | |||||
print(Logs.colors.RED + 'WARNING !! jackdbus will not be built because libdbus-dev is missing' + Logs.colors.NORMAL) | |||||
return | return | ||||
dbus_dir = conf.check_cfg(package='dbus-1', args='--variable=session_bus_services_dir') | dbus_dir = conf.check_cfg(package='dbus-1', args='--variable=session_bus_services_dir') | ||||
if not dbus_dir: | if not dbus_dir: | ||||
print Logs.colors.RED + 'WARNING !! jackdbus will not be built because service dir is unknown' + Logs.colors.NORMAL | |||||
print(Logs.colors.RED + 'WARNING !! jackdbus will not be built because service dir is unknown' + Logs.colors.NORMAL) | |||||
return | return | ||||
dbus_dir = dbus_dir.strip() | dbus_dir = dbus_dir.strip() | ||||
@@ -29,20 +29,18 @@ def configure(conf): | |||||
else: | else: | ||||
conf.env['DBUS_SERVICES_DIR'] = os.path.normpath(conf.env['PREFIX'] + '/share/dbus-1/services') | conf.env['DBUS_SERVICES_DIR'] = os.path.normpath(conf.env['PREFIX'] + '/share/dbus-1/services') | ||||
conf.check_tool('misc') | |||||
conf.check(header_name='expat.h', define_name="HAVE_EXPAT") | conf.check(header_name='expat.h', define_name="HAVE_EXPAT") | ||||
if conf.is_defined('HAVE_EXPAT'): | if conf.is_defined('HAVE_EXPAT'): | ||||
conf.env['LIB_EXPAT'] = ['expat'] | conf.env['LIB_EXPAT'] = ['expat'] | ||||
else: | else: | ||||
print Logs.colors.RED + 'WARNING !! jackdbus will not be built because of expat is missing' + Logs.colors.NORMAL | |||||
print(Logs.colors.RED + 'WARNING !! jackdbus will not be built because of expat is missing' + Logs.colors.NORMAL) | |||||
return | return | ||||
conf.env['BUILD_JACKDBUS'] = True | conf.env['BUILD_JACKDBUS'] = True | ||||
def build(bld): | def build(bld): | ||||
obj = bld.new_task_gen('cc', 'program') | |||||
obj = bld(features = ['c', 'cprogram'], idx=17) | |||||
if bld.env['IS_LINUX']: | if bld.env['IS_LINUX']: | ||||
sysdeps_dbus_include = ['../linux', '../posix'] | sysdeps_dbus_include = ['../linux', '../posix'] | ||||
if bld.env['IS_MACOSX']: | if bld.env['IS_MACOSX']: | ||||
@@ -65,20 +63,19 @@ def build(bld): | |||||
#'xml_nop.c', | #'xml_nop.c', | ||||
'xml_write_raw.c', | 'xml_write_raw.c', | ||||
'sigsegv.c', | 'sigsegv.c', | ||||
'reserve.c', | |||||
'reserve.c', | |||||
] | ] | ||||
obj.use = ['serverlib'] | |||||
if bld.env['IS_LINUX']: | if bld.env['IS_LINUX']: | ||||
obj.uselib = 'PTHREAD DL RT DBUS-1 EXPAT' | |||||
obj.use += ['PTHREAD', 'DL', 'RT', 'DBUS-1', 'EXPAT'] | |||||
if bld.env['IS_MACOSX']: | if bld.env['IS_MACOSX']: | ||||
obj.uselib = 'PTHREAD DL DBUS-1 EXPAT' | |||||
obj.uselib_local = 'serverlib' | |||||
obj.target = 'jackdbus' | |||||
obj.use += ['PTHREAD', 'DL', 'DBUS-1', 'EXPAT'] | |||||
obj.target = 'jackdbus' | |||||
# process org.jackaudio.service.in -> org.jackaudio.service | # process org.jackaudio.service.in -> org.jackaudio.service | ||||
import misc | |||||
obj = bld.new_task_gen('subst') | |||||
obj.source = 'org.jackaudio.service.in' | |||||
obj.target = 'org.jackaudio.service' | |||||
obj.dict = {'BINDIR': bld.env['PREFIX'] + '/bin'} | |||||
obj.install_path = '${DBUS_SERVICES_DIR}/' | |||||
obj.fun = misc.subst_func | |||||
obj = bld( | |||||
features = 'subst', | |||||
source = 'org.jackaudio.service.in', | |||||
target = 'org.jackaudio.service', | |||||
install_path = '${DBUS_SERVICES_DIR}/', | |||||
BINDIR = bld.env['PREFIX'] + '/bin') |
@@ -31,7 +31,7 @@ PROJECT_NAME = "Jack2" | |||||
# This could be handy for archiving the generated documentation or | # This could be handy for archiving the generated documentation or | ||||
# if some version control system is used. | # if some version control system is used. | ||||
PROJECT_NUMBER = 1.9.8 | |||||
PROJECT_NUMBER = 1.9.9 | |||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) | # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) | ||||
# base path where the generated documentation will be put. | # base path where the generated documentation will be put. | ||||