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.

783 lines
31KB

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