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.

737 lines
30KB

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