jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
11KB

  1. /*
  2. Copyright (C) 2008 Romain Moret at Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackConstants.h"
  16. #include "JackMidiPort.h"
  17. #include "JackExports.h"
  18. #include "JackError.h"
  19. #include "JackTools.h"
  20. #include "JackPlatformNetSocket.h"
  21. #include "types.h"
  22. #include <string>
  23. #include <algorithm>
  24. #include <cmath>
  25. using namespace std;
  26. namespace Jack
  27. {
  28. typedef struct _session_params session_params_t;
  29. typedef struct _packet_header packet_header_t;
  30. typedef struct _net_transport_data net_transport_data_t;
  31. typedef struct sockaddr socket_address_t;
  32. typedef struct in_addr address_t;
  33. typedef jack_default_audio_sample_t sample_t;
  34. //session params ******************************************************************************
  35. struct _session_params
  36. {
  37. char fPacketType[7]; //packet type ('param')
  38. char fProtocolVersion; //version
  39. uint32_t fPacketID; //indicates the packet type
  40. char fMasterNetName[256]; //master hostname (network)
  41. char fSlaveNetName[256]; //slave hostname (network)
  42. uint32_t fMtu; //connection mtu
  43. uint32_t fID; //slave's ID
  44. uint32_t fTransportSync; //is the transport synced ?
  45. uint32_t fSendAudioChannels; //number of master->slave channels
  46. uint32_t fReturnAudioChannels; //number of slave->master channels
  47. uint32_t fSendMidiChannels; //number of master->slave midi channels
  48. uint32_t fReturnMidiChannels; //number of slave->master midi channels
  49. uint32_t fSampleRate; //session sample rate
  50. uint32_t fPeriodSize; //period size
  51. uint32_t fFramesPerPacket; //complete frames per packet
  52. uint32_t fBitdepth; //samples bitdepth (unused)
  53. char fName[JACK_CLIENT_NAME_SIZE]; //slave's name
  54. };
  55. //net status **********************************************************************************
  56. enum _net_status
  57. {
  58. NET_SOCKET_ERROR = 0,
  59. NET_CONNECT_ERROR,
  60. NET_ERROR,
  61. NET_SEND_ERROR,
  62. NET_RECV_ERROR,
  63. NET_CONNECTED,
  64. NET_ROLLING
  65. };
  66. typedef enum _net_status net_status_t;
  67. //sync packet type ****************************************************************************
  68. enum _sync_packet_type
  69. {
  70. INVALID = 0, //...
  71. SLAVE_AVAILABLE, //a slave is available
  72. SLAVE_SETUP, //slave configuration
  73. START_MASTER, //slave is ready, start master
  74. START_SLAVE, //master is ready, activate slave
  75. KILL_MASTER //master must stop
  76. };
  77. typedef enum _sync_packet_type sync_packet_type_t;
  78. //packet header *******************************************************************************
  79. struct _packet_header
  80. {
  81. char fPacketType[7]; //packet type ( 'headr' )
  82. char fDataType; //a for audio, m for midi
  83. char fDataStream; //s for send, r for return
  84. uint32_t fID; //to identify the slave
  85. uint32_t fBitdepth; //bitdepth of the data samples
  86. uint32_t fMidiDataSize; //size of midi data (if packet is 'midi typed') in bytes
  87. uint32_t fNMidiPckt; //number of midi packets of the cycle
  88. uint32_t fCycle; //process cycle counter
  89. uint32_t fSubCycle; //midi/audio subcycle counter
  90. char fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n')
  91. char fFree[13]; //unused
  92. };
  93. //transport data ******************************************************************************
  94. struct _net_transport_data
  95. {
  96. char fTransportType[10]; //test value ('transport')
  97. jack_position_t fCurPos;
  98. jack_transport_state_t fCurState;
  99. };
  100. //midi data ***********************************************************************************
  101. class EXPORT NetMidiBuffer
  102. {
  103. private:
  104. int fNPorts;
  105. size_t fMaxBufsize;
  106. int fMaxPcktSize;
  107. char* fBuffer;
  108. char* fNetBuffer;
  109. JackMidiBuffer** fPortBuffer;
  110. public:
  111. NetMidiBuffer ( session_params_t* params, uint32_t nports, char* net_buffer );
  112. ~NetMidiBuffer();
  113. void Reset();
  114. size_t GetSize();
  115. //utility
  116. void DisplayEvents();
  117. //jack<->buffer
  118. int RenderFromJackPorts();
  119. int RenderToJackPorts();
  120. //network<->buffer
  121. int RenderFromNetwork ( int subcycle, size_t copy_size );
  122. int RenderToNetwork ( int subcycle, size_t total_size );
  123. void SetBuffer(int index, JackMidiBuffer* buffer);
  124. };
  125. // audio data *********************************************************************************
  126. class EXPORT NetAudioBuffer
  127. {
  128. private:
  129. int fNPorts;
  130. jack_nframes_t fPeriodSize;
  131. jack_nframes_t fSubPeriodSize;
  132. size_t fSubPeriodBytesSize;
  133. char* fNetBuffer;
  134. sample_t** fPortBuffer;
  135. public:
  136. NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer );
  137. ~NetAudioBuffer();
  138. size_t GetSize();
  139. //jack<->buffer
  140. void RenderFromJackPorts ( int subcycle );
  141. void RenderToJackPorts ( int subcycle );
  142. void SetBuffer(int index, sample_t* buffer);
  143. };
  144. // net monitor ********************************************************************************
  145. template <class T> class NetMonitor
  146. {
  147. private:
  148. uint fMeasureCnt;
  149. uint fMeasurePoints;
  150. T** fMeasureTable;
  151. uint fTablePos;
  152. void DisplayMeasure ( T* measure )
  153. {
  154. string display;
  155. for ( uint m_id = 0; m_id < fMeasurePoints; m_id++ )
  156. {
  157. char* value;
  158. sprintf ( value, "%llu ", measure[m_id] );
  159. display += string ( value );
  160. }
  161. cout << "NetMonitor:: '" << display << "'" << endl;
  162. }
  163. public:
  164. NetMonitor ( uint measure_cnt = 512, uint measure_points = 5 )
  165. {
  166. jack_log ( "JackNetMonitor::JackNetMonitor measure_cnt %u measure_points %u", measure_cnt, measure_points );
  167. fMeasureCnt = measure_cnt;
  168. fMeasurePoints = measure_points;
  169. fTablePos = 0;
  170. //allocate measure table
  171. fMeasureTable = new T*[fMeasureCnt];
  172. for ( uint i = 0; i < fMeasureCnt; i++ )
  173. fMeasureTable[i] = new T[fMeasurePoints];
  174. //init measure table
  175. for ( uint cnt = 0; cnt < fMeasureCnt; cnt++ )
  176. for ( uint point = 0; point < fMeasurePoints; point++ )
  177. fMeasureTable[cnt][point] = 0;
  178. }
  179. ~NetMonitor()
  180. {
  181. jack_log ( "NetMonitor::~NetMonitor" );
  182. for ( uint cnt = 0; cnt < fMeasureCnt; cnt++ )
  183. delete[] fMeasureTable[cnt];
  184. delete[] fMeasureTable;
  185. }
  186. void InitTable()
  187. {
  188. for ( uint cnt = 0; cnt < fMeasureCnt; cnt++ )
  189. for ( uint point = 0; point < fMeasurePoints; point++ )
  190. fMeasureTable[cnt][point] = 0;
  191. }
  192. uint Write ( T* measure )
  193. {
  194. for ( uint point = 0; point < fMeasurePoints; point++ )
  195. fMeasureTable[fTablePos][point] = measure[point];
  196. if ( ++fTablePos == fMeasureCnt )
  197. fTablePos = 0;
  198. return fTablePos;
  199. }
  200. int Save ( string& filename )
  201. {
  202. filename += "_netmonitor.log";
  203. jack_log ( "JackNetMonitor::Save filename %s", filename.c_str() );
  204. FILE* file = fopen ( filename.c_str(), "w" );
  205. //print each measure with tab separated values
  206. for ( uint cnt = 0; cnt < fMeasureCnt; cnt++ )
  207. {
  208. for ( uint pt = 0; pt < fMeasurePoints; pt++ )
  209. fprintf ( file, "%llu \t ", fMeasureTable[cnt][pt] );
  210. fprintf ( file, "\n" );
  211. }
  212. fclose(file);
  213. return 0;
  214. }
  215. int SetPlotFile ( string& name, string* options_list = NULL, uint options_number = 0, string* field_names = NULL, uint field_number = 0 )
  216. {
  217. //names and file
  218. string title = name + "_netmonitor";
  219. string plot_filename = title + ".plt";
  220. string data_filename = title + ".log";
  221. FILE* file = fopen ( plot_filename.c_str(), "w" );
  222. //base options
  223. fprintf ( file, "set multiplot\n" );
  224. fprintf ( file, "set grid\n" );
  225. fprintf ( file, "set title \"%s\"\n", title.c_str() );
  226. //additional options
  227. for ( uint i = 0; i < options_number; i++ )
  228. {
  229. jack_log ( "JackNetMonitor::SetPlotFile - Add plot option : '%s'", options_list[i].c_str() );
  230. fprintf ( file, "%s\n", options_list[i].c_str() );
  231. }
  232. //plot
  233. fprintf ( file, "plot " );
  234. for ( uint row = 1; row <= field_number; row++ )
  235. {
  236. jack_log ( "JackNetMonitor::SetPlotFile - Add plot : file '%s' row '%d' title '%s' field '%s'",
  237. data_filename.c_str(), row, name.c_str(), field_names[row-1].c_str() );
  238. fprintf ( file, "\"%s\" using %u title \"%s : %s\" with lines", data_filename.c_str(), row, name.c_str(), field_names[row-1].c_str() );
  239. fprintf ( file, ( row < field_number ) ? "," : "\n" );
  240. }
  241. jack_log ( "JackNetMonitor::SetPlotFile - Saving GnuPlot '.plt' file to '%s'", plot_filename.c_str() );
  242. fclose ( file );
  243. return 0;
  244. }
  245. };
  246. //utility *************************************************************************************
  247. //socket API management
  248. EXPORT int SocketAPIInit();
  249. EXPORT int SocketAPIEnd();
  250. //n<-->h functions
  251. EXPORT void SessionParamsHToN ( session_params_t* params );
  252. EXPORT void SessionParamsNToH ( session_params_t* params );
  253. EXPORT void PacketHeaderHToN ( packet_header_t* header );
  254. EXPORT void PacketHeaderNToH ( packet_header_t* header );
  255. //display session parameters
  256. EXPORT void SessionParamsDisplay ( session_params_t* params );
  257. //display packet header
  258. EXPORT void PacketHeaderDisplay ( packet_header_t* header );
  259. //get the packet type from a sesion parameters
  260. EXPORT sync_packet_type_t GetPacketType ( session_params_t* params );
  261. //set the packet type in a session parameters
  262. EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type );
  263. //step of network initialization
  264. EXPORT jack_nframes_t SetFramesPerPacket ( session_params_t* params );
  265. //get the midi packet number for a given cycle
  266. EXPORT int GetNMidiPckt ( session_params_t* params, size_t data_size );
  267. //set the recv timeout on a socket
  268. EXPORT int SetRxTimeout ( JackNetSocket* socket, session_params_t* params );
  269. //check if 'next' packet is really the next after 'previous'
  270. EXPORT bool IsNextPacket ( packet_header_t* previous, packet_header_t* next, uint subcycles );
  271. }