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.

582 lines
16KB

  1. /** @file simple_client.c
  2. *
  3. * @brief This simple client demonstrates the basic features of JACK
  4. * as they would be used by many applications.
  5. */
  6. #include <stdio.h>
  7. #include <errno.h>
  8. #include <unistd.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <netinet/in.h>
  12. #include <netdb.h>
  13. #include <alloca.h>
  14. #include <jack/jack.h>
  15. #include "net_driver.h"
  16. #include "netjack_packet.h"
  17. #include <samplerate.h>
  18. JSList *capture_ports = NULL;
  19. JSList *capture_srcs = NULL;
  20. int capture_channels = 2;
  21. JSList *playback_ports = NULL;
  22. JSList *playback_srcs = NULL;
  23. int playback_channels = 2;
  24. int latency = 1;
  25. jack_nframes_t factor = 1;
  26. int bitdepth = 0;
  27. int reply_port = 0;
  28. jack_client_t *client;
  29. int outsockfd;
  30. int insockfd;
  31. struct sockaddr destaddr;
  32. struct sockaddr bindaddr;
  33. int recv_channels;
  34. int recv_smaple_format;
  35. int sync_state;
  36. jack_transport_state_t last_transport_state;
  37. int framecnt = 0;
  38. int cont_miss = 0;
  39. SRC_STATE *src_state;
  40. /*
  41. * This Function allocates all the I/O Ports which are added the lists.
  42. * XXX: jack-midi is underway... so dont forget it.
  43. */
  44. void 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. snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1);
  53. port = jack_port_register (client, buf,
  54. JACK_DEFAULT_AUDIO_TYPE,
  55. port_flags, 0);
  56. if (!port) {
  57. jack_info("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. snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1);
  67. port = jack_port_register (client, buf,
  68. JACK_DEFAULT_AUDIO_TYPE,
  69. port_flags, 0);
  70. if (!port) {
  71. jack_info("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 sync_cb(jack_transport_state_t state, jack_position_t *pos, void *arg)
  84. {
  85. static int latency_count = 0;
  86. int retval = sync_state;
  87. if (latency_count) {
  88. latency_count--;
  89. retval = 0;
  90. } else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) {
  91. retval = 0;
  92. latency_count = latency - 1;
  93. }
  94. last_transport_state = state;
  95. return retval;
  96. }
  97. /**
  98. * The process callback for this JACK application.
  99. * It is called by JACK at the appropriate times.
  100. */
  101. int
  102. process (jack_nframes_t nframes, void *arg)
  103. {
  104. //static int old_count = 0;
  105. //SRC_DATA src;
  106. jack_nframes_t net_period = (float) nframes / (float) factor;
  107. //jack_position_t jack_pos;
  108. int rx_bufsize = get_sample_size(bitdepth) * capture_channels * net_period + sizeof(jacknet_packet_header);
  109. int tx_bufsize = get_sample_size(bitdepth) * playback_channels * net_period + sizeof(jacknet_packet_header);
  110. jack_default_audio_sample_t *buf;
  111. jack_port_t *port;
  112. JSList *node;
  113. channel_t chn;
  114. int size;
  115. jack_position_t local_trans_pos;
  116. uint32_t *packet_buf, *packet_bufX;
  117. // Allocate a buffer where both In and Out Buffer will fit
  118. packet_buf = alloca((rx_bufsize > tx_bufsize) ? rx_bufsize : tx_bufsize);
  119. jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf;
  120. packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(uint32_t);
  121. //////////////// receive ////////////////
  122. //////////////// ////////////////
  123. ReadAgain:
  124. if (reply_port)
  125. size = netjack_recv(insockfd, (char *)packet_buf, rx_bufsize, MSG_DONTWAIT, 1400);
  126. else
  127. size = netjack_recv(outsockfd, (char *)packet_buf, rx_bufsize, MSG_DONTWAIT, 1400);
  128. packet_header_ntoh(pkthdr);
  129. // evaluate rcvd data.
  130. // XXX: think about this a little more...
  131. //if((size == rx_bufsize) && (framecnt - pkthdr->framecnt) >= latency) {
  132. if ((size == rx_bufsize)) {
  133. cont_miss = 0;
  134. if ((framecnt - pkthdr->framecnt) > latency) {
  135. jack_info("FRAMCNT_DIFF = %d ----- A Packet was lost, or did came too late (try -l %d) ", pkthdr->framecnt - framecnt, framecnt - pkthdr->framecnt);
  136. goto ReadAgain;
  137. }
  138. // packet has expected size
  139. render_payload_to_jack_ports(bitdepth, packet_bufX, net_period, capture_ports, capture_srcs, nframes);
  140. // Now evaluate packet header;
  141. if (sync_state != pkthdr->sync_state)
  142. jack_info("sync = %d", pkthdr->sync_state);
  143. sync_state = pkthdr->sync_state;
  144. } else {
  145. jack_info("Packet Miss: (expected: %d, got: %d) framecnt=%d", rx_bufsize, size, framecnt);
  146. cont_miss += 1;
  147. chn = 0;
  148. node = capture_ports;
  149. while (node != NULL) {
  150. int i;
  151. port = (jack_port_t *) node->data;
  152. buf = jack_port_get_buffer (port, nframes);
  153. for (i = 0; i < nframes; i++) {
  154. buf[i] = 0.0;
  155. }
  156. node = jack_slist_next (node);
  157. chn++;
  158. }
  159. }
  160. ////////////////
  161. ////////////////
  162. // reset packet_bufX... and then send...
  163. packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
  164. //////////////// send ////////////////
  165. //////////////// ////////////////
  166. render_jack_ports_to_payload(bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period);
  167. // fill in packet hdr
  168. pkthdr->transport_state = jack_transport_query(client, &local_trans_pos);
  169. pkthdr->transport_frame = local_trans_pos.frame;
  170. pkthdr->framecnt = framecnt;
  171. pkthdr->latency = latency;
  172. pkthdr->reply_port = reply_port;
  173. pkthdr->sample_rate = jack_get_sample_rate(client);
  174. pkthdr->period_size = nframes;
  175. packet_header_hton(pkthdr);
  176. if (cont_miss < 10) {
  177. netjack_sendto(outsockfd, (char *)packet_buf, tx_bufsize, 0, &destaddr, sizeof(destaddr), 1400);
  178. } else {
  179. if (cont_miss > 50)
  180. cont_miss = 5;
  181. }
  182. framecnt++;
  183. return 0;
  184. }
  185. /**
  186. * This is the shutdown callback for this JACK application.
  187. * It is called by JACK if the server ever shuts down or
  188. * decides to disconnect the client.
  189. */
  190. void
  191. jack_shutdown (void *arg)
  192. {
  193. exit (1);
  194. }
  195. void
  196. init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t port)
  197. {
  198. name->sin_family = AF_INET ;
  199. name->sin_port = htons (port) ;
  200. if (hostname) {
  201. struct hostent *hostinfo = gethostbyname (hostname) ;
  202. if (hostinfo == NULL) {
  203. jack_info ("init_sockaddr_in: unknown host: %s", hostname) ;
  204. }
  205. name->sin_addr = *(struct in_addr *) hostinfo->h_addr ;
  206. } else {
  207. name->sin_addr.s_addr = htonl (INADDR_ANY) ;
  208. }
  209. }
  210. void
  211. printUsage()
  212. {
  213. fprintf(stderr, "usage: net_source [-n <jack name>] [-s <socket>] [-C <num channels>] [-P <num channels>] -p <host peer>\n"
  214. "\n"
  215. " -n <jack name> - reports a different name to jack\n"
  216. " -s <socket> select another socket than the default (3000).\n"
  217. " -p <host peer> the hostname of the \"other\" machine running the jack-slave.\n"
  218. " -P <num channels> number of playback channels.\n"
  219. " -C <num channels> number of capture channels.\n"
  220. " -l <latency in periods> number of packets on the wire to approach\n"
  221. " -r <reply port> When using a firewall use this port for incoming packets\n"
  222. " -f <downsample ratio> downsample data in the wire by this factor.\n"
  223. " -b <bitdepth> Set transport to use 16bit or 8bit\n"
  224. "\n");
  225. }
  226. int
  227. main (int argc, char *argv[])
  228. {
  229. char jack_name[30] = "net_source";
  230. char *peer_ip = "localhost";
  231. int peer_socket = 3000;
  232. if (argc < 3) {
  233. printUsage();
  234. return 1;
  235. }
  236. extern char *optarg;
  237. extern int optind, optopt;
  238. int errflg = 0;
  239. int c;
  240. while ((c = getopt(argc, argv, ":n:p:s:C:P:l:r:f:b:")) != -1) {
  241. switch (c) {
  242. case 'n':
  243. strcpy(jack_name, optarg);
  244. break;
  245. case 'p':
  246. peer_ip = optarg;
  247. break;
  248. case 's':
  249. peer_socket = atoi(optarg);
  250. break;
  251. case 'P':
  252. playback_channels = atoi(optarg);
  253. break;
  254. case 'C':
  255. capture_channels = atoi(optarg);
  256. break;
  257. case 'l':
  258. latency = atoi(optarg);
  259. break;
  260. case 'r':
  261. reply_port = atoi(optarg);
  262. break;
  263. case 'f':
  264. factor = atoi(optarg);
  265. break;
  266. case 'b':
  267. bitdepth = atoi(optarg);
  268. break;
  269. case ':': /* -n or -p without operand */
  270. fprintf(stderr,
  271. "Option -%c requires an operand\n", optopt);
  272. errflg++;
  273. break;
  274. case '?':
  275. fprintf(stderr,
  276. "Unrecognized option: -%c\n", optopt);
  277. errflg++;
  278. }
  279. }
  280. if (errflg) {
  281. printUsage();
  282. exit(2);
  283. }
  284. //src_state = src_new(SRC_LINEAR, 1, NULL);
  285. outsockfd = socket(PF_INET, SOCK_DGRAM, 0);
  286. insockfd = socket(PF_INET, SOCK_DGRAM, 0);
  287. init_sockaddr_in((struct sockaddr_in *)&destaddr, peer_ip, peer_socket);
  288. if (reply_port) {
  289. init_sockaddr_in((struct sockaddr_in *)&bindaddr, NULL, reply_port);
  290. bind(insockfd, &bindaddr, sizeof(bindaddr));
  291. }
  292. /* try to become a client of the JACK server */
  293. if ((client = jack_client_new (jack_name)) == 0) {
  294. fprintf (stderr, "jack server not running?\n");
  295. return 1;
  296. }
  297. /*
  298. send a ping to the peer
  299. -- this needs to be made more robust --
  300. */
  301. //sendto(outsockfd, "x", 1, 0, &destaddr, sizeof(destaddr));
  302. /* tell the JACK server to call `process()' whenever
  303. there is work to be done.
  304. */
  305. jack_set_process_callback (client, process, 0);
  306. jack_set_sync_callback (client, sync_cb, 0);
  307. /* tell the JACK server to call `jack_shutdown()' if
  308. it ever shuts down, either entirely, or if it
  309. just decides to stop calling us.
  310. */
  311. jack_on_shutdown (client, jack_shutdown, 0);
  312. /* display the current sample rate.
  313. */
  314. jack_info ("engine sample rate: %" PRIu32 "",
  315. jack_get_sample_rate (client));
  316. alloc_ports(capture_channels, playback_channels);
  317. jack_nframes_t net_period = (float) jack_get_buffer_size(client) / (float) factor;
  318. int rx_bufsize = get_sample_size(bitdepth) * capture_channels * net_period + sizeof(jacknet_packet_header);
  319. global_packcache = packet_cache_new(latency + 5, rx_bufsize, 1400);
  320. /* tell the JACK server that we are ready to roll */
  321. if (jack_activate (client)) {
  322. fprintf (stderr, "cannot activate client");
  323. return 1;
  324. }
  325. // Now sleep forever.......
  326. while (1)
  327. sleep(100);
  328. // Never reached. Well we will be a GtkApp someday....
  329. packet_cache_free(global_packcache);
  330. jack_client_close(client);
  331. exit (0);
  332. }
  333. /**
  334. * This required entry point is called after the client is loaded by
  335. * jack_internal_client_load().
  336. *
  337. * @param client pointer to JACK client structure.
  338. * @param load_init character string passed to the load operation.
  339. *
  340. * @return 0 if successful; otherwise jack_finish() will be called and
  341. * the client terminated immediately.
  342. */
  343. int
  344. jack_initialize (jack_client_t *int_client, const char *load_init)
  345. {
  346. int argc = 0;
  347. char* argv[32];
  348. char buffer[255];
  349. char jack_name[30] = "net_source";
  350. char *peer_ip = "localhost";
  351. int peer_socket = 3000;
  352. int ret;
  353. extern char *optarg;
  354. extern int optind, optopt;
  355. int errflg = 0;
  356. int i,c;
  357. client = int_client;
  358. jack_info("netsource: jack_initialize %s", load_init);
  359. /*
  360. ret = sscanf(load_init, "%s", buffer);
  361. while (ret != 0 && ret != EOF) {
  362. argv[argc] = (char*)malloc(64);
  363. strcpy(argv[argc], buffer);
  364. ret = sscanf(load_init, "%s", buffer);
  365. jack_info("netsource: jack_initialize %s %d",buffer, ret);
  366. argc++;
  367. }
  368. */
  369. argc = 4;
  370. argv[0] = "-P";
  371. argv[1] = "2";
  372. argv[2] = "-C";
  373. argv[3] = "2";
  374. jack_info("netsource: jack_initialize 0");
  375. while ((c = getopt(argc, argv, ":n:p:s:C:P:l:r:f:b:")) != -1) {
  376. switch (c) {
  377. case 'n':
  378. strcpy(jack_name, optarg);
  379. break;
  380. case 'p':
  381. peer_ip = optarg;
  382. break;
  383. case 's':
  384. peer_socket = atoi(optarg);
  385. break;
  386. case 'P':
  387. playback_channels = atoi(optarg);
  388. break;
  389. case 'C':
  390. capture_channels = atoi(optarg);
  391. break;
  392. case 'l':
  393. latency = atoi(optarg);
  394. break;
  395. case 'r':
  396. reply_port = atoi(optarg);
  397. break;
  398. case 'f':
  399. factor = atoi(optarg);
  400. break;
  401. case 'b':
  402. bitdepth = atoi(optarg);
  403. break;
  404. case ':': /* -n or -p without operand */
  405. fprintf(stderr,
  406. "Option -%c requires an operand\n", optopt);
  407. errflg++;
  408. break;
  409. case '?':
  410. fprintf(stderr,
  411. "Unrecognized option: -%c\n", optopt);
  412. errflg++;
  413. }
  414. }
  415. jack_info("netsource: jack_initialize 1");
  416. //src_state = src_new(SRC_LINEAR, 1, NULL);
  417. outsockfd = socket(PF_INET, SOCK_DGRAM, 0);
  418. insockfd = socket(PF_INET, SOCK_DGRAM, 0);
  419. init_sockaddr_in((struct sockaddr_in *)&destaddr, peer_ip, peer_socket);
  420. if (reply_port) {
  421. init_sockaddr_in((struct sockaddr_in *)&bindaddr, NULL, reply_port);
  422. bind(insockfd, &bindaddr, sizeof(bindaddr));
  423. }
  424. jack_info("netsource: jack_initialize 2");
  425. /*
  426. send a ping to the peer
  427. -- this needs to be made more robust --
  428. */
  429. //sendto(outsockfd, "x", 1, 0, &destaddr, sizeof(destaddr));
  430. /* tell the JACK server to call `process()' whenever
  431. there is work to be done.
  432. */
  433. jack_set_process_callback (client, process, 0);
  434. jack_set_sync_callback (client, sync_cb, 0);
  435. /* tell the JACK server to call `jack_shutdown()' if
  436. it ever shuts down, either entirely, or if it
  437. just decides to stop calling us.
  438. */
  439. jack_on_shutdown (client, jack_shutdown, 0);
  440. jack_info("netsource: jack_initialize 3");
  441. /* display the current sample rate.
  442. */
  443. jack_info ("engine sample rate: %d", jack_get_sample_rate (client));
  444. jack_info("netsource: capture_channels %d, playback_channels %d", capture_channels ,playback_channels);
  445. alloc_ports(capture_channels, playback_channels);
  446. jack_info("netsource: jack_initialize 4");
  447. jack_nframes_t net_period = (float) jack_get_buffer_size(client) / (float) factor;
  448. int rx_bufsize = get_sample_size(bitdepth) * capture_channels * net_period + sizeof(jacknet_packet_header);
  449. global_packcache = packet_cache_new(latency + 5, rx_bufsize, 1400);
  450. jack_info("netsource: jack_initialize 5");
  451. /*
  452. for (i = 0; i < argc; i++) {
  453. free(argv[i]);
  454. }
  455. */
  456. /* tell the JACK server that we are ready to roll */
  457. if (jack_activate (client)) {
  458. jack_info ("cannot activate client");
  459. return -1;
  460. }
  461. return 0; /* success */
  462. }
  463. /**
  464. * This required entry point is called immediately before the client
  465. * is unloaded, which could happen due to a call to
  466. * jack_internal_client_unload(), or a nonzero return from either
  467. * jack_initialize() or inprocess().
  468. *
  469. * @param arg the same parameter provided to inprocess().
  470. */
  471. void
  472. jack_finish (void *arg)
  473. {
  474. jack_info("netsource: jack_finish");
  475. packet_cache_free(global_packcache);
  476. }