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.

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