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.

831 lines
34KB

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