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.

744 lines
30KB

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