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.

763 lines
32KB

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