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.

441 lines
12KB

  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. printf("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. printf("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. printf("FRAMCNT_DIFF = %d ----- A Packet was lost, or did came too late (try -l %d) \n", 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) printf("sync = %d\n", pkthdr->sync_state);
  142. sync_state = pkthdr->sync_state;
  143. } else {
  144. printf("Packet Miss: (expected: %d, got: %d) framecnt=%d\n", rx_bufsize, size, framecnt);
  145. cont_miss += 1;
  146. chn = 0;
  147. node = capture_ports;
  148. while (node != NULL) {
  149. int i;
  150. port = (jack_port_t *) node->data;
  151. buf = jack_port_get_buffer (port, nframes);
  152. for (i = 0; i < nframes; i++) {
  153. buf[i] = 0.0;
  154. }
  155. node = jack_slist_next (node);
  156. chn++;
  157. }
  158. }
  159. ////////////////
  160. ////////////////
  161. // reset packet_bufX... and then send...
  162. packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
  163. //////////////// send ////////////////
  164. //////////////// ////////////////
  165. render_jack_ports_to_payload(bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period);
  166. // fill in packet hdr
  167. pkthdr->transport_state = jack_transport_query(client, &local_trans_pos);
  168. pkthdr->transport_frame = local_trans_pos.frame;
  169. pkthdr->framecnt = framecnt;
  170. pkthdr->latency = latency;
  171. pkthdr->reply_port = reply_port;
  172. pkthdr->sample_rate = jack_get_sample_rate(client);
  173. pkthdr->period_size = nframes;
  174. packet_header_hton(pkthdr);
  175. if (cont_miss < 10) {
  176. netjack_sendto(outsockfd, (char *)packet_buf, tx_bufsize, 0, &destaddr, sizeof(destaddr), 1400);
  177. } else {
  178. if (cont_miss > 50)
  179. cont_miss = 5;
  180. }
  181. framecnt++;
  182. return 0;
  183. }
  184. /**
  185. * This is the shutdown callback for this JACK application.
  186. * It is called by JACK if the server ever shuts down or
  187. * decides to disconnect the client.
  188. */
  189. void
  190. jack_shutdown (void *arg)
  191. {
  192. exit (1);
  193. }
  194. void
  195. init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t port)
  196. {
  197. name->sin_family = AF_INET ;
  198. name->sin_port = htons (port) ;
  199. if (hostname) {
  200. struct hostent *hostinfo = gethostbyname (hostname) ;
  201. if (hostinfo == NULL) {
  202. fprintf (stderr , "init_sockaddr_in: unknown host: %s.\n" , hostname) ;
  203. }
  204. name->sin_addr = *(struct in_addr *) hostinfo->h_addr ;
  205. } else {
  206. name->sin_addr.s_addr = htonl (INADDR_ANY) ;
  207. }
  208. }
  209. void
  210. printUsage()
  211. {
  212. fprintf(stderr, "usage: net_source [-n <jack name>] [-s <socket>] [-C <num channels>] [-P <num channels>] -p <host peer>\n"
  213. "\n"
  214. " -n <jack name> - reports a different name to jack\n"
  215. " -s <socket> select another socket than the default (3000).\n"
  216. " -p <host peer> the hostname of the \"other\" machine running the jack-slave.\n"
  217. " -P <num channels> number of playback channels.\n"
  218. " -C <num channels> number of capture channels.\n"
  219. " -l <latency in periods> number of packets on the wire to approach\n"
  220. " -r <reply port> When using a firewall use this port for incoming packets\n"
  221. " -f <downsample ratio> downsample data in the wire by this factor.\n"
  222. " -b <bitdepth> Set transport to use 16bit or 8bit\n"
  223. "\n");
  224. }
  225. int
  226. main (int argc, char *argv[])
  227. {
  228. char jack_name[30] = "net_source";
  229. char *peer_ip = "localhost";
  230. int peer_socket = 3000;
  231. if (argc < 3) {
  232. printUsage();
  233. return 1;
  234. }
  235. extern char *optarg;
  236. extern int optind, optopt;
  237. int errflg = 0;
  238. int c;
  239. while ((c = getopt(argc, argv, ":n:p:s:C:P:l:r:f:b:")) != -1) {
  240. switch (c) {
  241. case 'n':
  242. strcpy(jack_name, optarg);
  243. break;
  244. case 'p':
  245. peer_ip = optarg;
  246. break;
  247. case 's':
  248. peer_socket = atoi(optarg);
  249. break;
  250. case 'P':
  251. playback_channels = atoi(optarg);
  252. break;
  253. case 'C':
  254. capture_channels = atoi(optarg);
  255. break;
  256. case 'l':
  257. latency = atoi(optarg);
  258. break;
  259. case 'r':
  260. reply_port = atoi(optarg);
  261. break;
  262. case 'f':
  263. factor = atoi(optarg);
  264. break;
  265. case 'b':
  266. bitdepth = atoi(optarg);
  267. break;
  268. case ':': /* -n or -p without operand */
  269. fprintf(stderr,
  270. "Option -%c requires an operand\n", optopt);
  271. errflg++;
  272. break;
  273. case '?':
  274. fprintf(stderr,
  275. "Unrecognized option: -%c\n", optopt);
  276. errflg++;
  277. }
  278. }
  279. if (errflg) {
  280. printUsage();
  281. exit(2);
  282. }
  283. //src_state = src_new(SRC_LINEAR, 1, NULL);
  284. outsockfd = socket(PF_INET, SOCK_DGRAM, 0);
  285. insockfd = socket(PF_INET, SOCK_DGRAM, 0);
  286. init_sockaddr_in((struct sockaddr_in *)&destaddr, peer_ip, peer_socket);
  287. if (reply_port) {
  288. init_sockaddr_in((struct sockaddr_in *)&bindaddr, NULL, reply_port);
  289. bind(insockfd, &bindaddr, sizeof(bindaddr));
  290. }
  291. /* try to become a client of the JACK server */
  292. if ((client = jack_client_new (jack_name)) == 0) {
  293. fprintf (stderr, "jack server not running?\n");
  294. return 1;
  295. }
  296. /*
  297. send a ping to the peer
  298. -- this needs to be made more robust --
  299. */
  300. //sendto(outsockfd, "x", 1, 0, &destaddr, sizeof(destaddr));
  301. /* tell the JACK server to call `process()' whenever
  302. there is work to be done.
  303. */
  304. jack_set_process_callback (client, process, 0);
  305. jack_set_sync_callback (client, sync_cb, 0);
  306. /* tell the JACK server to call `jack_shutdown()' if
  307. it ever shuts down, either entirely, or if it
  308. just decides to stop calling us.
  309. */
  310. jack_on_shutdown (client, jack_shutdown, 0);
  311. /* display the current sample rate.
  312. */
  313. printf ("engine sample rate: %" PRIu32 "\n",
  314. jack_get_sample_rate (client));
  315. alloc_ports(capture_channels, playback_channels);
  316. jack_nframes_t net_period = (float) jack_get_buffer_size(client) / (float) factor;
  317. int rx_bufsize = get_sample_size(bitdepth) * capture_channels * net_period + sizeof(jacknet_packet_header);
  318. global_packcache = packet_cache_new(latency + 5, rx_bufsize, 1400);
  319. /* tell the JACK server that we are ready to roll */
  320. if (jack_activate (client)) {
  321. fprintf (stderr, "cannot activate client");
  322. return 1;
  323. }
  324. // Now sleep forever.......
  325. while (1)
  326. sleep(100);
  327. // Never reached. Well we will be a GtkApp someday....
  328. packet_cache_free(global_packcache);
  329. jack_client_close(client);
  330. exit (0);
  331. }
  332. /**
  333. * This required entry point is called after the client is loaded by
  334. * jack_internal_client_load().
  335. *
  336. * @param client pointer to JACK client structure.
  337. * @param load_init character string passed to the load operation.
  338. *
  339. * @return 0 if successful; otherwise jack_finish() will be called and
  340. * the client terminated immediately.
  341. */
  342. int
  343. jack_initialize (jack_client_t *client, const char *load_init)
  344. {
  345. jack_info("netsource: jack_initialize");
  346. return 0; /* success */
  347. }
  348. /**
  349. * This required entry point is called immediately before the client
  350. * is unloaded, which could happen due to a call to
  351. * jack_internal_client_unload(), or a nonzero return from either
  352. * jack_initialize() or inprocess().
  353. *
  354. * @param arg the same parameter provided to inprocess().
  355. */
  356. void
  357. jack_finish (void *arg)
  358. {
  359. jack_info("netsource: jack_finish");
  360. }