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.

388 lines
15KB

  1. /*
  2. Copyright (C) 2016-2019 Christoph Kuhr
  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 "JackAVBDriver.h"
  16. #include "JackEngineControl.h"
  17. #include "JackLockedEngine.h"
  18. #include "JackGraphManager.h"
  19. #include "JackWaitThreadedDriver.h"
  20. #include "JackTools.h"
  21. #include "driver_interface.h"
  22. #define MIN(x,y) ((x)<(y) ? (x) : (y))
  23. using namespace std;
  24. namespace Jack
  25. {
  26. JackAVBDriver::JackAVBDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
  27. char* stream_id, char* destination_mac, char* eth_dev,
  28. int sample_rate, int period_size, int adjust,
  29. int num_periods, int capture_ports, int playback_ports)
  30. : JackWaiterDriver(name, alias, engine, table)
  31. {
  32. jack_log("JackAVBDriver::JackAVBPDriver Ethernet Device %s", eth_dev);
  33. jack_log("Stream ID: %02x %02x %02x %02x %02x %02x %02x %02x",
  34. (uint8_t) stream_id[0],
  35. (uint8_t) stream_id[1],
  36. (uint8_t) stream_id[2],
  37. (uint8_t) stream_id[3],
  38. (uint8_t) stream_id[4],
  39. (uint8_t) stream_id[5],
  40. (uint8_t) stream_id[6],
  41. (uint8_t) stream_id[7]);
  42. jack_log("Destination MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
  43. (uint8_t) destination_mac[0],
  44. (uint8_t) destination_mac[1],
  45. (uint8_t) destination_mac[2],
  46. (uint8_t) destination_mac[3],
  47. (uint8_t) destination_mac[4],
  48. (uint8_t) destination_mac[5]);
  49. printf("JackAVBDriver::JackAVBPDriver Ethernet Device %s\n", eth_dev);
  50. printf("Stream ID: %02x %02x %02x %02x %02x %02x %02x %02x\n",
  51. (uint8_t) stream_id[0],
  52. (uint8_t) stream_id[1],
  53. (uint8_t) stream_id[2],
  54. (uint8_t) stream_id[3],
  55. (uint8_t) stream_id[4],
  56. (uint8_t) stream_id[5],
  57. (uint8_t) stream_id[6],
  58. (uint8_t) stream_id[7]);
  59. printf("Destination MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
  60. (uint8_t) destination_mac[0],
  61. (uint8_t) destination_mac[1],
  62. (uint8_t) destination_mac[2],
  63. (uint8_t) destination_mac[3],
  64. (uint8_t) destination_mac[4],
  65. (uint8_t) destination_mac[5]);
  66. num_packets_even_odd = 0; // even = 0, odd = 1
  67. lastPeriodDuration = 0;
  68. timeCompensation = 0;
  69. monotonicTime = 0;
  70. preRunCnt = 3;
  71. init_avb_driver( &(this->avb_ctx),
  72. eth_dev,
  73. stream_id,
  74. destination_mac,
  75. sample_rate,
  76. period_size,
  77. num_periods,
  78. adjust,
  79. capture_ports,
  80. playback_ports
  81. );
  82. }
  83. JackAVBDriver::~JackAVBDriver()
  84. {
  85. // No destructor yet.
  86. }
  87. int JackAVBDriver::Close()
  88. {
  89. // Generic audio driver close
  90. int res = JackWaiterDriver::Close();
  91. FreePorts();
  92. shutdown_avb_driver(&avb_ctx);
  93. return res;
  94. }
  95. int JackAVBDriver::AllocPorts()
  96. {
  97. jack_port_id_t port_index;
  98. char buf[64];
  99. int chn = 0;
  100. for (chn = 0; chn < (int)avb_ctx.capture_channels; chn++) {
  101. memset(buf, 0, sizeof(buf));
  102. snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
  103. if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
  104. CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
  105. jack_error("driver: cannot register port for %s", buf);
  106. return -1;
  107. }
  108. avb_ctx.capture_ports = jack_slist_append (avb_ctx.capture_ports, (void *)(intptr_t)port_index);
  109. }
  110. for (chn = 0; chn < (int)avb_ctx.playback_channels; chn++) {
  111. memset(buf, 0, sizeof(buf));
  112. snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
  113. if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
  114. PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
  115. jack_error("driver: cannot register port for %s", buf);
  116. return -1;
  117. }
  118. avb_ctx.playback_ports = jack_slist_append (avb_ctx.playback_ports, (void *)(intptr_t)port_index);
  119. }
  120. //port = fGraphManager->GetPort(port_index);
  121. return 0;
  122. }
  123. bool JackAVBDriver::Initialize()
  124. {
  125. jack_log("JackAVBDriver::Init");
  126. FreePorts();
  127. //display some additional infos
  128. printf("AVB driver started\n");
  129. if (startup_avb_driver(&avb_ctx)) {
  130. return false;
  131. }
  132. //register jack ports
  133. if (AllocPorts() != 0) {
  134. jack_error("Can't allocate ports.");
  135. return false;
  136. }
  137. //driver parametering
  138. JackTimedDriver::SetBufferSize(avb_ctx.period_size);
  139. JackTimedDriver::SetSampleRate(avb_ctx.sample_rate);
  140. JackDriver::NotifyBufferSize(avb_ctx.period_size);
  141. JackDriver::NotifySampleRate(avb_ctx.sample_rate);
  142. return true;
  143. }
  144. int JackAVBDriver::Read()
  145. {
  146. int ret = 0;
  147. JSList *node = avb_ctx.capture_ports;
  148. uint64_t cumulative_rx_int_ns = 0;
  149. uint64_t lateness = 0;
  150. int n = 0;
  151. for(n=0; n<avb_ctx.num_packets; n++){
  152. cumulative_rx_int_ns += await_avtp_rx_ts( &avb_ctx, n, &lateness );
  153. /*
  154. if( n == 0 && --this->preRunCnt >= 0 ){
  155. cumulative_rx_int_ns -= this->timeCompensation;
  156. }*/
  157. //jack_errors("duration: %lld", cumulative_rx_int_ns);
  158. }
  159. this->monotonicTime += cumulative_rx_int_ns;
  160. /*
  161. if( this->lastPeriodDuration != 0 ){
  162. this->timeCompensation = cumulative_rx_int_ns - this->lastPeriodDuration;
  163. }
  164. this->lastPeriodDuration = cumulative_rx_int_ns;
  165. */
  166. float cumulative_rx_int_us = (cumulative_rx_int_ns / 1000) - 0.5;
  167. if ( cumulative_rx_int_us > avb_ctx.period_usecs ) {
  168. ret = 1;
  169. NotifyXRun(fBeginDateUst, cumulative_rx_int_us);
  170. jack_error("avtp_xruns... duration: %.2f ms", lateness / 1000000);
  171. }
  172. JackDriver::CycleTakeBeginTime();
  173. if ( ret ) return -1;
  174. while (node != NULL) {
  175. jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
  176. JackPort *port = fGraphManager->GetPort(port_index);
  177. jack_default_audio_sample_t* buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
  178. //memcpy(buf, 0, avb_ctx.period_size * sizeof(jack_default_audio_sample_t));
  179. node = jack_slist_next (node);
  180. }
  181. return 0;
  182. }
  183. int JackAVBDriver::Write()
  184. {
  185. JSList *node = avb_ctx.playback_ports;
  186. while (node != NULL) {
  187. jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
  188. JackPort *port = fGraphManager->GetPort(port_index);
  189. jack_default_audio_sample_t* buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
  190. //memcpy(buf, 0, avb_ctx.period_size * sizeof(jack_default_audio_sample_t));
  191. node = jack_slist_next (node);
  192. }
  193. return 0;
  194. }
  195. void JackAVBDriver::FreePorts ()
  196. {
  197. JSList *node = avb_ctx.capture_ports;
  198. while (node != NULL) {
  199. JSList *this_node = node;
  200. jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
  201. node = jack_slist_remove_link(node, this_node);
  202. jack_slist_free_1(this_node);
  203. fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
  204. }
  205. avb_ctx.capture_ports = NULL;
  206. node = avb_ctx.playback_ports;
  207. while (node != NULL) {
  208. JSList *this_node = node;
  209. jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
  210. node = jack_slist_remove_link(node, this_node);
  211. jack_slist_free_1(this_node);
  212. fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
  213. }
  214. avb_ctx.playback_ports = NULL;
  215. }
  216. #ifdef __cplusplus
  217. extern "C"
  218. {
  219. #endif
  220. inline int argumentsSplitDelimiters(char* inputString, char* outputArray, int array_len)
  221. {
  222. int tokenCnt=0;
  223. char *token;
  224. char *der_string = strdup(inputString);
  225. int m = 0;
  226. for( m=0;m<array_len;m++){
  227. if(( token = strsep(&der_string, ":")) != NULL ){
  228. outputArray[m] = (char)strtol(strdup(token), NULL, 16); // number base 16
  229. } else {
  230. tokenCnt = m;
  231. break;
  232. }
  233. }
  234. free(der_string);
  235. return tokenCnt;
  236. }
  237. SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
  238. {
  239. jack_driver_desc_t * desc;
  240. jack_driver_desc_filler_t filler;
  241. jack_driver_param_value_t value;
  242. desc = jack_driver_descriptor_construct("avb", JackDriverMaster, "IEEE 1722 AVTP slave backend component", &filler);
  243. value.ui = 2U;
  244. jack_driver_descriptor_add_parameter(desc, &filler, "audio-ins", 'i', JackDriverParamUInt, &value, NULL, "Number of capture channels (defaults to 1)", NULL);
  245. jack_driver_descriptor_add_parameter(desc, &filler, "audio-outs", 'o', JackDriverParamUInt, &value, NULL, "Number of playback channels (defaults to 1)", NULL);
  246. value.ui = 48000U;
  247. jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
  248. value.ui = 64U;
  249. jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
  250. value.ui = 1U;
  251. jack_driver_descriptor_add_parameter(desc, &filler, "num-periods", 'n', JackDriverParamUInt, &value, NULL, "Network latency setting in no. of periods", NULL);
  252. value.ui = 0U;
  253. jack_driver_descriptor_add_parameter(desc, &filler, "adjust", 'a', JackDriverParamUInt, &value, NULL, "Adjust Timestamps", NULL);
  254. sprintf( value.str, "enp4s0");
  255. jack_driver_descriptor_add_parameter(desc, &filler, "eth-dev", 'e', JackDriverParamString, &value, NULL, "AVB Ethernet Device", NULL);
  256. sprintf( value.str, "00:22:97:00:41:2c:00:00");
  257. jack_driver_descriptor_add_parameter(desc, &filler, "stream-id", 's', JackDriverParamString, &value, NULL, "Stream ID for listening", NULL);
  258. sprintf( value.str, "91:e0:f0:11:11:11");
  259. jack_driver_descriptor_add_parameter(desc, &filler, "dst-mac", 'm', JackDriverParamString, &value, NULL, "Multicast Destination MAC Address for listening", NULL);
  260. return desc;
  261. }
  262. SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
  263. {
  264. unsigned int sample_rate = 48000;
  265. jack_nframes_t period_size = 64;
  266. unsigned int capture_ports = 2;
  267. unsigned int playback_ports = 2;
  268. int num_periods = 2;
  269. int adjust = 0;
  270. char sid[8];
  271. char dmac[6];
  272. char eth_dev[32];
  273. const JSList * node;
  274. const jack_driver_param_t * param;
  275. printf("foo bar\n");fflush(stdout);
  276. for (node = params; node; node = jack_slist_next(node)) {
  277. param = (const jack_driver_param_t*) node->data;
  278. switch (param->character) {
  279. case 'i':
  280. capture_ports = param->value.ui;
  281. break;
  282. case 'o':
  283. playback_ports = param->value.ui;
  284. break;
  285. case 'r':
  286. sample_rate = param->value.ui;
  287. break;
  288. case 'p':
  289. period_size = param->value.ui;
  290. break;
  291. case 'n':
  292. num_periods = param->value.ui;
  293. break;
  294. case 'a':
  295. adjust = param->value.ui;
  296. break;
  297. case 'e':
  298. sprintf(eth_dev, "%s", param->value.str);
  299. printf("Eth Dev: %s %s\n", param->value.str, eth_dev);fflush(stdout);
  300. break;
  301. case 's':
  302. // split stream ID
  303. argumentsSplitDelimiters((char *)param->value.str, sid, 8);
  304. printf("Stream ID: %s %02x %02x %02x %02x %02x %02x %02x %02x \n", param->value.str,
  305. sid[0], sid[1], sid[2], sid[3], sid[4], sid[5], sid[6], sid[7]);fflush(stdout);
  306. break;
  307. case 'm':
  308. // split destination mac address
  309. argumentsSplitDelimiters((char *)param->value.str, dmac, 6);
  310. printf("Destination MAC Address: %s %02x %02x %02x %02x %02x %02x \n", param->value.str,
  311. dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]);fflush(stdout);
  312. break;
  313. }
  314. }
  315. try {
  316. Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver (
  317. new Jack::JackAVBDriver("system", "avb_mc", engine, table, sid, dmac, eth_dev,
  318. sample_rate, period_size, num_periods,
  319. adjust, capture_ports, playback_ports));
  320. if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports,
  321. 0, "from_master", "to_master", 0, 0) == 0) {
  322. return driver;
  323. } else {
  324. delete driver;
  325. return NULL;
  326. }
  327. } catch (...) {
  328. return NULL;
  329. }
  330. }
  331. #ifdef __cplusplus
  332. }
  333. #endif
  334. }