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.

772 lines
31KB

  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. Copyright (C) 2008 Romain Moret at Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "JackNetDriver.h"
  17. #include "JackEngineControl.h"
  18. #include "JackGraphManager.h"
  19. #include "JackWaitThreadedDriver.h"
  20. using namespace std;
  21. namespace Jack
  22. {
  23. JackNetDriver::JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
  24. const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports,
  25. char* net_name, uint transport_sync, char network_mode )
  26. : JackAudioDriver ( name, alias, engine, table ), JackNetSlaveInterface ( ip, port )
  27. {
  28. jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip, port );
  29. // Use the hostname if no name parameter was given
  30. if ( strcmp ( net_name, "" ) == 0 )
  31. GetHostName ( net_name, JACK_CLIENT_NAME_SIZE );
  32. fParams.fMtu = mtu;
  33. fParams.fSendMidiChannels = midi_input_ports;
  34. fParams.fReturnMidiChannels = midi_output_ports;
  35. strcpy ( fParams.fName, net_name );
  36. fSocket.GetName ( fParams.fSlaveNetName );
  37. fParams.fTransportSync = transport_sync;
  38. fParams.fNetworkMode = network_mode;
  39. fSendTransportData.fState = -1;
  40. fReturnTransportData.fState = -1;
  41. fLastTransportState = -1;
  42. fLastTimebaseMaster = -1;
  43. fMidiCapturePortList = NULL;
  44. fMidiPlaybackPortList = NULL;
  45. #ifdef JACK_MONITOR
  46. fNetTimeMon = NULL;
  47. fRcvSyncUst = 0;
  48. #endif
  49. }
  50. JackNetDriver::~JackNetDriver()
  51. {
  52. delete[] fMidiCapturePortList;
  53. delete[] fMidiPlaybackPortList;
  54. #ifdef JACK_MONITOR
  55. delete fNetTimeMon;
  56. #endif
  57. }
  58. //open, close, attach and detach------------------------------------------------------
  59. int JackNetDriver::Open ( jack_nframes_t buffer_size, jack_nframes_t samplerate, bool capturing, bool playing,
  60. int inchannels, int outchannels, bool monitor,
  61. const char* capture_driver_name, const char* playback_driver_name,
  62. jack_nframes_t capture_latency, jack_nframes_t playback_latency )
  63. {
  64. if ( JackAudioDriver::Open ( buffer_size,
  65. samplerate,
  66. capturing,
  67. playing,
  68. inchannels,
  69. outchannels,
  70. monitor,
  71. capture_driver_name,
  72. playback_driver_name,
  73. capture_latency,
  74. playback_latency ) == 0 )
  75. {
  76. fEngineControl->fPeriod = 0;
  77. fEngineControl->fComputation = 500 * 1000;
  78. fEngineControl->fConstraint = 500 * 1000;
  79. return 0;
  80. }
  81. else
  82. {
  83. return -1;
  84. }
  85. }
  86. int JackNetDriver::Close()
  87. {
  88. #ifdef JACK_MONITOR
  89. if ( fNetTimeMon )
  90. fNetTimeMon->Save();
  91. #endif
  92. FreeAll();
  93. return JackDriver::Close();
  94. }
  95. // Attach and Detach are defined as empty methods: port allocation is done when driver actually start (that is in Init)
  96. int JackNetDriver::Attach()
  97. {
  98. return 0;
  99. }
  100. int JackNetDriver::Detach()
  101. {
  102. return 0;
  103. }
  104. //init and restart--------------------------------------------------------------------
  105. /*
  106. JackNetDriver is wrapped in a JackWaitThreadedDriver decorator that behaves
  107. as a "dummy driver, until Init method returns.
  108. */
  109. bool JackNetDriver::Initialize()
  110. {
  111. jack_log("JackNetDriver::Initialize()");
  112. //new loading, but existing socket, restart the driver
  113. if (fSocket.IsSocket()) {
  114. jack_info("Restarting driver...");
  115. FreeAll();
  116. }
  117. //set the parameters to send
  118. fParams.fSendAudioChannels = fCaptureChannels;
  119. fParams.fReturnAudioChannels = fPlaybackChannels;
  120. fParams.fSlaveSyncMode = fEngineControl->fSyncMode;
  121. //display some additional infos
  122. jack_info ( "NetDriver started in %s mode %s Master's transport sync.",
  123. ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
  124. //init network
  125. if (!JackNetSlaveInterface::Init()) {
  126. jack_error("Starting network fails...");
  127. return false;
  128. }
  129. //set global parameters
  130. SetParams();
  131. //allocate midi ports lists
  132. fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels];
  133. fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels];
  134. assert(fMidiCapturePortList);
  135. assert(fMidiPlaybackPortList);
  136. for (uint midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
  137. fMidiCapturePortList[midi_port_index] = NULL;
  138. }
  139. for (uint midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
  140. fMidiPlaybackPortList[midi_port_index] = NULL;
  141. }
  142. //register jack ports
  143. if (AllocPorts() != 0) {
  144. jack_error("Can't allocate ports.");
  145. return false;
  146. }
  147. //init done, display parameters
  148. SessionParamsDisplay(&fParams);
  149. //monitor
  150. #ifdef JACK_MONITOR
  151. string plot_name;
  152. //NetTimeMon
  153. plot_name = string ( fParams.fName );
  154. plot_name += string ( "_slave" );
  155. plot_name += ( fEngineControl->fSyncMode ) ? string ( "_sync" ) : string ( "_async" );
  156. switch ( fParams.fNetworkMode )
  157. {
  158. case 's' :
  159. plot_name += string ( "_slow" );
  160. break;
  161. case 'n' :
  162. plot_name += string ( "_normal" );
  163. break;
  164. case 'f' :
  165. plot_name += string ( "_fast" );
  166. break;
  167. }
  168. fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 5, plot_name );
  169. string net_time_mon_fields[] =
  170. {
  171. string ( "sync decoded" ),
  172. string ( "end of read" ),
  173. string ( "start of write" ),
  174. string ( "sync send" ),
  175. string ( "end of write" )
  176. };
  177. string net_time_mon_options[] =
  178. {
  179. string ( "set xlabel \"audio cycles\"" ),
  180. string ( "set ylabel \"% of audio cycle\"" )
  181. };
  182. fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 5 );
  183. #endif
  184. //driver parametering
  185. JackAudioDriver::SetBufferSize ( fParams.fPeriodSize );
  186. JackAudioDriver::SetSampleRate ( fParams.fSampleRate );
  187. JackDriver::NotifyBufferSize ( fParams.fPeriodSize );
  188. JackDriver::NotifySampleRate ( fParams.fSampleRate );
  189. //transport engine parametering
  190. fEngineControl->fTransport.SetNetworkSync ( fParams.fTransportSync );
  191. return true;
  192. }
  193. void JackNetDriver::FreeAll()
  194. {
  195. FreePorts();
  196. delete[] fTxBuffer;
  197. delete[] fRxBuffer;
  198. delete fNetAudioCaptureBuffer;
  199. delete fNetAudioPlaybackBuffer;
  200. delete fNetMidiCaptureBuffer;
  201. delete fNetMidiPlaybackBuffer;
  202. delete[] fMidiCapturePortList;
  203. delete[] fMidiPlaybackPortList;
  204. fTxBuffer = NULL;
  205. fRxBuffer = NULL;
  206. fNetAudioCaptureBuffer = NULL;
  207. fNetAudioPlaybackBuffer = NULL;
  208. fNetMidiCaptureBuffer = NULL;
  209. fNetMidiPlaybackBuffer = NULL;
  210. fMidiCapturePortList = NULL;
  211. fMidiPlaybackPortList = NULL;
  212. #ifdef JACK_MONITOR
  213. delete fNetTimeMon;
  214. fNetTimeMon = NULL;
  215. #endif
  216. }
  217. //jack ports and buffers--------------------------------------------------------------
  218. int JackNetDriver::AllocPorts()
  219. {
  220. jack_log ( "JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate );
  221. JackPort* port;
  222. jack_port_id_t port_id;
  223. char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
  224. char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
  225. unsigned long port_flags;
  226. int audio_port_index;
  227. uint midi_port_index;
  228. jack_latency_range_t range;
  229. //audio
  230. port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
  231. for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
  232. {
  233. snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1 );
  234. snprintf ( name, sizeof ( name ) - 1, "%s:capture_%d", fClientControl.fName, audio_port_index + 1 );
  235. if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
  236. static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
  237. {
  238. jack_error ( "driver: cannot register port for %s", name );
  239. return -1;
  240. }
  241. port = fGraphManager->GetPort ( port_id );
  242. port->SetAlias ( alias );
  243. //port latency
  244. range.min = range.max = fEngineControl->fBufferSize;
  245. port->SetLatencyRange(JackCaptureLatency, &range);
  246. fCapturePortList[audio_port_index] = port_id;
  247. jack_log ( "JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
  248. }
  249. port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
  250. for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
  251. {
  252. snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1 );
  253. snprintf ( name, sizeof ( name ) - 1, "%s:playback_%d",fClientControl.fName, audio_port_index + 1 );
  254. if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
  255. static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
  256. {
  257. jack_error ( "driver: cannot register port for %s", name );
  258. return -1;
  259. }
  260. port = fGraphManager->GetPort ( port_id );
  261. port->SetAlias ( alias );
  262. //port latency
  263. switch ( fParams.fNetworkMode )
  264. {
  265. case 'f' :
  266. range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize;
  267. break;
  268. case 'n' :
  269. range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
  270. break;
  271. case 's' :
  272. range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
  273. break;
  274. }
  275. port->SetLatencyRange(JackPlaybackLatency, &range);
  276. fPlaybackPortList[audio_port_index] = port_id;
  277. jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
  278. }
  279. //midi
  280. port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
  281. for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
  282. {
  283. snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1 );
  284. snprintf ( name, sizeof ( name ) - 1, "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1 );
  285. if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
  286. static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
  287. {
  288. jack_error ( "driver: cannot register port for %s", name );
  289. return -1;
  290. }
  291. port = fGraphManager->GetPort ( port_id );
  292. //port latency
  293. range.min = range.max = fEngineControl->fBufferSize;
  294. port->SetLatencyRange(JackCaptureLatency, &range);
  295. fMidiCapturePortList[midi_port_index] = port_id;
  296. jack_log ( "JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
  297. }
  298. port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
  299. for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
  300. {
  301. snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1 );
  302. snprintf ( name, sizeof ( name ) - 1, "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1 );
  303. if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
  304. static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
  305. {
  306. jack_error ( "driver: cannot register port for %s", name );
  307. return -1;
  308. }
  309. port = fGraphManager->GetPort ( port_id );
  310. //port latency
  311. switch ( fParams.fNetworkMode )
  312. {
  313. case 'f' :
  314. range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize;
  315. break;
  316. case 'n' :
  317. range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
  318. break;
  319. case 's' :
  320. range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
  321. break;
  322. }
  323. port->SetLatencyRange(JackPlaybackLatency, &range);
  324. fMidiPlaybackPortList[midi_port_index] = port_id;
  325. jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
  326. }
  327. return 0;
  328. }
  329. int JackNetDriver::FreePorts()
  330. {
  331. jack_log ( "JackNetDriver::FreePorts" );
  332. for (int audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) {
  333. if (fCapturePortList[audio_port_index] > 0) {
  334. fGraphManager->ReleasePort ( fClientControl.fRefNum, fCapturePortList[audio_port_index]);
  335. }
  336. }
  337. for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) {
  338. if (fPlaybackPortList[audio_port_index] > 0) {
  339. fGraphManager->ReleasePort ( fClientControl.fRefNum, fPlaybackPortList[audio_port_index]);
  340. }
  341. }
  342. for (uint midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
  343. if (fMidiCapturePortList && fMidiCapturePortList[midi_port_index] > 0) {
  344. fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiCapturePortList[midi_port_index]);
  345. }
  346. }
  347. for (uint midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
  348. if (fMidiPlaybackPortList && fMidiPlaybackPortList[midi_port_index] > 0) {
  349. fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index]);
  350. }
  351. }
  352. // Clear MIDI channels
  353. fParams.fSendMidiChannels = 0;
  354. fParams.fReturnMidiChannels = 0;
  355. return 0;
  356. }
  357. JackMidiBuffer* JackNetDriver::GetMidiInputBuffer ( int port_index )
  358. {
  359. return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiCapturePortList[port_index], fEngineControl->fBufferSize ) );
  360. }
  361. JackMidiBuffer* JackNetDriver::GetMidiOutputBuffer ( int port_index )
  362. {
  363. return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize ) );
  364. }
  365. //transport---------------------------------------------------------------------------
  366. void JackNetDriver::DecodeTransportData()
  367. {
  368. //is there a new timebase master on the net master ?
  369. // - release timebase master only if it's a non-conditional request
  370. // - no change or no request : don't do anything
  371. // - conditional request : don't change anything too, the master will know if this slave is actually the timebase master
  372. int refnum;
  373. bool conditional;
  374. if ( fSendTransportData.fTimebaseMaster == TIMEBASEMASTER )
  375. {
  376. fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
  377. if ( refnum != -1 )
  378. fEngineControl->fTransport.ResetTimebase ( refnum );
  379. jack_info ( "The NetMaster is now the new timebase master." );
  380. }
  381. //is there a transport state change to handle ?
  382. if ( fSendTransportData.fNewState && ( fSendTransportData.fState != fEngineControl->fTransport.GetState() ) )
  383. {
  384. switch ( fSendTransportData.fState )
  385. {
  386. case JackTransportStopped :
  387. fEngineControl->fTransport.SetCommand ( TransportCommandStop );
  388. jack_info ( "Master stops transport." );
  389. break;
  390. case JackTransportStarting :
  391. fEngineControl->fTransport.RequestNewPos ( &fSendTransportData.fPosition );
  392. fEngineControl->fTransport.SetCommand ( TransportCommandStart );
  393. jack_info ( "Master starts transport frame = %d", fSendTransportData.fPosition.frame);
  394. break;
  395. case JackTransportRolling :
  396. //fEngineControl->fTransport.SetCommand ( TransportCommandStart );
  397. fEngineControl->fTransport.SetState ( JackTransportRolling );
  398. jack_info ( "Master is rolling." );
  399. break;
  400. }
  401. }
  402. }
  403. void JackNetDriver::EncodeTransportData()
  404. {
  405. /* Desactivated
  406. //is there a timebase master change ?
  407. int refnum;
  408. bool conditional;
  409. fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
  410. if ( refnum != fLastTimebaseMaster )
  411. {
  412. //timebase master has released its function
  413. if ( refnum == -1 )
  414. {
  415. fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
  416. jack_info ( "Sending a timebase master release request." );
  417. }
  418. //there is a new timebase master
  419. else
  420. {
  421. fReturnTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
  422. jack_info ( "Sending a %s timebase master request.", ( conditional ) ? "conditional" : "non-conditional" );
  423. }
  424. fLastTimebaseMaster = refnum;
  425. }
  426. else
  427. fReturnTransportData.fTimebaseMaster = NO_CHANGE;
  428. */
  429. //update transport state and position
  430. fReturnTransportData.fState = fEngineControl->fTransport.Query ( &fReturnTransportData.fPosition );
  431. //is it a new state (that the master need to know...) ?
  432. fReturnTransportData.fNewState = (( fReturnTransportData.fState == JackTransportNetStarting) &&
  433. ( fReturnTransportData.fState != fLastTransportState ) &&
  434. ( fReturnTransportData.fState != fSendTransportData.fState ) );
  435. if ( fReturnTransportData.fNewState )
  436. jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData.fState ) );
  437. fLastTransportState = fReturnTransportData.fState;
  438. }
  439. //driver processes--------------------------------------------------------------------
  440. int JackNetDriver::Read()
  441. {
  442. uint midi_port_index;
  443. uint audio_port_index;
  444. //buffers
  445. for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
  446. fNetMidiCaptureBuffer->SetBuffer ( midi_port_index, GetMidiInputBuffer ( midi_port_index ) );
  447. for ( audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++ )
  448. fNetAudioCaptureBuffer->SetBuffer ( audio_port_index, GetInputBuffer ( audio_port_index ) );
  449. #ifdef JACK_MONITOR
  450. fNetTimeMon->New();
  451. #endif
  452. //receive sync (launch the cycle)
  453. if ( SyncRecv() == SOCKET_ERROR )
  454. return 0;
  455. #ifdef JACK_MONITOR
  456. // For timing
  457. fRcvSyncUst = GetMicroSeconds();
  458. #endif
  459. //decode sync
  460. //if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified
  461. DecodeSyncPacket();
  462. #ifdef JACK_MONITOR
  463. fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
  464. #endif
  465. //audio, midi or sync if driver is late
  466. if ( DataRecv() == SOCKET_ERROR )
  467. return SOCKET_ERROR;
  468. //take the time at the beginning of the cycle
  469. JackDriver::CycleTakeBeginTime();
  470. #ifdef JACK_MONITOR
  471. fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
  472. #endif
  473. return 0;
  474. }
  475. int JackNetDriver::Write()
  476. {
  477. uint midi_port_index;
  478. int audio_port_index;
  479. //buffers
  480. for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
  481. fNetMidiPlaybackBuffer->SetBuffer ( midi_port_index, GetMidiOutputBuffer ( midi_port_index ) );
  482. for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
  483. fNetAudioPlaybackBuffer->SetBuffer ( audio_port_index, GetOutputBuffer ( audio_port_index ) );
  484. #ifdef JACK_MONITOR
  485. fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
  486. #endif
  487. //sync
  488. EncodeSyncPacket();
  489. //send sync
  490. if ( SyncSend() == SOCKET_ERROR )
  491. return SOCKET_ERROR;
  492. #ifdef JACK_MONITOR
  493. fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
  494. #endif
  495. //send data
  496. if ( DataSend() == SOCKET_ERROR )
  497. return SOCKET_ERROR;
  498. #ifdef JACK_MONITOR
  499. fNetTimeMon->AddLast ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
  500. #endif
  501. return 0;
  502. }
  503. //driver loader-----------------------------------------------------------------------
  504. #ifdef __cplusplus
  505. extern "C"
  506. {
  507. #endif
  508. SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
  509. {
  510. jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  511. strcpy ( desc->name, "net" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  512. strcpy ( desc->desc, "netjack slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  513. desc->nparams = 10;
  514. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  515. int i = 0;
  516. strcpy ( desc->params[i].name, "multicast_ip" );
  517. desc->params[i].character = 'a';
  518. desc->params[i].type = JackDriverParamString;
  519. strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
  520. strcpy ( desc->params[i].short_desc, "Multicast Address" );
  521. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  522. i++;
  523. strcpy ( desc->params[i].name, "udp_net_port" );
  524. desc->params[i].character = 'p';
  525. desc->params[i].type = JackDriverParamInt;
  526. desc->params[i].value.i = DEFAULT_PORT;
  527. strcpy ( desc->params[i].short_desc, "UDP port" );
  528. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  529. i++;
  530. strcpy ( desc->params[i].name, "mtu" );
  531. desc->params[i].character = 'M';
  532. desc->params[i].type = JackDriverParamInt;
  533. desc->params[i].value.i = DEFAULT_MTU;
  534. strcpy ( desc->params[i].short_desc, "MTU to the master" );
  535. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  536. i++;
  537. strcpy ( desc->params[i].name, "input_ports" );
  538. desc->params[i].character = 'C';
  539. desc->params[i].type = JackDriverParamInt;
  540. desc->params[i].value.i = 2;
  541. strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
  542. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  543. i++;
  544. strcpy ( desc->params[i].name, "output_ports" );
  545. desc->params[i].character = 'P';
  546. desc->params[i].type = JackDriverParamInt;
  547. desc->params[i].value.i = 2;
  548. strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
  549. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  550. i++;
  551. strcpy ( desc->params[i].name, "midi_in_ports" );
  552. desc->params[i].character = 'i';
  553. desc->params[i].type = JackDriverParamInt;
  554. desc->params[i].value.i = 0;
  555. strcpy ( desc->params[i].short_desc, "Number of midi input ports" );
  556. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  557. i++;
  558. strcpy ( desc->params[i].name, "midi_out_ports" );
  559. desc->params[i].character = 'o';
  560. desc->params[i].type = JackDriverParamUInt;
  561. desc->params[i].value.i = 0;
  562. strcpy ( desc->params[i].short_desc, "Number of midi output ports" );
  563. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  564. i++;
  565. strcpy ( desc->params[i].name, "client_name" );
  566. desc->params[i].character = 'n';
  567. desc->params[i].type = JackDriverParamString;
  568. strcpy ( desc->params[i].value.str, "'hostname'" );
  569. strcpy ( desc->params[i].short_desc, "Name of the jack client" );
  570. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  571. i++;
  572. strcpy ( desc->params[i].name, "transport_sync" );
  573. desc->params[i].character = 't';
  574. desc->params[i].type = JackDriverParamUInt;
  575. desc->params[i].value.ui = 1U;
  576. strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
  577. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  578. i++;
  579. strcpy ( desc->params[i].name, "mode" );
  580. desc->params[i].character = 'm';
  581. desc->params[i].type = JackDriverParamString;
  582. strcpy ( desc->params[i].value.str, "slow" );
  583. strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
  584. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  585. return desc;
  586. }
  587. SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params )
  588. {
  589. char multicast_ip[16];
  590. strcpy ( multicast_ip, DEFAULT_MULTICAST_IP );
  591. char net_name[JACK_CLIENT_NAME_SIZE + 1];
  592. int udp_port = DEFAULT_PORT;
  593. int mtu = DEFAULT_MTU;
  594. uint transport_sync = 1;
  595. jack_nframes_t period_size = 128;
  596. jack_nframes_t sample_rate = 48000;
  597. int audio_capture_ports = 2;
  598. int audio_playback_ports = 2;
  599. int midi_input_ports = 0;
  600. int midi_output_ports = 0;
  601. bool monitor = false;
  602. char network_mode = 's';
  603. const JSList* node;
  604. const jack_driver_param_t* param;
  605. net_name[0] = 0;
  606. for ( node = params; node; node = jack_slist_next ( node ) )
  607. {
  608. param = ( const jack_driver_param_t* ) node->data;
  609. switch ( param->character )
  610. {
  611. case 'a' :
  612. strncpy ( multicast_ip, param->value.str, 15 );
  613. break;
  614. case 'p':
  615. udp_port = param->value.ui;
  616. break;
  617. case 'M':
  618. mtu = param->value.i;
  619. break;
  620. case 'C':
  621. audio_capture_ports = param->value.i;
  622. break;
  623. case 'P':
  624. audio_playback_ports = param->value.i;
  625. break;
  626. case 'i':
  627. midi_input_ports = param->value.i;
  628. break;
  629. case 'o':
  630. midi_output_ports = param->value.i;
  631. break;
  632. case 'n' :
  633. strncpy ( net_name, param->value.str, JACK_CLIENT_NAME_SIZE );
  634. break;
  635. case 't' :
  636. transport_sync = param->value.ui;
  637. break;
  638. case 'm' :
  639. if ( strcmp ( param->value.str, "normal" ) == 0 )
  640. network_mode = 'n';
  641. else if ( strcmp ( param->value.str, "slow" ) == 0 )
  642. network_mode = 's';
  643. else if ( strcmp ( param->value.str, "fast" ) == 0 )
  644. network_mode = 'f';
  645. else
  646. jack_error ( "Unknown network mode, using 'normal' mode." );
  647. break;
  648. }
  649. }
  650. try
  651. {
  652. Jack::JackDriverClientInterface* driver =
  653. new Jack::JackWaitThreadedDriver (
  654. new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
  655. midi_input_ports, midi_output_ports, net_name, transport_sync, network_mode ) );
  656. if ( driver->Open ( period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports,
  657. monitor, "from_master_", "to_master_", 0, 0 ) == 0 )
  658. {
  659. return driver;
  660. }
  661. else
  662. {
  663. delete driver;
  664. return NULL;
  665. }
  666. }
  667. catch ( ... )
  668. {
  669. return NULL;
  670. }
  671. }
  672. #ifdef __cplusplus
  673. }
  674. #endif
  675. }