The code used to be in common/JackTools.h until it got moved to
JackTools.cpp in aabbb62282
.
However, it is not possible to split a template implementation between
header and source file, so the code in JackTools.cpp was never compiled,
resulting in
Could not open component .so '/tmp/jacktest/lib/jack/jack_net.so':
/tmp/jacktest/lib/jack/jack_net.so: undefined symbol:
_ZN4Jack18JackGnuPlotMonitorIfED1E
See https://github.com/jackaudio/jack2/issues/4 for more.
Note that fill_n in JackTools.h needs additional modifications for
gcc-4.7.
fixes #4
tags/1.9.9.5
@@ -291,123 +291,6 @@ void BuildClientPath(char* path_to_so, int path_len, const char* so_name) | |||
#endif | |||
template <class T> | |||
JackGnuPlotMonitor<T>::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]; | |||
fill_n ( fMeasureTable[cnt], fMeasurePoints, 0 ); | |||
} | |||
} | |||
template <class T> | |||
JackGnuPlotMonitor<T>::~JackGnuPlotMonitor() | |||
{ | |||
jack_log ( "JackGnuPlotMonitor::~JackGnuPlotMonitor" ); | |||
for ( uint32_t cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||
delete[] fMeasureTable[cnt]; | |||
delete[] fMeasureTable; | |||
delete[] fCurrentMeasure; | |||
} | |||
template <class T> | |||
T JackGnuPlotMonitor<T>::AddNew(T measure_point) | |||
{ | |||
fMeasureId = 0; | |||
return fCurrentMeasure[fMeasureId++] = measure_point; | |||
} | |||
template <class T> | |||
uint32_t JackGnuPlotMonitor<T>::New() | |||
{ | |||
return fMeasureId = 0; | |||
} | |||
template <class T> | |||
T JackGnuPlotMonitor<T>::Add(T measure_point) | |||
{ | |||
return fCurrentMeasure[fMeasureId++] = measure_point; | |||
} | |||
template <class T> | |||
uint32_t JackGnuPlotMonitor<T>::AddLast(T measure_point) | |||
{ | |||
fCurrentMeasure[fMeasureId] = measure_point; | |||
fMeasureId = 0; | |||
return Write(); | |||
} | |||
template <class T> | |||
uint32_t JackGnuPlotMonitor<T>::Write() | |||
{ | |||
for ( uint32_t point = 0; point < fMeasurePoints; point++ ) | |||
fMeasureTable[fTablePos][point] = fCurrentMeasure[point]; | |||
if ( ++fTablePos == fMeasureCnt ) | |||
fTablePos = 0; | |||
return fTablePos; | |||
} | |||
template <class T> | |||
int JackGnuPlotMonitor<T>::Save(std::string name) | |||
{ | |||
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; | |||
} | |||
template <class T> | |||
int JackGnuPlotMonitor<T>::SetPlotFile(std::string* options_list, uint32_t options_number, | |||
std::string* field_names, uint32_t field_number, | |||
std::string name) | |||
{ | |||
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; | |||
} | |||
} // end of namespace | |||
@@ -37,6 +37,7 @@ | |||
#include "jslist.h" | |||
#include "JackCompilerDeps.h" | |||
#include "JackError.h" | |||
#include <string> | |||
#include <algorithm> | |||
@@ -109,26 +110,115 @@ namespace Jack | |||
std::string fName; | |||
public: | |||
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]; | |||
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; | |||
} | |||
JackGnuPlotMonitor(uint32_t measure_cnt = 512, uint32_t measure_points = 5, std::string name = std::string("default")); | |||
~JackGnuPlotMonitor(); | |||
T AddNew(T measure_point); | |||
uint32_t New(); | |||
T Add(T measure_point); | |||
uint32_t AddLast(T measure_point); | |||
uint32_t Write(); | |||
int Save(std::string name = std::string("")); | |||
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("")); | |||
}; | |||
void BuildClientPath(char* path_to_so, int path_len, const char* so_name); | |||