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.

844 lines
35KB

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