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.

310 lines
9.7KB

  1. /*
  2. Copyright (C) 2008-2011 Torben Horn
  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. /*
  25. * "enp4s0"
  26. */
  27. namespace Jack
  28. {
  29. JackAVBPDriver::JackAVBPDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
  30. char* stream_id, char* destination_mac, char* eth_dev,
  31. int sample_rate, int period_size, int num_periods)
  32. : JackWaiterDriver(name, alias, engine, table)
  33. {
  34. jack_log("JackAVBPDriver::JackAVBPDriver Ethernet Device %s", eth_dev);
  35. jack_log("Stream ID: %02x %02x %02x %02x %02x %02x %02x %02x",
  36. (uint8_t) stream_id[0],
  37. (uint8_t) stream_id[1],
  38. (uint8_t) stream_id[2],
  39. (uint8_t) stream_id[3],
  40. (uint8_t) stream_id[4],
  41. (uint8_t) stream_id[5],
  42. (uint8_t) stream_id[6],
  43. (uint8_t) stream_id[7]);
  44. jack_log("Destination MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
  45. (uint8_t) destination_mac[0],
  46. (uint8_t) destination_mac[1],
  47. (uint8_t) destination_mac[2],
  48. (uint8_t) destination_mac[3],
  49. (uint8_t) destination_mac[4],
  50. (uint8_t) destination_mac[5]);
  51. init_1722_driver(&this->ieee1722mc,
  52. eth_dev,
  53. stream_id,
  54. destination_mac,
  55. sample_rate,
  56. period_size,
  57. num_periods
  58. );
  59. }
  60. JackAVBPDriver::~JackAVBPDriver()
  61. {
  62. // No destructor yet.
  63. }
  64. //open, close, attach and detach------------------------------------------------------
  65. int JackAVBPDriver::Close()
  66. {
  67. // Generic audio driver close
  68. int res = JackWaiterDriver::Close();
  69. FreePorts();
  70. shutdown_1722_driver(&ieee1722mc);
  71. return res;
  72. }
  73. int JackAVBPDriver::AllocPorts()
  74. {
  75. jack_port_id_t port_index;
  76. char buf[64];
  77. snprintf (buf, sizeof(buf) - 1, "system:capture_1");
  78. if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
  79. CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
  80. jack_error("driver: cannot register port for %s", buf);
  81. return -1;
  82. }
  83. //port = fGraphManager->GetPort(port_index);
  84. ieee1722mc.capture_ports = jack_slist_append (ieee1722mc.capture_ports, (void *)(intptr_t)port_index);
  85. return 0;
  86. }
  87. //init and restart--------------------------------------------------------------------
  88. bool JackAVBPDriver::Initialize()
  89. {
  90. jack_log("JackAVBDriver::Init");
  91. FreePorts();
  92. //display some additional infos
  93. jack_info("AVB IEEE1722 AVTP driver started");
  94. if (startup_1722_driver(&ieee1722mc)) {
  95. return false;
  96. }
  97. //register jack ports
  98. if (AllocPorts() != 0) {
  99. jack_error("Can't allocate ports.");
  100. return false;
  101. }
  102. //monitor
  103. //driver parametering
  104. JackTimedDriver::SetBufferSize(ieee1722mc.period_size);
  105. JackTimedDriver::SetSampleRate(ieee1722mc.sample_rate);
  106. JackDriver::NotifyBufferSize(ieee1722mc.period_size);
  107. JackDriver::NotifySampleRate(ieee1722mc.sample_rate);
  108. return true;
  109. }
  110. //jack ports and buffers--------------------------------------------------------------
  111. //driver processes--------------------------------------------------------------------
  112. int JackAVBPDriver::Read()
  113. {
  114. JSList *node = ieee1722mc.capture_ports;
  115. int delay;
  116. delay = wait_recv_1722_mediaclockstream( &ieee1722mc );
  117. if (-1 != delay) {
  118. NotifyXRun(fBeginDateUst, (float) delay);
  119. jack_error("netxruns... duration: %dms", delay / 1000);
  120. }
  121. JackDriver::CycleTakeBeginTime();
  122. if (-1 == delay)
  123. return -1;
  124. while (node != NULL) {
  125. jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
  126. JackPort *port = fGraphManager->GetPort(port_index);
  127. jack_default_audio_sample_t* buf = (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
  128. memcpy(buf, 0, ieee1722mc.period_size * sizeof(jack_default_audio_sample_t));
  129. node = jack_slist_next (node);
  130. }
  131. return 0;
  132. }
  133. int JackAVBPDriver::Write()
  134. {
  135. return 0;
  136. }
  137. void
  138. JackAVBPDriver::FreePorts ()
  139. {
  140. JSList *node = ieee1722mc.capture_ports;
  141. while (node != NULL) {
  142. JSList *this_node = node;
  143. jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
  144. node = jack_slist_remove_link(node, this_node);
  145. jack_slist_free_1(this_node);
  146. fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
  147. }
  148. ieee1722mc.capture_ports = NULL;
  149. }
  150. //driver loader-----------------------------------------------------------------------
  151. #ifdef __cplusplus
  152. extern "C"
  153. {
  154. #endif
  155. SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
  156. {
  157. jack_driver_desc_t * desc;
  158. jack_driver_desc_filler_t filler;
  159. jack_driver_param_value_t value;
  160. desc = jack_driver_descriptor_construct("avb", JackDriverMaster, "IEEE 1722 AVTP slave backend component", &filler);
  161. value.ui = 1U;
  162. jack_driver_descriptor_add_parameter(desc, &filler, "audio-ins", 'i', JackDriverParamUInt, &value, NULL, "Number of capture channels (defaults to 2)", NULL);
  163. value.ui = 48000U;
  164. jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
  165. value.ui = 64U;
  166. jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
  167. value.ui = 1U;
  168. jack_driver_descriptor_add_parameter(desc, &filler, "num-periods", 'n', JackDriverParamUInt, &value, NULL, "Network latency setting in no. of periods", NULL);
  169. sprintf( value.str, "enp4s0");
  170. jack_driver_descriptor_add_parameter(desc, &filler, "ethernet-dev", 'd', JackDriverParamString, &value, NULL, "AVB Ethernet Device", NULL);
  171. sprintf( value.str, "00:22:97:00:41:2c:00:00");
  172. jack_driver_descriptor_add_parameter(desc, &filler, "stream-id", 's', JackDriverParamString, &value, NULL, "Stream ID for listening", NULL);
  173. sprintf( value.str, "91:e0:f0:11:11:11");
  174. jack_driver_descriptor_add_parameter(desc, &filler, "destination-mac", 'm', JackDriverParamUInt, &value, NULL, "Multicast Destination MAC Address for listening", NULL);
  175. return desc;
  176. }
  177. SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
  178. {
  179. jack_nframes_t sample_rate = 48000;
  180. jack_nframes_t period_size = 64;
  181. unsigned int capture_ports = 1;
  182. int num_periods = 2;
  183. char sid[23];
  184. char dmac[17];
  185. char eth_dev[32];
  186. int dont_htonl_floats = 0;
  187. int always_deadline = 0;
  188. int jitter_val = 0;
  189. const JSList * node;
  190. const jack_driver_param_t * param;
  191. for (node = params; node; node = jack_slist_next(node)) {
  192. param = (const jack_driver_param_t*) node->data;
  193. switch (param->character) {
  194. case 'i':
  195. capture_ports = param->value.ui;
  196. break;
  197. case 'r':
  198. sample_rate = param->value.ui;
  199. break;
  200. case 'p':
  201. period_size = param->value.ui;
  202. break;
  203. case 'n':
  204. num_periods = param->value.ui;
  205. break;
  206. case 'd':
  207. sprintf(eth_dev, "%s", param->value.str);
  208. break;
  209. case 's':
  210. sprintf(sid, "%s", param->value.str);
  211. break;
  212. case 'm':
  213. sprintf(dmac, "%s", param->value.str);
  214. break;
  215. }
  216. }
  217. try {
  218. Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver (
  219. new Jack::JackAVBPDriver("system", "net_pcm", engine, table, sid, dmac, eth_dev,
  220. sample_rate, period_size, num_periods));
  221. if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, 0,
  222. 0, "from_master", "to_master", 0, 0) == 0) {
  223. return driver;
  224. } else {
  225. delete driver;
  226. return NULL;
  227. }
  228. } catch (...) {
  229. return NULL;
  230. }
  231. }
  232. #ifdef __cplusplus
  233. }
  234. #endif
  235. }