git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2722 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
| @@ -30,24 +30,26 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #define DEFAULT_MULTICAST_IP "225.3.19.154" | |||
| #define DEFAULT_PORT 19000 | |||
| using namespace std; | |||
| namespace Jack | |||
| { | |||
| #ifdef JACK_MONITOR | |||
| uint JackNetDriver::fMeasureCnt = 50; | |||
| uint JackNetDriver::fMeasureCnt = 64; | |||
| uint JackNetDriver::fMeasurePoints = 5; | |||
| uint JackNetDriver::fMonitorPlotOptionsCnt = 2; | |||
| std::string JackNetDriver::fMonitorPlotOptions[] = | |||
| string JackNetDriver::fMonitorPlotOptions[] = | |||
| { | |||
| std::string ( "set xlabel \"audio cycles\"" ), | |||
| std::string ( "set ylabel \"usecs\"" ) | |||
| string ( "set xlabel \"audio cycles\"" ), | |||
| string ( "set ylabel \"% of audio cycle\"" ) | |||
| }; | |||
| std::string JackNetDriver::fMonitorFieldNames[] = | |||
| string JackNetDriver::fMonitorFieldNames[] = | |||
| { | |||
| std::string ( "cyclestart" ), | |||
| std::string ( "read end" ), | |||
| std::string ( "write start" ), | |||
| std::string ( "sync end" ), | |||
| std::string ( "send end" ) | |||
| string ( "cyclestart" ), | |||
| string ( "read end" ), | |||
| string ( "write start" ), | |||
| string ( "sync send" ), | |||
| string ( "send end" ) | |||
| }; | |||
| #endif | |||
| @@ -55,6 +57,8 @@ namespace Jack | |||
| 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 ) | |||
| { | |||
| jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip, port ); | |||
| fMulticastIP = new char[strlen ( ip ) + 1]; | |||
| strcpy ( fMulticastIP, ip ); | |||
| fParams.fMtu = mtu; | |||
| @@ -63,15 +67,6 @@ namespace Jack | |||
| strcpy ( fParams.fName, net_name ); | |||
| fSocket.GetName ( fParams.fSlaveNetName ); | |||
| fParams.fTransportSync = transport_sync; | |||
| //monitor | |||
| #ifdef JACK_MONITOR | |||
| fMonitor = new NetMonitor<jack_time_t> ( JackNetDriver::fMeasureCnt, JackNetDriver::fMeasurePoints ); | |||
| fMeasure = new jack_time_t[JackNetDriver::fMeasurePoints]; | |||
| std::string plot_file_name = std::string ( fParams.fName ); | |||
| fMonitor->SetPlotFile ( plot_file_name, JackNetDriver::fMonitorPlotOptions, JackNetDriver::fMonitorPlotOptionsCnt, | |||
| JackNetDriver::fMonitorFieldNames, JackNetDriver::fMeasurePoints ); | |||
| #endif | |||
| } | |||
| JackNetDriver::~JackNetDriver() | |||
| @@ -88,6 +83,7 @@ namespace Jack | |||
| delete[] fMidiCapturePortList; | |||
| delete[] fMidiPlaybackPortList; | |||
| #ifdef JACK_MONITOR | |||
| fMonitor->Save(); | |||
| delete[] fMeasure; | |||
| delete fMonitor; | |||
| #endif | |||
| @@ -108,16 +104,6 @@ namespace Jack | |||
| return res; | |||
| } | |||
| #ifdef JACK_MONITOR | |||
| int JackNetDriver::Close() | |||
| { | |||
| std::string filename = string ( fParams.fName ); | |||
| fMonitor->Save ( filename ); | |||
| return JackDriver::Close(); | |||
| } | |||
| #endif | |||
| int JackNetDriver::Attach() | |||
| { | |||
| return 0; | |||
| @@ -256,22 +242,26 @@ namespace Jack | |||
| { | |||
| jack_info ( "Restarting driver..." ); | |||
| delete[] fTxBuffer; | |||
| fTxBuffer = NULL; | |||
| delete[] fRxBuffer; | |||
| fRxBuffer = NULL; | |||
| delete fNetAudioCaptureBuffer; | |||
| fNetAudioCaptureBuffer = NULL; | |||
| delete fNetAudioPlaybackBuffer; | |||
| fNetAudioPlaybackBuffer = NULL; | |||
| delete fNetMidiCaptureBuffer; | |||
| fNetMidiCaptureBuffer = NULL; | |||
| delete fNetMidiPlaybackBuffer; | |||
| fNetMidiPlaybackBuffer = NULL; | |||
| FreePorts(); | |||
| delete[] fMidiCapturePortList; | |||
| delete[] fMidiPlaybackPortList; | |||
| fTxBuffer = NULL; | |||
| fRxBuffer = NULL; | |||
| fNetAudioCaptureBuffer = NULL; | |||
| fNetAudioPlaybackBuffer = NULL; | |||
| fNetMidiCaptureBuffer = NULL; | |||
| fNetMidiPlaybackBuffer = NULL; | |||
| fMidiCapturePortList = NULL; | |||
| delete[] fMidiPlaybackPortList; | |||
| fMidiPlaybackPortList = NULL; | |||
| delete[] fMeasure; | |||
| fMeasure = NULL; | |||
| delete fMonitor; | |||
| fMonitor = NULL; | |||
| } | |||
| int JackNetDriver::SetParams() | |||
| @@ -335,6 +325,17 @@ namespace Jack | |||
| //payload size | |||
| fPayloadSize = fParams.fMtu - sizeof ( packet_header_t ); | |||
| //monitor | |||
| #ifdef JACK_MONITOR | |||
| string plot_name = string ( fParams.fName ); | |||
| plot_name += string ( "_slave_" ); | |||
| plot_name += ( fEngineControl->fSyncMode ) ? string ( "sync" ) : string ( "async" ); | |||
| fMonitor = new JackGnuPlotMonitor<float> ( JackNetDriver::fMeasureCnt, JackNetDriver::fMeasurePoints, plot_name ); | |||
| fMeasure = new float[JackNetDriver::fMeasurePoints]; | |||
| fMonitor->SetPlotFile ( JackNetDriver::fMonitorPlotOptions, JackNetDriver::fMonitorPlotOptionsCnt, | |||
| JackNetDriver::fMonitorFieldNames, JackNetDriver::fMeasurePoints ); | |||
| #endif | |||
| return 0; | |||
| } | |||
| @@ -528,8 +529,8 @@ namespace Jack | |||
| JackDriver::CycleTakeBeginTime(); | |||
| #ifdef JACK_MONITOR | |||
| fUsecCycleStart = GetMicroSeconds(); | |||
| fMeasure[0] = GetMicroSeconds() - fUsecCycleStart; | |||
| fMeasureId = 0; | |||
| fMeasure[fMeasureId++] = ( ( (float)(GetMicroSeconds() - JackDriver::fBeginDateUst) ) / (float)fEngineControl->fPeriodUsecs ) * 100.f; | |||
| #endif | |||
| //audio, midi or sync if driver is late | |||
| @@ -572,7 +573,7 @@ namespace Jack | |||
| #ifdef JACK_MONITOR | |||
| fMeasure[1] = GetMicroSeconds() - fUsecCycleStart; | |||
| fMeasure[fMeasureId++] = ( ( (float)(GetMicroSeconds() - JackDriver::fBeginDateUst) ) / (float)fEngineControl->fPeriodUsecs ) * 100.f; | |||
| #endif | |||
| return 0; | |||
| @@ -594,7 +595,7 @@ namespace Jack | |||
| fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer ( audio_port_index )); | |||
| #ifdef JACK_MONITOR | |||
| fMeasure[2] = GetMicroSeconds() - fUsecCycleStart; | |||
| fMeasure[fMeasureId++] = ( ( (float)(GetMicroSeconds() - JackDriver::fBeginDateUst) ) / (float)fEngineControl->fPeriodUsecs ) * 100.f; | |||
| #endif | |||
| //sync | |||
| @@ -606,7 +607,7 @@ namespace Jack | |||
| tx_bytes = Send ( fParams.fMtu, 0 ); | |||
| #ifdef JACK_MONITOR | |||
| fMeasure[3] = GetMicroSeconds() - fUsecCycleStart; | |||
| fMeasure[fMeasureId++] = ( ( (float)(GetMicroSeconds() - JackDriver::fBeginDateUst) ) / (float)fEngineControl->fPeriodUsecs ) * 100.f; | |||
| #endif | |||
| //midi | |||
| @@ -642,7 +643,7 @@ namespace Jack | |||
| } | |||
| #ifdef JACK_MONITOR | |||
| fMeasure[4] = GetMicroSeconds() - fUsecCycleStart; | |||
| fMeasure[fMeasureId++] = ( ( (float)(GetMicroSeconds() - JackDriver::fBeginDateUst) ) / (float)fEngineControl->fPeriodUsecs ) * 100.f; | |||
| fMonitor->Write ( fMeasure ); | |||
| #endif | |||
| @@ -24,6 +24,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackAudioDriver.h" | |||
| #include "JackNetTool.h" | |||
| #ifdef JACK_MONITOR | |||
| #include "JackFrameTimer.h" | |||
| #endif | |||
| namespace Jack | |||
| { | |||
| class JackNetDriver : public JackAudioDriver | |||
| @@ -67,9 +71,9 @@ namespace Jack | |||
| static uint fMonitorPlotOptionsCnt; | |||
| static std::string fMonitorPlotOptions[]; | |||
| static std::string fMonitorFieldNames[]; | |||
| jack_time_t* fMeasure; | |||
| NetMonitor<jack_time_t>* fMonitor; | |||
| jack_time_t fUsecCycleStart; | |||
| float* fMeasure; | |||
| int fMeasureId; | |||
| JackGnuPlotMonitor<float>* fMonitor; | |||
| #endif | |||
| bool Init(); | |||
| @@ -98,10 +102,6 @@ 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 JACK_MONITOR | |||
| int Close(); | |||
| #endif | |||
| int Attach(); | |||
| int Detach(); | |||
| @@ -31,18 +31,18 @@ namespace Jack | |||
| uint JackNetMaster::fMeasureCnt = 50; | |||
| uint JackNetMaster::fMeasurePoints = 5; | |||
| uint JackNetMaster::fMonitorPlotOptionsCnt = 2; | |||
| std::string JackNetMaster::fMonitorPlotOptions[] = | |||
| string JackNetMaster::fMonitorPlotOptions[] = | |||
| { | |||
| std::string ( "set xlabel \"audio cycles\"" ), | |||
| std::string ( "set ylabel \"audio frames\"" ) | |||
| string ( "set xlabel \"audio cycles\"" ), | |||
| string ( "set ylabel \"% of audio cycle\"" ) | |||
| }; | |||
| std::string JackNetMaster::fMonitorFieldNames[] = | |||
| string JackNetMaster::fMonitorFieldNames[] = | |||
| { | |||
| std::string ( "cycle start" ), | |||
| std::string ( "sync send" ), | |||
| std::string ( "send end" ), | |||
| std::string ( "sync recv" ), | |||
| std::string ( "end of cycle" ) | |||
| string ( "cycle start" ), | |||
| string ( "sync send" ), | |||
| string ( "send end" ), | |||
| string ( "sync recv" ), | |||
| string ( "end of cycle" ) | |||
| }; | |||
| #endif | |||
| @@ -119,10 +119,12 @@ namespace Jack | |||
| //monitor | |||
| #ifdef JACK_MONITOR | |||
| fMonitor = new NetMonitor<jack_nframes_t> ( JackNetMaster::fMeasureCnt, JackNetMaster::fMeasurePoints ); | |||
| fMeasure = new jack_nframes_t[JackNetMaster::fMeasurePoints]; | |||
| std::string plot_file_name = std::string ( fParams.fName ); | |||
| fMonitor->SetPlotFile ( plot_file_name, JackNetMaster::fMonitorPlotOptions, JackNetMaster::fMonitorPlotOptionsCnt, | |||
| string plot_name = string ( fParams.fName ); | |||
| plot_name += string ( "_master" ); | |||
| //plot_name += ( fEngineControl->fSyncMode ) ? string ( "sync" ) : string ( "async" ); | |||
| fMonitor = new JackGnuPlotMonitor<float> ( JackNetMaster::fMeasureCnt, JackNetMaster::fMeasurePoints, plot_name ); | |||
| fMeasure = new float[JackNetMaster::fMeasurePoints]; | |||
| fMonitor->SetPlotFile ( JackNetMaster::fMonitorPlotOptions, JackNetMaster::fMonitorPlotOptionsCnt, | |||
| JackNetMaster::fMonitorFieldNames, JackNetMaster::fMeasurePoints ); | |||
| #endif | |||
| } | |||
| @@ -148,8 +150,7 @@ namespace Jack | |||
| delete[] fTxBuffer; | |||
| delete[] fRxBuffer; | |||
| #ifdef JACK_MONITOR | |||
| std::string filename = string ( fParams.fName ); | |||
| fMonitor->Save ( filename ); | |||
| fMonitor->Save(); | |||
| delete[] fMeasure; | |||
| delete fMonitor; | |||
| #endif | |||
| @@ -394,7 +395,8 @@ fail: | |||
| packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer ); | |||
| #ifdef JACK_MONITOR | |||
| fMeasure[0] = jack_frames_since_cycle_start( fJackClient ); | |||
| fMeasureId = 0; | |||
| fMeasure[fMeasureId++] = ( (float)jack_frames_since_cycle_start( fJackClient ) /(float)fParams.fPeriodSize ) * 100.f; | |||
| #endif | |||
| //buffers | |||
| @@ -428,7 +430,7 @@ fail: | |||
| return tx_bytes; | |||
| #ifdef JACK_MONITOR | |||
| fMeasure[1] = jack_frames_since_cycle_start( fJackClient ); | |||
| fMeasure[fMeasureId++] = ( (float)jack_frames_since_cycle_start( fJackClient ) /(float)fParams.fPeriodSize ) * 100.f; | |||
| #endif | |||
| //midi | |||
| @@ -468,7 +470,7 @@ fail: | |||
| } | |||
| #ifdef JACK_MONITOR | |||
| fMeasure[2] = jack_frames_since_cycle_start( fJackClient ); | |||
| fMeasure[fMeasureId++] = ( (float)jack_frames_since_cycle_start( fJackClient ) /(float)fParams.fPeriodSize ) * 100.f; | |||
| #endif | |||
| //receive -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -482,7 +484,7 @@ fail: | |||
| while ( !rx_bytes && ( rx_head->fDataType != 's' ) ); | |||
| #ifdef JACK_MONITOR | |||
| fMeasure[3] = jack_frames_since_cycle_start( fJackClient ); | |||
| fMeasure[fMeasureId++] = ( (float)jack_frames_since_cycle_start( fJackClient ) /(float)fParams.fPeriodSize ) * 100.f; | |||
| #endif | |||
| if ( fParams.fReturnMidiChannels || fParams.fReturnAudioChannels ) | |||
| @@ -524,7 +526,7 @@ fail: | |||
| } | |||
| #ifdef JACK_MONITOR | |||
| fMeasure[4] = jack_frames_since_cycle_start( fJackClient ); | |||
| fMeasure[fMeasureId++] = ( (float)jack_frames_since_cycle_start( fJackClient ) /(float)fParams.fPeriodSize ) * 100.f; | |||
| fMonitor->Write ( fMeasure ); | |||
| #endif | |||
| return 0; | |||
| @@ -85,8 +85,9 @@ namespace Jack | |||
| static uint fMonitorPlotOptionsCnt; | |||
| static std::string fMonitorPlotOptions[]; | |||
| static std::string fMonitorFieldNames[]; | |||
| jack_nframes_t* fMeasure; | |||
| NetMonitor<jack_nframes_t>* fMonitor; | |||
| float* fMeasure; | |||
| int fMeasureId; | |||
| JackGnuPlotMonitor<float>* fMonitor; | |||
| #endif | |||
| bool Init(); | |||
| @@ -24,9 +24,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackTools.h" | |||
| #include "JackPlatformNetSocket.h" | |||
| #include "types.h" | |||
| #include <string> | |||
| #include <algorithm> | |||
| #include <cmath> | |||
| using namespace std; | |||
| @@ -172,128 +169,6 @@ namespace Jack | |||
| void SetBuffer(int index, sample_t* buffer); | |||
| }; | |||
| // net monitor ******************************************************************************** | |||
| template <class T> class NetMonitor | |||
| { | |||
| private: | |||
| uint fMeasureCnt; | |||
| uint fMeasurePoints; | |||
| T** fMeasureTable; | |||
| uint fTablePos; | |||
| void DisplayMeasure ( T* measure ) | |||
| { | |||
| string display; | |||
| for ( uint m_id = 0; m_id < fMeasurePoints; m_id++ ) | |||
| { | |||
| char* value; | |||
| sprintf ( value, "%llu ", measure[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; | |||
| fTablePos = 0; | |||
| //allocate measure table | |||
| fMeasureTable = new T*[fMeasureCnt]; | |||
| for ( uint i = 0; i < fMeasureCnt; i++ ) | |||
| fMeasureTable[i] = new T[fMeasurePoints]; | |||
| //init measure table | |||
| for ( uint cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||
| for ( uint point = 0; point < fMeasurePoints; point++ ) | |||
| fMeasureTable[cnt][point] = 0; | |||
| } | |||
| ~NetMonitor() | |||
| { | |||
| jack_log ( "NetMonitor::~NetMonitor" ); | |||
| for ( uint cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||
| delete[] fMeasureTable[cnt]; | |||
| delete[] fMeasureTable; | |||
| } | |||
| void InitTable() | |||
| { | |||
| for ( uint cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||
| for ( uint point = 0; point < fMeasurePoints; point++ ) | |||
| fMeasureTable[cnt][point] = 0; | |||
| } | |||
| uint Write ( T* measure ) | |||
| { | |||
| for ( uint point = 0; point < fMeasurePoints; point++ ) | |||
| fMeasureTable[fTablePos][point] = measure[point]; | |||
| if ( ++fTablePos == fMeasureCnt ) | |||
| fTablePos = 0; | |||
| 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" ); | |||
| //print each measure with tab separated values | |||
| for ( uint cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||
| { | |||
| for ( uint pt = 0; pt < fMeasurePoints; pt++ ) | |||
| fprintf ( file, "%llu \t ", fMeasureTable[cnt][pt] ); | |||
| 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 = 0 ) | |||
| { | |||
| //names and file | |||
| 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 | |||
| @@ -23,7 +23,6 @@ | |||
| #include "JackConstants.h" | |||
| #include "JackTools.h" | |||
| #include "JackError.h" | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| @@ -35,56 +35,181 @@ | |||
| #include <string> | |||
| #include <algorithm> | |||
| #include <vector> | |||
| #include <iostream> | |||
| #include <fstream> | |||
| #include <strstream> | |||
| #include "jslist.h" | |||
| #include "driver_interface.h" | |||
| #include "JackExports.h" | |||
| #include "JackError.h" | |||
| namespace Jack | |||
| { | |||
| /*! | |||
| \brief Utility functions. | |||
| */ | |||
| struct EXPORT JackTools | |||
| { | |||
| static int GetPID(); | |||
| static int GetUID(); | |||
| static char* UserDir(); | |||
| static char* ServerDir(const char* server_name, char* server_dir); | |||
| static const char* DefaultServerName(); | |||
| static void CleanupFiles(const char* server_name); | |||
| static int GetTmpdir(); | |||
| static void RewriteName(const char* name, char* new_name); | |||
| }; | |||
| /*! | |||
| \brief Internal cient command line parser. | |||
| */ | |||
| class EXPORT JackArgParser | |||
| { | |||
| /*! | |||
| \brief Utility functions. | |||
| */ | |||
| struct EXPORT JackTools | |||
| { | |||
| static int GetPID(); | |||
| static int GetUID(); | |||
| static char* UserDir(); | |||
| static char* ServerDir(const char* server_name, char* server_dir); | |||
| static const char* DefaultServerName(); | |||
| static void CleanupFiles(const char* server_name); | |||
| static int GetTmpdir(); | |||
| static void RewriteName(const char* name, char* new_name); | |||
| }; | |||
| /*! | |||
| \brief Internal cient command line parser. | |||
| */ | |||
| class EXPORT JackArgParser | |||
| { | |||
| private: | |||
| std::string fArgString; | |||
| int fArgc; | |||
| std::vector<std::string> fArgv; | |||
| public: | |||
| JackArgParser(const char* arg); | |||
| ~JackArgParser(); | |||
| std::string GetArgString(); | |||
| std::string GetArgString(); | |||
| int GetNumArgv(); | |||
| int GetArgc(); | |||
| int GetArgv(std::vector<std::string>& argv); | |||
| int GetArgv(char** argv); | |||
| void DeleteArgv(const char** argv); | |||
| int ParseParams(jack_driver_desc_t* desc, JSList** param_list); | |||
| }; | |||
| }; | |||
| /*! | |||
| \brief Generic monitoring class. Saves data to GnuPlot files ('.plt' and '.log' datafile) | |||
| */ | |||
| template <class T> class JackGnuPlotMonitor | |||
| { | |||
| private: | |||
| uint32_t fMeasureCnt; | |||
| uint32_t fMeasurePoints; | |||
| T** fMeasureTable; | |||
| uint32_t fTablePos; | |||
| std::string fName; | |||
| void DisplayMeasure ( T* measure ) | |||
| { | |||
| std::string display; | |||
| for ( uint32_t m_id = 0; m_id < fMeasurePoints; m_id++ ) | |||
| { | |||
| std::ostrstream value ( display, measure[m_id] ); | |||
| display += std::string ( " " ); | |||
| } | |||
| std::cout << "JackGnuPlotMonitor::Display '" << display << "'" << std::endl; | |||
| } | |||
| public: | |||
| JackGnuPlotMonitor ( uint32_t measure_cnt = 512, uint32_t measure_points = 5, std::string name = std::string ( "default" ) ) | |||
| { | |||
| jack_log ( "JackGnuPlotMonitor::JackGnuPlotMonitor measure_cnt %u measure_points %u", measure_cnt, measure_points ); | |||
| fMeasureCnt = measure_cnt; | |||
| fMeasurePoints = measure_points; | |||
| fTablePos = 0; | |||
| fName = name; | |||
| 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; | |||
| } | |||
| void InitTable() | |||
| { | |||
| for ( uint32_t cnt = 0; cnt < fMeasureCnt; cnt++ ) | |||
| for ( uint32_t point = 0; point < fMeasurePoints; point++ ) | |||
| fMeasureTable[cnt][point] = 0; | |||
| } | |||
| uint32_t Write ( T* measure ) | |||
| { | |||
| for ( uint32_t point = 0; point < fMeasurePoints; point++ ) | |||
| fMeasureTable[fTablePos][point] = measure[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 = 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++ ) | |||
| { | |||
| jack_log ( "JackGnuPlotMonitor::SetPlotFile - Add plot option : '%s'", options_list[i].c_str() ); | |||
| file << options_list[i] << std::endl; | |||
| } | |||
| file << "plot "; | |||
| for ( uint32_t row = 1; row <= field_number; row++ ) | |||
| { | |||
| jack_log ( "JackGnuPlotMonitor::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() ); | |||
| file << "\"" << data_filename << "\" using " << row << " title \"" << title << " : " << field_names[row-1] << "\" with lines"; | |||
| file << ( ( row < field_number ) ? ", " : "\n" ); | |||
| } | |||
| jack_log ( "JackGnuPlotMonitor::SetPlotFile - Saving GnuPlot '.plt' file to '%s'", plot_filename.c_str() ); | |||
| file.close(); | |||
| return 0; | |||
| } | |||
| }; | |||
| } | |||
| #endif | |||