Commit 62966c28 authored by sletz's avatar sletz
Browse files

rebase form trunk 3367:3401

git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3402 0c269be4-1314-0410-8aa9-9f06e86f4224
parent aa157032
......@@ -23,6 +23,19 @@ Michael Voigt
Jackdmp changes log
---------------------------
2009-03-05 Stephane Letz <letz@grame.fr>
* Support for BIG_ENDIAN machines in NetJack2 for transport data.
* Add auto_connect parameter in netmanager and netadapter.
2009-03-03 Stephane Letz <letz@grame.fr>
* More robust profiling tools when clients come and go.
2009-03-01 Stephane Letz <letz@grame.fr>
* Raise default port number to 1024.
2009-02-27 Stephane Letz <letz@grame.fr>
* Improve generated gnuplot files for adapting code.
......
......@@ -69,6 +69,24 @@ namespace Jack
}
//JackAudioAdapter *********************************************************
JackAudioAdapter::JackAudioAdapter (jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params, bool system)
:fJackClient(jack_client), fAudioAdapter(audio_io)
{
const JSList* node;
const jack_driver_param_t* param;
fAutoConnect = false;
for (node = params; node; node = jack_slist_next(node)) {
param = (const jack_driver_param_t*) node->data;
switch (param->character) {
case 'c':
fAutoConnect = param->value.i;
break;
}
}
}
JackAudioAdapter::~JackAudioAdapter()
{
// When called, Close has already been used for the client, thus ports are already unregistered.
......@@ -87,6 +105,27 @@ namespace Jack
delete[] fCapturePortList;
delete[] fPlaybackPortList;
}
void JackAudioAdapter::ConnectPorts()
{
const char **ports;
ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
if (ports != NULL) {
for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) {
jack_connect(fJackClient,jack_port_name(fCapturePortList[i]), ports[i]);
}
free(ports);
}
ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
if (ports != NULL) {
for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) {
jack_connect(fJackClient, ports[i], jack_port_name(fPlaybackPortList[i]));
}
free(ports);
}
}
void JackAudioAdapter::Reset()
{
......@@ -126,6 +165,9 @@ namespace Jack
goto fail;
if ( jack_activate ( fJackClient ) < 0 )
goto fail;
if (fAutoConnect)
ConnectPorts();
// Ring buffer are now allocated..
return fAudioAdapter->Open();
......
......@@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#define __JackAudioAdapter__
#include "JackAudioAdapterInterface.h"
#include "driver_interface.h"
namespace Jack
{
......@@ -42,15 +43,15 @@ namespace Jack
jack_client_t* fJackClient;
JackAudioAdapterInterface* fAudioAdapter;
bool fAutoConnect;
void FreePorts();
void ConnectPorts();
void Reset();
public:
JackAudioAdapter ( jack_client_t* jack_client, JackAudioAdapterInterface* audio_io ) :
fJackClient ( jack_client ), fAudioAdapter ( audio_io )
{}
JackAudioAdapter(jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params = NULL, bool system = false);
~JackAudioAdapter();
int Open();
......
......@@ -34,7 +34,7 @@
#define JACK_CLIENT_NAME_SIZE 64
#ifndef PORT_NUM
#define PORT_NUM 512
#define PORT_NUM 1024
#endif
#define DRIVER_PORT_NUM 256
......
......@@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
namespace Jack
{
JackEngineProfiling::JackEngineProfiling():fAudioCycle(0)
JackEngineProfiling::JackEngineProfiling():fAudioCycle(0),fMeasuredClient(0)
{
jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024));
......@@ -36,66 +36,59 @@ JackEngineProfiling::JackEngineProfiling():fAudioCycle(0)
JackEngineProfiling::~JackEngineProfiling()
{
// Window monitoring
int max_client = 0;
char buffer[1024];
char* nameTable[CLIENT_NUM];
FILE* file = fopen("JackEngineProfiling.log", "w");
char buffer[1024];
jack_info("Write server and clients timing data...");
if (file == NULL) {
jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file");
} else {
// For each measured point
for (int i = 2; i < TIME_POINTS; i++) {
bool header = true;
bool printed = false;
int count = 0;
for (int j = REAL_REFNUM; j < CLIENT_NUM; j++) {
if (fProfileTable[i].fClientTable[j].fRefNum > 0) {
long d1 = long(fProfileTable[i - 1].fCurCycleBegin - fProfileTable[i - 2].fCurCycleBegin);
long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
if (d1 > 0 && fProfileTable[i].fClientTable[j].fStatus != NotTriggered) { // Valid cycle
count++;
nameTable[count] = fNameTable[fProfileTable[i].fClientTable[j].fRefNum];
// driver delta and end cycle
if (header) {
fprintf(file, "%ld \t %ld \t", d1, d2);
header = false;
}
long d5 = long(fProfileTable[i].fClientTable[j].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin);
long d6 = long(fProfileTable[i].fClientTable[j].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin);
long d7 = long(fProfileTable[i].fClientTable[j].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin);
// ref, signal, start, end, scheduling, duration, status
fprintf(file, "%d \t %ld \t %ld \t %ld \t %ld \t %ld \t %d \t",
fProfileTable[i].fClientTable[j].fRefNum,
((d5 > 0) ? d5 : 0),
((d6 > 0) ? d6 : 0),
((d7 > 0) ? d7 : 0),
((d6 > 0 && d5 > 0) ? (d6 - d5) : 0),
((d7 > 0 && d6 > 0) ? (d7 - d6) : 0),
fProfileTable[i].fClientTable[j].fStatus);
printed = true;
}
}
max_client = (count > max_client) ? count : max_client;
}
if (printed) {
fprintf(file, "\n");
} else if (fProfileTable[i].fAudioCycle > 0) { // Driver timing only
long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin);
long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
if (d1 > 0) { // Valid cycle
fprintf(file, "%ld \t %ld \n", d1, d2);
// Driver timing values
long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin);
long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
if (d1 <= 0 || fProfileTable[i].fAudioCycle <= 0)
continue; // Skip non valid cycles
// Print driver delta and end cycle
fprintf(file, "%ld \t %ld \t", d1, d2);
// For each measured client
for (unsigned int j = 0; j < fMeasuredClient; j++) {
int ref = fIntervalTable[j].fRefNum;
// Is valid client cycle
if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) {
long d5 = long(fProfileTable[i].fClientTable[ref].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin);
long d6 = long(fProfileTable[i].fClientTable[ref].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin);
long d7 = long(fProfileTable[i].fClientTable[ref].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin);
// Print ref, signal, start, end, scheduling, duration, status
fprintf(file, "%d \t %ld \t %ld \t %ld \t %ld \t %ld \t %d \t",
ref,
((d5 > 0) ? d5 : 0),
((d6 > 0) ? d6 : 0),
((d7 > 0) ? d7 : 0),
((d6 > 0 && d5 > 0) ? (d6 - d5) : 0),
((d7 > 0 && d6 > 0) ? (d7 - d6) : 0),
fProfileTable[i].fClientTable[ref].fStatus);
} else { // Print tabs
fprintf(file, "\t \t \t \t \t \t \t");
}
}
// Terminate line
fprintf(file, "\n");
}
fclose(file);
}
// Driver period
file = fopen("Timing1.plot", "w");
......@@ -145,9 +138,9 @@ JackEngineProfiling::~JackEngineProfiling()
fclose(file);
}
// Clients end date
if (max_client > 0) {
if (fMeasuredClient > 0) {
file = fopen("Timing3.plot", "w");
if (file == NULL) {
jack_error("JackEngineProfiling::Save cannot open Timing3.log file");
......@@ -158,21 +151,20 @@ JackEngineProfiling::~JackEngineProfiling()
fprintf(file, "set title \"Clients end date\"\n");
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"usec\"\n");
fprintf(file, "plot ");
for (int i = 0; i < max_client; i++) {
for (unsigned int i = 0; i < fMeasuredClient; i++) {
if (i == 0) {
if ((i + 1) == max_client) {
if (i + 1 == fMeasuredClient) { // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines",
((i + 1) * 7) - 1 , nameTable[(i + 1)]);
((i + 1) * 7) - 1 , fIntervalTable[i].fName);
} else {
sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,",
((i + 1) * 7) - 1 , nameTable[(i + 1)]);
((i + 1) * 7) - 1 , fIntervalTable[i].fName);
}
} else if ((i + 1) == max_client) { // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
} else if (i + 1 == fMeasuredClient) { // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
} else {
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]);
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, fIntervalTable[i].fName);
}
fprintf(file, buffer);
}
......@@ -187,28 +179,29 @@ JackEngineProfiling::~JackEngineProfiling()
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"usec\"\n");
fprintf(file, "plot ");
for (int i = 0; i < max_client; i++) {
for (unsigned int i = 0; i < fMeasuredClient; i++) {
if (i == 0) {
if ((i + 1) == max_client) {
if ((i + 1) == fMeasuredClient) { // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines",
((i + 1) * 7) - 1 , nameTable[(i + 1)]);
((i + 1) * 7) - 1 , fIntervalTable[i].fName);
} else {
sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,",
((i + 1) * 7) - 1 , nameTable[(i + 1)]);
((i + 1) * 7) - 1 , fIntervalTable[i].fName);
}
} else if ((i + 1) == max_client) { // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
} else if ((i + 1) == fMeasuredClient) { // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
} else {
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]);
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, fIntervalTable[i].fName);
}
fprintf(file, buffer);
}
fclose(file);
}
}
// Clients scheduling
if (max_client > 0) {
if (fMeasuredClient > 0) {
file = fopen("Timing4.plot", "w");
if (file == NULL) {
......@@ -221,11 +214,11 @@ JackEngineProfiling::~JackEngineProfiling()
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"usec\"\n");
fprintf(file, "plot ");
for (int i = 0; i < max_client; i++) {
if ((i + 1) == max_client) // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]);
for (unsigned int i = 0; i < fMeasuredClient; i++) {
if ((i + 1) == fMeasuredClient) // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), fIntervalTable[i].fName);
else
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]);
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), fIntervalTable[i].fName);
fprintf(file, buffer);
}
......@@ -239,11 +232,11 @@ JackEngineProfiling::~JackEngineProfiling()
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"usec\"\n");
fprintf(file, "plot ");
for (int i = 0; i < max_client; i++) {
if ((i + 1) == max_client) // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]);
for (unsigned int i = 0; i < fMeasuredClient; i++) {
if ((i + 1) == fMeasuredClient) // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), fIntervalTable[i].fName);
else
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]);
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), fIntervalTable[i].fName);
fprintf(file, buffer);
}
fclose(file);
......@@ -251,7 +244,7 @@ JackEngineProfiling::~JackEngineProfiling()
}
// Clients duration
if (max_client > 0) {
if (fMeasuredClient > 0) {
file = fopen("Timing5.plot", "w");
if (file == NULL) {
......@@ -264,11 +257,11 @@ JackEngineProfiling::~JackEngineProfiling()
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"usec\"\n");
fprintf(file, "plot ");
for (int i = 0; i < max_client; i++) {
if ((i + 1) == max_client) // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
for (unsigned int i = 0; i < fMeasuredClient; i++) {
if ((i + 1) == fMeasuredClient) // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
else
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
fprintf(file, buffer);
}
......@@ -282,11 +275,11 @@ JackEngineProfiling::~JackEngineProfiling()
fprintf(file, "set xlabel \"audio cycles\"\n");
fprintf(file, "set ylabel \"usec\"\n");
fprintf(file, "plot ");
for (int i = 0; i < max_client; i++) {
if ((i + 1) == max_client) // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
for (unsigned int i = 0; i < fMeasuredClient; i++) {
if ((i + 1) == fMeasuredClient) // Last client
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
else
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
fprintf(file, buffer);
}
fclose(file);
......@@ -294,6 +287,17 @@ JackEngineProfiling::~JackEngineProfiling()
}
}
bool JackEngineProfiling::CheckClient(const char* name, int cur_point)
{
for (int i = 0; i < MEASURED_CLIENTS; i++) {
if (strcmp(fIntervalTable[i].fName, name) == 0) {
fIntervalTable[i].fEndInterval = cur_point;
return true;
}
}
return false;
}
void JackEngineProfiling::Profile(JackClientInterface** table,
JackGraphManager* manager,
jack_time_t period_usecs,
......@@ -311,8 +315,16 @@ void JackEngineProfiling::Profile(JackClientInterface** table,
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i];
JackClientTiming* timing = manager->GetClientTiming(i);
if (client && client->GetClientControl()->fActive) {
strcpy(fNameTable[i], client->GetClientControl()->fName);
if (client && client->GetClientControl()->fActive && client->GetClientControl()->fCallback[kRealTimeCallback]) {
if (!CheckClient(client->GetClientControl()->fName, fAudioCycle)) {
// Keep new measured client
fIntervalTable[fMeasuredClient].fRefNum = i;
strcpy(fIntervalTable[fMeasuredClient].fName, client->GetClientControl()->fName);
fIntervalTable[fMeasuredClient].fBeginInterval = fAudioCycle;
fIntervalTable[fMeasuredClient].fEndInterval = fAudioCycle;
fMeasuredClient++;
}
fProfileTable[fAudioCycle].fClientTable[i].fRefNum = i;
fProfileTable[fAudioCycle].fClientTable[i].fSignaledAt = timing->fSignaledAt;
fProfileTable[fAudioCycle].fClientTable[i].fAwakeAt = timing->fAwakeAt;
......
......@@ -31,6 +31,7 @@ namespace Jack
#define TIME_POINTS 250000
#define FAILURE_TIME_POINTS 10000
#define FAILURE_WINDOW 10
#define MEASURED_CLIENTS 32
/*!
\brief Timing stucture for a client.
......@@ -43,6 +44,32 @@ struct JackTimingMeasureClient
jack_time_t fAwakeAt;
jack_time_t fFinishedAt;
jack_client_state_t fStatus;
JackTimingMeasureClient()
:fRefNum(-1),
fSignaledAt(0),
fAwakeAt(0),
fFinishedAt(0),
fStatus((jack_client_state_t)0)
{}
};
/*!
\brief Timing interval in the global table for a given client
*/
struct JackTimingClientInterval
{
int fRefNum;
char fName[JACK_CLIENT_NAME_SIZE + 1];
int fBeginInterval;
int fEndInterval;
JackTimingClientInterval()
:fRefNum(-1),
fBeginInterval(-1),
fEndInterval(-1)
{}
};
/*!
......@@ -56,6 +83,13 @@ struct JackTimingMeasure
jack_time_t fCurCycleBegin;
jack_time_t fPrevCycleEnd;
JackTimingMeasureClient fClientTable[CLIENT_NUM];
JackTimingMeasure()
:fAudioCycle(0),
fPeriodUsecs(0),
fCurCycleBegin(0),
fPrevCycleEnd(0)
{}
};
/*!
......@@ -71,9 +105,13 @@ class SERVER_EXPORT JackEngineProfiling
private:
JackTimingMeasure fProfileTable[TIME_POINTS];
char fNameTable[CLIENT_NUM][JACK_CLIENT_NAME_SIZE + 1];
JackTimingClientInterval fIntervalTable[MEASURED_CLIENTS];
unsigned int fAudioCycle;
unsigned int fMeasuredClient;
bool CheckClient(const char* name, int cur_point);
public:
JackEngineProfiling();
......
......@@ -354,9 +354,8 @@ struct JackNetExtMaster : public JackNetMasterInterface {
if (SyncRecv() == SOCKET_ERROR)
return 0;
if (DecodeSyncPacket() < 0)
return 0;
DecodeSyncPacket();
return DataRecv();
}
......@@ -373,9 +372,8 @@ struct JackNetExtMaster : public JackNetMasterInterface {
fNetMidiCaptureBuffer->SetBuffer(port_index, ((JackMidiBuffer**)midi_output_buffer)[port_index]);
}
if (EncodeSyncPacket() < 0)
return 0;
EncodeSyncPacket();
if (SyncSend() == SOCKET_ERROR)
return SOCKET_ERROR;
......@@ -383,15 +381,11 @@ struct JackNetExtMaster : public JackNetMasterInterface {
}
// Transport
int EncodeTransportData()
{
return 0;
}
void EncodeTransportData()
{}
int DecodeTransportData()
{
return 0;
}
void DecodeTransportData()
{}
};
......@@ -574,15 +568,11 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf
}
// Transport
int EncodeTransportData()
{
return 0;
}
void EncodeTransportData()
{}
int DecodeTransportData()
{
return 0;
}
void DecodeTransportData()
{}
bool Init()
{
......@@ -624,17 +614,15 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf
if (SyncRecv() == SOCKET_ERROR)
return 0;
if (DecodeSyncPacket() < 0)
return 0;
DecodeSyncPacket();
return DataRecv();
}
int Write()
{
if (EncodeSyncPacket() < 0)
return 0;
EncodeSyncPacket();
if (SyncSend() == SOCKET_ERROR)
return SOCKET_ERROR;
......
......@@ -260,7 +260,7 @@ namespace Jack
}
//transport---------------------------------------------------------------------------
int JackNetAdapter::DecodeTransportData()
void JackNetAdapter::DecodeTransportData()
{
//TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver)
......@@ -288,11 +288,9 @@ namespace Jack
break;
}
}
return 0;
}