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.

773 lines
32KB

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