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.

447 lines
13KB

  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. }
  215. name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
  216. }
  217. else
  218. {
  219. name->sin_addr.s_addr = htonl (INADDR_ANY) ;
  220. }
  221. }
  222. /**
  223. * This required entry point is called after the client is loaded by
  224. * jack_internal_client_load().
  225. *
  226. * @param client pointer to JACK client structure.
  227. * @param load_init character string passed to the load operation.
  228. *
  229. * @return 0 if successful; otherwise jack_finish() will be called and
  230. * the client terminated immediately.
  231. */
  232. int
  233. jack_initialize (jack_client_t *int_client, const char *load_init)
  234. {
  235. int argc = 2; // getopt() starts parsing at the third element of argv
  236. char *argv[32];
  237. char *load_init_copy, *current_arg, *jack_name, *peer_ip;
  238. extern char *optarg;
  239. extern int optind, optopt;
  240. int index, option, errflag = 0, peer_socket;
  241. /* Is that any good ? */
  242. client = int_client;
  243. /* We'll use a copy of load_init to determine how much
  244. should be allocated for each argument */
  245. load_init_copy = strdup (load_init); // Make a copy of our init string
  246. /* Fill in some defaults */
  247. jack_name = (char*) malloc (10);
  248. peer_ip = (char*) malloc (9);
  249. sprintf (jack_name, "net_source");
  250. sprintf (peer_ip, "localhost");
  251. peer_socket = 3000;
  252. /* Count the length of out first argument, and allocate accordingly */
  253. current_arg = strtok (load_init_copy, " ");
  254. argv[argc] = (char*) malloc (strlen (current_arg) * sizeof (char) + 1);
  255. /* Same for the rest of the list */
  256. while (sscanf (load_init, "%s%n", argv[argc], &index) == 1)
  257. {
  258. load_init += index; // Move on to the next arg
  259. argc++;
  260. if ((current_arg = strtok (NULL, " ")) != NULL)
  261. {
  262. argv[argc] = (char*) malloc (strlen (current_arg) * sizeof (char) + 1);
  263. }
  264. }
  265. /* let's make sure we can run multiple in process clients
  266. and still have our parametters parsed by getopt */
  267. optind = 2;
  268. /* We may now run our getopt loop just as if all of it came from a real command line */
  269. while ((option = getopt(argc, argv, ":n:p:s:P:C:l:r:f:b:")) != -1)
  270. {
  271. switch (option)
  272. {
  273. case 'n':
  274. free(jack_name);
  275. jack_name = optarg;
  276. break;
  277. case 'p':
  278. free(peer_ip);
  279. peer_ip = optarg;
  280. break;
  281. case 's':
  282. peer_socket = atoi(optarg);
  283. break;
  284. case 'P':
  285. playback_channels = atoi(optarg);
  286. break;
  287. case 'C':
  288. capture_channels = atoi(optarg);
  289. break;
  290. case 'l':
  291. latency = atoi(optarg);
  292. break;
  293. case 'r':
  294. reply_port = atoi(optarg);
  295. break;
  296. case 'f':
  297. factor = atoi(optarg);
  298. break;
  299. case 'b':
  300. bitdepth = atoi(optarg);
  301. break;
  302. case ':': // -n or -p without operand
  303. jack_error ("Option -%c requires an operand, ignoring\n", optopt);
  304. errflag++;
  305. break;
  306. case '?':
  307. jack_error ("Unrecognized option: -%c, ignoring.\n"
  308. "TODO : send the format to jack_load application...\n"
  309. "Go bug the devs about it", optopt);
  310. errflag++;
  311. }
  312. }
  313. jack_info ("Here's our netclient setup:\n"
  314. "jack name: `%s'\n"
  315. "peer ip/hostname: `%s'\n"
  316. "peer_socket: `%i'\n"
  317. "playback channels: `%i'\n"
  318. "capture channels: `%i'\n"
  319. "latency: `%i'\n"
  320. "reply port: `%i'\n"
  321. "factor: `%i'\n"
  322. "bitdepth: `%i'\n",
  323. jack_name,
  324. peer_ip,
  325. peer_socket,
  326. playback_channels,
  327. capture_channels,
  328. latency,
  329. reply_port,
  330. factor,
  331. bitdepth);
  332. /* Yet another line to understand...
  333. src_state = src_new(SRC_LINEAR, 1, NULL); */
  334. outsockfd = socket (PF_INET, SOCK_DGRAM, 0);
  335. insockfd = socket (PF_INET, SOCK_DGRAM, 0);
  336. init_sockaddr_in ((struct sockaddr_in *) &destaddr, peer_ip, peer_socket);
  337. if (reply_port) {
  338. init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port);
  339. bind(insockfd, &bindaddr, sizeof (bindaddr));
  340. }
  341. /* Send a ping to the peer to measure round trip time ?
  342. What if there are some ACLs on the remote host ?
  343. sendto(outsockfd, "x", 1, 0, &destaddr, sizeof(destaddr)); */
  344. /* Tell the JACK server to call `process()' whenever there is work to be done */
  345. jack_set_process_callback (client, process, 0);
  346. jack_set_sync_callback (client, sync_cb, 0);
  347. /* Tell the JACK server to call `jack_shutdown()' if
  348. it ever shuts down, either entirely, or if it
  349. just decides to stop calling us*/
  350. jack_on_shutdown (client, jack_shutdown, 0);
  351. /* Display the current sample rate
  352. TODO : Shall we remove that ? Who cares really... we're 'in process' ! */
  353. jack_info ("engine sample rate: %d", jack_get_sample_rate (client));
  354. alloc_ports (capture_channels, playback_channels);
  355. /* TODO : figure out what this does */
  356. jack_nframes_t net_period = (float) jack_get_buffer_size (client) / (float) factor;
  357. int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
  358. global_packcache = packet_cache_new (latency + 5, rx_bufsize, 1400);
  359. /* Cleanup the mess */
  360. for (index = 2; index < argc; index++)
  361. {
  362. free (argv[index]);
  363. }
  364. /* tell the JACK server that we are ready to roll,
  365. exit gracefully if we got something wrong before that */
  366. if (errflag > 0)
  367. {
  368. jack_error ("It seems something went badly wrong");
  369. return -1;
  370. }
  371. if (jack_activate (client))
  372. {
  373. jack_error ("Cannot activate client");
  374. return -1;
  375. }
  376. return 0;
  377. }
  378. /**
  379. * This required entry point is called immediately before the client
  380. * is unloaded, which could happen due to a call to
  381. * jack_internal_client_unload(), or a nonzero return from either
  382. * jack_initialize() or inprocess().
  383. *
  384. * @param arg the same parameter provided to inprocess().
  385. */
  386. void
  387. jack_finish (void *arg)
  388. {
  389. jack_info ("netsource client exits");
  390. packet_cache_free (global_packcache);
  391. }