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 | |||
| --------------------------- | |||
| 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> | |||
| * 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) | |||
| { | |||
| 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 | |||
| 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; | |||
| } | |||
| @@ -126,6 +128,9 @@ void JackAudioAdapter::FreePorts() | |||
| delete[] fCapturePortList; | |||
| delete[] fPlaybackPortList; | |||
| delete[] fInputBufferList; | |||
| delete[] fOutputBufferList; | |||
| } | |||
| void JackAudioAdapter::ConnectPorts() | |||
| @@ -164,6 +169,9 @@ int JackAudioAdapter::Open() | |||
| fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()]; | |||
| 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++) { | |||
| snprintf(name, sizeof(name), "capture_%d", i + 1); | |||
| 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** fPlaybackPortList; | |||
| jack_default_audio_sample_t** fInputBufferList; | |||
| jack_default_audio_sample_t** fOutputBufferList; | |||
| jack_client_t* fClient; | |||
| JackAudioAdapterInterface* fAudioAdapter; | |||
| bool fAutoConnect; | |||
| @@ -49,6 +52,7 @@ namespace Jack | |||
| void FreePorts(); | |||
| void ConnectPorts(); | |||
| void Reset(); | |||
| int ProcessAux(jack_nframes_t frames); | |||
| public: | |||
| @@ -26,6 +26,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackLibSampleRateResampler.h" | |||
| #endif | |||
| #include "JackTime.h" | |||
| #include "JackError.h" | |||
| #include <stdio.h> | |||
| namespace Jack | |||
| @@ -317,4 +318,75 @@ namespace Jack | |||
| 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 | |||
| @@ -154,75 +154,16 @@ namespace Jack | |||
| 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 GetOutputLatency(int port_index) { return 0; } | |||
| @@ -46,25 +46,20 @@ int JackAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | |||
| // Update engine and graph manager state | |||
| fEngineControl->fBufferSize = 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(); | |||
| // Redirect on slaves drivers... | |||
| // Redirected on slaves drivers... | |||
| return JackDriver::SetBufferSize(buffer_size); | |||
| } | |||
| int JackAudioDriver::SetSampleRate(jack_nframes_t 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); | |||
| } | |||
| @@ -35,6 +35,54 @@ class JackGraphManager; | |||
| 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. | |||
| */ | |||
| @@ -88,6 +88,19 @@ JackClient::JackClient(JackSynchro* table):fThread(this) | |||
| 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() | |||
| { | |||
| jack_log("JackClient::Close ref = %ld", GetClientControl()->fRefNum); | |||
| @@ -346,15 +359,18 @@ int JackClient::HandleLatencyCallback(int status) | |||
| if (port->GetFlags() & JackPortIsOutput) { | |||
| jack_latency_range_t other_latency; | |||
| port->GetLatencyRange(mode, &other_latency); | |||
| if (other_latency.max > latency.max) | |||
| if (other_latency.max > latency.max) { | |||
| latency.max = other_latency.max; | |||
| if (other_latency.min < latency.min) | |||
| } | |||
| if (other_latency.min < latency.min) { | |||
| latency.min = other_latency.min; | |||
| } | |||
| } | |||
| } | |||
| if (latency.min == UINT32_MAX) | |||
| if (latency.min == UINT32_MAX) { | |||
| latency.min = 0; | |||
| } | |||
| /* now set the found latency on all input ports | |||
| */ | |||
| @@ -373,15 +389,18 @@ int JackClient::HandleLatencyCallback(int status) | |||
| if (port->GetFlags() & JackPortIsInput) { | |||
| jack_latency_range_t other_latency; | |||
| port->GetLatencyRange(mode, &other_latency); | |||
| if (other_latency.max > latency.max) | |||
| if (other_latency.max > latency.max) { | |||
| latency.max = other_latency.max; | |||
| if (other_latency.min < latency.min) | |||
| } | |||
| if (other_latency.min < latency.min) { | |||
| latency.min = other_latency.min; | |||
| } | |||
| } | |||
| } | |||
| if (latency.min == UINT32_MAX) | |||
| if (latency.min == UINT32_MAX) { | |||
| latency.min = 0; | |||
| } | |||
| /* now set the found latency on all output ports | |||
| */ | |||
| @@ -409,13 +428,15 @@ connected to the client may not be activated. | |||
| int JackClient::Activate() | |||
| { | |||
| jack_log("JackClient::Activate"); | |||
| if (IsActive()) | |||
| if (IsActive()) { | |||
| return 0; | |||
| } | |||
| // RT thread is started only when needed... | |||
| if (IsRealTime()) { | |||
| if (StartThread() < 0) | |||
| if (StartThread() < 0) { | |||
| return -1; | |||
| } | |||
| } | |||
| /* | |||
| @@ -440,8 +461,9 @@ int JackClient::Activate() | |||
| int JackClient::Deactivate() | |||
| { | |||
| jack_log("JackClient::Deactivate"); | |||
| if (!IsActive()) | |||
| if (!IsActive()) { | |||
| return 0; | |||
| } | |||
| GetClientControl()->fActive = false; | |||
| @@ -455,8 +477,9 @@ int JackClient::Deactivate() | |||
| jack_log("JackClient::Deactivate res = %ld", result); | |||
| // RT thread is stopped only when needed... | |||
| if (IsRealTime()) | |||
| if (IsRealTime()) { | |||
| fThread.Kill(); | |||
| } | |||
| return result; | |||
| } | |||
| @@ -493,11 +516,13 @@ bool JackClient::Init() | |||
| InitAux(); | |||
| // 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(); | |||
| } | |||
| // Setup RT | |||
| if (GetEngineControl()->fRealTime) { | |||
| @@ -560,19 +585,22 @@ inline void JackClient::ExecuteThread() | |||
| inline jack_nframes_t JackClient::CycleWaitAux() | |||
| { | |||
| if (!WaitSync()) | |||
| if (!WaitSync()) { | |||
| Error(); // Terminates the thread | |||
| } | |||
| CallSyncCallbackAux(); | |||
| return GetEngineControl()->fBufferSize; | |||
| } | |||
| inline void JackClient::CycleSignalAux(int status) | |||
| { | |||
| if (status == 0) | |||
| if (status == 0) { | |||
| CallTimebaseCallbackAux(); | |||
| } | |||
| SignalSync(); | |||
| if (status != 0) | |||
| if (status != 0) { | |||
| End(); // Terminates the thread | |||
| } | |||
| } | |||
| jack_nframes_t JackClient::CycleWait() | |||
| @@ -747,27 +775,6 @@ int JackClient::ComputeTotalLatencies() | |||
| 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 | |||
| //---------------------- | |||
| @@ -780,8 +787,9 @@ inline int JackClient::ActivateAux() | |||
| jack_log("JackClient::ActivateAux"); | |||
| // RT thread is started | |||
| if (StartThread() < 0) | |||
| if (StartThread() < 0) { | |||
| return -1; | |||
| } | |||
| int result = -1; | |||
| GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime(); | |||
| @@ -1001,8 +1009,7 @@ int JackClient::SetInitCallback(JackThreadInitCallback callback, void *arg) | |||
| fInitArg = arg; | |||
| fInit = callback; | |||
| /* 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; | |||
| fSampleRate = callback; | |||
| // Now invoke it | |||
| if (callback) | |||
| if (callback) { | |||
| callback(GetEngineControl()->fSampleRate, arg); | |||
| } | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -1122,7 +1130,7 @@ int JackClient::SetProcessThread(JackThreadCallback fun, void *arg) | |||
| jack_error("You cannot set callbacks on an active client"); | |||
| return -1; | |||
| } 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; | |||
| } else { | |||
| fThreadFun = fun; | |||
| @@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| #include "JackSynchro.h" | |||
| #include "JackPlatformPlug.h" | |||
| #include "JackChannel.h" | |||
| #include "JackRequest.h" | |||
| #include "varargs.h" | |||
| #include <list> | |||
| @@ -86,7 +87,7 @@ class SERVER_EXPORT JackClient : public JackClientInterface, public JackRunnable | |||
| void* fThreadFunArg; | |||
| void* fSessionArg; | |||
| void* fLatencyArg; | |||
| char fServerName[64]; | |||
| char fServerName[JACK_SERVER_CONTROL_NAME_SIZE]; | |||
| JackThread fThread; /*! Thread to execute the Process function */ | |||
| detail::JackClientChannelInterface* fChannel; | |||
| @@ -13,7 +13,7 @@ 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 | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| @@ -36,12 +36,12 @@ class SERVER_EXPORT JackClientInterface | |||
| { | |||
| public: | |||
| JackClientInterface() | |||
| {} | |||
| virtual ~JackClientInterface() | |||
| {} | |||
| virtual int Close() = 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" | |||
| #endif | |||
| #define VERSION "1.9.8" | |||
| #define VERSION "1.9.9" | |||
| #define BUFFER_SIZE_MAX 8192 | |||
| @@ -71,7 +71,7 @@ | |||
| #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 FREEWHEEL_DRIVER_TIMEOUT 10 // in sec | |||
| #define DRIVER_TIMEOUT_FACTOR 10 | |||
| @@ -237,7 +237,7 @@ jackctl_add_driver_parameters( | |||
| jackctl_value.b = descriptor_ptr->value.i; | |||
| break; | |||
| 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); | |||
| goto fail; | |||
| } | |||
| @@ -330,7 +330,7 @@ jackctl_create_param_list( | |||
| retparam_ptr->value.i = param_ptr->value_ptr->b; | |||
| break; | |||
| default: | |||
| jack_error("unknown parameter type %i", (int)param_ptr->type); | |||
| jack_error("Unknown parameter type %i", (int)param_ptr->type); | |||
| assert(0); | |||
| goto free; | |||
| } | |||
| @@ -361,7 +361,7 @@ jackctl_drivers_load( | |||
| descriptor_node_ptr = jack_drivers_load(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; | |||
| } | |||
| @@ -370,7 +370,7 @@ jackctl_drivers_load( | |||
| driver_ptr = (struct jackctl_driver *)malloc(sizeof(struct jackctl_driver)); | |||
| if (driver_ptr == NULL) | |||
| { | |||
| jack_error("memory allocation of jackctl_driver structure failed."); | |||
| jack_error("Memory allocation of jackctl_driver structure failed."); | |||
| goto next; | |||
| } | |||
| @@ -430,7 +430,7 @@ jackctl_internals_load( | |||
| descriptor_node_ptr = jack_internals_load(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; | |||
| } | |||
| @@ -439,7 +439,7 @@ jackctl_internals_load( | |||
| internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal)); | |||
| if (internal_ptr == NULL) | |||
| { | |||
| jack_error("memory allocation of jackctl_driver structure failed."); | |||
| jack_error("Memory allocation of jackctl_driver structure failed."); | |||
| goto next; | |||
| } | |||
| @@ -506,57 +506,68 @@ jackctl_server_free_parameters( | |||
| #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); | |||
| SetEvent(waitEvent); | |||
| SetEvent(sigmask.wait_event); | |||
| } | |||
| sigset_t | |||
| jackctl_sigmask_t * | |||
| jackctl_setup_signals( | |||
| 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()); | |||
| 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()); | |||
| } | |||
| } | |||
| #else | |||
| struct jackctl_sigmask | |||
| { | |||
| sigset_t signals; | |||
| }; | |||
| static jackctl_sigmask sigmask; | |||
| static | |||
| void | |||
| do_nothing_handler(int sig) | |||
| signal_handler(int sig) | |||
| { | |||
| /* this is used by the child (active) process, but it never | |||
| gets called unless we are already shutting down after | |||
| another signal. | |||
| */ | |||
| 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( | |||
| unsigned int flags) | |||
| { | |||
| sigset_t signals; | |||
| sigset_t allsignals; | |||
| struct sigaction action; | |||
| int i; | |||
| @@ -595,54 +606,54 @@ jackctl_setup_signals( | |||
| 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 | |||
| * explicitly reset it | |||
| */ | |||
| pthread_sigmask(SIG_BLOCK, &signals, 0); | |||
| pthread_sigmask(SIG_BLOCK, &sigmask.signals, 0); | |||
| /* install a do-nothing handler because otherwise pthreads | |||
| behaviour is undefined when we enter sigwait. | |||
| */ | |||
| sigfillset(&allsignals); | |||
| action.sa_handler = do_nothing_handler; | |||
| action.sa_handler = signal_handler; | |||
| action.sa_mask = allsignals; | |||
| action.sa_flags = SA_RESTART|SA_RESETHAND; | |||
| for (i = 1; i < NSIG; i++) | |||
| { | |||
| if (sigismember (&signals, i)) | |||
| if (sigismember (&sigmask.signals, i)) | |||
| { | |||
| sigaction(i, &action, 0); | |||
| } | |||
| } | |||
| return signals; | |||
| return &sigmask; | |||
| } | |||
| SERVER_EXPORT void | |||
| jackctl_wait_signals(sigset_t signals) | |||
| jackctl_wait_signals(jackctl_sigmask_t * sigmask) | |||
| { | |||
| int sig; | |||
| bool waiting = true; | |||
| while (waiting) { | |||
| #if defined(sun) && !defined(__sun__) // SUN compiler only, to check | |||
| sigwait(&signals); | |||
| sigwait(&sigmask->signals); | |||
| #else | |||
| sigwait(&signals, &sig); | |||
| sigwait(&sigmask->signals, &sig); | |||
| #endif | |||
| fprintf(stderr, "jack main caught signal %d\n", sig); | |||
| fprintf(stderr, "Jack main caught signal %d\n", sig); | |||
| switch (sig) { | |||
| case SIGUSR1: | |||
| @@ -664,7 +675,7 @@ jackctl_wait_signals(sigset_t signals) | |||
| // unblock signals so we can see them during shutdown. | |||
| // this will help prod developers not to lose sight of | |||
| // bugs that cause segfaults etc. during shutdown. | |||
| sigprocmask(SIG_UNBLOCK, &signals, 0); | |||
| sigprocmask(SIG_UNBLOCK, &sigmask->signals, 0); | |||
| } | |||
| } | |||
| #endif | |||
| @@ -911,15 +922,15 @@ SERVER_EXPORT bool jackctl_server_close(jackctl_server *server_ptr) | |||
| delete server_ptr->engine; | |||
| /* 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_log("cleaning up files"); | |||
| jack_log("Cleaning up files"); | |||
| 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); | |||
| @@ -956,14 +967,14 @@ jackctl_server_open( | |||
| jack_error("`%s' server already active", server_ptr->name.str); | |||
| goto fail; | |||
| case ENOSPC: | |||
| jack_error("too many servers already active"); | |||
| jack_error("Too many servers already active"); | |||
| goto fail; | |||
| case ENOMEM: | |||
| jack_error("no access to shm registry"); | |||
| jack_error("No access to shm registry"); | |||
| 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 | |||
| * instance of this server name */ | |||
| @@ -976,7 +987,7 @@ jackctl_server_open( | |||
| /* check port max value before allocating server */ | |||
| 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; | |||
| } | |||
| @@ -1003,7 +1014,7 @@ jackctl_server_open( | |||
| jackctl_destroy_param_list(paramlist); | |||
| if (rc < 0) | |||
| { | |||
| jack_error("JackServer::Open() failed with %d", rc); | |||
| jack_error("JackServer::Open failed with %d", rc); | |||
| goto fail_delete; | |||
| } | |||
| @@ -1019,15 +1030,15 @@ fail_delete: | |||
| server_ptr->engine = NULL; | |||
| fail_unregister: | |||
| jack_log("cleaning up shared memory"); | |||
| jack_log("Cleaning up shared memory"); | |||
| jack_cleanup_shm(); | |||
| jack_log("cleaning up files"); | |||
| jack_log("Cleaning up files"); | |||
| 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); | |||
| @@ -1138,7 +1149,7 @@ SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constrain | |||
| strcpy(jackctl_value.str, value_ptr->str); | |||
| break; | |||
| 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); | |||
| } | |||
| @@ -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; | |||
| return; | |||
| 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); | |||
| } | |||
| } | |||
| @@ -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->engine->IsRunning()) { | |||
| jack_error("cannot add a slave in a running server"); | |||
| jack_error("Cannot add a slave in a running server"); | |||
| return false; | |||
| } else { | |||
| 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->engine->IsRunning()) { | |||
| jack_error("cannot remove a slave from a running server"); | |||
| jack_error("Cannot remove a slave from a running server"); | |||
| return false; | |||
| } else { | |||
| if (driver_ptr->infos) { | |||
| @@ -25,15 +25,6 @@ | |||
| #include "jslist.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 */ | |||
| typedef enum | |||
| { | |||
| @@ -80,6 +71,9 @@ typedef struct jackctl_internal jackctl_internal_t; | |||
| /** opaque type for parameter object */ | |||
| typedef struct jackctl_parameter jackctl_parameter_t; | |||
| /** opaque type for sigmask object */ | |||
| typedef struct jackctl_sigmask jackctl_sigmask_t; | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| @@ -87,13 +81,13 @@ extern "C" { | |||
| } /* Adjust editor indent */ | |||
| #endif | |||
| SERVER_EXPORT sigset_t | |||
| SERVER_EXPORT jackctl_sigmask_t * | |||
| jackctl_setup_signals( | |||
| unsigned int flags); | |||
| SERVER_EXPORT void | |||
| jackctl_wait_signals( | |||
| sigset_t signals); | |||
| jackctl_sigmask_t * signals); | |||
| SERVER_EXPORT jackctl_server_t * | |||
| jackctl_server_create( | |||
| @@ -252,6 +246,9 @@ SERVER_EXPORT bool | |||
| jackctl_server_switch_master(jackctl_server_t * server, | |||
| jackctl_driver_t * driver); | |||
| SERVER_EXPORT int | |||
| jackctl_parse_driver_params(jackctl_driver * driver_ptr, int argc, char* argv[]); | |||
| #if 0 | |||
| { /* Adjust editor indent */ | |||
| #endif | |||
| @@ -115,7 +115,11 @@ int JackDebugClient::Close() | |||
| 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; | |||
| #endif | |||
| if (fIsClosed > 0) { | |||
| *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"); | |||
| 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 i; | |||
| 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].IsUnregistered != 0) | |||
| *fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl; | |||
| *fStream << "!!! ERROR !!! : Disconnecting port " << src << " previoulsy unregistered !" << endl; | |||
| fPortList[i].IsConnected--; | |||
| *fStream << "Disconnecting port " << src << ". " << endl; | |||
| break; | |||
| @@ -313,9 +317,17 @@ int JackDebugClient::PortDisconnect(jack_port_id_t src) | |||
| int JackDebugClient::PortIsMine(jack_port_id_t port_index) | |||
| { | |||
| CheckClient("PortIsMine"); | |||
| *fStream << "JackClientDebug : PortIsMine port_index " << port_index << endl; | |||
| 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 | |||
| //-------------------- | |||
| @@ -323,6 +335,7 @@ int JackDebugClient::PortIsMine(jack_port_id_t port_index) | |||
| int JackDebugClient::SetBufferSize(jack_nframes_t buffer_size) | |||
| { | |||
| CheckClient("SetBufferSize"); | |||
| *fStream << "JackClientDebug : SetBufferSize buffer_size " << buffer_size << endl; | |||
| return fClient->SetBufferSize(buffer_size); | |||
| } | |||
| @@ -330,13 +343,19 @@ int JackDebugClient::SetFreeWheel(int onoff) | |||
| { | |||
| CheckClient("SetFreeWheel"); | |||
| 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) | |||
| *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; | |||
| return fClient->SetFreeWheel(onoff); | |||
| } | |||
| int JackDebugClient::ComputeTotalLatencies() | |||
| { | |||
| CheckClient("ComputeTotalLatencies"); | |||
| return fClient->ComputeTotalLatencies(); | |||
| } | |||
| /* | |||
| ShutDown is called: | |||
| - from the RT thread when Execute method fails | |||
| @@ -346,6 +365,7 @@ ShutDown is called: | |||
| void JackDebugClient::ShutDown() | |||
| { | |||
| CheckClient("ShutDown"); | |||
| fClient->ShutDown(); | |||
| } | |||
| @@ -368,6 +388,7 @@ int JackDebugClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg) | |||
| int JackDebugClient::SetSyncTimeout(jack_time_t timeout) | |||
| { | |||
| CheckClient("SetSyncTimeout"); | |||
| *fStream << "JackClientDebug : SetSyncTimeout timeout " << timeout << endl; | |||
| return fClient->SetSyncTimeout(timeout); | |||
| } | |||
| @@ -380,6 +401,7 @@ int JackDebugClient::SetTimebaseCallback(int conditional, JackTimebaseCallback t | |||
| void JackDebugClient::TransportLocate(jack_nframes_t frame) | |||
| { | |||
| CheckClient("TransportLocate"); | |||
| *fStream << "JackClientDebug : TransportLocate frame " << frame << endl; | |||
| fClient->TransportLocate(frame); | |||
| } | |||
| @@ -435,10 +457,11 @@ int JackDebugClient::TimeCallback(jack_nframes_t nframes, void *arg) | |||
| jack_time_t t1 = GetMicroSeconds(); | |||
| int res = client->fProcessTimeCallback(nframes, client->fProcessTimeCallbackArg); | |||
| if (res == 0) { | |||
| jack_time_t t2 = GetMicroSeconds(); | |||
| jack_time_t t2 = GetMicroSeconds(); | |||
| 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; | |||
| } | |||
| } | |||
| return res; | |||
| } | |||
| @@ -446,9 +469,17 @@ int JackDebugClient::TimeCallback(jack_nframes_t nframes, void *arg) | |||
| int JackDebugClient::SetProcessCallback(JackProcessCallback callback, void *arg) | |||
| { | |||
| CheckClient("SetProcessCallback"); | |||
| fProcessTimeCallback = callback; | |||
| 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) | |||
| @@ -517,9 +548,16 @@ int JackDebugClient::SetLatencyCallback(JackLatencyCallback callback, void *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) | |||
| { | |||
| CheckClient("SessionNotify"); | |||
| *fStream << "JackClientDebug : SessionNotify target " << target << "type " << type << "path " << path << endl; | |||
| 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) | |||
| { | |||
| CheckClient("GetUUIDForClientName"); | |||
| *fStream << "JackClientDebug : GetUUIDForClientName client_name " << client_name << endl; | |||
| return fClient->GetUUIDForClientName(client_name); | |||
| } | |||
| char* JackDebugClient::GetClientNameByUUID(const char* uuid) | |||
| { | |||
| CheckClient("GetClientNameByUUID"); | |||
| *fStream << "JackClientDebug : GetClientNameByUUID uuid " << uuid << endl; | |||
| return fClient->GetClientNameByUUID(uuid); | |||
| } | |||
| int JackDebugClient::ReserveClientName(const char* client_name, const char* uuid) | |||
| { | |||
| CheckClient("ReserveClientName"); | |||
| *fStream << "JackClientDebug : ReserveClientName client_name " << client_name << "uuid " << uuid << endl; | |||
| return fClient->ReserveClientName(client_name, uuid); | |||
| } | |||
| int JackDebugClient::ClientHasSessionCallback(const char* client_name) | |||
| { | |||
| CheckClient("ClientHasSessionCallback"); | |||
| *fStream << "JackClientDebug : ClientHasSessionCallback client_name " << client_name << endl; | |||
| return fClient->ClientHasSessionCallback(client_name); | |||
| } | |||
| @@ -46,7 +46,7 @@ PortFollower; | |||
| \brief A "decorator" debug client to validate API use. | |||
| */ | |||
| class LIB_EXPORT JackDebugClient : public JackClient | |||
| class JackDebugClient : public JackClient | |||
| { | |||
| protected: | |||
| @@ -83,6 +83,7 @@ class LIB_EXPORT JackDebugClient : public JackClient | |||
| // Context | |||
| int SetBufferSize(jack_nframes_t buffer_size); | |||
| int SetFreeWheel(int onoff); | |||
| int ComputeTotalLatencies(); | |||
| void ShutDown(); | |||
| jack_native_thread_t GetThreadID(); | |||
| @@ -95,6 +96,7 @@ class LIB_EXPORT JackDebugClient : public JackClient | |||
| int PortDisconnect(jack_port_id_t src); | |||
| int PortIsMine(jack_port_id_t port_index); | |||
| int PortRename(jack_port_id_t port_index, const char* name); | |||
| // Transport | |||
| int ReleaseTimebase(); | |||
| @@ -129,6 +131,9 @@ class LIB_EXPORT JackDebugClient : public JackClient | |||
| 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); | |||
| void InternalClientUnload(int ref, jack_status_t* status); | |||
| // RT Thread | |||
| int SetProcessThread(JackThreadCallback fun, void *arg); | |||
| // Session API | |||
| 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(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 | |||
| SetupDriverSync(fClientControl.fRefNum, false); | |||
| @@ -183,10 +180,7 @@ int JackDriver::Open(jack_nframes_t buffer_size, | |||
| strcpy(fCaptureDriverName, capture_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->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])); | |||
| 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]); | |||
| } | |||
| free(connections); | |||
| @@ -510,7 +504,7 @@ void JackDriver::SaveConnections() | |||
| fConnections.push_back(make_pair(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()); | |||
| } | |||
| free(connections); | |||
| @@ -176,7 +176,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||
| void CycleTakeEndTime(); | |||
| void SetupDriverSync(int ref, bool freewheel); | |||
| 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 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 "JackDriverLoader.h" | |||
| #include "JackDriverInfo.h" | |||
| #include "JackConstants.h" | |||
| #include "JackError.h" | |||
| #include <getopt.h> | |||
| @@ -31,9 +32,57 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include <dirent.h> | |||
| #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); | |||
| 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; | |||
| 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", | |||
| desc->params[param].name, desc->name); | |||
| 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*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; | |||
| 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], | |||
| desc->name); | |||
| } | |||
| @@ -218,8 +265,7 @@ jack_parse_driver_params(jack_driver_desc_t* desc, int argc, char* argv[], JSLis | |||
| 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; | |||
| 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], | |||
| desc->name); | |||
| } | |||
| @@ -352,8 +398,7 @@ jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[]) | |||
| return 0; | |||
| } | |||
| jack_driver_desc_t* | |||
| jack_find_driver_descriptor (JSList * drivers, const char* name) | |||
| jack_driver_desc_t* jack_find_driver_descriptor (JSList * drivers, const char* name) | |||
| { | |||
| jack_driver_desc_t* desc = 0; | |||
| JSList* node; | |||
| @@ -371,193 +416,87 @@ jack_find_driver_descriptor (JSList * drivers, const char* name) | |||
| 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 | |||
| int dlerr; | |||
| jack_error ("Could not open component .dll '%s': %ld", filename, GetLastError()); | |||
| #else | |||
| const char* dlerr; | |||
| jack_error ("Could not open component .so '%s': %s", filename, dlerror()); | |||
| #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 { | |||
| 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) { | |||
| 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 */ | |||
| for (node = drivers; node; node = jack_slist_next (node)) { | |||
| other_descriptor = (jack_driver_desc_t*) node->data; | |||
| 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); | |||
| /* FIXME: delete the descriptor */ | |||
| free(filename); | |||
| return NULL; | |||
| goto error; | |||
| } | |||
| } | |||
| 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 | |||
| 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; | |||
| HANDLE file; | |||
| const char* ptr = NULL; | |||
| JSList* driver_list = 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 { | |||
| @@ -570,17 +509,18 @@ jack_drivers_load (JSList * drivers) { | |||
| if (!ptr) { | |||
| continue; | |||
| } | |||
| ptr++; | |||
| if (strncmp ("dll", ptr, 3) != 0) { | |||
| continue; | |||
| } | |||
| /* 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) { | |||
| driver_list = jack_slist_append (driver_list, desc); | |||
| } else { | |||
| @@ -590,17 +530,21 @@ jack_drivers_load (JSList * drivers) { | |||
| } while (FindNextFile(file, &filedata)); | |||
| 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; | |||
| } | |||
| #else | |||
| JSList * | |||
| jack_drivers_load (JSList * drivers) { | |||
| JSList* jack_drivers_load (JSList * drivers) | |||
| { | |||
| struct dirent * dir_entry; | |||
| DIR * dir_stream; | |||
| const char* ptr; | |||
| @@ -617,7 +561,7 @@ jack_drivers_load (JSList * drivers) { | |||
| from the .so files in it */ | |||
| dir_stream = opendir (driver_dir); | |||
| 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)); | |||
| return NULL; | |||
| } | |||
| @@ -639,11 +583,11 @@ jack_drivers_load (JSList * drivers) { | |||
| } | |||
| /* 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) { | |||
| driver_list = jack_slist_append (driver_list, desc); | |||
| } else { | |||
| @@ -653,12 +597,12 @@ jack_drivers_load (JSList * drivers) { | |||
| err = closedir (dir_stream); | |||
| if (err) { | |||
| jack_error ("error closing driver directory %s: %s", | |||
| jack_error ("Error closing driver directory %s: %s", | |||
| driver_dir, strerror (errno)); | |||
| } | |||
| 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; | |||
| } | |||
| @@ -669,40 +613,19 @@ jack_drivers_load (JSList * drivers) { | |||
| #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; | |||
| HANDLE file; | |||
| const char* ptr = NULL; | |||
| JSList* driver_list = NULL; | |||
| 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 { | |||
| @@ -711,17 +634,18 @@ jack_internals_load (JSList * internals) { | |||
| if (!ptr) { | |||
| continue; | |||
| } | |||
| ptr++; | |||
| if (strncmp ("dll", ptr, 3) != 0) { | |||
| continue; | |||
| } | |||
| /* 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) { | |||
| driver_list = jack_slist_append (driver_list, desc); | |||
| } else { | |||
| @@ -731,17 +655,21 @@ jack_internals_load (JSList * internals) { | |||
| } while (FindNextFile(file, &filedata)); | |||
| 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; | |||
| } | |||
| #else | |||
| JSList * | |||
| jack_internals_load (JSList * internals) { | |||
| JSList* jack_internals_load(JSList * internals) | |||
| { | |||
| struct dirent * dir_entry; | |||
| DIR * dir_stream; | |||
| const char* ptr; | |||
| @@ -758,7 +686,7 @@ jack_internals_load (JSList * internals) { | |||
| from the .so files in it */ | |||
| dir_stream = opendir (driver_dir); | |||
| 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)); | |||
| return NULL; | |||
| } | |||
| @@ -769,17 +697,18 @@ jack_internals_load (JSList * internals) { | |||
| if (!ptr) { | |||
| continue; | |||
| } | |||
| ptr++; | |||
| if (strncmp ("so", ptr, 2) != 0) { | |||
| continue; | |||
| } | |||
| /* 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) { | |||
| driver_list = jack_slist_append (driver_list, desc); | |||
| } else { | |||
| @@ -789,12 +718,12 @@ jack_internals_load (JSList * internals) { | |||
| err = closedir (dir_stream); | |||
| if (err) { | |||
| jack_error ("error closing internal directory %s: %s\n", | |||
| jack_error ("Error closing internal directory %s: %s\n", | |||
| driver_dir, strerror (errno)); | |||
| } | |||
| 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; | |||
| } | |||
| @@ -819,14 +748,14 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||
| if (fHandle == NULL) { | |||
| #ifdef WIN32 | |||
| 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 | |||
| 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 | |||
| } 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; | |||
| } | |||
| @@ -838,7 +767,7 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||
| #else | |||
| if ((fInitialize == NULL) && (errstr = dlerror ()) != 0) { | |||
| #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; | |||
| } | |||
| @@ -849,13 +778,12 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||
| JackDriverInfo::~JackDriverInfo() | |||
| { | |||
| delete fBackend; | |||
| if (fHandle) | |||
| if (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, | |||
| jack_driver_type_t type, | |||
| const char * description, | |||
| @@ -876,7 +804,7 @@ jack_driver_descriptor_construct( | |||
| desc_ptr = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t)); | |||
| 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; | |||
| } | |||
| @@ -893,9 +821,7 @@ jack_driver_descriptor_construct( | |||
| 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_filler_t * filler_ptr, | |||
| const char* name, | |||
| @@ -933,7 +859,7 @@ jack_driver_descriptor_add_parameter( | |||
| 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)); | |||
| 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; | |||
| } | |||
| filler_ptr->size = newsize; | |||
| @@ -952,6 +878,5 @@ jack_driver_descriptor_add_parameter( | |||
| memcpy(param_ptr->long_desc, long_desc, long_desc_len + 1); | |||
| desc_ptr->nparams++; | |||
| return true; | |||
| } | |||
| @@ -24,53 +24,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "driver_interface.h" | |||
| #include "JackControlAPI.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); | |||
| JSList* jack_drivers_load(JSList* drivers); | |||
| 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 | |||
| @@ -38,13 +38,16 @@ namespace Jack | |||
| JackEngine::JackEngine(JackGraphManager* manager, | |||
| JackSynchro* table, | |||
| JackEngineControl* control) | |||
| JackEngineControl* control) | |||
| : JackLockAble(control->fServerName), | |||
| fSignal(control->fServerName) | |||
| { | |||
| fGraphManager = manager; | |||
| fSynchroTable = table; | |||
| fEngineControl = control; | |||
| for (int i = 0; i < CLIENT_NUM; i++) | |||
| for (int i = 0; i < CLIENT_NUM; i++) { | |||
| fClientTable[i] = NULL; | |||
| } | |||
| fLastSwitchUsecs = 0; | |||
| fMaxUUID = 0; | |||
| fSessionPendingReplies = 0; | |||
| @@ -78,20 +81,33 @@ int JackEngine::Close() | |||
| if (JackLoadableInternalClient* loadable_client = dynamic_cast<JackLoadableInternalClient*>(fClientTable[i])) { | |||
| jack_log("JackEngine::Close loadable client = %s", loadable_client->GetClientControl()->fName); | |||
| loadable_client->Close(); | |||
| // Close does not delete the pointer for internal clients | |||
| fClientTable[i] = NULL; | |||
| delete loadable_client; | |||
| } else if (JackExternalClient* external_client = dynamic_cast<JackExternalClient*>(fClientTable[i])) { | |||
| jack_log("JackEngine::Close external client = %s", external_client->GetClientControl()->fName); | |||
| external_client->Close(); | |||
| // Close deletes the pointer for external clients | |||
| fClientTable[i] = NULL; | |||
| delete external_client; | |||
| } | |||
| } | |||
| 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() | |||
| { | |||
| fChannel.NotifyQuit(); | |||
| @@ -119,8 +135,9 @@ void JackEngine::ReleaseRefnum(int ref) | |||
| if (fEngineControl->fTemporary) { | |||
| int i; | |||
| for (i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) { | |||
| if (fClientTable[i]) | |||
| if (fClientTable[i]) { | |||
| break; | |||
| } | |||
| } | |||
| if (i == CLIENT_NUM) { | |||
| // 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) | |||
| { | |||
| 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); | |||
| } | |||
| fGraphManager->RunCurrentGraph(); | |||
| } | |||
| @@ -157,7 +175,7 @@ bool JackEngine::Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end | |||
| // Cycle begin | |||
| fEngineControl->CycleBegin(fClientTable, fGraphManager, cur_cycle_begin, prev_cycle_end); | |||
| // Graph | |||
| if (fGraphManager->IsFinishedGraph()) { | |||
| ProcessNext(cur_cycle_begin); | |||
| @@ -236,26 +254,42 @@ int JackEngine::ComputeTotalLatencies() | |||
| // 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) | |||
| { | |||
| JackClientInterface* client = fClientTable[refnum]; | |||
| // The client may be notified by the RT thread while closing | |||
| 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. | |||
| for (int i = 0; i < CLIENT_NUM; i++) { | |||
| JackClientInterface* old_client = fClientTable[i]; | |||
| 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... | |||
| } | |||
| 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; | |||
| } | |||
| } | |||
| @@ -291,10 +327,7 @@ void JackEngine::NotifyRemoveClient(const char* name, int refnum) | |||
| { | |||
| // Notify existing clients (including the one beeing suppressed) of the removed client | |||
| 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++) { | |||
| JackClientInterface* client = fClientTable[i]; | |||
| if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) | |||
| if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) { | |||
| return true; | |||
| } | |||
| } | |||
| 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 false; | |||
| @@ -510,8 +545,9 @@ int JackEngine::GetNewUUID() | |||
| 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++) { | |||
| JackClientInterface* client = fClientTable[i]; | |||
| @@ -525,8 +561,9 @@ int JackEngine::GetClientPID(const char* name) | |||
| { | |||
| for (int i = 0; i < CLIENT_NUM; 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 0; | |||
| @@ -536,8 +573,9 @@ int JackEngine::GetClientRefNum(const char* name) | |||
| { | |||
| for (int i = 0; i < CLIENT_NUM; 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 -1; | |||
| @@ -657,9 +695,9 @@ error: | |||
| // Used for external clients | |||
| int JackEngine::ClientExternalClose(int refnum) | |||
| { | |||
| jack_log("JackEngine::ClientExternalClose ref = %ld", refnum); | |||
| JackClientInterface* client = fClientTable[refnum]; | |||
| fEngineControl->fTransport.ResetTimebase(refnum); | |||
| int res = ClientCloseAux(refnum, client, true); | |||
| int res = ClientCloseAux(refnum, true); | |||
| client->Close(); | |||
| delete client; | |||
| return res; | |||
| @@ -668,13 +706,16 @@ int JackEngine::ClientExternalClose(int refnum) | |||
| // Used for server internal clients or drivers when the RT thread is stopped | |||
| 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); | |||
| JackClientInterface* client = fClientTable[refnum]; | |||
| fEngineControl->fTransport.ResetTimebase(refnum); | |||
| // Unregister all ports ==> notifications are sent | |||
| 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]; | |||
| jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName); | |||
| if (is_real_time) | |||
| if (is_real_time) { | |||
| fGraphManager->Activate(refnum); | |||
| } | |||
| // Wait for graph state change to be effective | |||
| 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... | |||
| *port_index = fGraphManager->AllocatePort(refnum, name, type, (JackPortFlags)flags, fEngineControl->fBufferSize); | |||
| if (*port_index != NO_PORT) { | |||
| if (client->GetClientControl()->fActive) | |||
| if (client->GetClientControl()->fActive) { | |||
| NotifyPortRegistation(*port_index, true); | |||
| } | |||
| return 0; | |||
| } else { | |||
| return -1; | |||
| @@ -819,8 +862,9 @@ int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index) | |||
| PortDisconnect(refnum, port_index, ALL_PORTS); | |||
| if (fGraphManager->ReleasePort(refnum, port_index) == 0) { | |||
| if (client->GetClientControl()->fActive) | |||
| if (client->GetClientControl()->fActive) { | |||
| NotifyPortRegistation(port_index, false); | |||
| } | |||
| return 0; | |||
| } else { | |||
| return -1; | |||
| @@ -843,8 +887,9 @@ int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst) | |||
| JackClientInterface* client; | |||
| int ref; | |||
| if (fGraphManager->CheckPorts(src, dst) < 0) | |||
| if (fGraphManager->CheckPorts(src, dst) < 0) { | |||
| return -1; | |||
| } | |||
| ref = fGraphManager->GetOutputRefNum(src); | |||
| 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); | |||
| if (res == 0) | |||
| if (res == 0) { | |||
| NotifyPortConnect(src, dst, true); | |||
| } | |||
| return res; | |||
| } | |||
| @@ -932,7 +978,7 @@ int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name) | |||
| // 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) { | |||
| 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); | |||
| int res = JackTools::MkDir(path_buf); | |||
| if (res) | |||
| if (res) { | |||
| 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); | |||
| @@ -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]; | |||
| char uuid_buf[JACK_UUID_SIZE]; | |||
| @@ -1013,78 +1060,78 @@ void JackEngine::SessionReply(int refnum) | |||
| if (fSessionPendingReplies == 0) { | |||
| fSessionResult->Write(fSessionTransaction); | |||
| if (fSessionTransaction != NULL) | |||
| { | |||
| if (fSessionTransaction != NULL) { | |||
| delete fSessionResult; | |||
| } | |||
| 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++) { | |||
| JackClientInterface* client = fClientTable[i]; | |||
| if (client && (strcmp(client_name, client->GetClientControl()->fName) == 0)) { | |||
| snprintf(uuid_res, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); | |||
| *result = 0; | |||
| return; | |||
| return 0; | |||
| } | |||
| } | |||
| // 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++) { | |||
| JackClientInterface* client = fClientTable[i]; | |||
| if (!client) | |||
| if (!client) { | |||
| continue; | |||
| } | |||
| char uuid_buf[JACK_UUID_SIZE]; | |||
| snprintf(uuid_buf, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); | |||
| if (strcmp(uuid,uuid_buf) == 0) { | |||
| strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE); | |||
| *result = 0; | |||
| return; | |||
| return 0; | |||
| } | |||
| } | |||
| // 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); | |||
| if (ClientCheckName(name)) { | |||
| *result = -1; | |||
| jack_log("name already taken"); | |||
| return; | |||
| return -1; | |||
| } | |||
| EnsureUUID(atoi(uuid)); | |||
| 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; | |||
| for (int i = 0; i < CLIENT_NUM; i++) { | |||
| client = fClientTable[i]; | |||
| if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) | |||
| if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) { | |||
| break; | |||
| } | |||
| } | |||
| if (client) { | |||
| *result = client->GetClientControl()->fCallback[kSessionCallback]; | |||
| return client->GetClientControl()->fCallback[kSessionCallback]; | |||
| } else { | |||
| *result = -1; | |||
| return -1; | |||
| } | |||
| } | |||
| @@ -26,6 +26,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackMutex.h" | |||
| #include "JackTransportEngine.h" | |||
| #include "JackPlatformPlug.h" | |||
| #include "JackRequest.h" | |||
| #include "JackChannel.h" | |||
| #include <map> | |||
| namespace Jack | |||
| @@ -54,15 +56,15 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||
| jack_time_t fLastSwitchUsecs; | |||
| int fSessionPendingReplies; | |||
| JackChannelTransaction* fSessionTransaction; | |||
| detail::JackChannelTransactionInterface* fSessionTransaction; | |||
| JackSessionNotifyResult* fSessionResult; | |||
| std::map<int,std::string> fReservationMap; | |||
| int fMaxUUID; | |||
| int ClientCloseAux(int refnum, JackClientInterface* client, bool wait); | |||
| int ClientCloseAux(int refnum, bool wait); | |||
| 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 ProcessNext(jack_time_t callback_usecs); | |||
| @@ -74,6 +76,8 @@ class SERVER_EXPORT JackEngine : public JackLockAble | |||
| int AllocateRefnum(); | |||
| 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 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 Close(); | |||
| void ShutDown(); | |||
| // Client management | |||
| 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(); | |||
| // 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) | |||
| { | |||
| ResetFrameTime(callback_usecs); | |||
| ResetFrameTime(callback_usecs); | |||
| fXrunDelayedUsecs = delayed_usecs; | |||
| if (delayed_usecs > fMaxDelayedUsecs) | |||
| if (delayed_usecs > fMaxDelayedUsecs) { | |||
| fMaxDelayedUsecs = delayed_usecs; | |||
| } | |||
| } | |||
| } // end of namespace | |||
| @@ -124,6 +124,14 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem | |||
| ~JackEngineControl() | |||
| {} | |||
| void UpdateTimeOut() | |||
| { | |||
| fPeriodUsecs = jack_time_t(1000000.f / fSampleRate * fBufferSize); // In microsec | |||
| if (!(fTimeOut && fTimeOutUsecs > 2 * fPeriodUsecs)) { | |||
| fTimeOutUsecs = 2 * fPeriodUsecs; | |||
| } | |||
| } | |||
| // Cycle | |||
| void CycleIncTime(jack_time_t callback_usecs) | |||
| @@ -154,7 +162,7 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem | |||
| void ResetFrameTime(jack_time_t callback_usecs) | |||
| { | |||
| fFrameTimer.ResetFrameTime(fSampleRate, callback_usecs, fPeriodUsecs); | |||
| fFrameTimer.ResetFrameTime(callback_usecs); | |||
| } | |||
| void ReadFrameTime(JackTimer* timer) | |||
| @@ -2,21 +2,21 @@ | |||
| Copyright (C) 2001 Paul Davis | |||
| Copyright (C) 2004-2008 Grame | |||
| Copyright (C) 2008 Nedko Arnaudov | |||
| 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 <stdarg.h> | |||
| @@ -29,7 +29,7 @@ using namespace Jack; | |||
| 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)); | |||
| } | |||
| @@ -31,14 +31,8 @@ extern "C" | |||
| { | |||
| #endif | |||
| #define LOG_LEVEL_INFO 1 | |||
| #define LOG_LEVEL_ERROR 2 | |||
| SERVER_EXPORT void jack_error(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 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_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 | |||
| } | |||
| @@ -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__ | |||
| #define __JackException__ | |||
| #include "JackCompilerDeps.h" | |||
| #include <stdexcept> | |||
| #include <iostream> | |||
| #include <string> | |||
| #include "JackError.h" | |||
| namespace Jack | |||
| { | |||
| @@ -55,14 +56,9 @@ class SERVER_EXPORT JackException : public std::runtime_error { | |||
| 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. | |||
| @@ -43,14 +43,26 @@ JackTimer::JackTimer() | |||
| fCurrentWakeup = 0; | |||
| fCurrentCallback = 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) { | |||
| 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 { | |||
| 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) | |||
| { | |||
| 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 { | |||
| 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) | |||
| { | |||
| 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) { | |||
| InitFrameTimeAux(callback_usecs, period_usecs); | |||
| 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 | |||
| 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->fCurrentCallback = callback_usecs; | |||
| timer->fNextWakeUp = callback_usecs + period_usecs; | |||
| WriteNextStateStop(); | |||
| 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) | |||
| { | |||
| /* 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(); | |||
| timer->fSecondOrderIntegrator = 0.0f; | |||
| timer->fPeriodUsecs = (float)period_usecs; | |||
| timer->fCurrentCallback = callback_usecs; | |||
| timer->fNextWakeUp = callback_usecs + period_usecs; | |||
| timer->fNextWakeUp = callback_usecs; | |||
| timer->fFilterOmega = period_usecs * 7.854e-7f; | |||
| WriteNextStateStop(); | |||
| 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) | |||
| { | |||
| 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->fCurrentCallback = callback_usecs; | |||
| 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; | |||
| WriteNextStateStop(); | |||
| TrySwitchState(); // always succeed since there is only one writer | |||
| } | |||
| @@ -44,8 +44,8 @@ class SERVER_EXPORT JackTimer | |||
| jack_time_t fCurrentWakeup; | |||
| jack_time_t fCurrentCallback; | |||
| jack_time_t fNextWakeUp; | |||
| float fSecondOrderIntegrator; | |||
| float fFilterCoefficient; /* set once, never altered */ | |||
| float fPeriodUsecs; | |||
| float fFilterOmega; /* set once, never altered */ | |||
| bool fInitialized; | |||
| public: | |||
| @@ -57,6 +57,7 @@ class SERVER_EXPORT JackTimer | |||
| 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_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() | |||
| { | |||
| @@ -92,7 +93,7 @@ class SERVER_EXPORT JackFrameTimer : public JackAtomicState<JackTimer> | |||
| {} | |||
| 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 ReadFrameTime(JackTimer* timer); | |||
| @@ -37,7 +37,8 @@ int JackFreewheelDriver::Process() | |||
| if (fEngine->Process(fBeginDateUst, fEndDateUst)) { | |||
| if (ResumeRefNum()) { // Signal all clients | |||
| // Resume connected clients in the graph | |||
| if (ResumeRefNum()) { | |||
| jack_error("JackFreewheelDriver::Process: ResumeRefNum error"); | |||
| res = -1; | |||
| } | |||
| @@ -61,6 +62,7 @@ int JackFreewheelDriver::Process() | |||
| int JackFreewheelDriver::ProcessReadSync() | |||
| { | |||
| // Resume connected clients in the graph | |||
| if (ResumeRefNum() < 0) { // Signal all clients | |||
| jack_error("JackFreewheelDriver::ProcessReadSync: ResumeRefNum error"); | |||
| return -1; | |||
| @@ -80,6 +82,7 @@ int JackFreewheelDriver::ProcessWriteSync() | |||
| int JackFreewheelDriver::ProcessReadAsync() | |||
| { | |||
| // Resume connected clients in the graph | |||
| if (ResumeRefNum() < 0) { // Signal all clients | |||
| jack_error("JackFreewheelDriver::ProcessReadAsync: ResumeRefNum error"); | |||
| 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; | |||
| 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; | |||
| static bool fKeyLogFunctionInitialized = jack_tls_allocate_key(&JackGlobals::fKeyLogFunction); | |||
| @@ -39,6 +42,7 @@ jack_thread_creator_t JackGlobals::fJackThreadCreator = pthread_create; | |||
| #endif | |||
| #ifdef __CLIENTDEBUG__ | |||
| std::ofstream* JackGlobals::fStream = NULL; | |||
| 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; | |||
| } | |||
| #else | |||
| void JackGlobals::CheckContext(const char* name) | |||
| {} | |||
| #endif | |||
| } // end of namespace | |||
| @@ -37,7 +37,8 @@ namespace Jack | |||
| // Globals used for client management on server or library side. | |||
| struct JackGlobals { | |||
| static jack_tls_key fRealTime; | |||
| static jack_tls_key fRealTimeThread; | |||
| static jack_tls_key fNotificationThread; | |||
| static jack_tls_key fKeyLogFunction; | |||
| static JackMutex* fOpenMutex; | |||
| static volatile bool fServerRunning; | |||
| @@ -49,8 +50,8 @@ struct JackGlobals { | |||
| #ifdef __CLIENTDEBUG__ | |||
| static std::ofstream* fStream; | |||
| static void CheckContext(const char* name); | |||
| #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. | |||
| @@ -344,7 +344,7 @@ void JackGraphManager::RecalculateLatency(jack_port_id_t port_index, jack_latenc | |||
| next_index = GetCurrentIndex(); | |||
| } 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 | |||
| @@ -27,7 +27,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackServer.h" | |||
| #include "JackEngineControl.h" | |||
| #include "JackClientControl.h" | |||
| #include "JackInternalClientChannel.h" | |||
| #include "JackGenericClientChannel.h" | |||
| #include "JackTools.h" | |||
| #include <assert.h> | |||
| @@ -98,11 +101,16 @@ int JackInternalClient::Open(const char* server_name, const char* name, int uuid | |||
| return 0; | |||
| error: | |||
| fChannel->Stop(); | |||
| fChannel->Close(); | |||
| return -1; | |||
| } | |||
| void JackInternalClient::ShutDown() | |||
| { | |||
| jack_log("JackInternalClient::ShutDown"); | |||
| JackClient::ShutDown(); | |||
| } | |||
| JackGraphManager* JackInternalClient::GetGraphManager() const | |||
| { | |||
| assert(fGraphManager); | |||
| @@ -193,10 +201,12 @@ JackLoadableInternalClient2::JackLoadableInternalClient2(JackServer* server, Jac | |||
| JackLoadableInternalClient::~JackLoadableInternalClient() | |||
| { | |||
| if (fFinish != NULL) | |||
| if (fFinish != NULL) { | |||
| fFinish(fProcessArg); | |||
| if (fHandle != NULL) | |||
| } | |||
| if (fHandle != NULL) { | |||
| UnloadJackModule(fHandle); | |||
| } | |||
| } | |||
| 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(); | |||
| int Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status); | |||
| void ShutDown(); | |||
| JackGraphManager* GetGraphManager() const; | |||
| JackEngineControl* GetEngineControl() const; | |||
| @@ -63,7 +64,6 @@ class JackInternalClient : public JackClient | |||
| typedef int (*InitializeCallback)(jack_client_t*, const char*); | |||
| typedef int (*InternalInitializeCallback)(jack_client_t*, const JSList* params); | |||
| typedef void (*FinishCallback)(void *); | |||
| typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | |||
| class JackLoadableInternalClient : public JackInternalClient | |||
| { | |||
| @@ -92,7 +92,7 @@ class JackLoadableInternalClient1 : public JackLoadableInternalClient | |||
| InitializeCallback fInitialize; | |||
| char fObjectData[JACK_LOAD_INIT_LIMIT]; | |||
| public: | |||
| JackLoadableInternalClient1(JackServer* server, JackSynchro* table, const char* object_data); | |||
| @@ -111,7 +111,7 @@ class JackLoadableInternalClient2 : public JackLoadableInternalClient | |||
| InternalInitializeCallback fInitialize; | |||
| const JSList* fParameters; | |||
| public: | |||
| JackLoadableInternalClient2(JackServer* server, JackSynchro* table, const JSList* parameters); | |||
| @@ -44,12 +44,6 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||
| 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) | |||
| { | |||
| *result = fEngine->ClientCheck(name, uuid, name_res, protocol, options, status); | |||
| @@ -148,8 +142,7 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||
| { | |||
| JackSessionNotifyResult* res; | |||
| fEngine->SessionNotify(refnum, target, type, path, NULL, &res); | |||
| if (res == NULL) | |||
| { | |||
| if (res == NULL) { | |||
| *result = NULL; | |||
| return; | |||
| } | |||
| @@ -160,28 +153,27 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||
| 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) | |||
| { | |||
| 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) | |||
| { | |||
| 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) | |||
| { | |||
| fEngine->ReserveClientName(client_name, uuid, result); | |||
| *result = fEngine->ReserveClientName(client_name, uuid); | |||
| } | |||
| 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, ...) | |||
| { | |||
| #ifdef __CLIENTDEBUG__ | |||
| JackGlobals::CheckContext("jack_client_open"); | |||
| #endif | |||
| try { | |||
| assert(JackGlobals::fOpenMutex); | |||
| 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) | |||
| { | |||
| #ifdef __CLIENTDEBUG__ | |||
| JackGlobals::CheckContext("jack_client_close"); | |||
| #endif | |||
| assert(JackGlobals::fOpenMutex); | |||
| JackGlobals::fOpenMutex->Lock(); | |||
| int res = -1; | |||
| @@ -55,6 +55,20 @@ JackSynchro* GetSynchroTable() | |||
| // 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) | |||
| { | |||
| jack_log("JackLibClient::JackLibClient table = %x", table); | |||
| @@ -32,7 +32,7 @@ namespace Jack | |||
| \brief Client on the library side. | |||
| */ | |||
| class LIB_EXPORT JackLibClient : public JackClient | |||
| class JackLibClient : public JackClient | |||
| { | |||
| private: | |||
| @@ -45,6 +45,7 @@ class LIB_EXPORT JackLibClient : public JackClient | |||
| virtual ~JackLibClient(); | |||
| 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); | |||
| @@ -50,7 +50,7 @@ class JackClient; | |||
| \brief Global library static structure: singleton kind of pattern. | |||
| */ | |||
| struct LIB_EXPORT JackLibGlobals | |||
| struct JackLibGlobals | |||
| { | |||
| JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */ | |||
| JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable | |||
| @@ -63,7 +63,9 @@ struct LIB_EXPORT JackLibGlobals | |||
| JackLibGlobals() | |||
| { | |||
| jack_log("JackLibGlobals"); | |||
| JackMessageBuffer::Create(); | |||
| if (!JackMessageBuffer::Create()) { | |||
| jack_error("Cannot create message buffer"); | |||
| } | |||
| fGraphManager = -1; | |||
| fEngineControl = -1; | |||
| @@ -127,6 +129,7 @@ struct LIB_EXPORT JackLibGlobals | |||
| { | |||
| if (--fClientCount == 0 && fGlobals) { | |||
| jack_log("JackLibGlobals Destroy %x", fGlobals); | |||
| EndTime(); | |||
| delete fGlobals; | |||
| fGlobals = NULL; | |||
| } | |||
| @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "JackLibSampleRateResampler.h" | |||
| #include "JackError.h" | |||
| namespace Jack | |||
| { | |||
| @@ -103,6 +103,14 @@ class SERVER_EXPORT JackLockedEngine | |||
| return fEngine.Close(); | |||
| CATCH_EXCEPTION_RETURN | |||
| } | |||
| void ShutDown() | |||
| { | |||
| // No lock needed | |||
| TRY_CALL | |||
| fEngine.ShutDown(); | |||
| CATCH_EXCEPTION | |||
| } | |||
| // Client management | |||
| 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 | |||
| } | |||
| 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 | |||
| JackLock lock(&fEngine); | |||
| @@ -333,42 +341,42 @@ class SERVER_EXPORT JackLockedEngine | |||
| CATCH_EXCEPTION | |||
| } | |||
| void SessionReply(int refnum) | |||
| int SessionReply(int refnum) | |||
| { | |||
| TRY_CALL | |||
| 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 | |||
| 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 | |||
| 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 | |||
| 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 | |||
| 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); | |||
| } | |||
| // Resume connected clients in the graph | |||
| if (ResumeRefNum() < 0) { | |||
| jack_error("JackLoopbackDriver::ProcessReadSync - ResumeRefNum error"); | |||
| res = -1; | |||
| @@ -51,6 +52,7 @@ int JackLoopbackDriver::ProcessReadSync() | |||
| int JackLoopbackDriver::ProcessWriteSync() | |||
| { | |||
| // Suspend on connected clients in the graph | |||
| if (SuspendRefNum() < 0) { | |||
| jack_error("JackLoopbackDriver::ProcessWriteSync SuspendRefNum error"); | |||
| return -1; | |||
| @@ -67,6 +69,7 @@ int JackLoopbackDriver::ProcessReadAsync() | |||
| memcpy(GetInputBuffer(i), GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | |||
| } | |||
| // Resume connected clients in the graph | |||
| if (ResumeRefNum() < 0) { | |||
| jack_error("JackLoopbackDriver::ProcessReadAsync - ResumeRefNum error"); | |||
| res = -1; | |||
| @@ -22,6 +22,7 @@ | |||
| #include "JackMessageBuffer.h" | |||
| #include "JackGlobals.h" | |||
| #include "JackError.h" | |||
| #include "JackTime.h" | |||
| namespace Jack | |||
| { | |||
| @@ -29,19 +30,32 @@ namespace Jack | |||
| JackMessageBuffer* JackMessageBuffer::fInstance = NULL; | |||
| 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() | |||
| {} | |||
| void JackMessageBuffer::Start() | |||
| bool JackMessageBuffer::Start() | |||
| { | |||
| // Before StartSync()... | |||
| fRunning = true; | |||
| fThread.StartSync(); | |||
| if (fThread.StartSync() == 0) { | |||
| return true; | |||
| } else { | |||
| fRunning = false; | |||
| return false; | |||
| } | |||
| } | |||
| void JackMessageBuffer::Stop() | |||
| bool JackMessageBuffer::Stop() | |||
| { | |||
| if (fOverruns > 0) { | |||
| jack_error("WARNING: %d message buffer overruns!", fOverruns); | |||
| @@ -59,6 +73,7 @@ void JackMessageBuffer::Stop() | |||
| } | |||
| Flush(); | |||
| return true; | |||
| } | |||
| void JackMessageBuffer::Flush() | |||
| @@ -96,7 +111,7 @@ bool JackMessageBuffer::Execute() | |||
| /* and we're done */ | |||
| fGuard.Signal(); | |||
| } | |||
| /* releasing the mutex reduces contention */ | |||
| fGuard.Unlock(); | |||
| Flush(); | |||
| @@ -110,20 +125,30 @@ bool JackMessageBuffer::Execute() | |||
| return false; | |||
| } | |||
| void JackMessageBuffer::Create() | |||
| bool JackMessageBuffer::Create() | |||
| { | |||
| if (fInstance == NULL) { | |||
| 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) { | |||
| fInstance->Stop(); | |||
| delete fInstance; | |||
| 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 */ | |||
| fInitArg = arg; | |||
| fInit = callback; | |||
| /* wake msg buffer thread */ | |||
| #ifndef WIN32 | |||
| // wake msg buffer thread | |||
| fGuard.Signal(); | |||
| /* wait for it to be done */ | |||
| // wait for it to be done | |||
| fGuard.Wait(); | |||
| /* and we're done */ | |||
| // and we're done | |||
| 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: | |||
| JackThreadInitCallback fInit; | |||
| volatile JackThreadInitCallback fInit; | |||
| void* fInitArg; | |||
| JackMessage fBuffers[MB_BUFFERS]; | |||
| JackThread fThread; | |||
| @@ -69,8 +69,8 @@ class JackMessageBuffer : public JackRunnableInterface | |||
| void Flush(); | |||
| void Start(); | |||
| void Stop(); | |||
| bool Start(); | |||
| bool Stop(); | |||
| public: | |||
| @@ -80,11 +80,11 @@ class JackMessageBuffer : public JackRunnableInterface | |||
| // JackRunnableInterface interface | |||
| bool Execute(); | |||
| void static Create(); | |||
| void static Destroy(); | |||
| bool static Create(); | |||
| bool static Destroy(); | |||
| void AddMessage(int level, const char *message); | |||
| void SetInitCallback(JackThreadInitCallback callback, void *arg); | |||
| int SetInitCallback(JackThreadInitCallback callback, void *arg); | |||
| static JackMessageBuffer* fInstance; | |||
| }; | |||
| @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| #include "JackMidiBufferReadQueue.h" | |||
| #include "JackMidiUtil.h" | |||
| #include "JackError.h" | |||
| using Jack::JackMidiBufferReadQueue; | |||
| @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| #include "JackMidiBufferWriteQueue.h" | |||
| #include "JackMidiUtil.h" | |||
| #include "JackError.h" | |||
| using Jack::JackMidiBufferWriteQueue; | |||
| @@ -136,6 +136,8 @@ int JackMidiDriver::SetBufferSize(jack_nframes_t buffer_size) | |||
| int JackMidiDriver::ProcessReadSync() | |||
| { | |||
| int res = 0; | |||
| jack_log("JackMidiDriver::ProcessReadSync"); | |||
| // Read input buffers for the current cycle | |||
| if (Read() < 0) { | |||
| @@ -154,6 +156,8 @@ int JackMidiDriver::ProcessReadSync() | |||
| int JackMidiDriver::ProcessWriteSync() | |||
| { | |||
| int res = 0; | |||
| jack_log("JackMidiDriver::ProcessWriteSync"); | |||
| if (SuspendRefNum() < 0) { | |||
| jack_error("JackMidiDriver::ProcessWriteSync: SuspendRefNum error"); | |||
| @@ -172,6 +176,8 @@ int JackMidiDriver::ProcessWriteSync() | |||
| int JackMidiDriver::ProcessReadAsync() | |||
| { | |||
| int res = 0; | |||
| jack_log("JackMidiDriver::ProcessReadAsync"); | |||
| // Read input buffers for the current cycle | |||
| if (Read() < 0) { | |||
| @@ -195,6 +201,7 @@ int JackMidiDriver::ProcessReadAsync() | |||
| int JackMidiDriver::ProcessWriteAsync() | |||
| { | |||
| jack_log("JackMidiDriver::ProcessWriteAsync"); | |||
| return 0; | |||
| } | |||
| @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| #include <new> | |||
| #include "JackMidiRawInputWriteQueue.h" | |||
| #include "JackError.h" | |||
| using Jack::JackMidiRawInputWriteQueue; | |||
| @@ -40,7 +40,8 @@ class JackLockAble | |||
| JackMutex fMutex; | |||
| JackLockAble() | |||
| JackLockAble(const char* name = NULL) | |||
| :fMutex(name) | |||
| {} | |||
| ~JackLockAble() | |||
| {} | |||
| @@ -19,9 +19,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| #include <assert.h> | |||
| #include <stdarg.h> | |||
| #include "JackNetInterface.h" | |||
| #include "JackError.h" | |||
| #include "JackException.h" | |||
| #include "JackAudioAdapterInterface.h" | |||
| #ifdef __cplusplus | |||
| @@ -86,41 +85,48 @@ extern "C" | |||
| typedef int (*JackNetSlaveSampleRateCallback) (jack_nframes_t nframes, void *arg); | |||
| 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 | |||
| 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 | |||
| 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_sample_rate, | |||
| jack_nframes_t adapted_buffer_size, | |||
| 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 | |||
| } | |||
| @@ -151,6 +157,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| fSocket.SetPort(port); | |||
| fRequest.buffer_size = request->buffer_size; | |||
| fRequest.sample_rate = request->sample_rate; | |||
| fRequest.audio_input = request->audio_input; | |||
| fRequest.audio_output = request->audio_output; | |||
| fAudioCaptureBuffer = NULL; | |||
| fAudioPlaybackBuffer = NULL; | |||
| fMidiCaptureBuffer = NULL; | |||
| @@ -215,11 +223,10 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| } | |||
| if (rx_bytes == sizeof(session_params_t )) { | |||
| switch (GetPacketType(&fParams)) { | |||
| case SLAVE_AVAILABLE: | |||
| if (MasterInit() == 0) { | |||
| if (InitMaster(result) == 0) { | |||
| SessionParamsDisplay(&fParams); | |||
| fRunning = false; | |||
| } else { | |||
| @@ -238,8 +245,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| } | |||
| } | |||
| while (fRunning); | |||
| // Set result paramaters | |||
| // Set result parameters | |||
| result->audio_input = fParams.fSendAudioChannels; | |||
| result->audio_output = fParams.fReturnAudioChannels; | |||
| result->midi_input = fParams.fSendMidiChannels; | |||
| @@ -253,7 +260,7 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| return -1; | |||
| } | |||
| int MasterInit() | |||
| int InitMaster(jack_slave_t* result) | |||
| { | |||
| // Check MASTER <==> SLAVE network protocol coherency | |||
| if (fParams.fProtocolVersion != MASTER_PROTOCOL) { | |||
| @@ -264,14 +271,45 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| // Settings | |||
| fSocket.GetName(fParams.fMasterNetName); | |||
| fParams.fID = 1; | |||
| fParams.fSampleEncoder = JackFloatEncoder; | |||
| fParams.fPeriodSize = fRequest.buffer_size; | |||
| 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 | |||
| fSocket.Close(); | |||
| // Network slave init | |||
| /// Network init | |||
| if (!JackNetMasterInterface::Init()) { | |||
| 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) | |||
| { | |||
| try { | |||
| assert(audio_input == fParams.fReturnAudioChannels); | |||
| 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++) { | |||
| 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(); | |||
| 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) | |||
| { | |||
| try { | |||
| assert(audio_output == fParams.fSendAudioChannels); | |||
| 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++) { | |||
| 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) { | |||
| jack_error("Connection lost."); | |||
| return -1; | |||
| } | |||
| } | |||
| } | |||
| // Transport | |||
| void EncodeTransportData() | |||
| @@ -490,6 +545,13 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| 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) { | |||
| jack_error("Error : network latency is limited to %d", NETWORK_MAX_LATENCY); | |||
| return -1; | |||
| @@ -541,7 +603,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| return -1; | |||
| } | |||
| // Finish connection... | |||
| // Finish connection | |||
| if (!JackNetSlaveInterface::InitRendering()) { | |||
| jack_error("Starting network fails..."); | |||
| return -1; | |||
| @@ -604,29 +666,33 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| void FreePorts() | |||
| { | |||
| 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; | |||
| fAudioCaptureBuffer = NULL; | |||
| } | |||
| 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; | |||
| fMidiCaptureBuffer = NULL; | |||
| } | |||
| 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; | |||
| fAudioPlaybackBuffer = NULL; | |||
| } | |||
| 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; | |||
| fMidiPlaybackBuffer = NULL; | |||
| } | |||
| @@ -661,9 +727,9 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| } | |||
| return false; | |||
| } catch (JackNetException& e) { | |||
| // Otherwise just restart... | |||
| e.PrintMessage(); | |||
| jack_info("NetSlave is restarted"); | |||
| fThread.DropRealTime(); | |||
| fThread.SetStatus(JackThread::kIniting); | |||
| FreePorts(); | |||
| @@ -855,7 +921,7 @@ struct JackNetAdapter : public JackAudioAdapterInterface { | |||
| 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); | |||
| 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; | |||
| slave->Close(); | |||
| @@ -874,37 +940,37 @@ SERVER_EXPORT int jack_net_slave_close(jack_net_slave_t* net) | |||
| 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; | |||
| 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; | |||
| 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; | |||
| 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; | |||
| 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; | |||
| 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; | |||
| 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 | |||
| 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); | |||
| 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; | |||
| master->Close(); | |||
| delete master; | |||
| 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; | |||
| 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; | |||
| 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 | |||
| 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_sample_rate, | |||
| 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); | |||
| 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; | |||
| 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; | |||
| 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; | |||
| 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) | |||
| { | |||
| 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_start(ap, fmt); | |||
| @@ -1010,7 +1078,7 @@ SERVER_EXPORT void jack_error(const char *fmt, ...) | |||
| va_end(ap); | |||
| } | |||
| SERVER_EXPORT void jack_info(const char *fmt, ...) | |||
| LIB_EXPORT void jack_info(const char *fmt, ...) | |||
| { | |||
| va_list ap; | |||
| va_start(ap, fmt); | |||
| @@ -1018,26 +1086,10 @@ SERVER_EXPORT void jack_info(const char *fmt, ...) | |||
| va_end(ap); | |||
| } | |||
| SERVER_EXPORT void jack_log(const char *fmt, ...) | |||
| LIB_EXPORT void jack_log(const char *fmt, ...) | |||
| { | |||
| va_list ap; | |||
| va_start(ap, fmt); | |||
| jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, 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; | |||
| } catch (JackNetException& e) { | |||
| // Otherwise just restart... | |||
| e.PrintMessage(); | |||
| jack_info("NetAdapter is restarted"); | |||
| Reset(); | |||
| @@ -413,7 +414,7 @@ extern "C" | |||
| 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, "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 | |||
| 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. | |||
| */ | |||
| #include "JackCompilerDeps.h" | |||
| #include "driver_interface.h" | |||
| #include "JackNetDriver.h" | |||
| #include "JackEngineControl.h" | |||
| #include "JackLockedEngine.h" | |||
| @@ -509,7 +511,7 @@ namespace Jack | |||
| DecodeSyncPacket(); | |||
| #ifdef JACK_MONITOR | |||
| fNetTimeMon->Add((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||
| fNetTimeMon->Add(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||
| #endif | |||
| //audio, midi or sync if driver is late | |||
| int res = DataRecv(); | |||
| @@ -524,7 +526,7 @@ namespace Jack | |||
| JackDriver::CycleTakeBeginTime(); | |||
| #ifdef JACK_MONITOR | |||
| fNetTimeMon->Add((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||
| fNetTimeMon->Add(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||
| #endif | |||
| return 0; | |||
| @@ -555,7 +557,7 @@ namespace Jack | |||
| } | |||
| #ifdef JACK_MONITOR | |||
| fNetTimeMon->AddLast((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||
| fNetTimeMon->AddLast(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||
| #endif | |||
| //sync | |||
| @@ -588,6 +590,7 @@ namespace Jack | |||
| extern "C" | |||
| { | |||
| #endif | |||
| SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() | |||
| { | |||
| jack_driver_desc_t * desc; | |||
| @@ -620,8 +623,11 @@ namespace Jack | |||
| strcpy(value.str, "'hostname'"); | |||
| 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; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); | |||
| */ | |||
| value.ui = 5U; | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL); | |||
| @@ -696,9 +702,12 @@ namespace Jack | |||
| case 'n' : | |||
| strncpy(net_name, param->value.str, JACK_CLIENT_NAME_SIZE); | |||
| break; | |||
| /* | |||
| Deactivated for now.. | |||
| case 't' : | |||
| transport_sync = param->value.ui; | |||
| break; | |||
| */ | |||
| case 'l' : | |||
| network_latency = param->value.ui; | |||
| if (network_latency > NETWORK_MAX_LATENCY) { | |||
| @@ -18,6 +18,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackNetInterface.h" | |||
| #include "JackException.h" | |||
| #include "JackError.h" | |||
| #include <assert.h> | |||
| using namespace std; | |||
| @@ -52,6 +54,7 @@ namespace Jack | |||
| void JackNetInterface::Initialize() | |||
| { | |||
| fSetTimeOut = false; | |||
| fTxBuffer = NULL; | |||
| fRxBuffer = NULL; | |||
| fNetAudioCaptureBuffer = NULL; | |||
| @@ -196,6 +199,7 @@ namespace Jack | |||
| fRxHeader.fCycle = rx_head->fCycle; | |||
| fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | |||
| buffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); | |||
| // Last midi packet is received, so finish rendering... | |||
| if (++recvd_midi_pckt == rx_head->fNumPacket) { | |||
| buffer->RenderToJackPorts(); | |||
| @@ -211,6 +215,7 @@ namespace Jack | |||
| fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | |||
| fRxHeader.fActivePorts = rx_head->fActivePorts; | |||
| rx_bytes = buffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, fRxHeader.fActivePorts); | |||
| // Last audio packet is received, so finish rendering... | |||
| if (fRxHeader.fIsLastPckt) { | |||
| buffer->RenderToJackPorts(); | |||
| @@ -220,7 +225,6 @@ namespace Jack | |||
| int JackNetInterface::FinishRecv(NetAudioBuffer* buffer) | |||
| { | |||
| // TODO : finish midi and audio rendering ? | |||
| buffer->RenderToJackPorts(); | |||
| return NET_PACKET_ERROR; | |||
| } | |||
| @@ -242,12 +246,23 @@ namespace Jack | |||
| } | |||
| 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 ************************************************************************************ | |||
| bool JackNetMasterInterface::Init() | |||
| { | |||
| jack_log("JackNetMasterInterface::Init, ID %u", fParams.fID); | |||
| jack_log("JackNetMasterInterface::Init : ID %u", fParams.fID); | |||
| session_params_t host_params; | |||
| uint attempt = 0; | |||
| @@ -260,8 +275,9 @@ namespace Jack | |||
| } | |||
| // 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 | |||
| if (fSocket.Connect() == SOCKET_ERROR) { | |||
| @@ -291,6 +307,7 @@ namespace Jack | |||
| SessionParamsNToH(&net_params, &host_params); | |||
| } | |||
| while ((GetPacketType(&host_params) != START_MASTER) && (++attempt < SLAVE_SETUP_RETRY)); | |||
| if (attempt == SLAVE_SETUP_RETRY) { | |||
| jack_error("Slave doesn't respond, exiting"); | |||
| return false; | |||
| @@ -299,13 +316,6 @@ namespace Jack | |||
| 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() | |||
| { | |||
| jack_log("JackNetMasterInterface::SetParams audio in = %d audio out = %d MIDI in = %d MIDI out = %d", | |||
| @@ -346,14 +356,6 @@ namespace Jack | |||
| 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 | |||
| if (SetNetBufferSize() == SOCKET_ERROR) { | |||
| jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE)); | |||
| @@ -418,19 +420,6 @@ namespace Jack | |||
| int rx_bytes; | |||
| 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(); | |||
| } | |||
| @@ -446,14 +435,6 @@ namespace Jack | |||
| PacketHeaderHToN(header, header); | |||
| 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(); | |||
| } | |||
| return tx_bytes; | |||
| @@ -466,6 +447,8 @@ namespace Jack | |||
| int JackNetMasterInterface::SyncSend() | |||
| { | |||
| SetRcvTimeOut(); | |||
| fTxHeader.fCycle++; | |||
| fTxHeader.fSubCycle = 0; | |||
| fTxHeader.fDataType = 's'; | |||
| @@ -490,17 +473,6 @@ namespace Jack | |||
| int rx_bytes = 0; | |||
| 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) | |||
| do { | |||
| rx_bytes = Recv(fParams.fMtu, MSG_PEEK); | |||
| @@ -532,7 +504,7 @@ namespace Jack | |||
| while (!fRxHeader.fIsLastPckt) { | |||
| // how much data is queued on the rx buffer ? | |||
| rx_bytes = Recv(fParams.fMtu, MSG_PEEK); | |||
| // error here, problem with recv, just skip the cycle (return -1) | |||
| if (rx_bytes == SOCKET_ERROR) { | |||
| return rx_bytes; | |||
| @@ -556,7 +528,7 @@ namespace Jack | |||
| } | |||
| } | |||
| } | |||
| return rx_bytes; | |||
| } | |||
| @@ -608,6 +580,17 @@ namespace Jack | |||
| 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() | |||
| { | |||
| jack_log("JackNetSlaveInterface::Init()"); | |||
| @@ -674,8 +657,9 @@ namespace Jack | |||
| // then tell the master we are ready | |||
| jack_info("Initializing connection with %s...", fParams.fMasterNetName); | |||
| status = SendStartToMaster(); | |||
| if (status == NET_ERROR) | |||
| if (status == NET_ERROR) { | |||
| return false; | |||
| } | |||
| } | |||
| 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 | |||
| if (fSocket.SetLocalLoop() == SOCKET_ERROR) | |||
| if (fSocket.SetLocalLoop() == SOCKET_ERROR) { | |||
| jack_error("Can't disable multicast loop : %s", StrError(NET_ERROR_CODE)); | |||
| } | |||
| // send 'AVAILABLE' until 'SLAVE_SETUP' received | |||
| jack_info("Waiting for a master..."); | |||
| @@ -720,8 +706,9 @@ namespace Jack | |||
| session_params_t net_params; | |||
| memset(&net_params, 0, sizeof(session_params_t)); | |||
| 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)); | |||
| } | |||
| // filter incoming packets : don't exit while no error is detected | |||
| memset(&net_params, 0, sizeof(session_params_t)); | |||
| @@ -833,20 +820,9 @@ namespace Jack | |||
| int JackNetSlaveInterface::Recv(size_t size, int flags) | |||
| { | |||
| int rx_bytes = fSocket.Recv(fRxBuffer, size, flags); | |||
| // handle errors | |||
| 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(); | |||
| } | |||
| @@ -863,17 +839,9 @@ namespace Jack | |||
| // handle errors | |||
| 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(); | |||
| } | |||
| return tx_bytes; | |||
| } | |||
| @@ -881,7 +849,7 @@ namespace Jack | |||
| { | |||
| int rx_bytes = 0; | |||
| packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); | |||
| // receive sync (launch the cycle) | |||
| do { | |||
| rx_bytes = Recv(fParams.fMtu, 0); | |||
| @@ -893,6 +861,8 @@ namespace Jack | |||
| while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's')); | |||
| fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | |||
| SetRcvTimeOut(); | |||
| return rx_bytes; | |||
| } | |||
| @@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #define __JackNetInterface__ | |||
| #include "JackNetTool.h" | |||
| #include <limits.h> | |||
| namespace Jack | |||
| { | |||
| @@ -31,9 +32,10 @@ namespace Jack | |||
| #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 | |||
| @@ -45,6 +47,8 @@ namespace Jack | |||
| { | |||
| protected: | |||
| bool fSetTimeOut; | |||
| void Initialize(); | |||
| @@ -106,6 +110,8 @@ namespace Jack | |||
| int AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer); | |||
| int FinishRecv(NetAudioBuffer* buffer); | |||
| void SetRcvTimeOut(); | |||
| NetAudioBuffer* AudioBufferFactory(int nports, char* buffer); | |||
| @@ -129,13 +135,10 @@ namespace Jack | |||
| protected: | |||
| bool fRunning; | |||
| int fCurrentCycleOffset; | |||
| int fMaxCycleOffset; | |||
| int fLastfCycleOffset; | |||
| bool Init(); | |||
| int SetRxTimeout(); | |||
| bool SetParams(); | |||
| void Exit(); | |||
| @@ -160,10 +163,10 @@ namespace Jack | |||
| 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) | |||
| : JackNetInterface(params, socket, multicast_ip) | |||
| : JackNetInterface(params, socket, multicast_ip), fRunning(false), fCurrentCycleOffset(0), fMaxCycleOffset(0) | |||
| {} | |||
| virtual~JackNetMasterInterface() | |||
| @@ -206,16 +209,7 @@ namespace Jack | |||
| void FatalRecvError(); | |||
| 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: | |||
| @@ -33,8 +33,8 @@ namespace Jack | |||
| jack_log("JackNetMaster::JackNetMaster"); | |||
| //settings | |||
| fClientName = const_cast<char*>(fParams.fName); | |||
| fJackClient = NULL; | |||
| fName = const_cast<char*>(fParams.fName); | |||
| fClient = NULL; | |||
| fSendTransportData.fState = -1; | |||
| fReturnTransportData.fState = -1; | |||
| fLastTransportState = -1; | |||
| @@ -91,10 +91,10 @@ namespace Jack | |||
| { | |||
| jack_log("JackNetMaster::~JackNetMaster ID = %u", fParams.fID); | |||
| if (fJackClient) { | |||
| jack_deactivate(fJackClient); | |||
| if (fClient) { | |||
| jack_deactivate(fClient); | |||
| FreePorts(); | |||
| jack_client_close(fJackClient); | |||
| jack_client_close(fClient); | |||
| } | |||
| delete[] fAudioCapturePorts; | |||
| delete[] fAudioPlaybackPorts; | |||
| @@ -122,18 +122,24 @@ namespace Jack | |||
| //jack client and process | |||
| 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"); | |||
| return false; | |||
| } | |||
| if (jack_set_process_callback(fJackClient, SetProcess, this) < 0) { | |||
| if (jack_set_process_callback(fClient, SetProcess, this) < 0) { | |||
| 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; | |||
| } | |||
| */ | |||
| if (AllocPorts() != 0) { | |||
| jack_error("Can't allocate JACK ports"); | |||
| @@ -144,7 +150,7 @@ namespace Jack | |||
| fRunning = true; | |||
| //finally activate jack client | |||
| if (jack_activate(fJackClient) != 0) { | |||
| if (jack_activate(fClient) != 0) { | |||
| jack_error("Can't activate JACK client"); | |||
| goto fail; | |||
| } | |||
| @@ -157,8 +163,8 @@ namespace Jack | |||
| fail: | |||
| FreePorts(); | |||
| jack_client_close(fJackClient); | |||
| fJackClient = NULL; | |||
| jack_client_close(fClient); | |||
| fClient = NULL; | |||
| return false; | |||
| } | |||
| @@ -167,7 +173,7 @@ namespace Jack | |||
| { | |||
| int i; | |||
| 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_log("JackNetMaster::AllocPorts"); | |||
| @@ -175,7 +181,7 @@ namespace Jack | |||
| //audio | |||
| for (i = 0; i < fParams.fSendAudioChannels; i++) { | |||
| 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; | |||
| //port latency | |||
| range.min = range.max = 0; | |||
| @@ -184,7 +190,7 @@ namespace Jack | |||
| for (i = 0; i < fParams.fReturnAudioChannels; i++) { | |||
| 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; | |||
| //port latency | |||
| range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; | |||
| @@ -194,7 +200,7 @@ namespace Jack | |||
| //midi | |||
| for (i = 0; i < fParams.fSendMidiChannels; i++) { | |||
| 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; | |||
| //port latency | |||
| range.min = range.max = 0; | |||
| @@ -203,7 +209,7 @@ namespace Jack | |||
| for (i = 0; i < fParams.fReturnMidiChannels; i++) { | |||
| 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; | |||
| //port latency | |||
| range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency; | |||
| @@ -216,18 +222,18 @@ namespace Jack | |||
| { | |||
| const char **ports; | |||
| ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); | |||
| ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); | |||
| if (ports != NULL) { | |||
| 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); | |||
| } | |||
| ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); | |||
| ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); | |||
| if (ports != NULL) { | |||
| 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); | |||
| } | |||
| @@ -240,22 +246,22 @@ namespace Jack | |||
| int port_index; | |||
| for (port_index = 0; port_index < fParams.fSendAudioChannels; 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++) { | |||
| 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++) { | |||
| 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++) { | |||
| 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; | |||
| //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 ? | |||
| fSendTransportData.fNewState = ((fSendTransportData.fState != fLastTransportState) && (fSendTransportData.fState != fReturnTransportData.fState)); | |||
| @@ -287,7 +293,7 @@ namespace Jack | |||
| switch (fReturnTransportData.fTimebaseMaster) | |||
| { | |||
| case RELEASE_TIMEBASEMASTER : | |||
| timebase = jack_release_timebase(fJackClient); | |||
| timebase = jack_release_timebase(fClient); | |||
| if (timebase < 0) { | |||
| jack_error("Can't release timebase master"); | |||
| } else { | |||
| @@ -296,7 +302,7 @@ namespace Jack | |||
| break; | |||
| case TIMEBASEMASTER : | |||
| timebase = jack_set_timebase_callback(fJackClient, 0, SetTimebaseCallback, this); | |||
| timebase = jack_set_timebase_callback(fClient, 0, SetTimebaseCallback, this); | |||
| if (timebase < 0) { | |||
| jack_error("Can't set a new timebase master"); | |||
| } else { | |||
| @@ -305,7 +311,7 @@ namespace Jack | |||
| break; | |||
| 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 < 0) | |||
| 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 ? | |||
| if (fReturnTransportData.fNewState && (fReturnTransportData.fState != jack_transport_query(fJackClient, NULL))) { | |||
| if (fReturnTransportData.fNewState && (fReturnTransportData.fState != jack_transport_query(fClient, NULL))) { | |||
| switch (fReturnTransportData.fState) | |||
| { | |||
| case JackTransportStopped : | |||
| jack_transport_stop(fJackClient); | |||
| jack_transport_stop(fClient); | |||
| jack_info("'%s' stops transport", fParams.fName); | |||
| break; | |||
| 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_transport_start(fJackClient); | |||
| jack_transport_start(fClient); | |||
| jack_info("'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame); | |||
| break; | |||
| @@ -387,11 +393,22 @@ namespace Jack | |||
| 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 res; | |||
| if (!fRunning) { | |||
| return 0; | |||
| } | |||
| @@ -474,35 +491,15 @@ namespace Jack | |||
| #endif | |||
| } else { | |||
| jack_error("Connection is not synched, skip cycle..."); | |||
| jack_info("Connection is not synched, skip cycle..."); | |||
| } | |||
| //receive sync | |||
| res = SyncRecv(); | |||
| int res = SyncRecv(); | |||
| if ((res == 0) || (res == SOCKET_ERROR)) { | |||
| 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 | |||
| fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | |||
| #endif | |||
| @@ -519,26 +516,6 @@ namespace Jack | |||
| 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 | |||
| fNetTimeMon->AddLast((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | |||
| #endif | |||
| @@ -551,15 +528,17 @@ namespace Jack | |||
| { | |||
| jack_log("JackNetMasterManager::JackNetMasterManager"); | |||
| fManagerClient = client; | |||
| fManagerName = jack_get_client_name(fManagerClient); | |||
| fClient = client; | |||
| fName = jack_get_client_name(fClient); | |||
| fGlobalID = 0; | |||
| fRunning = true; | |||
| fAutoConnect = false; | |||
| const JSList* node; | |||
| const jack_driver_param_t* param; | |||
| jack_on_shutdown(fClient, SetShutDown, this); | |||
| // Possibly use env variable | |||
| const char* default_udp_port = getenv("JACK_NETJACK_PORT"); | |||
| fSocket.SetPort((default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT); | |||
| @@ -595,15 +574,15 @@ namespace Jack | |||
| } | |||
| //set sync callback | |||
| jack_set_sync_callback(fManagerClient, SetSyncCallback, this); | |||
| jack_set_sync_callback(fClient, SetSyncCallback, this); | |||
| //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"); | |||
| } | |||
| //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"); | |||
| } | |||
| } | |||
| @@ -611,15 +590,7 @@ namespace Jack | |||
| 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) | |||
| @@ -628,10 +599,10 @@ namespace Jack | |||
| int count = 0; | |||
| jack_port_t* port; | |||
| ports = jack_get_ports(fManagerClient, NULL, NULL, flags); | |||
| ports = jack_get_ports(fClient, NULL, NULL, flags); | |||
| if (ports != NULL) { | |||
| 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)) { | |||
| count++; | |||
| } | |||
| @@ -639,6 +610,27 @@ namespace Jack | |||
| } | |||
| 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) | |||
| { | |||
| @@ -719,6 +711,7 @@ namespace Jack | |||
| session_params_t net_params; | |||
| rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0); | |||
| SessionParamsNToH(&net_params, &host_params); | |||
| if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) { | |||
| jack_error("Error in receive : %s", StrError(NET_ERROR_CODE)); | |||
| if (++attempt == 10) { | |||
| @@ -728,7 +721,7 @@ namespace Jack | |||
| } | |||
| if (rx_bytes == sizeof(session_params_t)) { | |||
| switch (GetPacketType (&host_params)) | |||
| switch (GetPacketType(&host_params)) | |||
| { | |||
| case SLAVE_AVAILABLE: | |||
| if ((net_master = InitMaster(host_params))) { | |||
| @@ -764,8 +757,8 @@ namespace Jack | |||
| //settings | |||
| fSocket.GetName(params.fMasterNetName); | |||
| 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) { | |||
| params.fSendAudioChannels = CountIO(JackPortIsPhysical | JackPortIsOutput); | |||
| @@ -875,7 +868,7 @@ extern "C" | |||
| SERVER_EXPORT void jack_finish(void* arg) | |||
| { | |||
| if (master_manager) { | |||
| jack_log ("Unloading Master Manager"); | |||
| jack_log("Unloading Master Manager"); | |||
| delete master_manager; | |||
| master_manager = NULL; | |||
| } | |||
| @@ -39,14 +39,15 @@ namespace Jack | |||
| friend class JackNetMasterManager; | |||
| private: | |||
| static int SetProcess(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 SetConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg); | |||
| //jack client | |||
| jack_client_t* fJackClient; | |||
| const char* fClientName; | |||
| jack_client_t* fClient; | |||
| const char* fName; | |||
| //jack ports | |||
| jack_port_t** fAudioCapturePorts; | |||
| @@ -74,6 +75,7 @@ namespace Jack | |||
| int Process(); | |||
| void TimebaseCallback(jack_position_t* pos); | |||
| void ConnectPorts(); | |||
| void ConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect); | |||
| public: | |||
| @@ -96,14 +98,15 @@ namespace Jack | |||
| private: | |||
| static void SetShutDown(void* arg); | |||
| static int SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg); | |||
| static void* NetManagerThread(void* arg); | |||
| jack_client_t* fManagerClient; | |||
| const char* fManagerName; | |||
| jack_client_t* fClient; | |||
| const char* fName; | |||
| char fMulticastIP[32]; | |||
| JackNetSocket fSocket; | |||
| jack_native_thread_t fManagerThread; | |||
| jack_native_thread_t fThread; | |||
| master_list_t fMasterList; | |||
| uint32_t fGlobalID; | |||
| bool fRunning; | |||
| @@ -115,6 +118,7 @@ namespace Jack | |||
| int KillMaster(session_params_t* params); | |||
| int SyncCallback(jack_transport_state_t state, jack_position_t* pos); | |||
| int CountIO(int flags); | |||
| void ShutDown(); | |||
| public: | |||
| @@ -56,7 +56,7 @@ JackNetOneDriver::JackNetOneDriver(const char* name, const char* alias, JackLock | |||
| #ifdef WIN32 | |||
| WSADATA wsa; | |||
| int rc = WSAStartup(MAKEWORD(2, 0), &wsa); | |||
| WSAStartup(MAKEWORD(2, 0), &wsa); | |||
| #endif | |||
| netjack_init(& (this->netj), | |||
| @@ -753,6 +753,7 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p | |||
| extern "C" | |||
| { | |||
| #endif | |||
| SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor () | |||
| { | |||
| jack_driver_desc_t * desc; | |||
| @@ -20,7 +20,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #ifndef __JackNetSocket__ | |||
| #define __JackNetSocket__ | |||
| #include "JackError.h" | |||
| #include "JackCompilerDeps.h" | |||
| #include <cstdlib> | |||
| #include <cstdio> | |||
| #include <iostream> | |||
| @@ -29,7 +30,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| namespace Jack | |||
| { | |||
| //get host name********************************* | |||
| SERVER_EXPORT int GetHostName ( char * name, int size ); | |||
| SERVER_EXPORT int GetHostName(char * name, int size); | |||
| //net errors *********************************** | |||
| enum _net_error | |||
| @@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include "JackNetTool.h" | |||
| #include "JackError.h" | |||
| #ifdef __APPLE__ | |||
| @@ -274,7 +275,7 @@ namespace Jack | |||
| *active_port_address = htonl(port_index); | |||
| active_port_address++; | |||
| active_ports++; | |||
| assert(active_ports < 256); | |||
| assert(active_ports < 256); | |||
| } | |||
| } | |||
| @@ -306,7 +307,6 @@ namespace Jack | |||
| // Count active ports | |||
| int active_ports = 0; | |||
| for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
| if (fPortBuffer[port_index]) { | |||
| active_ports++; | |||
| } | |||
| @@ -627,7 +627,7 @@ namespace Jack | |||
| int NetCeltAudioBuffer::RenderFromJackPorts() | |||
| { | |||
| float buffer[fPeriodSize]; | |||
| float buffer[BUFFER_SIZE_MAX]; | |||
| for (int port_index = 0; port_index < fNPorts; 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; | |||
| fCaptureLatency.min = fCaptureLatency.max = 0; | |||
| fTied = NO_PORT; | |||
| fAlias1[0] = '\0'; | |||
| fAlias2[0] = '\0'; | |||
| // DB: At this point we do not know current buffer size in frames, | |||
| // but every time buffer will be returned to any user, | |||
| // it will be called with either ClearBuffer or MixBuffers | |||
| @@ -58,7 +58,7 @@ class SERVER_EXPORT JackPort | |||
| bool fInUse; | |||
| 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 | |||
| { | |||
| @@ -108,7 +108,7 @@ class SERVER_EXPORT JackPort | |||
| // Since we are in shared memory, the resulting pointer cannot be cached, so align it here... | |||
| 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; | |||
| @@ -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 "JackError.h" | |||
| #include <stdio.h> | |||
| namespace Jack | |||
| @@ -22,7 +22,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "ringbuffer.h" | |||
| #include "types.h" | |||
| #include "JackError.h" | |||
| namespace Jack | |||
| { | |||
| @@ -78,7 +78,9 @@ JackServer::~JackServer() | |||
| int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) | |||
| { | |||
| // 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) { | |||
| jack_error("Cannot initialize driver"); | |||
| @@ -140,6 +142,7 @@ int JackServer::Close() | |||
| fEngine->Close(); | |||
| // TODO: move that in reworked JackServerGlobals::Destroy() | |||
| JackMessageBuffer::Destroy(); | |||
| EndTime(); | |||
| return 0; | |||
| } | |||
| @@ -188,6 +191,8 @@ int JackServer::Stop() | |||
| { | |||
| jack_log("JackServer::Stop"); | |||
| fChannel.Stop(); | |||
| fEngine->ShutDown(); | |||
| if (fFreewheel) { | |||
| return fThreadedFreewheelDriver->Stop(); | |||
| @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackCompilerDeps.h" | |||
| #include "driver_interface.h" | |||
| #include "JackDriverLoader.h" | |||
| #include "JackDriverInfo.h" | |||
| #include "JackConnectionManager.h" | |||
| #include "JackGlobals.h" | |||
| #include "JackPlatformPlug.h" | |||
| @@ -47,10 +47,6 @@ extern "C" | |||
| 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_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, ...) | |||
| { | |||
| #ifdef __CLIENTDEBUG__ | |||
| JackGlobals::CheckContext("jack_client_open"); | |||
| #endif | |||
| try { | |||
| assert(JackGlobals::fOpenMutex); | |||
| 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) | |||
| { | |||
| #ifdef __CLIENTDEBUG__ | |||
| JackGlobals::CheckContext("jack_client_close"); | |||
| #endif | |||
| assert(JackGlobals::fOpenMutex); | |||
| JackGlobals::fOpenMutex->Lock(); | |||
| int res = -1; | |||
| @@ -33,11 +33,11 @@ | |||
| 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 | |||
| { | |||
| @@ -30,10 +30,12 @@ extern "C" | |||
| #endif | |||
| SERVER_EXPORT void InitTime(); | |||
| SERVER_EXPORT void EndTime(); | |||
| SERVER_EXPORT jack_time_t GetMicroSeconds(void); | |||
| 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 | |||
| } | |||
| @@ -24,6 +24,7 @@ | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <assert.h> | |||
| #include <signal.h> | |||
| #ifdef WIN32 | |||
| #include <process.h> | |||
| @@ -36,11 +37,7 @@ namespace Jack { | |||
| void JackTools::KillServer() | |||
| { | |||
| #ifdef WIN32 | |||
| exit(1); | |||
| #else | |||
| kill(GetPID(), SIGINT); | |||
| #endif | |||
| raise(SIGINT); | |||
| } | |||
| void JackTools::ThrowJackNetException() | |||
| @@ -294,5 +291,6 @@ void BuildClientPath(char* path_to_so, int path_len, const char* so_name) | |||
| #endif | |||
| } // end of namespace | |||
| @@ -36,10 +36,8 @@ | |||
| #endif | |||
| #include "jslist.h" | |||
| #include "driver_interface.h" | |||
| #include "JackCompilerDeps.h" | |||
| #include "JackError.h" | |||
| #include "JackException.h" | |||
| #include <string> | |||
| #include <algorithm> | |||
| @@ -112,114 +110,115 @@ namespace Jack | |||
| std::string fName; | |||
| 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); | |||
| @@ -44,8 +44,11 @@ static HMODULE libjack_handle = 0; | |||
| #else | |||
| static void *libjack_handle = 0; | |||
| #endif | |||
| #ifndef WIN32 | |||
| static void __attribute__((constructor)) tryload_libjack() | |||
| #else | |||
| void tryload_libjack() | |||
| #endif | |||
| { | |||
| if (getenv("SKIP_LIBJACK") == 0) { // just in case libjack is causing troubles.. | |||
| #ifdef __APPLE__ | |||
| @@ -30,8 +30,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "types.h" | |||
| #include "jack.h" | |||
| #include "control.h" | |||
| #include "JackConstants.h" | |||
| #include "JackDriverLoader.h" | |||
| #include "JackPlatformPlug.h" | |||
| #if defined(JACK_DBUS) && defined(__linux__) | |||
| #include <dbus/dbus.h> | |||
| @@ -86,7 +88,7 @@ static void copyright(FILE* file) | |||
| { | |||
| fprintf(file, "jackdmp " VERSION "\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" | |||
| "This is free software, and you are welcome to redistribute it\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 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; | |||
| } | |||
| 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; | |||
| } | |||
| 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; | |||
| } | |||
| parameters_list = jack_slist_next(parameters_list); | |||
| } | |||
| return NULL; | |||
| } | |||
| // Prototype to be found in libjackserver | |||
| extern "C" void silent_jack_error_callback(const char *desc); | |||
| int main(int argc, char** argv) | |||
| { | |||
| jackctl_server_t * server_ctl; | |||
| @@ -236,7 +227,7 @@ int main(int argc, char** argv) | |||
| int do_unlock = 0; | |||
| int loopback = 0; | |||
| bool show_version = false; | |||
| sigset_t signals; | |||
| jackctl_sigmask_t * sigmask; | |||
| jackctl_parameter_t* param; | |||
| union jackctl_parameter_value value; | |||
| @@ -454,12 +445,12 @@ int main(int argc, char** argv) | |||
| 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; | |||
| } | |||
| // Setup signals | |||
| signals = jackctl_setup_signals(0); | |||
| sigmask = jackctl_setup_signals(0); | |||
| // Open server | |||
| if (! jackctl_server_open(server_ctl, master_driver_ctl)) { | |||
| @@ -529,7 +520,7 @@ int main(int argc, char** argv) | |||
| return_value = 0; | |||
| // Waits for signal | |||
| jackctl_wait_signals(signals); | |||
| jackctl_wait_signals(sigmask); | |||
| stop_server: | |||
| if (!jackctl_server_stop(server_ctl)) { | |||
| @@ -28,6 +28,7 @@ extern "C" | |||
| #include <limits.h> | |||
| #include "jslist.h" | |||
| #include "JackCompilerDeps.h" | |||
| #include "JackSystemDeps.h" | |||
| @@ -75,7 +76,6 @@ typedef struct { | |||
| typedef struct { | |||
| uint32_t flags; /**< JACK_CONSTRAINT_FLAG_XXX */ | |||
| union { | |||
| struct { | |||
| jack_driver_param_value_t min; | |||
| @@ -124,28 +124,32 @@ typedef struct { | |||
| } | |||
| 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( | |||
| 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. | |||
| Can be NULL for drivers that have no parameters. */ | |||
| SERVER_EXPORT int /* 0 on failure */ | |||
| 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(). */ | |||
| 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 */ | |||
| 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 */ | |||
| 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 */ | |||
| typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| @@ -29,9 +29,10 @@ | |||
| #ifndef 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/systemdeps.h> | |||
| #if !defined (__sun__) | |||
| #if !defined(sun) && !defined(__sun__) | |||
| #include <stdbool.h> | |||
| #endif | |||
| @@ -81,6 +82,9 @@ typedef struct jackctl_internal jackctl_internal_t; | |||
| /** opaque type for parameter object */ | |||
| typedef struct jackctl_parameter jackctl_parameter_t; | |||
| /** opaque type for sigmask object */ | |||
| typedef struct jackctl_sigmask jackctl_sigmask_t; | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| @@ -102,7 +106,7 @@ extern "C" { | |||
| * | |||
| * @return the configurated signal set. | |||
| */ | |||
| sigset_t | |||
| jackctl_sigmask_t * | |||
| jackctl_setup_signals( | |||
| unsigned int flags); | |||
| @@ -113,7 +117,7 @@ jackctl_setup_signals( | |||
| */ | |||
| void | |||
| jackctl_wait_signals( | |||
| sigset_t signals); | |||
| jackctl_sigmask_t * signals); | |||
| /** | |||
| * Call this function to create server object. | |||
| @@ -330,6 +334,21 @@ const JSList * | |||
| jackctl_driver_get_parameters( | |||
| 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. | |||
| * | |||
| @@ -76,6 +76,11 @@ jack_get_version( | |||
| const char * | |||
| jack_get_version_string() JACK_OPTIONAL_WEAK_EXPORT; | |||
| /** | |||
| * @defgroup ClientFunctions Creating & manipulating clients | |||
| * @{ | |||
| */ | |||
| /** | |||
| * Open an external client session with a JACK server. This interface | |||
| * 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. | |||
| * | |||
| * @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; | |||
| @@ -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 | |||
| * 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. | |||
| */ | |||
| 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. | |||
| @@ -432,9 +437,9 @@ int jack_set_sample_rate_callback (jack_client_t *client, | |||
| * | |||
| * @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 | |||
| @@ -449,7 +454,7 @@ int jack_set_client_registration_callback (jack_client_t *, | |||
| * | |||
| * @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 | |||
| 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 | |||
| */ | |||
| int jack_set_port_connect_callback (jack_client_t *, | |||
| int jack_set_port_connect_callback (jack_client_t *client, | |||
| JackPortConnectCallback | |||
| 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 | |||
| */ | |||
| int jack_set_port_rename_callback (jack_client_t *, | |||
| int jack_set_port_rename_callback (jack_client_t *client, | |||
| JackPortRenameCallback | |||
| 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 | |||
| */ | |||
| int jack_set_graph_order_callback (jack_client_t *, | |||
| int jack_set_graph_order_callback (jack_client_t *client, | |||
| JackGraphOrderCallback graph_callback, | |||
| 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 | |||
| */ | |||
| 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; | |||
| /*@}*/ | |||
| @@ -575,7 +580,7 @@ int jack_set_xrun_callback (jack_client_t *, | |||
| * | |||
| * @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, | |||
| 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 | |||
| */ | |||
| 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 | |||
| @@ -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"). | |||
| * 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 | |||
| @@ -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. | |||
| */ | |||
| 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. | |||
| @@ -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, | |||
| * 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 *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 | |||
| */ | |||
| int jack_disconnect (jack_client_t *, | |||
| int jack_disconnect (jack_client_t *client, | |||
| const char *source_port, | |||
| 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 | |||
| * 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 | |||
| @@ -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 | |||
| * 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 | |||
| @@ -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 | |||
| * 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 | |||
| @@ -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 | |||
| * 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; | |||
| /** | |||
| @@ -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() | |||
| */ | |||
| const char ** jack_get_ports (jack_client_t *, | |||
| const char ** jack_get_ports (jack_client_t *client, | |||
| const char *port_name_pattern, | |||
| const char *type_name_pattern, | |||
| unsigned long flags) JACK_OPTIONAL_WEAK_EXPORT; | |||
| @@ -1230,7 +1235,7 @@ const char ** jack_get_ports (jack_client_t *, | |||
| * | |||
| * @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. | |||
| @@ -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; | |||
| /** | |||
| * 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 | |||
| */ | |||
| @@ -44,10 +44,10 @@ enum JackNetEncoder { | |||
| 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 time_out; // in second, -1 means in infinite | |||
| int encoder; // encoder type (one of JackNetEncoder) | |||
| @@ -58,10 +58,10 @@ 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 sample_rate; // mater sample rate | |||
| 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 | |||
| 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__ | |||
| #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 | |||
| #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 ! | |||
| #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 | |||
| /** | |||
| * 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 */ | |||
| #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 | |||
| @@ -259,6 +259,7 @@ typedef void (*JackLatencyCallback)(jack_latency_callback_mode_t mode, void *arg | |||
| /** | |||
| * the new latency API operates on Ranges. | |||
| */ | |||
| PRE_PACKED_STRUCTURE | |||
| struct _jack_latency_range | |||
| { | |||
| /** | |||
| @@ -269,7 +270,7 @@ struct _jack_latency_range | |||
| * maximum latency | |||
| */ | |||
| jack_nframes_t max; | |||
| }; | |||
| } POST_PACKED_STRUCTURE; | |||
| typedef struct _jack_latency_range jack_latency_range_t; | |||
| @@ -548,7 +549,8 @@ typedef enum { | |||
| #define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode) | |||
| #define EXTENDED_TIME_INFO | |||
| typedef struct { | |||
| PRE_PACKED_STRUCTURE | |||
| struct _jack_position { | |||
| /* these four cannot be set from clients: the server sets them */ | |||
| jack_unique_t unique_1; /**< unique ID */ | |||
| @@ -614,7 +616,9 @@ typedef struct { | |||
| /* When (unique_1 == unique_2) the contents are consistent. */ | |||
| 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. | |||
| @@ -67,6 +67,10 @@ | |||
| #endif | |||
| #endif | |||
| #ifndef JACK_WEAK_EXPORT | |||
| #define JACK_WEAK_EXPORT | |||
| #endif | |||
| #ifndef JACK_OPTIONAL_WEAK_EXPORT | |||
| #define JACK_OPTIONAL_WEAK_EXPORT | |||
| #endif | |||
| @@ -82,6 +86,11 @@ | |||
| #endif | |||
| #endif /* __GNUC__ */ | |||
| #ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT | |||
| #define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT | |||
| #endif | |||
| #endif | |||
| #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> | |||
| #endif | |||
| #ifdef __linux__ | |||
| #if defined(HAVE_CONFIG_H) | |||
| #include "config.h" | |||
| #endif | |||
| @@ -26,7 +26,7 @@ | |||
| * | |||
| */ | |||
| #ifdef __linux__ | |||
| #if defined(HAVE_CONFIG_H) | |||
| #include "config.h" | |||
| #endif | |||
| @@ -75,7 +75,7 @@ | |||
| #include "netjack_packet.h" | |||
| #include "JackError.h" | |||
| #ifdef NO_JACK_ERROR | |||
| #ifdef NO_JACK_ERROR | |||
| #define jack_error printf | |||
| #endif | |||
| @@ -505,11 +505,11 @@ packet_cache_drain_socket( packet_cache *pcache, int sockfd ) | |||
| cache_packet *cpack; | |||
| struct sockaddr_in sender_address; | |||
| #ifdef WIN32 | |||
| size_t senderlen = sizeof( struct sockaddr_in ); | |||
| int senderlen = sizeof( struct sockaddr_in ); | |||
| u_long parm = 1; | |||
| ioctlsocket( sockfd, FIONBIO, &parm ); | |||
| #else | |||
| socklen_t senderlen = sizeof( struct sockaddr_in ); | |||
| int senderlen = sizeof( struct sockaddr_in ); | |||
| #endif | |||
| while (1) { | |||
| #ifdef WIN32 | |||
| @@ -117,20 +117,17 @@ extern "C" | |||
| */ | |||
| PRE_PACKED_STRUCTURE | |||
| typedef struct _jack_shm_info { | |||
| struct _jack_shm_info { | |||
| jack_shm_registry_index_t index; /* offset into the registry */ | |||
| uint32_t size; | |||
| union { | |||
| void *attached_at; /* address where attached */ | |||
| char ptr_size[8]; | |||
| } 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 */ | |||
| 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') | |||
| 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'] | |||
| if bld.env['IS_MACOSX']: | |||
| env_includes = ['../macosx', '../posix', '../macosx/coreaudio'] | |||
| if bld.env['IS_LINUX']: | |||
| env_includes = ['../linux', '../posix', '../linux/alsa'] | |||
| env_includes = ['../linux', '../posix', '../linux/alsa'] | |||
| if bld.env['IS_SUN']: | |||
| env_includes = ['../solaris', '../posix', '../solaris/oss'] | |||
| 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("CPPFLAGS", "-fvisibility=hidden") | |||
| process.install_path = '${ADDON_DIR}/' | |||
| process.uselib_local = uselib.name | |||
| process.use = [uselib.name] | |||
| return process | |||
| def build(bld): | |||
| @@ -46,6 +46,7 @@ def build(bld): | |||
| 'JackConnectionManager.cpp', | |||
| 'ringbuffer.c', | |||
| 'JackError.cpp', | |||
| 'JackException.cpp', | |||
| 'JackFrameTimer.cpp', | |||
| 'JackGraphManager.cpp', | |||
| 'JackPort.cpp', | |||
| @@ -55,6 +56,7 @@ def build(bld): | |||
| 'JackMidiAPI.cpp', | |||
| 'JackEngineControl.cpp', | |||
| 'JackShmMem.cpp', | |||
| 'JackGenericClientChannel.cpp', | |||
| 'shm.c', | |||
| 'JackGlobals.cpp', | |||
| 'JackDebugClient.cpp', | |||
| @@ -72,8 +74,8 @@ def build(bld): | |||
| common_libsources += [ | |||
| '../posix/JackPosixThread.cpp', | |||
| '../posix/JackPosixSemaphore.cpp', | |||
| '../posix/JackFifo.cpp', | |||
| '../posix/JackProcessSync.cpp', | |||
| '../posix/JackPosixProcessSync.cpp', | |||
| '../posix/JackPosixMutex.cpp', | |||
| '../posix/JackSocket.cpp', | |||
| '../linux/JackLinuxTime.c', | |||
| ] | |||
| @@ -85,7 +87,8 @@ def build(bld): | |||
| common_libsources += [ | |||
| '../posix/JackPosixThread.cpp', | |||
| '../posix/JackFifo.cpp', | |||
| '../posix/JackProcessSync.cpp', | |||
| '../posix/JackPosixProcessSync.cpp', | |||
| '../posix/JackPosixMutex.cpp', | |||
| '../posix/JackSocket.cpp', | |||
| '../solaris/JackSolarisTime.c', | |||
| ] | |||
| @@ -94,7 +97,7 @@ def build(bld): | |||
| if bld.env['IS_MACOSX']: | |||
| common_libsources += [ | |||
| '../posix/JackProcessSync.cpp', | |||
| '../posix/JackPosixProcessSync.cpp', | |||
| '../posix/JackPosixThread.cpp', | |||
| '../macosx/JackMachThread.cpp', | |||
| '../macosx/JackMachSemaphore.cpp', | |||
| @@ -103,18 +106,17 @@ def build(bld): | |||
| ] | |||
| 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.includes = includes | |||
| serverlib.name = 'serverlib' | |||
| serverlib.target = 'jackserver' | |||
| serverlib.uselib = uselib | |||
| serverlib.use = uselib | |||
| serverlib.install_path = '${LIBDIR}' | |||
| serverlib.source = [] + common_libsources | |||
| serverlib.source += [ | |||
| 'JackAudioDriver.cpp', | |||
| 'JackTimedDriver.cpp', | |||
| 'JackTimedDriver.cpp', | |||
| 'JackMidiDriver.cpp', | |||
| 'JackDriver.cpp', | |||
| 'JackEngine.cpp', | |||
| @@ -132,6 +134,7 @@ def build(bld): | |||
| 'JackNetTool.cpp', | |||
| 'JackNetInterface.cpp', | |||
| 'JackArgParser.cpp', | |||
| 'JackRequestDecoder.cpp', | |||
| 'JackMidiAsyncQueue.cpp', | |||
| 'JackMidiAsyncWaitQueue.cpp', | |||
| 'JackMidiBufferReadQueue.cpp', | |||
| @@ -185,22 +188,23 @@ def build(bld): | |||
| serverlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") | |||
| 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.includes = includes | |||
| netlib.name = 'netlib' | |||
| netlib.target = 'jacknet' | |||
| netlib.uselib = ['SAMPLERATE', 'CELT', 'PTHREAD' , 'RT'] | |||
| netlib.use = ['SAMPLERATE', 'CELT', 'PTHREAD' , 'RT'] | |||
| netlib.install_path = '${LIBDIR}' | |||
| netlib.source = [ | |||
| 'JackNetAPI.cpp', | |||
| 'JackNetInterface.cpp', | |||
| 'JackNetTool.cpp', | |||
| 'JackException.cpp', | |||
| 'JackAudioAdapterInterface.cpp', | |||
| 'JackLibSampleRateResampler.cpp', | |||
| 'JackResampler.cpp', | |||
| 'JackGlobals.cpp', | |||
| '../posix/JackPosixMutex.cpp', | |||
| 'ringbuffer.c'] | |||
| if bld.env['IS_LINUX']: | |||
| @@ -218,13 +222,12 @@ def build(bld): | |||
| 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.uselib = uselib | |||
| clientlib.use = uselib | |||
| clientlib.install_path = '${LIBDIR}' | |||
| 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.name = 'clientlib' | |||
| clientlib.target = 'jack' | |||
| @@ -268,7 +271,7 @@ def build(bld): | |||
| clientlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") | |||
| if bld.env['BUILD_WITH_32_64']: | |||
| print "create 32bit lib..." | |||
| print("create 32bit lib...") | |||
| clientlib32bit = clientlib.clone('lib32') | |||
| create_jack_process_obj(bld, 'netmanager', 'JackNetManager.cpp', serverlib) | |||
| @@ -285,7 +288,7 @@ def build(bld): | |||
| if bld.env['BUILD_ADAPTER'] == True: | |||
| process = create_jack_process_obj(bld, 'netadapter', net_adapter_sources, serverlib) | |||
| process.uselib = 'SAMPLERATE' | |||
| process.use = 'SAMPLERATE' | |||
| audio_adapter_sources = [ | |||
| 'JackResampler.cpp', | |||
| @@ -299,33 +302,29 @@ def build(bld): | |||
| audio_adapter_sources += ['../macosx/coreaudio/JackCoreAudioAdapter.cpp'] | |||
| 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.uselib = 'SAMPLERATE' | |||
| process.use = 'SAMPLERATE' | |||
| if bld.env['BUILD_ADAPTER'] and bld.env['IS_LINUX'] and bld.env['BUILD_DRIVER_ALSA']: | |||
| audio_adapter_sources += ['../linux/alsa/JackAlsaAdapter.cpp'] | |||
| 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']: | |||
| audio_adapter_sources += ['../solaris/oss/JackOSSAdapter.cpp', 'memops.c'] | |||
| process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | |||
| process.uselib = 'SAMPLERATE' | |||
| process.use = 'SAMPLERATE' | |||
| #audio_adapter_sources += ['../windows/JackPortAudioAdapter.cpp'] | |||
| #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 | |||
| 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 "audio_reserve.h" | |||
| #include "JackError.h" | |||
| #include "jack/control.h" | |||
| #define DEVICE_MAX 2 | |||
| @@ -782,7 +782,7 @@ jack_controller_patchbay_disconnect( | |||
| ret = jack_disconnect(controller_ptr->client, port1_name, port2_name); | |||
| 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; | |||
| } | |||
| @@ -30,7 +30,7 @@ | |||
| #include "jackdbus.h" | |||
| #include "controller_internal.h" | |||
| #include "jack/session.h" | |||
| #include "common/JackError.h" | |||
| #include "jack/control.h" | |||
| #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); | |||
| #endif | |||
| #include "JackError.h" | |||
| #include "jack/control.h" | |||
| #if defined(REG_RIP) | |||
| # 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"}; | |||
| size_t i; | |||
| const char *si_code_str; | |||
| ucontext_t *ucontext = (ucontext_t*)ptr; | |||
| #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!"); | |||
| } | |||
| 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_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); | |||
| #if !defined(__alpha__) && !defined(__ia64__) && !defined(__FreeBSD_kernel__) && !defined(__arm__) && !defined(__hppa__) && !defined(__sh__) | |||
| for(i = 0; i < NGREG; i++) | |||
| @@ -171,7 +177,9 @@ int setup_sigsegv() { | |||
| memset(&action, 0, sizeof(action)); | |||
| action.sa_sigaction = signal_segv; | |||
| #ifdef SA_SIGINFO | |||
| action.sa_flags = SA_SIGINFO; | |||
| #endif | |||
| if(sigaction(SIGSEGV, &action, NULL) < 0) { | |||
| jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno)); | |||
| return 0; | |||
| @@ -6,19 +6,19 @@ import Options | |||
| import re # subst_func | |||
| 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') | |||
| def configure(conf): | |||
| 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'): | |||
| 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 | |||
| dbus_dir = conf.check_cfg(package='dbus-1', args='--variable=session_bus_services_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 | |||
| dbus_dir = dbus_dir.strip() | |||
| @@ -29,20 +29,18 @@ def configure(conf): | |||
| else: | |||
| 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") | |||
| if conf.is_defined('HAVE_EXPAT'): | |||
| conf.env['LIB_EXPAT'] = ['expat'] | |||
| 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 | |||
| conf.env['BUILD_JACKDBUS'] = True | |||
| def build(bld): | |||
| obj = bld.new_task_gen('cc', 'program') | |||
| obj = bld(features = ['c', 'cprogram'], idx=17) | |||
| if bld.env['IS_LINUX']: | |||
| sysdeps_dbus_include = ['../linux', '../posix'] | |||
| if bld.env['IS_MACOSX']: | |||
| @@ -65,20 +63,19 @@ def build(bld): | |||
| #'xml_nop.c', | |||
| 'xml_write_raw.c', | |||
| 'sigsegv.c', | |||
| 'reserve.c', | |||
| 'reserve.c', | |||
| ] | |||
| obj.use = ['serverlib'] | |||
| 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']: | |||
| 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 | |||
| 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 | |||
| # 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) | |||
| # base path where the generated documentation will be put. | |||