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.

716 lines
29KB

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