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.

739 lines
30KB

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