Browse Source

Marc-Olivier Barre patch for net_source.c

git-svn-id: svn+ssh://jackaudio.org/trunk/jack@1117 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.115.6
sletz 18 years ago
parent
commit
7bcc8d6ae5
1 changed files with 190 additions and 301 deletions
  1. +190
    -301
      drivers/netjack/net_source.c

+ 190
- 301
drivers/netjack/net_source.c View File

@@ -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);
}


Loading…
Cancel
Save