diff --git a/drivers/netjack/net_source.c b/drivers/netjack/net_source.c index d90bb49..24e1b82 100644 --- a/drivers/netjack/net_source.c +++ b/drivers/netjack/net_source.c @@ -1,9 +1,7 @@ -/** @file simple_client.c +/** @file net_source.c * - * @brief This simple client demonstrates the basic features of JACK - * as they would be used by many applications. + * @brief This is an in process version of the netjack client */ - #include #include #include @@ -21,11 +19,11 @@ #include "netjack_packet.h" #include -JSList *capture_ports = NULL; -JSList *capture_srcs = NULL; +JSList *capture_ports = NULL; +JSList *capture_srcs = NULL; int capture_channels = 2; -JSList *playback_ports = NULL; -JSList *playback_srcs = NULL; +JSList *playback_ports = NULL; +JSList *playback_srcs = NULL; int playback_channels = 2; int latency = 1; @@ -49,12 +47,13 @@ int framecnt = 0; int cont_miss = 0; SRC_STATE *src_state; -/* + +/** * This Function allocates all the I/O Ports which are added the lists. * XXX: jack-midi is underway... so dont forget it. */ - -void alloc_ports(int n_capture, int n_playback) +void +alloc_ports (int n_capture, int n_playback) { int port_flags = JackPortIsOutput; int chn; @@ -62,18 +61,15 @@ void alloc_ports(int n_capture, int n_playback) char buf[32]; capture_ports = NULL; - for (chn = 0; chn < n_capture; chn++) { + for (chn = 0; chn < n_capture; chn++) + { snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1); - - port = jack_port_register (client, buf, - JACK_DEFAULT_AUDIO_TYPE, - port_flags, 0); - - if (!port) { - jack_info("jacknet_client: cannot register port for %s", buf); + port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); + if (!port) + { + jack_error ("jacknet_client: cannot register port for %s", buf); break; } - capture_srcs = jack_slist_append(capture_srcs, src_new(SRC_LINEAR, 1, NULL)); capture_ports = jack_slist_append(capture_ports, port); } @@ -81,42 +77,40 @@ void alloc_ports(int n_capture, int n_playback) port_flags = JackPortIsInput; playback_ports = NULL; - for (chn = 0; chn < n_playback; chn++) { - snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1); - - port = jack_port_register (client, buf, - JACK_DEFAULT_AUDIO_TYPE, - port_flags, 0); - - if (!port) { - jack_info("jacknet_client: cannot register port for %s", buf); + for (chn = 0; chn < n_playback; chn++) + { + snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1); + port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); + if (!port) + { + jack_error ("jacknet_client: cannot register port for %s", buf); break; } - - playback_srcs = jack_slist_append(playback_srcs, src_new(SRC_LINEAR, 1, NULL)); - playback_ports = jack_slist_append(playback_ports, port); + playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL)); + playback_ports = jack_slist_append (playback_ports, port); } } - -/* +/** * The Sync callback... sync state is set elsewhere... * we will see if this is working correctly. * i dont really believe in it yet. */ - -int sync_cb(jack_transport_state_t state, jack_position_t *pos, void *arg) +int +sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg) { static int latency_count = 0; int retval = sync_state; - - if (latency_count) { + if (latency_count) + { latency_count--; retval = 0; - } else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) { - retval = 0; - latency_count = latency - 1; - } + } + else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) + { + retval = 0; + latency_count = latency - 1; + } last_transport_state = state; return retval; } @@ -136,8 +130,8 @@ process (jack_nframes_t nframes, void *arg) //jack_position_t jack_pos; - int rx_bufsize = get_sample_size(bitdepth) * capture_channels * net_period + sizeof(jacknet_packet_header); - int tx_bufsize = get_sample_size(bitdepth) * playback_channels * net_period + sizeof(jacknet_packet_header); + int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); + int tx_bufsize = get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header); jack_default_audio_sample_t *buf; jack_port_t *port; @@ -149,16 +143,15 @@ process (jack_nframes_t nframes, void *arg) uint32_t *packet_buf, *packet_bufX; - // Allocate a buffer where both In and Out Buffer will fit - packet_buf = alloca((rx_bufsize > tx_bufsize) ? rx_bufsize : tx_bufsize); + /* Allocate a buffer where both In and Out Buffer will fit */ + packet_buf = alloca ((rx_bufsize > tx_bufsize) ? rx_bufsize : tx_bufsize); - jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf; + jacknet_packet_header *pkthdr = (jacknet_packet_header*) packet_buf; - packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(uint32_t); + packet_bufX = packet_buf + sizeof (jacknet_packet_header) / sizeof (uint32_t); - //////////////// receive //////////////// - //////////////// //////////////// + /* ---- receive ---- */ ReadAgain: if (reply_port) size = netjack_recv(insockfd, (char *)packet_buf, rx_bufsize, MSG_DONTWAIT, 1400); @@ -170,50 +163,49 @@ ReadAgain: // XXX: think about this a little more... //if((size == rx_bufsize) && (framecnt - pkthdr->framecnt) >= latency) { - if ((size == rx_bufsize)) { - + if ((size == rx_bufsize)) + { cont_miss = 0; - if ((framecnt - pkthdr->framecnt) > latency) { - jack_info("FRAMCNT_DIFF = %d ----- A Packet was lost, or did came too late (try -l %d) ", pkthdr->framecnt - framecnt, framecnt - pkthdr->framecnt); + if ((framecnt - pkthdr->framecnt) > latency) + { + jack_log("FRAMCNT_DIFF = %d ----- A Packet was lost, or did came too late (try -l %d) ", pkthdr->framecnt - framecnt, framecnt - pkthdr->framecnt); goto ReadAgain; } - // packet has expected size - render_payload_to_jack_ports(bitdepth, packet_bufX, net_period, capture_ports, capture_srcs, nframes); // Now evaluate packet header; - if (sync_state != pkthdr->sync_state) - jack_info("sync = %d", pkthdr->sync_state); + if (sync_state != pkthdr->sync_state) + { + jack_log("sync = %d", pkthdr->sync_state); + } sync_state = pkthdr->sync_state; - } else { - jack_info("Packet Miss: (expected: %d, got: %d) framecnt=%d", rx_bufsize, size, framecnt); + } + else + { + jack_log("Packet Miss: (expected: %d, got: %d) framecnt=%d", rx_bufsize, size, framecnt); cont_miss += 1; chn = 0; node = capture_ports; - while (node != NULL) { + while (node != NULL) + { int i; port = (jack_port_t *) node->data; buf = jack_port_get_buffer (port, nframes); - - for (i = 0; i < nframes; i++) { + for (i = 0; i < nframes; i++) + { buf[i] = 0.0; } node = jack_slist_next (node); chn++; } } - //////////////// - //////////////// - // reset packet_bufX... and then send... + /* reset packet_bufX... and then send... */ packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t); - //////////////// send //////////////// - //////////////// //////////////// - + /* ---- send ---- */ render_jack_ports_to_payload(bitdepth, playback_ports, playback_srcs, nframes, packet_bufX, net_period); - - // fill in packet hdr + /* fill in packet hdr */ pkthdr->transport_state = jack_transport_query(client, &local_trans_pos); pkthdr->transport_frame = local_trans_pos.frame; pkthdr->framecnt = framecnt; @@ -243,169 +235,27 @@ ReadAgain: void jack_shutdown (void *arg) { - exit (1); + jack_error ("jack_shutdown was called"); } void -init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t port) +init_sockaddr_in (struct sockaddr_in *name, const char *hostname, uint16_t port) { name->sin_family = AF_INET ; name->sin_port = htons (port) ; - if (hostname) { - struct hostent *hostinfo = gethostbyname (hostname) ; - if (hostinfo == NULL) { - jack_info ("init_sockaddr_in: unknown host: %s", hostname) ; + if (hostname) + { + struct hostent *hostinfo = gethostbyname (hostname); + if (hostinfo == NULL) + { + jack_error ("init_sockaddr_in: unknown host: %s", hostname); } - name->sin_addr = *(struct in_addr *) hostinfo->h_addr ; - } else { - name->sin_addr.s_addr = htonl (INADDR_ANY) ; + name->sin_addr = *(struct in_addr *) hostinfo->h_addr; } -} - -void -printUsage() -{ - fprintf(stderr, "usage: net_source [-n ] [-s ] [-C ] [-P ] -p \n" - "\n" - " -n - reports a different name to jack\n" - " -s select another socket than the default (3000).\n" - " -p the hostname of the \"other\" machine running the jack-slave.\n" - " -P number of playback channels.\n" - " -C number of capture channels.\n" - " -l number of packets on the wire to approach\n" - " -r When using a firewall use this port for incoming packets\n" - " -f downsample data in the wire by this factor.\n" - " -b Set transport to use 16bit or 8bit\n" - "\n"); -} - -int -main (int argc, char *argv[]) -{ - char jack_name[30] = "net_source"; - char *peer_ip = "localhost"; - int peer_socket = 3000; - - if (argc < 3) { - printUsage(); - return 1; - } - extern char *optarg; - extern int optind, optopt; - int errflg = 0; - int c; - - while ((c = getopt(argc, argv, ":n:p:s:C:P:l:r:f:b:")) != -1) { - switch (c) { - case 'n': - strcpy(jack_name, optarg); - break; - case 'p': - peer_ip = optarg; - break; - case 's': - peer_socket = atoi(optarg); - break; - case 'P': - playback_channels = atoi(optarg); - break; - case 'C': - capture_channels = atoi(optarg); - break; - case 'l': - latency = atoi(optarg); - break; - case 'r': - reply_port = atoi(optarg); - break; - case 'f': - factor = atoi(optarg); - break; - case 'b': - bitdepth = atoi(optarg); - break; - case ':': /* -n or -p without operand */ - fprintf(stderr, - "Option -%c requires an operand\n", optopt); - errflg++; - break; - case '?': - fprintf(stderr, - "Unrecognized option: -%c\n", optopt); - errflg++; - } - } - if (errflg) { - printUsage(); - exit(2); - } - - //src_state = src_new(SRC_LINEAR, 1, NULL); - - outsockfd = socket(PF_INET, SOCK_DGRAM, 0); - insockfd = socket(PF_INET, SOCK_DGRAM, 0); - init_sockaddr_in((struct sockaddr_in *)&destaddr, peer_ip, peer_socket); - if (reply_port) { - init_sockaddr_in((struct sockaddr_in *)&bindaddr, NULL, reply_port); - bind(insockfd, &bindaddr, sizeof(bindaddr)); - } - /* try to become a client of the JACK server */ - - if ((client = jack_client_new (jack_name)) == 0) { - fprintf (stderr, "jack server not running?\n"); - return 1; - } - - /* - send a ping to the peer - -- this needs to be made more robust -- - */ - - //sendto(outsockfd, "x", 1, 0, &destaddr, sizeof(destaddr)); - - /* tell the JACK server to call `process()' whenever - there is work to be done. - */ - - jack_set_process_callback (client, process, 0); - jack_set_sync_callback (client, sync_cb, 0); - - /* tell the JACK server to call `jack_shutdown()' if - it ever shuts down, either entirely, or if it - just decides to stop calling us. - */ - - jack_on_shutdown (client, jack_shutdown, 0); - - /* display the current sample rate. - */ - - jack_info ("engine sample rate: %" PRIu32 "", - jack_get_sample_rate (client)); - - alloc_ports(capture_channels, playback_channels); - - jack_nframes_t net_period = (float) jack_get_buffer_size(client) / (float) factor; - int rx_bufsize = get_sample_size(bitdepth) * capture_channels * net_period + sizeof(jacknet_packet_header); - global_packcache = packet_cache_new(latency + 5, rx_bufsize, 1400); - - /* tell the JACK server that we are ready to roll */ - - if (jack_activate (client)) { - fprintf (stderr, "cannot activate client"); - return 1; + else + { + name->sin_addr.s_addr = htonl (INADDR_ANY) ; } - - // Now sleep forever....... - - while (1) - sleep(100); - - // Never reached. Well we will be a GtkApp someday.... - - packet_cache_free(global_packcache); - jack_client_close(client); - exit (0); } /** @@ -421,39 +271,55 @@ main (int argc, char *argv[]) int jack_initialize (jack_client_t *int_client, const char *load_init) { - int argc = 0; - char* argv[32]; - char jack_name[30] = "net_source"; - char *peer_ip = "localhost"; - int peer_socket = 3000; - extern char *optarg; + int argc = 2; // getopt() starts parsing at the third element of argv + char *argv[32]; + char *load_init_copy, *current_arg, *jack_name, *peer_ip; + extern char *optarg; extern int optind, optopt; - int errflg = 0; - int i,c; - - client = int_client; - - argv[argc] = (char*)malloc(64); - while (sscanf(load_init, "%31[^ ]%n", argv[argc], &i) == 1) { - load_init += i; // advance the pointer by the number of characters read - if (*load_init != ' ') { - break; // didn't find an expected delimiter, done? - } - while (*load_init == ' ') { load_init++; } // skip the space - argc++; - argv[argc] = (char*)malloc(64); - } - - // last topken - sscanf(load_init, "%s", argv[argc]); - argc++; - - while ((c = getopt(argc, argv, ":n:p:s:C:P:l:r:f:b:")) != -1) { - switch (c) { + int index, option, errflag = 0, peer_socket; + + /* Is that any good ? */ + client = int_client; + + /* We'll use a copy of load_init to determine how much + should be allocated for each argument */ + load_init_copy = strdup (load_init); // Make a copy of our init string + + /* Fill in some defaults */ + jack_name = (char*) malloc (10); + peer_ip = (char*) malloc (9); + sprintf (jack_name, "net_source"); + sprintf (peer_ip, "localhost"); + peer_socket = 3000; + + /* Count the length of out first argument, and allocate accordingly */ + current_arg = strtok (load_init_copy, " "); + argv[argc] = (char*) malloc (strlen (current_arg) * sizeof (char) + 1); + /* Same for the rest of the list */ + while (sscanf (load_init, "%s%n", argv[argc], &index) == 1) + { + load_init += index; // Move on to the next arg + argc++; + if ((current_arg = strtok (NULL, " ")) != NULL) + { + argv[argc] = (char*) malloc (strlen (current_arg) * sizeof (char) + 1); + } + } + + /* let's make sure we can run multiple in process clients + and still have our parametters parsed by getopt */ + optind = 2; + /* We may now run our getopt loop just as if all of it came from a real command line */ + while ((option = getopt(argc, argv, ":n:p:s:P:C:l:r:f:b:")) != -1) + { + switch (option) + { case 'n': - strcpy(jack_name, optarg); + free(jack_name); + jack_name = optarg; break; case 'p': + free(peer_ip); peer_ip = optarg; break; case 's': @@ -477,67 +343,91 @@ jack_initialize (jack_client_t *int_client, const char *load_init) case 'b': bitdepth = atoi(optarg); break; - case ':': /* -n or -p without operand */ - fprintf(stderr, - "Option -%c requires an operand\n", optopt); - errflg++; + case ':': // -n or -p without operand + jack_error ("Option -%c requires an operand, ignoring\n", optopt); + errflag++; break; case '?': - fprintf(stderr, - "Unrecognized option: -%c\n", optopt); - errflg++; + jack_error ("Unrecognized option: -%c, ignoring.\n" + "TODO : send the format to jack_load application...\n" + "Go bug the devs about it", optopt); + errflag++; } } - //src_state = src_new(SRC_LINEAR, 1, NULL); - - outsockfd = socket(PF_INET, SOCK_DGRAM, 0); - insockfd = socket(PF_INET, SOCK_DGRAM, 0); - init_sockaddr_in((struct sockaddr_in *)&destaddr, peer_ip, peer_socket); + jack_info ("Here's our netclient setup:\n" + "jack name: `%s'\n" + "peer ip/hostname: `%s'\n" + "peer_socket: `%i'\n" + "playback channels: `%i'\n" + "capture channels: `%i'\n" + "latency: `%i'\n" + "reply port: `%i'\n" + "factor: `%i'\n" + "bitdepth: `%i'\n", + jack_name, + peer_ip, + peer_socket, + playback_channels, + capture_channels, + latency, + reply_port, + factor, + bitdepth); + + /* Yet another line to understand... + src_state = src_new(SRC_LINEAR, 1, NULL); */ + + outsockfd = socket (PF_INET, SOCK_DGRAM, 0); + insockfd = socket (PF_INET, SOCK_DGRAM, 0); + init_sockaddr_in ((struct sockaddr_in *) &destaddr, peer_ip, peer_socket); if (reply_port) { - init_sockaddr_in((struct sockaddr_in *)&bindaddr, NULL, reply_port); - bind(insockfd, &bindaddr, sizeof(bindaddr)); + init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port); + bind(insockfd, &bindaddr, sizeof (bindaddr)); } - /* - send a ping to the peer - -- this needs to be made more robust -- - */ + /* Send a ping to the peer to measure round trip time ? + What if there are some ACLs on the remote host ? + sendto(outsockfd, "x", 1, 0, &destaddr, sizeof(destaddr)); */ - //sendto(outsockfd, "x", 1, 0, &destaddr, sizeof(destaddr)); - - /* tell the JACK server to call `process()' whenever - there is work to be done. - */ + /* Tell the JACK server to call `process()' whenever there is work to be done */ jack_set_process_callback (client, process, 0); jack_set_sync_callback (client, sync_cb, 0); - /* tell the JACK server to call `jack_shutdown()' if + /* Tell the JACK server to call `jack_shutdown()' if it ever shuts down, either entirely, or if it - just decides to stop calling us. - */ + just decides to stop calling us*/ jack_on_shutdown (client, jack_shutdown, 0); - /* display the current sample rate. - */ - jack_info ("engine sample rate: %d", jack_get_sample_rate (client)); - alloc_ports(capture_channels, playback_channels); - - jack_nframes_t net_period = (float) jack_get_buffer_size(client) / (float) factor; - int rx_bufsize = get_sample_size(bitdepth) * capture_channels * net_period + sizeof(jacknet_packet_header); - global_packcache = packet_cache_new(latency + 5, rx_bufsize, 1400); - - for (i = 0; i < argc; i++) { - free(argv[i]); - } - - /* tell the JACK server that we are ready to roll */ - if (jack_activate (client)) { - jack_info ("cannot activate client"); - return -1; + /* Display the current sample rate + TODO : Shall we remove that ? Who cares really... we're 'in process' ! */ + jack_log ("engine sample rate: %d", jack_get_sample_rate (client)); + alloc_ports (capture_channels, playback_channels); + + /* TODO : figure out what this does */ + jack_nframes_t net_period = (float) jack_get_buffer_size (client) / (float) factor; + int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); + global_packcache = packet_cache_new (latency + 5, rx_bufsize, 1400); + + /* Cleanup the mess */ + for (index = 2; index < argc; index++) + { + free (argv[index]); } - return 0; /* success */ + /* tell the JACK server that we are ready to roll, + exit gracefully if we got something wrong before that */ + if (errflag > 0) + { + jack_error ("It seems something went badly wrong"); + return -1; + } + if (jack_activate (client)) + { + jack_error ("Cannot activate client"); + return -1; + } + return 0; } /** @@ -551,7 +441,6 @@ jack_initialize (jack_client_t *int_client, const char *load_init) void jack_finish (void *arg) { - jack_info("netsource: jack_finish"); - packet_cache_free(global_packcache); + jack_info ("netsource client exits"); + packet_cache_free (global_packcache); } -