|
|
|
@@ -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 <stdio.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <unistd.h> |
|
|
|
@@ -21,11 +19,11 @@ |
|
|
|
#include "netjack_packet.h" |
|
|
|
#include <samplerate.h> |
|
|
|
|
|
|
|
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 <jack name>] [-s <socket>] [-C <num channels>] [-P <num channels>] -p <host peer>\n" |
|
|
|
"\n" |
|
|
|
" -n <jack name> - reports a different name to jack\n" |
|
|
|
" -s <socket> select another socket than the default (3000).\n" |
|
|
|
" -p <host peer> the hostname of the \"other\" machine running the jack-slave.\n" |
|
|
|
" -P <num channels> number of playback channels.\n" |
|
|
|
" -C <num channels> number of capture channels.\n" |
|
|
|
" -l <latency in periods> number of packets on the wire to approach\n" |
|
|
|
" -r <reply port> When using a firewall use this port for incoming packets\n" |
|
|
|
" -f <downsample ratio> downsample data in the wire by this factor.\n" |
|
|
|
" -b <bitdepth> 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); |
|
|
|
} |
|
|
|
|