Commit 76fd95b7 authored by moret's avatar moret
Browse files

Add NetMonitor to trunk

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2717 0c269be4-1314-0410-8aa9-9f06e86f4224
parent c5a03d3b
......@@ -32,6 +32,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack
{
#ifdef NETMONITOR
std::string JackNetDriver::fMonitorPlotOptions[] =
{
std::string ( "set xlabel \"audio cycles\"" ),
std::string ( "set ylabel \"usecs\"" )
};
std::string JackNetDriver::fMonitorFieldNames[] =
{
std::string ( "cyclestart" ),
std::string ( "read end" ),
std::string ( "write start" ),
std::string ( "sync end" ),
std::string ( "send end" )
};
#endif
JackNetDriver::JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, const char* net_name, uint transport_sync )
: JackAudioDriver ( name, alias, engine, table ), fSocket ( ip, port )
......@@ -44,6 +60,12 @@ namespace Jack
strcpy ( fParams.fName, net_name );
fSocket.GetName ( fParams.fSlaveNetName );
fParams.fTransportSync = transport_sync;
//monitor
#ifdef NETMONITOR
std::string plot_file_name = std::string ( fParams.fName );
fMonitor.SetPlotFile ( plot_file_name, JackNetDriver::fMonitorPlotOptions, 2, JackNetDriver::fMonitorFieldNames, 5 );
#endif
}
JackNetDriver::~JackNetDriver()
......@@ -76,6 +98,16 @@ namespace Jack
return res;
}
#ifdef NETMONITOR
int JackNetDriver::Close()
{
std::string filename = string ( fParams.fName );
fMonitor.Save ( filename );
return JackDriver::Close();
}
#endif
int JackNetDriver::Attach()
{
return 0;
......@@ -290,7 +322,7 @@ namespace Jack
fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize();
fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize();
//payload size
//payload size
fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );
return 0;
......@@ -485,6 +517,11 @@ namespace Jack
//take the time at the beginning of the cycle
JackDriver::CycleTakeBeginTime();
#ifdef NETMONITOR
fUsecCycleStart = GetMicroSeconds();
fMeasure.fTable[0] = GetMicroSeconds() - fUsecCycleStart;
#endif
//audio, midi or sync if driver is late
if ( fParams.fSendMidiChannels || fParams.fSendAudioChannels )
{
......@@ -522,6 +559,12 @@ namespace Jack
while ( fRxHeader.fIsLastPckt != 'y' );
}
fRxHeader.fCycle = rx_head->fCycle;
#ifdef NETMONITOR
fMeasure.fTable[1] = GetMicroSeconds() - fUsecCycleStart;
#endif
return 0;
}
......@@ -540,6 +583,10 @@ namespace Jack
for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer ( audio_port_index ));
#ifdef NETMONITOR
fMeasure.fTable[2] = GetMicroSeconds() - fUsecCycleStart;
#endif
//sync
fTxHeader.fDataType = 's';
if ( !fParams.fSendMidiChannels && !fParams.fSendAudioChannels )
......@@ -548,6 +595,10 @@ namespace Jack
SetSyncPacket();
tx_bytes = Send ( fParams.fMtu, 0 );
#ifdef NETMONITOR
fMeasure.fTable[3] = GetMicroSeconds() - fUsecCycleStart;
#endif
//midi
if ( fParams.fReturnMidiChannels )
{
......@@ -579,6 +630,12 @@ namespace Jack
tx_bytes = Send ( fAudioTxLen, 0 );
}
}
#ifdef NETMONITOR
fMeasure.fTable[4] = GetMicroSeconds() - fUsecCycleStart;
fMonitor.Write ( fMeasure );
#endif
return 0;
}
......
......@@ -35,31 +35,40 @@ namespace Jack
uint fNSubProcess;
net_transport_data_t fTransportData;
//jack ports
//jack ports
jack_port_id_t* fMidiCapturePortList;
jack_port_id_t* fMidiPlaybackPortList;
//headers
//headers
packet_header_t fTxHeader;
packet_header_t fRxHeader;
//network buffers
//network buffers
char* fTxBuffer;
char* fRxBuffer;
char* fTxData;
char* fRxData;
//jack buffers
//jack buffers
NetMidiBuffer* fNetMidiCaptureBuffer;
NetMidiBuffer* fNetMidiPlaybackBuffer;
NetAudioBuffer* fNetAudioCaptureBuffer;
NetAudioBuffer* fNetAudioPlaybackBuffer;
//sizes
//sizes
int fAudioRxLen;
int fAudioTxLen;
int fPayloadSize;
//monitoring
#ifdef NETMONITOR
static std::string fMonitorPlotOptions[];
static std::string fMonitorFieldNames[];
jack_time_t fUsecCycleStart;
NetMeasure<jack_time_t> fMeasure;
NetMonitor<jack_time_t> fMonitor;
#endif
bool Init();
net_status_t GetNetMaster();
net_status_t SendMasterStartSync();
......@@ -74,7 +83,7 @@ namespace Jack
int Recv ( size_t size, int flags );
int Send ( size_t size, int flags );
int SetSyncPacket();
int SetSyncPacket();
int TransportSync();
public:
......@@ -86,6 +95,10 @@ namespace Jack
int inchannels, int outchannels, bool monitor, const char* capture_driver_name,
const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency );
#ifdef NETMONITOR
int Close();
#endif
int Attach();
int Detach();
......
......@@ -27,6 +27,21 @@ using namespace std;
namespace Jack
{
//JackNetMaster******************************************************************************************************
#ifdef NETMONITOR
std::string JackNetMaster::fMonitorPlotOptions[] =
{
std::string ( "set xlabel \"audio cycles\"" ),
std::string ( "set ylabel \"audio frames\"" )
};
std::string JackNetMaster::fMonitorFieldNames[] =
{
std::string ( "cycle start" ),
std::string ( "sync send" ),
std::string ( "send end" ),
std::string ( "sync recv" ),
std::string ( "end of cycle" )
};
#endif
JackNetMaster::JackNetMaster ( JackNetMasterManager* manager, session_params_t& params ) : fSocket()
{
......@@ -98,6 +113,12 @@ namespace Jack
//payload size
fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );
//monitor
#ifdef NETMONITOR
std::string plot_file_name = std::string ( fParams.fName );
fMonitor.SetPlotFile ( plot_file_name, fMonitorPlotOptions, 2, fMonitorFieldNames, 5 );
#endif
}
JackNetMaster::~JackNetMaster()
......@@ -120,6 +141,10 @@ namespace Jack
delete[] fMidiPlaybackPorts;
delete[] fTxBuffer;
delete[] fRxBuffer;
#ifdef NETMONITOR
std::string filename = string ( fParams.fName );
fMonitor.Save ( filename );
#endif
}
bool JackNetMaster::Init()
......@@ -360,20 +385,29 @@ fail:
fTxHeader.fIsLastPckt = 'n';
packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
#ifdef NETMONITOR
NetMeasure<jack_nframes_t> measure;
measure.fTable[0] = jack_frames_since_cycle_start( fJackClient );
#endif
//buffers
uint port_index;
for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
fNetMidiCaptureBuffer->SetBuffer(port_index,
static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiCapturePorts[port_index], fParams.fPeriodSize )));
static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiCapturePorts[port_index],
fParams.fPeriodSize )));
for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
fNetAudioCaptureBuffer->SetBuffer(port_index,
static_cast<sample_t*> ( jack_port_get_buffer ( fAudioCapturePorts[port_index], fParams.fPeriodSize )));
static_cast<sample_t*> ( jack_port_get_buffer ( fAudioCapturePorts[port_index],
fParams.fPeriodSize )));
for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
fNetMidiPlaybackBuffer->SetBuffer(port_index,
static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index], fParams.fPeriodSize )));
static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index],
fParams.fPeriodSize )));
for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
fNetAudioPlaybackBuffer->SetBuffer(port_index,
static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index], fParams.fPeriodSize )));
static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index],
fParams.fPeriodSize )));
//send ------------------------------------------------------------------------------------------------------------------
//sync
......@@ -386,6 +420,10 @@ fail:
if ( ( tx_bytes == 0 ) || ( tx_bytes == SOCKET_ERROR ) )
return tx_bytes;
#ifdef NETMONITOR
measure.fTable[1] = jack_frames_since_cycle_start( fJackClient );
#endif
//midi
if ( fParams.fSendMidiChannels )
{
......@@ -422,20 +460,23 @@ fail:
}
}
//receive ( if there is stg to receive...)-------------------------------------------------------------------------------------
#ifdef NETMONITOR
measure.fTable[2] = jack_frames_since_cycle_start( fJackClient );
#endif
//receive --------------------------------------------------------------------------------------------------------------------
//sync
if ( fParams.fTransportSync )
do
{
do
{
rx_bytes = Recv ( fParams.fMtu, 0 );
if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
return rx_bytes;
}
while ( !rx_bytes && ( rx_head->fDataType != 's' ) );
//then update fSyncState from received sync packet
rx_bytes = Recv ( fParams.fMtu, 0 );
if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
return rx_bytes;
}
while ( !rx_bytes && ( rx_head->fDataType != 's' ) );
#ifdef NETMONITOR
measure.fTable[3] = jack_frames_since_cycle_start( fJackClient );
#endif
if ( fParams.fReturnMidiChannels || fParams.fReturnAudioChannels )
{
......@@ -474,6 +515,11 @@ fail:
}
while ( fRxHeader.fIsLastPckt != 'y' );
}
#ifdef NETMONITOR
measure.fTable[4] = jack_frames_since_cycle_start( fJackClient );
fMonitor.Write ( measure );
#endif
return 0;
}
......@@ -542,6 +588,7 @@ fail:
if ( ( *it )->fSyncState == 0 )
ret = 0;
jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" );
return ret;
}
void* JackNetMasterManager::NetManagerThread ( void* arg )
......
......@@ -43,46 +43,53 @@ namespace Jack
int fNetJumpCnt;
bool fRunning;
//jack client
//jack client
jack_client_t* fJackClient;
const char* fClientName;
//jack ports
//jack ports
jack_port_t** fAudioCapturePorts;
jack_port_t** fAudioPlaybackPorts;
jack_port_t** fMidiCapturePorts;
jack_port_t** fMidiPlaybackPorts;
//sync and transport
//sync and transport
int fSyncState;
net_transport_data_t fTransportData;
//network headers
//network headers
packet_header_t fTxHeader;
packet_header_t fRxHeader;
//network buffers
//network buffers
char* fTxBuffer;
char* fRxBuffer;
char* fTxData;
char* fRxData;
//jack buffers
//jack buffers
NetAudioBuffer* fNetAudioCaptureBuffer;
NetAudioBuffer* fNetAudioPlaybackBuffer;
NetMidiBuffer* fNetMidiCaptureBuffer;
NetMidiBuffer* fNetMidiPlaybackBuffer;
//sizes
//sizes
int fAudioTxLen;
int fAudioRxLen;
int fPayloadSize;
//monitoring
#ifdef NETMONITOR
static std::string fMonitorPlotOptions[];
static std::string fMonitorFieldNames[];
NetMonitor<jack_nframes_t> fMonitor;
#endif
bool Init();
void FreePorts();
void Exit();
int SetSyncPacket();
int SetSyncPacket();
int Send ( char* buffer, size_t size, int flags );
int Recv ( size_t size, int flags );
......
......@@ -188,8 +188,8 @@ namespace Jack
EXPORT void SessionParamsDisplay ( session_params_t* params )
{
char bitdepth[16];
( params->fBitdepth ) ? sprintf ( bitdepth, "%u", params->fBitdepth ) : sprintf ( bitdepth, "%s", "float" );
char bitdepth[16];
( params->fBitdepth ) ? sprintf ( bitdepth, "%u", params->fBitdepth ) : sprintf ( bitdepth, "%s", "float" );
jack_info ( "**************** Network parameters ****************" );
jack_info ( "Name : %s", params->fName );
jack_info ( "Protocol revision : %c", params->fProtocolVersion );
......@@ -274,8 +274,8 @@ namespace Jack
EXPORT void PacketHeaderDisplay ( packet_header_t* header )
{
char bitdepth[16];
( header->fBitdepth ) ? sprintf ( bitdepth, "%u", header->fBitdepth ) : sprintf ( bitdepth, "%s", "float" );
char bitdepth[16];
( header->fBitdepth ) ? sprintf ( bitdepth, "%u", header->fBitdepth ) : sprintf ( bitdepth, "%s", "float" );
jack_info ( "********************Header********************" );
jack_info ( "Data type : %c", header->fDataType );
jack_info ( "Data stream : %c", header->fDataStream );
......
......@@ -29,6 +29,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include <algorithm>
#include <cmath>
using namespace std;
namespace Jack
{
typedef struct _session_params session_params_t;
......@@ -61,7 +63,6 @@ namespace Jack
char fName[JACK_CLIENT_NAME_SIZE]; //slave's name
};
//net status **********************************************************************************
enum _net_status
......@@ -111,12 +112,12 @@ namespace Jack
//transport data ******************************************************************************
struct _net_transport_data
{
char fTransportType[10]; //test value ('transport')
jack_position_t fCurPos;
jack_transport_state_t fCurState;
};
struct _net_transport_data
{
char fTransportType[10]; //test value ('transport')
jack_position_t fCurPos;
jack_transport_state_t fCurState;
};
//midi data ***********************************************************************************
......@@ -145,7 +146,7 @@ namespace Jack
int RenderFromNetwork ( int subcycle, size_t copy_size );
int RenderToNetwork ( int subcycle, size_t total_size );
void SetBuffer(int index, JackMidiBuffer* buffer);
void SetBuffer(int index, JackMidiBuffer* buffer);
};
// audio data *********************************************************************************
......@@ -171,6 +172,142 @@ namespace Jack
void SetBuffer(int index, sample_t* buffer);
};
// net measure ********************************************************************************
template <class T> struct NetMeasure
{
uint fTableSize;;
T* fTable;
NetMeasure ( uint table_size = 5 )
{
fTableSize = table_size;
fTable = new T[fTableSize];
}
~NetMeasure()
{
delete[] fTable;
}
};
// net monitor ********************************************************************************
template <class T> class NetMonitor
{
private:
uint fMeasureCnt;
uint fMeasurePoints;
NetMeasure<T>* fMeasureTable;
uint fTablePos;
void DisplayMeasure ( NetMeasure<T>& measure )
{
string display;
for ( uint m_id = 0; m_id < measure.fTableSize; m_id++ )
{
char* value;
sprintf ( value, "%lu ", measure.fTable[m_id] );
display += string ( value );
}
cout << "NetMonitor:: '" << display << "'" << endl;
}
public:
NetMonitor ( uint measure_cnt = 512, uint measure_points = 5 )
{
jack_log ( "JackNetMonitor::JackNetMonitor measure_cnt %u measure_points %u", measure_cnt, measure_points );
fMeasureCnt = measure_cnt;
fMeasurePoints = measure_points;
fMeasureTable = new NetMeasure<T>[fMeasureCnt];
fTablePos = 0;
for ( uint i = 0; i < fMeasureCnt; i++ )
InitTable();
}
~NetMonitor()
{
jack_log ( "NetMonitor::~NetMonitor" );
delete fMeasureTable;
}
uint InitTable()
{
uint measure_id;
for ( measure_id = 0; measure_id < fMeasureTable[fTablePos].fTableSize; measure_id++ )
fMeasureTable[fTablePos].fTable[measure_id] = 0;
if ( ++fTablePos == fMeasureCnt )
fTablePos = 0;
return fTablePos;
}
uint Write ( NetMeasure<T>& measure )
{
for ( uint m_id = 0; m_id < measure.fTableSize; m_id++ )
fMeasureTable[fTablePos].fTable[m_id] = measure.fTable[m_id];
if ( ++fTablePos == fMeasureCnt )
fTablePos = 0;
//DisplayMeasure ( fMeasureTable[fTablePos] );
return fTablePos;
}
int Save ( string& filename )
{
filename += "_netmonitor.log";
jack_log ( "JackNetMonitor::Save filename %s", filename.c_str() );
FILE* file = fopen ( filename.c_str(), "w" );
//printf each measure with tab separated values
for ( uint id = 0; id < fMeasureCnt; id++ )
{
for ( uint m_id = 0; m_id < fMeasureTable[id].fTableSize; m_id++ )
fprintf ( file, "%lu \t ", fMeasureTable[id].fTable[m_id] );
fprintf ( file, "\n" );
}
fclose(file);
return 0;
}
int SetPlotFile ( string& name, string* options_list = NULL, uint options_number = 0, string* field_names = NULL, uint field_number )
{
string title = name + "_netmonitor";
string plot_filename = title + ".plt";
string data_filename = title + ".log";
FILE* file = fopen ( plot_filename.c_str(), "w" );
//base options
fprintf ( file, "set multiplot\n" );
fprintf ( file, "set grid\n" );
fprintf ( file, "set title \"%s\"\n", title.c_str() );
//additional options
for ( uint i = 0; i < options_number; i++ )
{
jack_log ( "JackNetMonitor::SetPlotFile : Add plot option : '%s'", options_list[i].c_str() );
fprintf ( file, "%s\n", options_list[i].c_str() );
}
//plot
fprintf ( file, "plot " );
for ( uint row = 1; row <= field_number; row++ )
{
jack_log ( "JackNetMonitor::SetPlotFile - Add plot : file '%s' row '%d' title '%s' field '%s'",
data_filename.c_str(), row, name.c_str(), field_names[row-1].c_str() );
fprintf ( file, "\"%s\" using %u title \"%s : %s\" with lines", data_filename.c_str(), row, name.c_str(), field_names[row-1].c_str() );
fprintf ( file, ( row < field_number ) ? "," : "\n" );
}
jack_log ( "JackNetMonitor::SetPlotFile - Saving GnuPlot '.plt' file to '%s'", plot_filename.c_str() );
fclose ( file );
return 0;
}
};
//utility *************************************************************************************
//socket API management
......
......@@ -72,10 +72,61 @@
<Add directory="Debug\bin" />
</Linker>
</Target>
<Target title="Win32 Monitor">
<Option output="Release\bin\jackmp\audioadapter" prefix_auto="1" extension_auto="1" />
<Option object_output="Release\" />
<Option type="3" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
<Add option="-Wall" />
<Add option="-DBUILD_DLL" />
<Add option="-D__SMP__" />
<Add option="-DNETMONITOR" />
<Add directory="..\common" />
<Add directory="..\common\jack" />
<Add directory="..\windows" />
</Compiler>
<Linker>
<Add library="kernel32" />
<Add library="user32" />
<Add library="gdi32" />