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.

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