jack1 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.

431 lines
12KB

  1. /** @file net_source.c
  2. *
  3. * @brief This is an in process version of the netjack client
  4. */
  5. #include <stdio.h>
  6. #include <errno.h>
  7. #include <unistd.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <netinet/in.h>
  11. #include <netdb.h>
  12. #include <alloca.h>
  13. #include <jack/jack.h>
  14. #include "net_driver.h"
  15. #include "netjack_packet.h"
  16. #include <samplerate.h>
  17. JSList *capture_ports = NULL;
  18. JSList *capture_srcs = NULL;
  19. int capture_channels = 2;
  20. JSList *playback_ports = NULL;
  21. JSList *playback_srcs = NULL;
  22. int playback_channels = 2;
  23. int latency = 1;
  24. jack_nframes_t factor = 1;
  25. int bitdepth = 0;
  26. int reply_port = 0;
  27. jack_client_t *client;
  28. int outsockfd;
  29. int insockfd;
  30. struct sockaddr destaddr;
  31. struct sockaddr bindaddr;
  32. int recv_channels;
  33. int recv_smaple_format;
  34. int sync_state;
  35. jack_transport_state_t last_transport_state;
  36. int framecnt = 0;
  37. int cont_miss = 0;
  38. SRC_STATE *src_state;
  39. /**
  40. * This Function allocates all the I/O Ports which are added the lists.
  41. * XXX: jack-midi is underway... so dont forget it.
  42. */
  43. void
  44. alloc_ports (int n_capture, int n_playback)
  45. {
  46. int port_flags = JackPortIsOutput;
  47. int chn;
  48. jack_port_t *port;
  49. char buf[32];
  50. capture_ports = NULL;
  51. for (chn = 0; chn < n_capture; chn++)
  52. {
  53. snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1);
  54. port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
  55. if (!port)
  56. {
  57. jack_error ("jacknet_client: cannot register port for %s", buf);
  58. break;
  59. }
  60. capture_srcs = jack_slist_append(capture_srcs, src_new(SRC_LINEAR, 1, NULL));
  61. capture_ports = jack_slist_append(capture_ports, port);
  62. }
  63. port_flags = JackPortIsInput;
  64. playback_ports = NULL;
  65. for (chn = 0; chn < n_playback; chn++)
  66. {
  67. snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1);
  68. port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
  69. if (!port)
  70. {
  71. jack_error ("jacknet_client: cannot register port for %s", buf);
  72. break;
  73. }
  74. playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL));
  75. playback_ports = jack_slist_append (playback_ports, port);
  76. }
  77. }
  78. /**
  79. * The Sync callback... sync state is set elsewhere...
  80. * we will see if this is working correctly.
  81. * i dont really believe in it yet.
  82. */
  83. int
  84. sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg)
  85. {
  86. static int latency_count = 0;
  87. int retval = sync_state;
  88. if (latency_count)
  89. {
  90. latency_count--;
  91. retval = 0;
  92. }
  93. else if (state == JackTransportStarting && last_transport_state != JackTransportStarting)
  94. {
  95. retval = 0;
  96. latency_count = latency - 1;
  97. }
  98. last_transport_state = state;
  99. return retval;
  100. }
  101. /**
  102. * The process callback for this JACK application.
  103. * It is called by JACK at the appropriate times.
  104. */
  105. int
  106. process (jack_nframes_t nframes, void *arg)
  107. {
  108. //static int old_count = 0;
  109. //SRC_DATA src;
  110. jack_nframes_t net_period = (float) nframes / (float) factor;
  111. //jack_position_t jack_pos;
  112. int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
  113. int tx_bufsize = get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header);
  114. jack_default_audio_sample_t *buf;
  115. jack_port_t *port;
  116. JSList *node;
  117. channel_t chn;
  118. int size;
  119. jack_position_t local_trans_pos;
  120. uint32_t *packet_buf, *packet_bufX;
  121. /* Allocate a buffer where both In and Out Buffer will fit */
  122. packet_buf = alloca ((rx_bufsize > tx_bufsize) ? rx_bufsize : tx_bufsize);
  123. jacknet_packet_header *pkthdr = (jacknet_packet_header*) packet_buf;
  124. packet_bufX = packet_buf + sizeof (jacknet_packet_header) / sizeof (uint32_t);
  125. /* ---- receive ---- */
  126. ReadAgain:
  127. if (reply_port)
  128. size = netjack_recv(insockfd, (char *)packet_buf, rx_bufsize, MSG_DONTWAIT, 1400);
  129. else
  130. size = netjack_recv(outsockfd, (char *)packet_buf, rx_bufsize, MSG_DONTWAIT, 1400);
  131. packet_header_ntoh(pkthdr);
  132. // evaluate rcvd data.
  133. // XXX: think about this a little more...
  134. //if((size == rx_bufsize) && (framecnt - pkthdr->framecnt) >= latency) {
  135. if ((size == rx_bufsize))
  136. {
  137. cont_miss = 0;
  138. if ((framecnt - pkthdr->framecnt) > latency)
  139. {
  140. jack_info("FRAMCNT_DIFF = %d ----- A Packet was lost, or did came too late (try -l %d) ", pkthdr->framecnt - framecnt, framecnt - pkthdr->framecnt);
  141. goto ReadAgain;
  142. }
  143. // packet has expected size
  144. render_payload_to_jack_ports(bitdepth, packet_bufX, net_period, capture_ports, capture_srcs, nframes);
  145. // Now evaluate packet header;
  146. if (sync_state != pkthdr->sync_state)
  147. {
  148. jack_info("sync = %d", pkthdr->sync_state);
  149. }
  150. sync_state = pkthdr->sync_state;
  151. }
  152. else
  153. {
  154. // jack_info("Packet Miss: (expected: %d, got: %d) framecnt=%d", rx_bufsize, size, framecnt);
  155. cont_miss += 1;
  156. chn = 0;
  157. node = capture_ports;
  158. while (node != NULL)
  159. {
  160. int i;
  161. port = (jack_port_t *) node->data;
  162. buf = jack_port_get_buffer (port, nframes);
  163. for (i = 0; i < nframes; i++)
  164. {
  165. buf[i] = 0.0;
  166. }
  167. node = jack_slist_next (node);
  168. chn++;
  169. }
  170. }
  171. /* reset packet_bufX... and then send... */
  172. packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
  173. /* ---- send ---- */
  174. render_jack_ports_to_payload(bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period);
  175. /* fill in packet hdr */
  176. pkthdr->transport_state = jack_transport_query(client, &local_trans_pos);
  177. pkthdr->transport_frame = local_trans_pos.frame;
  178. pkthdr->framecnt = framecnt;
  179. pkthdr->latency = latency;
  180. pkthdr->reply_port = reply_port;
  181. pkthdr->sample_rate = jack_get_sample_rate(client);
  182. pkthdr->period_size = nframes;
  183. packet_header_hton(pkthdr);
  184. if (cont_miss < 10) {
  185. netjack_sendto(outsockfd, (char *)packet_buf, tx_bufsize, 0, &destaddr, sizeof(destaddr), 1400);
  186. } else {
  187. if (cont_miss > 50)
  188. cont_miss = 5;
  189. }
  190. framecnt++;
  191. return 0;
  192. }
  193. /**
  194. * This is the shutdown callback for this JACK application.
  195. * It is called by JACK if the server ever shuts down or
  196. * decides to disconnect the client.
  197. */
  198. void
  199. jack_shutdown (void *arg)
  200. {
  201. jack_error ("jack_shutdown was called");
  202. }
  203. void
  204. init_sockaddr_in (struct sockaddr_in *name, const char *hostname, uint16_t port)
  205. {
  206. name->sin_family = AF_INET ;
  207. name->sin_port = htons (port) ;
  208. if (hostname)
  209. {
  210. struct hostent *hostinfo = gethostbyname (hostname);
  211. if (hostinfo == NULL)
  212. {
  213. jack_error ("init_sockaddr_in: unknown host: %s", hostname);
  214. } else {
  215. name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
  216. }
  217. }
  218. else
  219. {
  220. name->sin_addr.s_addr = htonl (INADDR_ANY) ;
  221. }
  222. }
  223. /**
  224. * This required entry point is called after the client is loaded by
  225. * jack_internal_client_load().
  226. *
  227. * @param client pointer to JACK client structure.
  228. * @param load_init character string passed to the load operation.
  229. *
  230. * @return 0 if successful; otherwise jack_finish() will be called and
  231. * the client terminated immediately.
  232. */
  233. int
  234. jack_initialize (jack_client_t *int_client, const char *load_init)
  235. {
  236. int argc = 2; // getopt() starts parsing at the third element of argv
  237. char **argv;
  238. char *load_init_dup, *peer_ip = "localhost";
  239. extern char *optarg;
  240. extern int optind, optopt;
  241. int index, option, errflag = 0, peer_socket;
  242. client = int_client;
  243. /* Fill in some defaults */
  244. peer_socket = 3000;
  245. /* We'll use a copy of load_init since we'll be using strtok
  246. which modifies the string to split */
  247. load_init_dup = strdup (load_init);
  248. /* Count how many elements we have */
  249. strtok (load_init_dup, " ");
  250. argc++;
  251. while (strtok (NULL, " ") != NULL)
  252. {
  253. argc++;
  254. }
  255. /* Allocate as needed */
  256. argv = (char**) malloc (argc * sizeof(char*));
  257. /* Get the arguments */
  258. for (index = 2; index < argc; index++)
  259. {
  260. argv[index] = load_init_dup;
  261. load_init_dup += strlen (argv[index]) + 1;
  262. }
  263. /* let's make sure we can run multiple in process clients
  264. and still have our parametters parsed by getopt */
  265. optind = 2;
  266. /* We may now run our getopt loop just as if all of it came from a real command line */
  267. while ((option = getopt (argc, argv, ":p:s:P:C:l:r:f:b:")) != -1)
  268. {
  269. switch (option)
  270. {
  271. case 'p':
  272. peer_ip = optarg;
  273. break;
  274. case 's':
  275. peer_socket = atoi(optarg);
  276. break;
  277. case 'P':
  278. playback_channels = atoi(optarg);
  279. break;
  280. case 'C':
  281. capture_channels = atoi(optarg);
  282. break;
  283. case 'l':
  284. latency = atoi(optarg);
  285. break;
  286. case 'r':
  287. reply_port = atoi(optarg);
  288. break;
  289. case 'f':
  290. factor = atoi(optarg);
  291. break;
  292. case 'b':
  293. bitdepth = atoi(optarg);
  294. break;
  295. case ':': // -n or -p without operand
  296. jack_error ("Option -%c requires an operand, ignoring\n", optopt);
  297. break;
  298. case '?':
  299. jack_error ("Unrecognized option: -%c, ignoring.\n", optopt);
  300. }
  301. }
  302. jack_info ("Here's our netclient setup:\n"
  303. "peer ip/hostname: `%s'\n"
  304. "peer_socket: `%i'\n"
  305. "playback channels: `%i'\n"
  306. "capture channels: `%i'\n"
  307. "latency: `%i'\n"
  308. "reply port: `%i'\n"
  309. "factor: `%i'\n"
  310. "bitdepth: `%i'\n",
  311. peer_ip,
  312. peer_socket,
  313. playback_channels,
  314. capture_channels,
  315. latency,
  316. reply_port,
  317. factor,
  318. bitdepth);
  319. /* Yet another line to understand...
  320. src_state = src_new(SRC_LINEAR, 1, NULL); */
  321. outsockfd = socket (PF_INET, SOCK_DGRAM, 0);
  322. insockfd = socket (PF_INET, SOCK_DGRAM, 0);
  323. init_sockaddr_in ((struct sockaddr_in *) &destaddr, peer_ip, peer_socket);
  324. if (reply_port) {
  325. init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port);
  326. bind(insockfd, &bindaddr, sizeof (bindaddr));
  327. }
  328. /* Send a ping to the peer to measure round trip time ?
  329. What if there are some ACLs on the remote host ?
  330. sendto(outsockfd, "x", 1, 0, &destaddr, sizeof(destaddr)); */
  331. /* Tell the JACK server to call `process()' whenever there is work to be done */
  332. jack_set_process_callback (client, process, 0);
  333. jack_set_sync_callback (client, sync_cb, 0);
  334. /* Tell the JACK server to call `jack_shutdown()' if
  335. it ever shuts down, either entirely, or if it
  336. just decides to stop calling us*/
  337. jack_on_shutdown (client, jack_shutdown, 0);
  338. /* Display the current sample rate
  339. TODO : Shall we remove that ? Who cares really... we're 'in process' ! */
  340. jack_info ("engine sample rate: %d", jack_get_sample_rate (client));
  341. alloc_ports (capture_channels, playback_channels);
  342. /* TODO : figure out what this does */
  343. jack_nframes_t net_period = (float) jack_get_buffer_size (client) / (float) factor;
  344. int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
  345. global_packcache = packet_cache_new (latency + 5, rx_bufsize, 1400);
  346. /* We're ready to clear previous allocations */
  347. free (argv[2]);
  348. free (argv);
  349. /* tell the JACK server that we are ready to roll,
  350. exit gracefully if we got something wrong before that */
  351. if (errflag > 0)
  352. {
  353. jack_error ("It seems something went badly wrong");
  354. return -1;
  355. }
  356. if (jack_activate (client))
  357. {
  358. jack_error ("Cannot activate client");
  359. return -1;
  360. }
  361. return 0;
  362. }
  363. /**
  364. * This required entry point is called immediately before the client
  365. * is unloaded, which could happen due to a call to
  366. * jack_internal_client_unload(), or a nonzero return from either
  367. * jack_initialize() or inprocess().
  368. *
  369. * @param arg the same parameter provided to inprocess().
  370. */
  371. void
  372. jack_finish (void *arg)
  373. {
  374. jack_info ("netsource client exits");
  375. packet_cache_free (global_packcache);
  376. }