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.

508 lines
18KB

  1. /*
  2. Copyright (C) 2008 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 "JackNetAdapter.h"
  16. #include "JackException.h"
  17. #include "JackServerGlobals.h"
  18. #include "JackEngineControl.h"
  19. #include "JackArgParser.h"
  20. #include <assert.h>
  21. namespace Jack
  22. {
  23. JackNetAdapter::JackNetAdapter(jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
  24. : JackAudioAdapterInterface(buffer_size, sample_rate), JackNetSlaveInterface(), fThread(this)
  25. {
  26. jack_log("JackNetAdapter::JackNetAdapter");
  27. //global parametering
  28. //we can't call JackNetSlaveInterface constructor with some parameters before
  29. //because we don't have full parametering right now
  30. //parameters will be parsed from the param list, and then JackNetSlaveInterface will be filled with proper values
  31. strcpy(fMulticastIP, DEFAULT_MULTICAST_IP);
  32. uint port = DEFAULT_PORT;
  33. GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE);
  34. fSocket.GetName(fParams.fSlaveNetName);
  35. fParams.fMtu = DEFAULT_MTU;
  36. fParams.fTransportSync = 0;
  37. int send_audio = -1;
  38. int return_audio = -1;
  39. fParams.fSendMidiChannels = 0;
  40. fParams.fReturnMidiChannels = 0;
  41. fParams.fSampleRate = sample_rate;
  42. fParams.fPeriodSize = buffer_size;
  43. fParams.fSlaveSyncMode = 1;
  44. fParams.fNetworkMode = 's';
  45. fJackClient = jack_client;
  46. //options parsing
  47. const JSList* node;
  48. const jack_driver_param_t* param;
  49. for (node = params; node; node = jack_slist_next(node))
  50. {
  51. param = (const jack_driver_param_t*) node->data;
  52. switch (param->character)
  53. {
  54. case 'a' :
  55. if (strlen(param->value.str) < 32)
  56. strcpy(fMulticastIP, param->value.str);
  57. else
  58. jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP);
  59. break;
  60. case 'p' :
  61. fSocket.SetPort(param->value.ui);
  62. break;
  63. case 'M' :
  64. fParams.fMtu = param->value.i;
  65. break;
  66. case 'C' :
  67. send_audio = param->value.i;
  68. break;
  69. case 'P' :
  70. return_audio = param->value.i;
  71. break;
  72. case 'n' :
  73. strncpy(fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE);
  74. break;
  75. case 't' :
  76. //fParams.fTransportSync = param->value.ui;
  77. break;
  78. #if HAVE_CELT
  79. case 'c':
  80. if (param->value.i > 0) {
  81. fParams.fSampleEncoder = JackCeltEncoder;
  82. fParams.fKBps = param->value.i;
  83. } else {
  84. fParams.fSampleEncoder = JackFloatEncoder;
  85. }
  86. break;
  87. #endif
  88. case 'm' :
  89. if (strcmp(param->value.str, "normal") == 0)
  90. fParams.fNetworkMode = 'n';
  91. else if (strcmp(param->value.str, "slow") == 0)
  92. fParams.fNetworkMode = 's';
  93. else if (strcmp(param->value.str, "fast") == 0)
  94. fParams.fNetworkMode = 'f';
  95. else
  96. jack_error("Unknown network mode, using 'normal' mode.");
  97. break;
  98. case 'q':
  99. fQuality = param->value.ui;
  100. break;
  101. case 'g':
  102. fRingbufferCurSize = param->value.ui;
  103. fAdaptative = false;
  104. break;
  105. }
  106. }
  107. //set the socket parameters
  108. fSocket.SetPort(port);
  109. fSocket.SetAddress(fMulticastIP, port);
  110. // If not set, takes deafault
  111. fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio;
  112. // If not set, takes deafault
  113. fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio;
  114. //set the audio adapter interface channel values
  115. SetInputs(fParams.fSendAudioChannels);
  116. SetOutputs(fParams.fReturnAudioChannels);
  117. //soft buffers will be allocated later (once network initialization done)
  118. fSoftCaptureBuffer = NULL;
  119. fSoftPlaybackBuffer = NULL;
  120. }
  121. JackNetAdapter::~JackNetAdapter()
  122. {
  123. jack_log("JackNetAdapter::~JackNetAdapter");
  124. int port_index;
  125. if (fSoftCaptureBuffer) {
  126. for (port_index = 0; port_index < fCaptureChannels; port_index++)
  127. delete[] fSoftCaptureBuffer[port_index];
  128. delete[] fSoftCaptureBuffer;
  129. }
  130. if (fSoftPlaybackBuffer) {
  131. for (port_index = 0; port_index < fPlaybackChannels; port_index++)
  132. delete[] fSoftPlaybackBuffer[port_index];
  133. delete[] fSoftPlaybackBuffer;
  134. }
  135. }
  136. //open/close--------------------------------------------------------------------------
  137. int JackNetAdapter::Open()
  138. {
  139. jack_log("JackNetAdapter::Open");
  140. jack_info("NetAdapter started in %s mode %s Master's transport sync.",
  141. (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without");
  142. if (fThread.StartSync() < 0) {
  143. jack_error("Cannot start netadapter thread");
  144. return -1;
  145. }
  146. return 0;
  147. }
  148. int JackNetAdapter::Close()
  149. {
  150. jack_log("JackNetAdapter::Close");
  151. #ifdef JACK_MONITOR
  152. fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
  153. #endif
  154. fSocket.Close();
  155. switch (fThread.GetStatus())
  156. {
  157. // Kill the thread in Init phase
  158. case JackThread::kStarting:
  159. case JackThread::kIniting:
  160. if (fThread.Kill() < 0) {
  161. jack_error("Cannot kill thread");
  162. return -1;
  163. }
  164. break;
  165. // Stop when the thread cycle is finished
  166. case JackThread::kRunning:
  167. if (fThread.Stop() < 0) {
  168. jack_error ("Cannot stop thread");
  169. return -1;
  170. }
  171. break;
  172. default:
  173. break;
  174. }
  175. return 0;
  176. }
  177. int JackNetAdapter::SetBufferSize(jack_nframes_t buffer_size)
  178. {
  179. JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
  180. return 0;
  181. }
  182. //thread------------------------------------------------------------------------------
  183. // TODO : if failure, thread exist... need to restart ?
  184. bool JackNetAdapter::Init()
  185. {
  186. jack_log("JackNetAdapter::Init");
  187. int port_index;
  188. //init network connection
  189. if (!JackNetSlaveInterface::Init()) {
  190. jack_error("JackNetSlaveInterface::Init() error...");
  191. return false;
  192. }
  193. //then set global parameters
  194. if (!SetParams()) {
  195. jack_error("SetParams error...");
  196. return false;
  197. }
  198. //set buffers
  199. if (fCaptureChannels > 0) {
  200. fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
  201. for (port_index = 0; port_index < fCaptureChannels; port_index++)
  202. {
  203. fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  204. fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]);
  205. }
  206. }
  207. if (fPlaybackChannels > 0) {
  208. fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
  209. for (port_index = 0; port_index < fPlaybackChannels; port_index++)
  210. {
  211. fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
  212. fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]);
  213. }
  214. }
  215. //set audio adapter parameters
  216. SetAdaptedBufferSize(fParams.fPeriodSize);
  217. SetAdaptedSampleRate(fParams.fSampleRate);
  218. // Will do "something" on OSX only...
  219. fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
  220. if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
  221. jack_error("AcquireSelfRealTime error");
  222. } else {
  223. set_threaded_log_function();
  224. }
  225. //init done, display parameters
  226. SessionParamsDisplay(&fParams);
  227. return true;
  228. }
  229. bool JackNetAdapter::Execute()
  230. {
  231. try {
  232. // Keep running even in case of error
  233. while (fThread.GetStatus() == JackThread::kRunning)
  234. if (Process() == SOCKET_ERROR)
  235. return false;
  236. return false;
  237. } catch (JackNetException& e) {
  238. e.PrintMessage();
  239. jack_info("NetAdapter is restarted.");
  240. Reset();
  241. fThread.DropSelfRealTime();
  242. fThread.SetStatus(JackThread::kIniting);
  243. if (Init()) {
  244. fThread.SetStatus(JackThread::kRunning);
  245. return true;
  246. } else {
  247. return false;
  248. }
  249. }
  250. }
  251. //transport---------------------------------------------------------------------------
  252. void JackNetAdapter::DecodeTransportData()
  253. {
  254. //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver)
  255. //is there a new transport state ?
  256. if (fSendTransportData.fNewState &&(fSendTransportData.fState != jack_transport_query(fJackClient, NULL))) {
  257. switch (fSendTransportData.fState)
  258. {
  259. case JackTransportStopped :
  260. jack_transport_stop(fJackClient);
  261. jack_info("NetMaster : transport stops.");
  262. break;
  263. case JackTransportStarting :
  264. jack_transport_reposition(fJackClient, &fSendTransportData.fPosition);
  265. jack_transport_start(fJackClient);
  266. jack_info("NetMaster : transport starts.");
  267. break;
  268. case JackTransportRolling :
  269. //TODO , we need to :
  270. // - find a way to call TransportEngine->SetNetworkSync()
  271. // - turn the transport state to JackTransportRolling
  272. jack_info("NetMaster : transport rolls.");
  273. break;
  274. }
  275. }
  276. }
  277. void JackNetAdapter::EncodeTransportData()
  278. {
  279. //is there a timebase master change ?
  280. int refnum = -1;
  281. bool conditional = 0;
  282. //TODO : get the actual timebase master
  283. if (refnum != fLastTimebaseMaster) {
  284. //timebase master has released its function
  285. if (refnum == -1) {
  286. fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
  287. jack_info("Sending a timebase master release request.");
  288. } else {
  289. //there is a new timebase master
  290. fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
  291. jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional");
  292. }
  293. fLastTimebaseMaster = refnum;
  294. } else {
  295. fReturnTransportData.fTimebaseMaster = NO_CHANGE;
  296. }
  297. //update transport state and position
  298. fReturnTransportData.fState = jack_transport_query(fJackClient, &fReturnTransportData.fPosition);
  299. //is it a new state (that the master need to know...) ?
  300. fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) &&
  301. (fReturnTransportData.fState != fSendTransportData.fState));
  302. if (fReturnTransportData.fNewState)
  303. jack_info("Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState));
  304. fLastTransportState = fReturnTransportData.fState;
  305. }
  306. //read/write operations---------------------------------------------------------------
  307. int JackNetAdapter::Read()
  308. {
  309. //don't return -1 in case of sync recv failure
  310. //we need the process to continue for network error detection
  311. if (SyncRecv() == SOCKET_ERROR)
  312. return 0;
  313. DecodeSyncPacket();
  314. return DataRecv();
  315. }
  316. int JackNetAdapter::Write()
  317. {
  318. EncodeSyncPacket();
  319. if (SyncSend() == SOCKET_ERROR)
  320. return SOCKET_ERROR;
  321. return DataSend();
  322. }
  323. //process-----------------------------------------------------------------------------
  324. int JackNetAdapter::Process()
  325. {
  326. //read data from the network
  327. //in case of fatal network error, stop the process
  328. if (Read() == SOCKET_ERROR)
  329. return SOCKET_ERROR;
  330. PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize);
  331. //then write data to network
  332. //in case of failure, stop process
  333. if (Write() == SOCKET_ERROR)
  334. return SOCKET_ERROR;
  335. return 0;
  336. }
  337. } // namespace Jack
  338. //loader------------------------------------------------------------------------------
  339. #ifdef __cplusplus
  340. extern "C"
  341. {
  342. #endif
  343. #include "driver_interface.h"
  344. #include "JackAudioAdapter.h"
  345. using namespace Jack;
  346. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  347. {
  348. jack_driver_desc_t * desc;
  349. jack_driver_desc_filler_t filler;
  350. jack_driver_param_value_t value;
  351. desc = jack_driver_descriptor_construct("netadapter", "netjack net <==> audio backend adapter", &filler);
  352. strcpy(value.str, DEFAULT_MULTICAST_IP);
  353. jack_driver_descriptor_add_parameter(desc, &filler, "multicast_ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL);
  354. value.i = DEFAULT_PORT;
  355. jack_driver_descriptor_add_parameter(desc, &filler, "udp_net_port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
  356. value.i = DEFAULT_MTU;
  357. jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL);
  358. value.i = 2;
  359. jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", NULL);
  360. jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio output ports", NULL);
  361. #if HAVE_CELT
  362. value.i = -1;
  363. jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL);
  364. #endif
  365. strcpy(value.str, "'hostname'");
  366. jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL);
  367. value.ui = 1U;
  368. jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL);
  369. strcpy(value.str, "slow");
  370. jack_driver_descriptor_add_parameter(desc, &filler, "mode", 'm', JackDriverParamString, &value, NULL, "Slow, Normal or Fast mode.", NULL);
  371. value.i = 0;
  372. jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
  373. value.i = 32768;
  374. jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
  375. value.i = false;
  376. jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netmaster to system ports", "");
  377. return desc;
  378. }
  379. SERVER_EXPORT int jack_internal_initialize(jack_client_t* jack_client, const JSList* params)
  380. {
  381. jack_log("Loading netadapter");
  382. Jack::JackAudioAdapter* adapter;
  383. jack_nframes_t buffer_size = jack_get_buffer_size(jack_client);
  384. jack_nframes_t sample_rate = jack_get_sample_rate(jack_client);
  385. try {
  386. adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackNetAdapter(jack_client, buffer_size, sample_rate, params), params, false);
  387. assert(adapter);
  388. if (adapter->Open() == 0) {
  389. return 0;
  390. } else {
  391. delete adapter;
  392. return 1;
  393. }
  394. } catch (...) {
  395. return 1;
  396. }
  397. }
  398. SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init)
  399. {
  400. JSList* params = NULL;
  401. bool parse_params = true;
  402. int res = 1;
  403. jack_driver_desc_t* desc = jack_get_descriptor();
  404. Jack::JackArgParser parser(load_init);
  405. if (parser.GetArgc() > 0)
  406. parse_params = parser.ParseParams(desc, &params);
  407. if (parse_params) {
  408. res = jack_internal_initialize(jack_client, params);
  409. parser.FreeParams(params);
  410. }
  411. return res;
  412. }
  413. SERVER_EXPORT void jack_finish(void* arg)
  414. {
  415. Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*>(arg);
  416. if (adapter) {
  417. jack_log("Unloading netadapter");
  418. adapter->Close();
  419. delete adapter;
  420. }
  421. }
  422. #ifdef __cplusplus
  423. }
  424. #endif