Browse Source

Merge branch 'master' into param-order

Conflicts:
	common/JackControlAPI.cpp
tags/1.9.9.5
Nedko Arnaudov 13 years ago
parent
commit
13f7852c26
100 changed files with 3507 additions and 1694 deletions
  1. +4
    -0
      .gitignore
  2. +82
    -0
      ChangeLog
  3. +317
    -0
      common/JackAC3Encoder.cpp
  4. +100
    -0
      common/JackAC3Encoder.h
  5. +149
    -243
      common/JackAPI.cpp
  6. +16
    -8
      common/JackAudioAdapter.cpp
  7. +4
    -0
      common/JackAudioAdapter.h
  8. +72
    -0
      common/JackAudioAdapterInterface.cpp
  9. +10
    -69
      common/JackAudioAdapterInterface.h
  10. +5
    -10
      common/JackAudioDriver.cpp
  11. +48
    -0
      common/JackChannel.h
  12. +50
    -42
      common/JackClient.cpp
  13. +2
    -1
      common/JackClient.h
  14. +3
    -3
      common/JackClientInterface.h
  15. +2
    -2
      common/JackConstants.h
  16. +65
    -54
      common/JackControlAPI.cpp
  17. +8
    -11
      common/JackControlAPI.h
  18. +49
    -7
      common/JackDebugClient.cpp
  19. +6
    -1
      common/JackDebugClient.h
  20. +4
    -10
      common/JackDriver.cpp
  21. +1
    -1
      common/JackDriver.h
  22. +55
    -0
      common/JackDriverInfo.h
  23. +154
    -229
      common/JackDriverLoader.cpp
  24. +4
    -42
      common/JackDriverLoader.h
  25. +118
    -71
      common/JackEngine.cpp
  26. +15
    -9
      common/JackEngine.h
  27. +3
    -2
      common/JackEngineControl.cpp
  28. +9
    -1
      common/JackEngineControl.h
  29. +5
    -5
      common/JackError.cpp
  30. +7
    -11
      common/JackError.h
  31. +34
    -0
      common/JackException.cpp
  32. +5
    -9
      common/JackException.h
  33. +109
    -16
      common/JackFrameTimer.cpp
  34. +4
    -3
      common/JackFrameTimer.h
  35. +4
    -1
      common/JackFreewheelDriver.cpp
  36. +298
    -0
      common/JackGenericClientChannel.cpp
  37. +103
    -0
      common/JackGenericClientChannel.h
  38. +12
    -2
      common/JackGlobals.cpp
  39. +3
    -2
      common/JackGlobals.h
  40. +1
    -1
      common/JackGraphManager.cpp
  41. +13
    -3
      common/JackInternalClient.cpp
  42. +3
    -3
      common/JackInternalClient.h
  43. +6
    -14
      common/JackInternalClientChannel.h
  44. +2
    -4
      common/JackLibAPI.cpp
  45. +14
    -0
      common/JackLibClient.cpp
  46. +2
    -1
      common/JackLibClient.h
  47. +5
    -2
      common/JackLibGlobals.h
  48. +1
    -0
      common/JackLibSampleRateResampler.cpp
  49. +24
    -16
      common/JackLockedEngine.h
  50. +3
    -0
      common/JackLoopbackDriver.cpp
  51. +61
    -15
      common/JackMessageBuffer.cpp
  52. +6
    -6
      common/JackMessageBuffer.h
  53. +1
    -0
      common/JackMidiBufferReadQueue.cpp
  54. +1
    -0
      common/JackMidiBufferWriteQueue.cpp
  55. +7
    -0
      common/JackMidiDriver.cpp
  56. +1
    -0
      common/JackMidiRawInputWriteQueue.cpp
  57. +2
    -1
      common/JackMutex.h
  58. +147
    -95
      common/JackNetAPI.cpp
  59. +2
    -1
      common/JackNetAdapter.cpp
  60. +12
    -3
      common/JackNetDriver.cpp
  61. +51
    -81
      common/JackNetInterface.cpp
  62. +13
    -19
      common/JackNetInterface.h
  63. +91
    -98
      common/JackNetManager.cpp
  64. +10
    -6
      common/JackNetManager.h
  65. +2
    -1
      common/JackNetOneDriver.cpp
  66. +3
    -2
      common/JackNetSocket.h
  67. +3
    -3
      common/JackNetTool.cpp
  68. +2
    -0
      common/JackPort.cpp
  69. +2
    -2
      common/JackPort.h
  70. +209
    -120
      common/JackRequest.h
  71. +351
    -0
      common/JackRequestDecoder.cpp
  72. +63
    -0
      common/JackRequestDecoder.h
  73. +1
    -0
      common/JackResampler.cpp
  74. +0
    -1
      common/JackResampler.h
  75. +6
    -1
      common/JackServer.cpp
  76. +1
    -0
      common/JackServer.h
  77. +2
    -8
      common/JackServerAPI.cpp
  78. +5
    -5
      common/JackShmMem.h
  79. +4
    -2
      common/JackTime.h
  80. +3
    -5
      common/JackTools.cpp
  81. +108
    -109
      common/JackTools.h
  82. +4
    -1
      common/JackWeakAPI.c
  83. +19
    -28
      common/Jackdmp.cpp
  84. +13
    -9
      common/driver_interface.h
  85. +22
    -3
      common/jack/control.h
  86. +78
    -24
      common/jack/jack.h
  87. +8
    -8
      common/jack/net.h
  88. +88
    -50
      common/jack/systemdeps.h
  89. +7
    -3
      common/jack/types.h
  90. +9
    -0
      common/jack/weakmacros.h
  91. +1
    -1
      common/netjack.c
  92. +4
    -4
      common/netjack_packet.c
  93. +5
    -8
      common/shm.h
  94. +36
    -37
      common/wscript
  95. +1
    -1
      dbus/audio_reserve.c
  96. +1
    -1
      dbus/controller_iface_patchbay.c
  97. +1
    -1
      dbus/controller_iface_session_manager.c
  98. +10
    -2
      dbus/sigsegv.c
  99. +16
    -19
      dbus/wscript
  100. +1
    -1
      doxyfile

+ 4
- 0
.gitignore View File

@@ -0,0 +1,4 @@
build/
man/*.1
.waf*
.lock*

+ 82
- 0
ChangeLog View File

@@ -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.


+ 317
- 0
common/JackAC3Encoder.cpp View File

@@ -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

+ 100
- 0
common/JackAC3Encoder.h View File

@@ -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

+ 149
- 243
common/JackAPI.cpp
File diff suppressed because it is too large
View File


+ 16
- 8
common/JackAudioAdapter.cpp View File

@@ -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) {


+ 4
- 0
common/JackAudioAdapter.h View File

@@ -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:



+ 72
- 0
common/JackAudioAdapterInterface.cpp View File

@@ -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

+ 10
- 69
common/JackAudioAdapterInterface.h View File

@@ -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; }


+ 5
- 10
common/JackAudioDriver.cpp View File

@@ -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);
}



+ 48
- 0
common/JackChannel.h View File

@@ -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.
*/


+ 50
- 42
common/JackClient.cpp View File

@@ -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;


+ 2
- 1
common/JackClient.h View File

@@ -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;


+ 3
- 3
common/JackClientInterface.h View File

@@ -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;


+ 2
- 2
common/JackConstants.h View File

@@ -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


+ 65
- 54
common/JackControlAPI.cpp View File

@@ -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) {


+ 8
- 11
common/JackControlAPI.h View File

@@ -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


+ 49
- 7
common/JackDebugClient.cpp View File

@@ -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);
}



+ 6
- 1
common/JackDebugClient.h View File

@@ -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);


+ 4
- 10
common/JackDriver.cpp View File

@@ -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);


+ 1
- 1
common/JackDriver.h View File

@@ -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


+ 55
- 0
common/JackDriverInfo.h View File

@@ -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


+ 154
- 229
common/JackDriverLoader.cpp View File

@@ -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;
}

+ 4
- 42
common/JackDriverLoader.h View File

@@ -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


+ 118
- 71
common/JackEngine.cpp View File

@@ -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;
}
}



+ 15
- 9
common/JackEngine.h View File

@@ -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);
};




+ 3
- 2
common/JackEngineControl.cpp View File

@@ -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

+ 9
- 1
common/JackEngineControl.h View File

@@ -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)


+ 5
- 5
common/JackError.cpp View File

@@ -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));
}



+ 7
- 11
common/JackError.h View File

@@ -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
}


+ 34
- 0
common/JackException.cpp View File

@@ -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());
}
}

}

+ 5
- 9
common/JackException.h View File

@@ -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.


+ 109
- 16
common/JackFrameTimer.cpp View File

@@ -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
}


+ 4
- 3
common/JackFrameTimer.h View File

@@ -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);



+ 4
- 1
common/JackFreewheelDriver.cpp View File

@@ -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;


+ 298
- 0
common/JackGenericClientChannel.cpp View File

@@ -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






+ 103
- 0
common/JackGenericClientChannel.h View File

@@ -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


+ 12
- 2
common/JackGlobals.cpp View File

@@ -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

+ 3
- 2
common/JackGlobals.h View File

@@ -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.


+ 1
- 1
common/JackGraphManager.cpp View File

@@ -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


+ 13
- 3
common/JackInternalClient.cpp View File

@@ -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)


+ 3
- 3
common/JackInternalClient.h View File

@@ -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);


+ 6
- 14
common/JackInternalClientChannel.h View File

@@ -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);
}




+ 2
- 4
common/JackLibAPI.cpp View File

@@ -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;


+ 14
- 0
common/JackLibClient.cpp View File

@@ -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);


+ 2
- 1
common/JackLibClient.h View File

@@ -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);



+ 5
- 2
common/JackLibGlobals.h View File

@@ -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;
}


+ 1
- 0
common/JackLibSampleRateResampler.cpp View File

@@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "JackLibSampleRateResampler.h"
#include "JackError.h"

namespace Jack
{


+ 24
- 16
common/JackLockedEngine.h View File

@@ -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
}
};



+ 3
- 0
common/JackLoopbackDriver.cpp View File

@@ -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;


+ 61
- 15
common/JackMessageBuffer.cpp View File

@@ -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;
}

};


+ 6
- 6
common/JackMessageBuffer.h View File

@@ -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;
};


+ 1
- 0
common/JackMidiBufferReadQueue.cpp View File

@@ -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;



+ 1
- 0
common/JackMidiBufferWriteQueue.cpp View File

@@ -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;



+ 7
- 0
common/JackMidiDriver.cpp View File

@@ -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;
}



+ 1
- 0
common/JackMidiRawInputWriteQueue.cpp View File

@@ -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;



+ 2
- 1
common/JackMutex.h View File

@@ -40,7 +40,8 @@ class JackLockAble

JackMutex fMutex;

JackLockAble()
JackLockAble(const char* name = NULL)
:fMutex(name)
{}
~JackLockAble()
{}


+ 147
- 95
common/JackNetAPI.cpp View File

@@ -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


+ 2
- 1
common/JackNetAdapter.cpp View File

@@ -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;


+ 12
- 3
common/JackNetDriver.cpp View File

@@ -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) {


+ 51
- 81
common/JackNetInterface.cpp View File

@@ -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;
}



+ 13
- 19
common/JackNetInterface.h View File

@@ -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:



+ 91
- 98
common/JackNetManager.cpp View File

@@ -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;
}


+ 10
- 6
common/JackNetManager.h View File

@@ -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:



+ 2
- 1
common/JackNetOneDriver.cpp View File

@@ -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;


+ 3
- 2
common/JackNetSocket.h View File

@@ -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


+ 3
- 3
common/JackNetTool.cpp View File

@@ -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]) {


+ 2
- 0
common/JackPort.cpp View File

@@ -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


+ 2
- 2
common/JackPort.h View File

@@ -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;


+ 209
- 120
common/JackRequest.h
File diff suppressed because it is too large
View File


+ 351
- 0
common/JackRequestDecoder.cpp View File

@@ -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



+ 63
- 0
common/JackRequestDecoder.h View File

@@ -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

+ 1
- 0
common/JackResampler.cpp View File

@@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "JackResampler.h"
#include "JackError.h"
#include <stdio.h>

namespace Jack


+ 0
- 1
common/JackResampler.h View File

@@ -22,7 +22,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "ringbuffer.h"
#include "types.h"
#include "JackError.h"

namespace Jack
{


+ 6
- 1
common/JackServer.cpp View File

@@ -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();


+ 1
- 0
common/JackServer.h View File

@@ -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"


+ 2
- 8
common/JackServerAPI.cpp View File

@@ -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;


+ 5
- 5
common/JackShmMem.h View File

@@ -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
{


+ 4
- 2
common/JackTime.h View File

@@ -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
}


+ 3
- 5
common/JackTools.cpp View File

@@ -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


+ 108
- 109
common/JackTools.h View File

@@ -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);


+ 4
- 1
common/JackWeakAPI.c View File

@@ -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__


+ 19
- 28
common/Jackdmp.cpp View File

@@ -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)) {


+ 13
- 9
common/driver_interface.h View File

@@ -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


+ 22
- 3
common/jack/control.h View File

@@ -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.
*


+ 78
- 24
common/jack/jack.h View File

@@ -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
*/


+ 8
- 8
common/jack/net.h View File

@@ -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


+ 88
- 50
common/jack/systemdeps.h View File

@@ -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

+ 7
- 3
common/jack/types.h View File

@@ -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.


+ 9
- 0
common/jack/weakmacros.h View File

@@ -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__ */


+ 1
- 1
common/netjack.c View File

@@ -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



+ 4
- 4
common/netjack_packet.c View File

@@ -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


+ 5
- 8
common/shm.h View File

@@ -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*,


+ 36
- 37
common/wscript View File

@@ -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,
)

+ 1
- 1
dbus/audio_reserve.c View File

@@ -26,7 +26,7 @@

#include "reserve.h"
#include "audio_reserve.h"
#include "JackError.h"
#include "jack/control.h"

#define DEVICE_MAX 2



+ 1
- 1
dbus/controller_iface_patchbay.c View File

@@ -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;
}



+ 1
- 1
dbus/controller_iface_session_manager.c View File

@@ -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"



+ 10
- 2
dbus/sigsegv.c View File

@@ -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;


+ 16
- 19
dbus/wscript View File

@@ -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')

+ 1
- 1
doxyfile View File

@@ -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.


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save