Commit 1685eec0 authored by Nedko Arnaudov's avatar Nedko Arnaudov
Browse files

Merge branch 'master' into no-self-connect

Conflicts:
	common/JackEngine.cpp
	common/JackServerGlobals.cpp
	common/Jackdmp.cpp
parents e23d840f f2a40116
......@@ -27,11 +27,102 @@ Mario Lang
Arnold Krille
Jan Engelhardt
Adrian Knoth
David Garcia Garzon
David Garcia Garzon
Valerio Pilo
---------------------------
Jackdmp changes log
---------------------------
---------------------------
2011-03-13 Stephane Letz <letz@grame.fr>
* Rework internal slave driver management, JackServerGlobals now handle same parameters as jackdmp.
2011-03-11 Stephane Letz <letz@grame.fr>
* Correct JackNetMaster::SetBufferSize.
* Use jack_default_audio_sample_t instead of float consistently, fix ticket #201."
* -X now allows to add several slave backends, add -I to load several internal clients.
2011-03-10 Stephane Letz <letz@grame.fr>
* Latency callback must always be activated.
* Correct TopologicalSort.
* Add jack_midi_dump client.
* Synchronize netjack1 with JACK1 version.
* Synchronize jack_connect/jack_disconnect with JACK1 version.
2011-03-09 Stephane Letz <letz@grame.fr>
* jack_client_has_session_callback implementation.
* Fix jdelay for new latency API.
* Check requested buffer size and limit to 1..8192 - avoids wierd behaviour caused by jack_bufsize foobar.
* jack_port_type_get_buffer_size implementation.
* Stop using alloca and allocate buffer on the heap for alsa_io.
* Rename jdelay to jack_iodelay as per Fons' request.
* Call buffer size callback in activate (actually this is done on client side in the RT thread Init method).
* JackEngine::ComputeTotalLatencies in progress.
2011-03-08 Stephane Letz <letz@grame.fr>
* Use of latency range in all backends.
* ComputeTotalLatencies now a client/server call.
* Add latent test client for latency API.
* Also print playback and capture latency in jack_lsp.
2011-03-04 Stephane Letz <letz@grame.fr>
* Revert r4119 (RT notification in the server). JackAudioDriver::ProcessSync now skip backend write in case of graph process failure.
* Fix incorrect error codes in alsa/usx2y.c and alsa/JackAlsaDriver.cpp.
* Synchronize public headers with JACK1. Update OSX project.
* New latency API implementation (in progress).
2011-02-09 Stephane Letz <letz@grame.fr>
* Remove JackPortIsActive flag.
2011-02-07 Stephane Letz <letz@grame.fr>
* Valerio Pilo second CAS for ARMv7 patch.
2011-02-03 Stephane Letz <letz@grame.fr>
* Valerio Pilo CAS for ARMv7 patch.
2011-01-11 Stephane Letz <letz@grame.fr>
* Adrian Knoth jack_lsp patch.
2010-11-17 Stephane Letz <letz@grame.fr>
* ALSA backend : suspend/resume handling (jack1 r4075).
* Correct dummy driver.
2010-11-05 Stephane Letz <letz@grame.fr>
* In jackdmp.cpp, jackctl_setup_signals moved before jackctl_server_start.
* Correct symbols export in backends on OSX.
2010-11-03 Stephane Letz <letz@grame.fr>
* Improve backend error handling: fatal error returned by Read/Write now cause a Process failure (so a thread exit for blocking backends). Recoverable ones (XRuns..) are now treated internally in ALSA, FreeBob and FFADO backends.
2010-10-30 Stephane Letz <letz@grame.fr>
* Correct JackServer::Open to avoid a race when control API is used on OSX.
2010-10-29 Stephane Letz <letz@grame.fr>
* Correct lsp.c code.
* Add note about unique port-name requirement.
2010-09-08 Stephane Letz <letz@grame.fr>
* Sync JackAlsaDriver::alsa_driver_check_card_type with JACK1 backend.
2010-08-30 Stephane Letz <letz@grame.fr>
* Version 1.9.7 started.
2010-08-25 Stephane Letz <letz@grame.fr>
......
This diff is collapsed.
......@@ -36,17 +36,17 @@ namespace Jack
int JackAudioAdapter::Process (jack_nframes_t frames, void* arg)
{
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
float* inputBuffer[adapter->fAudioAdapter->GetInputs()];
float* outputBuffer[adapter->fAudioAdapter->GetOutputs()];
jack_default_audio_sample_t* inputBuffer[adapter->fAudioAdapter->GetInputs()];
jack_default_audio_sample_t* outputBuffer[adapter->fAudioAdapter->GetOutputs()];
// Always clear output
for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
inputBuffer[i] = (float*)jack_port_get_buffer(adapter->fCapturePortList[i], frames);
memset(inputBuffer[i], 0, frames * sizeof(float));
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 < adapter->fAudioAdapter->GetOutputs(); i++) {
outputBuffer[i] = (float*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames);
outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames);
}
adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames);
......
......@@ -88,18 +88,18 @@ namespace Jack
JackResampler** fCaptureRingBuffer;
JackResampler** fPlaybackRingBuffer;
unsigned int fQuality;
unsigned int fRingbufferCurSize;
jack_time_t fPullAndPushTime;
bool fRunning;
bool fAdaptative;
void ResetRingBuffers();
void AdaptRingBufferSize();
void GrowRingBufferSize();
public:
JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ):
......@@ -122,15 +122,15 @@ namespace Jack
{}
virtual void Reset();
void Create();
void Destroy();
virtual int Open()
{
return 0;
}
virtual int Close()
{
return 0;
......@@ -139,7 +139,7 @@ namespace Jack
virtual int SetHostBufferSize ( jack_nframes_t buffer_size )
{
fHostBufferSize = buffer_size;
if (fAdaptative)
if (fAdaptative)
AdaptRingBufferSize();
return 0;
}
......@@ -147,7 +147,7 @@ namespace Jack
virtual int SetAdaptedBufferSize ( jack_nframes_t buffer_size )
{
fAdaptedBufferSize = buffer_size;
if (fAdaptative)
if (fAdaptative)
AdaptRingBufferSize();
return 0;
}
......@@ -179,7 +179,7 @@ namespace Jack
SetAdaptedSampleRate ( sample_rate );
return 0;
}
void SetInputs ( int inputs )
{
jack_log ( "JackAudioAdapterInterface::SetInputs %d", inputs );
......@@ -203,10 +203,10 @@ namespace Jack
jack_log ( "JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels );
return fPlaybackChannels;
}
int PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int inNumberFrames);
int PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int inNumberFrames);
int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int inNumberFrames);
int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int inNumberFrames);
};
}
......
......@@ -101,6 +101,7 @@ int JackAudioDriver::Attach()
jack_port_id_t port_index;
char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
jack_latency_range_t range;
int i;
jack_log("JackAudioDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
......@@ -114,7 +115,8 @@ int JackAudioDriver::Attach()
}
port = fGraphManager->GetPort(port_index);
port->SetAlias(alias);
port->SetLatency(fEngineControl->fBufferSize + fCaptureLatency);
range.min = range.max = fEngineControl->fBufferSize + fCaptureLatency;
port->SetLatencyRange(JackCaptureLatency, &range);
fCapturePortList[i] = port_index;
jack_log("JackAudioDriver::Attach fCapturePortList[i] port_index = %ld", port_index);
}
......@@ -129,7 +131,8 @@ int JackAudioDriver::Attach()
port = fGraphManager->GetPort(port_index);
port->SetAlias(alias);
// Add more latency if "async" mode is used...
port->SetLatency(fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + fPlaybackLatency);
range.min = range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + fPlaybackLatency;
port->SetLatencyRange(JackPlaybackLatency, &range);
fPlaybackPortList[i] = port_index;
jack_log("JackAudioDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index);
......@@ -143,7 +146,8 @@ int JackAudioDriver::Attach()
} else {
port = fGraphManager->GetPort(port_index);
port->SetAlias(alias);
port->SetLatency(fEngineControl->fBufferSize);
range.min = range.max = fEngineControl->fBufferSize;
port->SetLatencyRange(JackCaptureLatency, &range);
fMonitorPortList[i] = port_index;
}
}
......@@ -174,8 +178,8 @@ int JackAudioDriver::Write()
{
for (int i = 0; i < fPlaybackChannels; i++) {
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
float* buffer = GetOutputBuffer(i);
int size = sizeof(float) * fEngineControl->fBufferSize;
jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
// Monitor ports
if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
memcpy(GetMonitorBuffer(i), buffer, size);
......@@ -188,14 +192,14 @@ int JackAudioDriver::ProcessNull()
{
// Keep begin cycle time
JackDriver::CycleTakeBeginTime();
if (fEngineControl->fSyncMode) {
ProcessGraphSync();
} else {
ProcessGraphAsync();
}
// Keep end cycle time
// Keep end cycle time
JackDriver::CycleTakeEndTime();
WaitUntilNextCycle();
return 0;
......@@ -214,23 +218,24 @@ synchronize to the end of client graph execution.
int JackAudioDriver::ProcessAsync()
{
// Read input buffers for the current cycle
if (Read() < 0) {
jack_error("JackAudioDriver::ProcessAsync: read error, skip cycle");
return 0; // Skip cycle, but continue processing...
if (Read() < 0) {
jack_error("JackAudioDriver::ProcessAsync: read error, stopping...");
return -1;
}
// Write output buffers from the previous cycle
if (Write() < 0) {
jack_error("JackAudioDriver::ProcessAsync: write error, skip cycle");
return 0; // Skip cycle, but continue processing...
jack_error("JackAudioDriver::ProcessAsync: write error, stopping...");
return -1;
}
// Process graph
if (fIsMaster) {
ProcessGraphAsync();
} else {
fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
}
// Keep end cycle time
JackDriver::CycleTakeEndTime();
return 0;
......@@ -238,29 +243,38 @@ int JackAudioDriver::ProcessAsync()
/*
The driver SYNC mode: the server does synchronize to the end of client graph execution,
output buffers computed at the *current cycle* are used.
if graph process succeed, output buffers computed at the *current cycle* are used.
*/
int JackAudioDriver::ProcessSync()
{
// Read input buffers for the current cycle
if (Read() < 0) {
jack_error("JackAudioDriver::ProcessSync: read error, skip cycle");
return 0; // Skip cycle, but continue processing...
if (Read() < 0) {
jack_error("JackAudioDriver::ProcessSync: read error, stopping...");
return -1;
}
// Process graph
if (fIsMaster) {
ProcessGraphSync();
if (ProcessGraphSync() < 0) {
jack_error("JackAudioDriver::ProcessSync: process error, skip cycle...");
goto end;
}
} else {
fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) {
jack_error("JackAudioDriver::ProcessSync: process error, skip cycle...");
goto end;
}
}
// Write output buffers for the current cycle
if (Write() < 0) {
jack_error("JackAudioDriver::ProcessSync: write error, skip cycle");
return 0; // Skip cycle, but continue processing...
// Write output buffers from the current cycle
if (Write() < 0) {
jack_error("JackAudioDriver::ProcessSync: write error, stopping...");
return -1;
}
end:
// Keep end cycle time
JackDriver::CycleTakeEndTime();
return 0;
......@@ -269,25 +283,34 @@ int JackAudioDriver::ProcessSync()
void JackAudioDriver::ProcessGraphAsync()
{
// fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle
if (!fEngine->Process(fBeginDateUst, fEndDateUst))
jack_error("JackAudioDriver::ProcessAsync Process error");
if (!fEngine->Process(fBeginDateUst, fEndDateUst))
jack_error("JackAudioDriver::ProcessGraphAsync: Process error");
fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
if (ProcessSlaves() < 0)
jack_error("JackAudioDriver::ProcessAsync ProcessSlaves error");
jack_error("JackAudioDriver::ProcessGraphAsync: ProcessSlaves error");
}
void JackAudioDriver::ProcessGraphSync()
int JackAudioDriver::ProcessGraphSync()
{
int res = 0;
// fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle
if (fEngine->Process(fBeginDateUst, fEndDateUst)) {
if (fEngine->Process(fBeginDateUst, fEndDateUst)) {
fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
if (ProcessSlaves() < 0)
jack_error("JackAudioDriver::ProcessSync ProcessSlaves error, engine may now behave abnormally!!");
if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0)
jack_error("JackAudioDriver::ProcessSync SuspendRefNum error, engine may now behave abnormally!!");
if (ProcessSlaves() < 0) {
jack_error("JackAudioDriver::ProcessGraphSync: ProcessSlaves error, engine may now behave abnormally!!");
res = -1;
}
if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0) {
jack_error("JackAudioDriver::ProcessGraphSync: SuspendRefNum error, engine may now behave abnormally!!");
res = -1;
}
} else { // Graph not finished: do not activate it
jack_error("JackAudioDriver::ProcessSync: error");
jack_error("JackAudioDriver::ProcessGraphSync: Process error");
res = -1;
}
return res;
}
void JackAudioDriver::WaitUntilNextCycle()
......@@ -316,4 +339,37 @@ jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index)
return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize);
}
int JackAudioDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
switch (notify) {
case kLatencyCallback:
HandleLatencyCallback(value1);
break;
default:
JackDriver::ClientNotify(refnum, name, notify, sync, message, value1, value2);
break;
}
return 0;
}
void JackAudioDriver::HandleLatencyCallback(int status)
{
jack_latency_callback_mode_t mode = (status == 0) ? JackCaptureLatency : JackPlaybackLatency;
for (int i = 0; i < fCaptureChannels; i++) {
if (mode == JackPlaybackLatency) {
fGraphManager->RecalculateLatency(fCapturePortList[i], mode);
}
}
for (int i = 0; i < fPlaybackChannels; i++) {
if (mode == JackCaptureLatency) {
fGraphManager->RecalculateLatency(fPlaybackPortList[i], mode);
}
}
}
} // end of namespace
......@@ -36,12 +36,12 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver
protected:
void ProcessGraphAsync();
void ProcessGraphSync();
int ProcessGraphSync();
void WaitUntilNextCycle();
virtual int ProcessAsync();
virtual int ProcessSync();
int fCaptureChannels;
int fPlaybackChannels;
......@@ -57,6 +57,8 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver
jack_default_audio_sample_t* GetOutputBuffer(int port_index);
jack_default_audio_sample_t* GetMonitorBuffer(int port_index);
void HandleLatencyCallback(int status);
public:
JackAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table);
......@@ -73,7 +75,7 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver
const char* playback_driver_name,
jack_nframes_t capture_latency,
jack_nframes_t playback_latency);
virtual int Open(bool capturing,
bool playing,
int inchannels,
......@@ -83,18 +85,20 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver
const char* playback_driver_name,
jack_nframes_t capture_latency,
jack_nframes_t playback_latency);
virtual int Process();
virtual int ProcessNull();
virtual int Attach();
virtual int Detach();
virtual int Write();
virtual int SetBufferSize(jack_nframes_t buffer_size);
virtual int SetSampleRate(jack_nframes_t sample_rate);
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2);
};
} // end of namespace
......
......@@ -18,7 +18,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "JackGlobals.h"
#include "JackEngineControl.h"
#include "JackPortType.h"
#include <string.h>
#if defined (__APPLE__)
......@@ -35,18 +38,18 @@ static void AudioBufferInit(void* buffer, size_t buffer_size, jack_nframes_t)
memset(buffer, 0, buffer_size);
}
static inline void MixAudioBuffer(float* mixbuffer, float* buffer, jack_nframes_t frames)
static inline void MixAudioBuffer(jack_default_audio_sample_t* mixbuffer, jack_default_audio_sample_t* buffer, jack_nframes_t frames)
{
#ifdef __APPLE__
// It seems that a vector mult only operation does not exist...
float gain = 1.0f;
jack_default_audio_sample_t gain = jack_default_audio_sample_t(1.0);
vDSP_vsma(buffer, 1, &gain, mixbuffer, 1, mixbuffer, 1, frames);
#else
jack_nframes_t frames_group = frames / 4;
frames = frames % 4;
while (frames_group > 0) {
#if defined (__SSE__) && !defined (__sun__)
#if defined (__SSE__) && !defined (__sun__)
__m128 vec = _mm_add_ps(_mm_load_ps(mixbuffer), _mm_load_ps(buffer));
_mm_store_ps(mixbuffer, vec);
......@@ -54,14 +57,14 @@ static inline void MixAudioBuffer(float* mixbuffer, float* buffer, jack_nframes_
buffer += 4;
frames_group--;
#else
register float mixFloat1 = *mixbuffer;
register float sourceFloat1 = *buffer;
register float mixFloat2 = *(mixbuffer + 1);
register float sourceFloat2 = *(buffer + 1);
register float mixFloat3 = *(mixbuffer + 2);
register float sourceFloat3 = *(buffer + 2);
register float mixFloat4 = *(mixbuffer + 3);
register float sourceFloat4 = *(buffer + 3);
register jack_default_audio_sample_t mixFloat1 = *mixbuffer;
register jack_default_audio_sample_t sourceFloat1 = *buffer;
register jack_default_audio_sample_t mixFloat2 = *(mixbuffer + 1);
register jack_default_audio_sample_t sourceFloat2 = *(buffer + 1);
register jack_default_audio_sample_t mixFloat3 = *(mixbuffer + 2);
register jack_default_audio_sample_t sourceFloat3 = *(buffer + 2);
register jack_default_audio_sample_t mixFloat4 = *(mixbuffer + 3);
register jack_default_audio_sample_t sourceFloat4 = *(buffer + 3);
buffer += 4;
frames_group--;
......@@ -81,8 +84,8 @@ static inline void MixAudioBuffer(float* mixbuffer, float* buffer, jack_nframes_
}
while (frames > 0) {
register float mixFloat1 = *mixbuffer;
register float sourceFloat1 = *buffer;
register jack_default_audio_sample_t mixFloat1 = *mixbuffer;
register jack_default_audio_sample_t sourceFloat1 = *buffer;
buffer++;
frames--;
mixFloat1 += sourceFloat1;
......@@ -97,12 +100,12 @@ static void AudioBufferMixdown(void* mixbuffer, void** src_buffers, int src_coun
void* buffer;
// Copy first buffer
#if defined (__SSE__) && !defined (__sun__)
#if defined (__SSE__) && !defined (__sun__)
jack_nframes_t frames_group = nframes / 4;
jack_nframes_t remaining_frames = nframes % 4;
float * source = static_cast<float*>(src_buffers[0]);
float * target = static_cast<float*>(mixbuffer);
jack_default_audio_sample_t * source = static_cast<jack_default_audio_sample_t*>(src_buffers[0]);
jack_default_audio_sample_t * target = static_cast<jack_default_audio_sample_t*>(mixbuffer);
while (frames_group > 0)
{
......@@ -117,22 +120,28 @@ static void AudioBufferMixdown(void* mixbuffer, void** src_buffers, int src_coun
target[i] = source[i];
#else
memcpy(mixbuffer, src_buffers[0], nframes * sizeof(float));
memcpy(mixbuffer, src_buffers[0], nframes * sizeof(jack_default_audio_sample_t));
#endif
// Mix remaining buffers
for (int i = 1; i < src_count; ++i) {
buffer = src_buffers[i];
MixAudioBuffer(static_cast<float*>(mixbuffer), static_cast<float*>(buffer), nframes);
MixAudioBuffer(static_cast<jack_default_audio_sample_t*>(mixbuffer), static_cast<jack_default_audio_sample_t*>(buffer), nframes);
}
}
static size_t AudioBufferSize()
{
return GetEngineControl()->fBufferSize * sizeof(jack_default_audio_sample_t);
}
const JackPortType gAudioPortType =
{
JACK_DEFAULT_AUDIO_TYPE,
AudioBufferInit,
AudioBufferMixdown
};
{
JACK_DEFAULT_AUDIO_TYPE,
AudioBufferSize,
AudioBufferInit,
AudioBufferMixdown
};
} // namespace Jack
......@@ -12,7 +12,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.