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.

313 lines
11KB

  1. #include "JackNetTool.h"
  2. #include "JackError.h"
  3. using namespace std;
  4. namespace Jack
  5. {
  6. // NetMidiBuffer**********************************************************************************
  7. NetMidiBuffer::NetMidiBuffer ( session_params_t* params, unsigned int nports, char* net_buffer )
  8. {
  9. fNPorts = nports;
  10. fMaxBufsize = fNPorts * sizeof ( sample_t ) * params->fPeriodSize ;
  11. fMaxPcktSize = params->fMtu - sizeof ( packet_header_t );
  12. fBuffer = new char[fMaxBufsize];
  13. fPortBuffer = new JackMidiBuffer* [fNPorts];
  14. for ( int port_index = 0; port_index < fNPorts; port_index++ )
  15. fPortBuffer[port_index] = NULL;
  16. fNetBuffer = net_buffer;
  17. }
  18. NetMidiBuffer::~NetMidiBuffer()
  19. {
  20. delete[] fBuffer;
  21. delete[] fPortBuffer;
  22. }
  23. unsigned int NetMidiBuffer::GetSize()
  24. {
  25. return fMaxBufsize;
  26. }
  27. void NetMidiBuffer::DisplayEvents()
  28. {
  29. for ( int port_index = 0; port_index < fNPorts; port_index++ )
  30. {
  31. for ( unsigned int event = 0; event < fPortBuffer[port_index]->event_count; event++ )
  32. if ( fPortBuffer[port_index]->IsValid() )
  33. jack_info ( "port %d : midi event %u/%u -> time : %u, size : %u",
  34. port_index + 1, event + 1, fPortBuffer[port_index]->event_count,
  35. fPortBuffer[port_index]->events[event].time, fPortBuffer[port_index]->events[event].size );
  36. }
  37. }
  38. int NetMidiBuffer::RenderFromJackPorts()
  39. {
  40. int pos = 0;
  41. int copy_size;
  42. for ( int port_index = 0; port_index < fNPorts; port_index++ )
  43. {
  44. copy_size = sizeof ( JackMidiBuffer ) + fPortBuffer[port_index]->event_count * sizeof ( JackMidiEvent );
  45. memcpy ( fBuffer + pos, fPortBuffer[port_index], copy_size );
  46. pos += copy_size;
  47. memcpy ( fBuffer + pos, fPortBuffer[port_index] + ( fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos ),
  48. fPortBuffer[port_index]->write_pos );
  49. pos += fPortBuffer[port_index]->write_pos;
  50. }
  51. return pos;
  52. }
  53. int NetMidiBuffer::RenderToJackPorts()
  54. {
  55. int pos = 0;
  56. int copy_size;
  57. for ( int port_index = 0; port_index < fNPorts; port_index++ )
  58. {
  59. copy_size = sizeof ( JackMidiBuffer ) + reinterpret_cast<JackMidiBuffer*>(fBuffer + pos)->event_count * sizeof ( JackMidiEvent );
  60. memcpy ( fPortBuffer[port_index], fBuffer + pos, copy_size );
  61. pos += copy_size;
  62. memcpy ( fPortBuffer[port_index] + ( fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos ),
  63. fBuffer + pos, fPortBuffer[port_index]->write_pos );
  64. pos += fPortBuffer[port_index]->write_pos;
  65. }
  66. return pos;
  67. }
  68. int NetMidiBuffer::RenderFromNetwork ( unsigned int subcycle, unsigned int copy_size )
  69. {
  70. memcpy ( fBuffer + subcycle * fMaxPcktSize, fNetBuffer, copy_size );
  71. return copy_size;
  72. }
  73. int NetMidiBuffer::RenderToNetwork ( unsigned int subcycle, unsigned int total_size )
  74. {
  75. int size = total_size - subcycle * fMaxPcktSize;
  76. int copy_size = ( size <= fMaxPcktSize ) ? size : fMaxPcktSize;
  77. memcpy ( fNetBuffer, fBuffer + subcycle * fMaxPcktSize, copy_size );
  78. return copy_size;
  79. }
  80. // net audio buffer *********************************************************************************
  81. NetAudioBuffer::NetAudioBuffer ( session_params_t* params, unsigned int nports, char* net_buffer )
  82. {
  83. fNPorts = nports;
  84. fPeriodSize = params->fPeriodSize;
  85. fSubPeriodSize = params->fFramesPerPacket;
  86. fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t );
  87. fPortBuffer = new sample_t* [fNPorts];
  88. for ( int port_index = 0; port_index < fNPorts; port_index++ )
  89. fPortBuffer[port_index] = NULL;
  90. fNetBuffer = net_buffer;
  91. }
  92. NetAudioBuffer::~NetAudioBuffer()
  93. {
  94. delete[] fPortBuffer;
  95. }
  96. unsigned int NetAudioBuffer::GetSize()
  97. {
  98. return fNPorts * fSubPeriodBytesSize;
  99. }
  100. void NetAudioBuffer::RenderFromJackPorts ( unsigned int subcycle )
  101. {
  102. for ( int port_index = 0; port_index < fNPorts; port_index++ )
  103. memcpy ( fNetBuffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize );
  104. }
  105. void NetAudioBuffer::RenderToJackPorts ( unsigned int subcycle )
  106. {
  107. for ( int port_index = 0; port_index < fNPorts; port_index++ )
  108. memcpy ( fPortBuffer[port_index] + subcycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize );
  109. }
  110. // SessionParams ************************************************************************************
  111. EXPORT void SessionParamsHToN ( session_params_t* params )
  112. {
  113. params->fPacketID = htonl ( params->fPacketID );
  114. params->fMtu = htonl ( params->fMtu );
  115. params->fID = htonl ( params->fID );
  116. params->fSendAudioChannels = htonl ( params->fSendAudioChannels );
  117. params->fReturnAudioChannels = htonl ( params->fReturnAudioChannels );
  118. params->fSendMidiChannels = htonl ( params->fSendMidiChannels );
  119. params->fReturnMidiChannels = htonl ( params->fReturnMidiChannels );
  120. params->fSampleRate = htonl ( params->fSampleRate );
  121. params->fPeriodSize = htonl ( params->fPeriodSize );
  122. params->fFramesPerPacket = htonl ( params->fFramesPerPacket );
  123. params->fBitdepth = htonl ( params->fBitdepth );
  124. }
  125. EXPORT void SessionParamsNToH ( session_params_t* params )
  126. {
  127. params->fPacketID = ntohl ( params->fPacketID );
  128. params->fMtu = ntohl ( params->fMtu );
  129. params->fID = ntohl ( params->fID );
  130. params->fSendAudioChannels = ntohl ( params->fSendAudioChannels );
  131. params->fReturnAudioChannels = ntohl ( params->fReturnAudioChannels );
  132. params->fSendMidiChannels = ntohl ( params->fSendMidiChannels );
  133. params->fReturnMidiChannels = ntohl ( params->fReturnMidiChannels );
  134. params->fSampleRate = ntohl ( params->fSampleRate );
  135. params->fPeriodSize = ntohl ( params->fPeriodSize );
  136. params->fFramesPerPacket = ntohl ( params->fFramesPerPacket );
  137. params->fBitdepth = ntohl ( params->fBitdepth );
  138. }
  139. EXPORT void SessionParamsDisplay ( session_params_t* params )
  140. {
  141. jack_info ( "********************Params********************" );
  142. jack_info ( "Protocol revision : %c", params->fProtocolVersion );
  143. jack_info ( "MTU : %u", params->fMtu );
  144. jack_info ( "Master name : %s", params->fMasterNetName );
  145. jack_info ( "Slave name : %s", params->fSlaveNetName );
  146. jack_info ( "ID : %u", params->fID );
  147. jack_info ( "Send channels (audio - midi) : %d - %d", params->fSendAudioChannels, params->fSendMidiChannels );
  148. jack_info ( "Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels );
  149. jack_info ( "Sample rate : %u frames per second", params->fSampleRate );
  150. jack_info ( "Period size : %u frames per period", params->fPeriodSize );
  151. jack_info ( "Frames per packet : %u", params->fFramesPerPacket );
  152. jack_info ( "Packet per period : %u", params->fPeriodSize / params->fFramesPerPacket );
  153. jack_info ( "Bitdepth (0 for float) : %u", params->fBitdepth );
  154. jack_info ( "Name : %s", params->fName );
  155. jack_info ( "**********************************************" );
  156. }
  157. EXPORT sync_packet_type_t GetPacketType ( session_params_t* params )
  158. {
  159. switch ( params->fPacketID )
  160. {
  161. case 0:
  162. return SLAVE_AVAILABLE;
  163. case 1:
  164. return SLAVE_SETUP;
  165. case 2:
  166. return START_MASTER;
  167. case 3:
  168. return START_SLAVE;
  169. case 4:
  170. return KILL_MASTER;
  171. }
  172. return INVALID;
  173. }
  174. EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type )
  175. {
  176. switch ( packet_type )
  177. {
  178. case INVALID:
  179. return -1;
  180. case SLAVE_AVAILABLE:
  181. params->fPacketID = 0;
  182. break;
  183. case SLAVE_SETUP:
  184. params->fPacketID = 1;
  185. break;
  186. case START_MASTER:
  187. params->fPacketID = 2;
  188. break;
  189. case START_SLAVE:
  190. params->fPacketID = 3;
  191. break;
  192. case KILL_MASTER:
  193. params->fPacketID = 4;
  194. }
  195. return 0;
  196. }
  197. // Packet header **********************************************************************************
  198. EXPORT void PacketHeaderHToN ( packet_header_t* header )
  199. {
  200. header->fID = htonl ( header->fID );
  201. header->fMidiDataSize = htonl ( header->fMidiDataSize );
  202. header->fBitdepth = htonl ( header->fBitdepth );
  203. header->fNMidiPckt = htonl ( header->fNMidiPckt );
  204. header->fCycle = ntohl ( header->fCycle );
  205. header->fSubCycle = htonl ( header->fSubCycle );
  206. }
  207. EXPORT void PacketHeaderNToH ( packet_header_t* header )
  208. {
  209. header->fID = ntohl ( header->fID );
  210. header->fMidiDataSize = ntohl ( header->fMidiDataSize );
  211. header->fBitdepth = ntohl ( header->fBitdepth );
  212. header->fNMidiPckt = ntohl ( header->fNMidiPckt );
  213. header->fCycle = ntohl ( header->fCycle );
  214. header->fSubCycle = ntohl ( header->fSubCycle );
  215. }
  216. EXPORT void PacketHeaderDisplay ( packet_header_t* header )
  217. {
  218. jack_info ( "********************Header********************" );
  219. jack_info ( "Data type : %c", header->fDataType );
  220. jack_info ( "Data stream : %c", header->fDataStream );
  221. jack_info ( "ID : %u", header->fID );
  222. jack_info ( "Cycle : %u", header->fCycle );
  223. jack_info ( "SubCycle : %u", header->fSubCycle );
  224. jack_info ( "Midi packets : %u", header->fNMidiPckt );
  225. jack_info ( "Midi data size : %u", header->fMidiDataSize );
  226. jack_info ( "Last packet : '%c'", header->fIsLastPckt );
  227. jack_info ( "Bitdepth : %u (0 for float)", header->fBitdepth );
  228. jack_info ( "**********************************************" );
  229. }
  230. // Utility *******************************************************************************************************
  231. EXPORT unsigned int SetFramesPerPacket ( session_params_t* params )
  232. {
  233. if ( !params->fSendAudioChannels && !params->fReturnAudioChannels )
  234. return ( params->fFramesPerPacket = params->fPeriodSize );
  235. unsigned int period = ( int ) powf ( 2.f, ( int ) log2 ( ( params->fMtu - sizeof ( packet_header_t ) )
  236. / ( max ( params->fReturnAudioChannels, params->fSendAudioChannels ) * sizeof ( sample_t ) ) ) );
  237. ( period > params->fPeriodSize ) ? params->fFramesPerPacket = params->fPeriodSize : params->fFramesPerPacket = period;
  238. return params->fFramesPerPacket;
  239. }
  240. EXPORT unsigned int GetNMidiPckt ( session_params_t* params, unsigned int data_size )
  241. {
  242. //even if there is no midi data, jack need an empty buffer to know there is no event to read
  243. //99% of the cases : all data in one packet
  244. if ( data_size <= ( params->fMtu - sizeof ( packet_header_t ) ) )
  245. return 1;
  246. //else, get the number of needed packets (simply slice the biiig buffer)
  247. unsigned int npckt = data_size / ( params->fMtu - sizeof ( packet_header_t ) );
  248. if ( data_size % ( params->fMtu - sizeof ( packet_header_t ) ) )
  249. return ++npckt;
  250. return npckt;
  251. }
  252. EXPORT int SetRxTimeout ( int* sockfd, session_params_t* params )
  253. {
  254. int ret;
  255. struct timeval timeout;
  256. float time = static_cast<float> ( params->fFramesPerPacket ) / static_cast<float> ( params->fSampleRate );
  257. timeout.tv_sec = ( int ) time;
  258. float usec = 1.25 * ( time - timeout.tv_sec ) * 1000000;
  259. timeout.tv_usec = ( int ) usec;
  260. if ( ( ret = setsockopt ( *sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) ) ) < 0 )
  261. return ret;
  262. return timeout.tv_usec;
  263. }
  264. // Packet *******************************************************************************************************
  265. EXPORT bool IsNextPacket ( packet_header_t* previous, packet_header_t* next, unsigned int subcycles )
  266. {
  267. //ignore first cycle
  268. if ( previous->fCycle <= 1 )
  269. return true;
  270. //same PcktID (cycle), next SubPcktID (subcycle)
  271. if ( ( previous->fSubCycle < ( subcycles - 1 ) ) && ( next->fCycle == previous->fCycle ) && ( next->fSubCycle == ( previous->fSubCycle + 1 ) ) )
  272. return true;
  273. //next PcktID (cycle), SubPcktID reset to 1 (first subcyle)
  274. if ( ( next->fCycle == ( previous->fCycle + 1 ) ) && ( previous->fSubCycle == ( subcycles - 1 ) ) && ( next->fSubCycle == 0 ) )
  275. return true;
  276. //else, next is'nt next, return false
  277. return false;
  278. }
  279. }