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.

416 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>(#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 alloc_ports(int n_capture, int n_playback)
  44. {
  45. int port_flags = JackPortIsOutput;
  46. int chn;
  47. jack_port_t *port;
  48. char buf[32];
  49. capture_ports = NULL;
  50. for (chn = 0; chn < n_capture; chn++) {
  51. snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1);
  52. port = jack_port_register (client, buf,
  53. JACK_DEFAULT_AUDIO_TYPE,
  54. port_flags, 0);
  55. if (!port) {
  56. printf("jacknet_client: cannot register port for %s", buf);
  57. break;
  58. }
  59. capture_srcs = jack_slist_append(capture_srcs, src_new(SRC_LINEAR, 1, NULL));
  60. capture_ports = jack_slist_append(capture_ports, port);
  61. }
  62. port_flags = JackPortIsInput;
  63. playback_ports = NULL;
  64. for (chn = 0; chn < n_playback; chn++) {
  65. snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1);
  66. port = jack_port_register (client, buf,
  67. JACK_DEFAULT_AUDIO_TYPE,
  68. port_flags, 0);
  69. if (!port) {
  70. printf("jacknet_client: cannot register port for %s", buf);
  71. break;
  72. }
  73. playback_srcs = jack_slist_append(playback_srcs, src_new(SRC_LINEAR, 1, NULL));
  74. playback_ports = jack_slist_append(playback_ports, port);
  75. }
  76. }
  77. /*
  78. * The Sync callback... sync state is set elsewhere...
  79. * we will see if this is working correctly.
  80. * i dont really believe in it yet.
  81. */
  82. int sync_cb(jack_transport_state_t state, jack_position_t *pos, void *arg)
  83. {
  84. static int latency_count = 0;
  85. int retval = sync_state;
  86. if (latency_count) {
  87. latency_count--;
  88. retval = 0;
  89. } else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) {
  90. retval = 0;
  91. latency_count = latency - 1;
  92. }
  93. last_transport_state = state;
  94. return retval;
  95. }
  96. /**
  97. * The process callback for this JACK application.
  98. * It is called by JACK at the appropriate times.
  99. */
  100. int
  101. process (jack_nframes_t nframes, void *arg)
  102. {
  103. //static int old_count = 0;
  104. //SRC_DATA src;
  105. jack_nframes_t net_period = (float) nframes / (float) factor;
  106. //jack_position_t jack_pos;
  107. int rx_bufsize = get_sample_size(bitdepth) * capture_channels * net_period + sizeof(jacknet_packet_header);
  108. int tx_bufsize = get_sample_size(bitdepth) * playback_channels * net_period + sizeof(jacknet_packet_header);
  109. jack_default_audio_sample_t *buf;
  110. jack_port_t *port;
  111. JSList *node;
  112. channel_t chn;
  113. int size;
  114. jack_position_t local_trans_pos;
  115. uint32_t *packet_buf, *packet_bufX;
  116. // Allocate a buffer where both In and Out Buffer will fit
  117. packet_buf = alloca((rx_bufsize > tx_bufsize) ? rx_bufsize : tx_bufsize);
  118. jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf;
  119. packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(uint32_t);
  120. //////////////// receive ////////////////
  121. //////////////// ////////////////
  122. ReadAgain:
  123. if (reply_port)
  124. size = netjack_recv(insockfd, (char *)packet_buf, rx_bufsize, MSG_DONTWAIT, 1400);
  125. else
  126. size = netjack_recv(outsockfd, (char *)packet_buf, rx_bufsize, MSG_DONTWAIT, 1400);
  127. packet_header_ntoh(pkthdr);
  128. // evaluate rcvd data.
  129. // XXX: think about this a little more...
  130. //if((size == rx_bufsize) && (framecnt - pkthdr->framecnt) >= latency) {
  131. if ((size == rx_bufsize)) {
  132. cont_miss = 0;
  133. if ((framecnt - pkthdr->framecnt) > latency) {
  134. printf("FRAMCNT_DIFF = %d ----- A Packet was lost, or did came too late (try -l %d) \n", pkthdr->framecnt - framecnt, framecnt - pkthdr->framecnt);
  135. goto ReadAgain;
  136. }
  137. // packet has expected size
  138. render_payload_to_jack_ports(bitdepth, packet_bufX, net_period, capture_ports, capture_srcs, nframes);
  139. // Now evaluate packet header;
  140. if (sync_state != pkthdr->sync_state) printf("sync = %d\n", pkthdr->sync_state);
  141. sync_state = pkthdr->sync_state;
  142. } else {
  143. printf("Packet Miss: (expected: %d, got: %d) framecnt=%d\n", rx_bufsize, size, framecnt);
  144. cont_miss += 1;
  145. chn = 0;
  146. node = capture_ports;
  147. while (node != NULL) {
  148. int i;
  149. port = (jack_port_t *) node->data;
  150. buf = jack_port_get_buffer (port, nframes);
  151. for (i = 0; i < nframes; i++) {
  152. buf[i] = 0.0;
  153. }
  154. node = jack_slist_next (node);
  155. chn++;
  156. }
  157. }
  158. ////////////////
  159. ////////////////
  160. // reset packet_bufX... and then send...
  161. packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
  162. //////////////// send ////////////////
  163. //////////////// ////////////////
  164. render_jack_ports_to_payload(bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period);
  165. // fill in packet hdr
  166. pkthdr->transport_state = jack_transport_query(client, &local_trans_pos);
  167. pkthdr->transport_frame = local_trans_pos.frame;
  168. pkthdr->framecnt = framecnt;
  169. pkthdr->latency = latency;
  170. pkthdr->reply_port = reply_port;
  171. pkthdr->sample_rate = jack_get_sample_rate(client);
  172. pkthdr->period_size = nframes;
  173. packet_header_hton(pkthdr);
  174. if (cont_miss < 10) {
  175. netjack_sendto(outsockfd, (char *)packet_buf, tx_bufsize, 0, &destaddr, sizeof(destaddr), 1400);
  176. } else {
  177. if (cont_miss > 50)
  178. cont_miss = 5;
  179. }
  180. framecnt++;
  181. return 0;
  182. }
  183. /**
  184. * This is the shutdown callback for this JACK application.
  185. * It is called by JACK if the server ever shuts down or
  186. * decides to disconnect the client.
  187. */
  188. void
  189. jack_shutdown (void *arg)
  190. {
  191. exit (1);
  192. }
  193. void
  194. init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t port)
  195. {
  196. name->sin_family = AF_INET ;
  197. name->sin_port = htons (port) ;
  198. if (hostname) {
  199. struct hostent *hostinfo = gethostbyname (hostname) ;
  200. if (hostinfo == NULL) {
  201. fprintf (stderr , "init_sockaddr_in: unknown host: %s.\n" , hostname) ;
  202. }
  203. name->sin_addr = *(struct in_addr *) hostinfo->h_addr ;
  204. } else {
  205. name->sin_addr.s_addr = htonl (INADDR_ANY) ;
  206. }
  207. }
  208. void
  209. printUsage()
  210. {
  211. fprintf(stderr, "usage: net_source [-n <jack name>] [-s <socket>] [-C <num channels>] [-P <num channels>] -p <host peer>\n"
  212. "\n"
  213. " -n <jack name> - reports a different name to jack\n"
  214. " -s <socket> select another socket than the default (3000).\n"
  215. " -p <host peer> the hostname of the \"other\" machine running the jack-slave.\n"
  216. " -P <num channels> number of playback channels.\n"
  217. " -C <num channels> number of capture channels.\n"
  218. " -l <latency in periods> number of packets on the wire to approach\n"
  219. " -r <reply port> When using a firewall use this port for incoming packets\n"
  220. " -f <downsample ratio> downsample data in the wire by this factor.\n"
  221. " -b <bitdepth> Set transport to use 16bit or 8bit\n"
  222. "\n");
  223. }
  224. int
  225. main (int argc, char *argv[])
  226. {
  227. char jack_name[30] = "net_source";
  228. char *peer_ip = "localhost";
  229. int peer_socket = 3000;
  230. if (argc < 3) {
  231. printUsage();
  232. return 1;
  233. }
  234. extern char *optarg;
  235. extern int optind, optopt;
  236. int errflg = 0;
  237. int c;
  238. while ((c = getopt(argc, argv, ":n:p:s:C:P:l:r:f:b:")) != -1) {
  239. switch (c) {
  240. case 'n':
  241. strcpy(jack_name, optarg);
  242. break;
  243. case 'p':
  244. peer_ip = optarg;
  245. break;
  246. case 's':
  247. peer_socket = atoi(optarg);
  248. break;
  249. case 'P':
  250. playback_channels = atoi(optarg);
  251. break;
  252. case 'C':
  253. capture_channels = atoi(optarg);
  254. break;
  255. case 'l':
  256. latency = atoi(optarg);
  257. break;
  258. case 'r':
  259. reply_port = atoi(optarg);
  260. break;
  261. case 'f':
  262. factor = atoi(optarg);
  263. break;
  264. case 'b':
  265. bitdepth = atoi(optarg);
  266. break;
  267. case ':': /* -n or -p without operand */
  268. fprintf(stderr,
  269. "Option -%c requires an operand\n", optopt);
  270. errflg++;
  271. break;
  272. case '?':
  273. fprintf(stderr,
  274. "Unrecognized option: -%c\n", optopt);
  275. errflg++;
  276. }
  277. }
  278. if (errflg) {
  279. printUsage();
  280. exit(2);
  281. }
  282. //src_state = src_new(SRC_LINEAR, 1, NULL);
  283. outsockfd = socket(PF_INET, SOCK_DGRAM, 0);
  284. insockfd = socket(PF_INET, SOCK_DGRAM, 0);
  285. init_sockaddr_in((struct sockaddr_in *)&destaddr, peer_ip, peer_socket);
  286. if (reply_port) {
  287. init_sockaddr_in((struct sockaddr_in *)&bindaddr, NULL, reply_port);
  288. bind(insockfd, &bindaddr, sizeof(bindaddr));
  289. }
  290. /* try to become a client of the JACK server */
  291. if ((client = jack_client_new (jack_name)) == 0) {
  292. fprintf (stderr, "jack server not running?\n");
  293. return 1;
  294. }
  295. /*
  296. send a ping to the peer
  297. -- this needs to be made more robust --
  298. */
  299. //sendto(outsockfd, "x", 1, 0, &destaddr, sizeof(destaddr));
  300. /* tell the JACK server to call `process()' whenever
  301. there is work to be done.
  302. */
  303. jack_set_process_callback (client, process, 0);
  304. jack_set_sync_callback (client, sync_cb, 0);
  305. /* tell the JACK server to call `jack_shutdown()' if
  306. it ever shuts down, either entirely, or if it
  307. just decides to stop calling us.
  308. */
  309. jack_on_shutdown (client, jack_shutdown, 0);
  310. /* display the current sample rate.
  311. */
  312. printf ("engine sample rate: %" PRIu32 "\n",
  313. jack_get_sample_rate (client));
  314. alloc_ports(capture_channels, playback_channels);
  315. jack_nframes_t net_period = (float) jack_get_buffer_size(client) / (float) factor;
  316. int rx_bufsize = get_sample_size(bitdepth) * capture_channels * net_period + sizeof(jacknet_packet_header);
  317. global_packcache = packet_cache_new(latency + 5, rx_bufsize, 1400);
  318. /* tell the JACK server that we are ready to roll */
  319. if (jack_activate (client)) {
  320. fprintf (stderr, "cannot activate client");
  321. return 1;
  322. }
  323. // Now sleep forever.......
  324. while (1)
  325. sleep(100);
  326. // Never reached. Well we will be a GtkApp someday....
  327. packet_cache_free(global_packcache);
  328. jack_client_close(client);
  329. exit (0);
  330. }