diff --git a/common/JackNetOneDriver.cpp b/common/JackNetOneDriver.cpp index 1768de7f..008d6bba 100644 --- a/common/JackNetOneDriver.cpp +++ b/common/JackNetOneDriver.cpp @@ -50,8 +50,8 @@ namespace Jack JackNetOneDriver::JackNetOneDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports, int sample_rate, int period_size, int resample_factor, - char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, - int latency, int redundancy, int dont_htonl_floats, int always_deadline ) + const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, + int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val ) : JackAudioDriver ( name, alias, engine, table ) { jack_log ( "JackNetOneDriver::JackNetOneDriver port %d", port ); @@ -79,7 +79,8 @@ namespace Jack latency, redundancy, dont_htonl_floats, - always_deadline); + always_deadline, + jitter_val); } JackNetOneDriver::~JackNetOneDriver() @@ -823,11 +824,11 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p strcpy ( desc->name, "netone" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 strcpy ( desc->desc, "netjack one slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 - desc->nparams = 17; + desc->nparams = 18; params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); int i = 0; - strcpy (params[i].name, "inchannels"); + strcpy (params[i].name, "audio-ins"); params[i].character = 'i'; params[i].type = JackDriverParamUInt; params[i].value.ui = 2U; @@ -835,7 +836,7 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p strcpy (params[i].long_desc, params[i].short_desc); i++; - strcpy (params[i].name, "outchannels"); + strcpy (params[i].name, "audio-outs"); params[i].character = 'o'; params[i].type = JackDriverParamUInt; params[i].value.ui = 2U; @@ -843,7 +844,7 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p strcpy (params[i].long_desc, params[i].short_desc); i++; - strcpy (params[i].name, "midi inchannels"); + strcpy (params[i].name, "midi-ins"); params[i].character = 'I'; params[i].type = JackDriverParamUInt; params[i].value.ui = 1U; @@ -851,7 +852,7 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p strcpy (params[i].long_desc, params[i].short_desc); i++; - strcpy (params[i].name, "midi outchannels"); + strcpy (params[i].name, "midi-outs"); params[i].character = 'O'; params[i].type = JackDriverParamUInt; params[i].value.ui = 1U; @@ -874,6 +875,15 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p strcpy (params[i].short_desc, "Frames per period"); strcpy (params[i].long_desc, params[i].short_desc); + i++; + strcpy (params[i].name, "num-periods"); + params[i].character = 'n'; + params[i].type = JackDriverParamUInt; + params[i].value.ui = 5U; + strcpy (params[i].short_desc, + "Network latency setting in no. of periods"); + strcpy (params[i].long_desc, params[i].short_desc); + i++; strcpy (params[i].name, "listen-port"); params[i].character = 'l'; @@ -907,7 +917,7 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p params[i].type = JackDriverParamUInt; params[i].value.ui = 0U; strcpy (params[i].short_desc, - "sets celt encoding and number of bytes per channel"); + "sets celt encoding and number of kbits per channel"); strcpy (params[i].long_desc, params[i].short_desc); i++; @@ -937,15 +947,6 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p "Whether to use Autoconfig, or just start."); strcpy (params[i].long_desc, params[i].short_desc); - i++; - strcpy (params[i].name, "latency"); - params[i].character = 'L'; - params[i].type = JackDriverParamUInt; - params[i].value.ui = 5U; - strcpy (params[i].short_desc, - "Latency setting"); - strcpy (params[i].long_desc, params[i].short_desc); - i++; strcpy (params[i].name, "redundancy"); params[i].character = 'R'; @@ -956,8 +957,8 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p strcpy (params[i].long_desc, params[i].short_desc); i++; - strcpy (params[i].name, "no-htonl"); - params[i].character = 'H'; + strcpy (params[i].name, "native-endian"); + params[i].character = 'e'; params[i].type = JackDriverParamBool; params[i].value.ui = 0U; strcpy (params[i].short_desc, @@ -965,12 +966,21 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p strcpy (params[i].long_desc, params[i].short_desc); i++; - strcpy (params[i].name, "deadline"); + strcpy (params[i].name, "jitterval"); + params[i].character = 'J'; + params[i].type = JackDriverParamInt; + params[i].value.i = 0; + strcpy (params[i].short_desc, + "attempted jitterbuffer microseconds on master"); + strcpy (params[i].long_desc, params[i].short_desc); + + i++; + strcpy (params[i].name, "always-deadline"); params[i].character = 'D'; params[i].type = JackDriverParamBool; params[i].value.ui = 0U; strcpy (params[i].short_desc, - "always use deadline (recommended for internet connect)"); + "always use deadline"); strcpy (params[i].long_desc, params[i].short_desc); desc->params = params; @@ -997,6 +1007,7 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p unsigned int mtu = 1400; int dont_htonl_floats = 0; int always_deadline = 0; + int jitter_val = 0; const JSList * node; const jack_driver_param_t * param; @@ -1075,7 +1086,7 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p use_autoconfig = param->value.ui; break; - case 'L': + case 'n': latency = param->value.ui; break; @@ -1087,6 +1098,10 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p dont_htonl_floats = param->value.ui; break; + case 'J': + jitter_val = param->value.i; + break; + case 'D': always_deadline = param->value.ui; break; @@ -1102,7 +1117,7 @@ JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_p capture_ports_midi, playback_ports_midi, capture_ports, playback_ports, sample_rate, period_size, resample_factor, "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy, - dont_htonl_floats, always_deadline ) ); + dont_htonl_floats, always_deadline, jitter_val ) ); if ( driver->Open ( period_size, sample_rate, 1, 1, capture_ports, playback_ports, 0, "from_master_", "to_master_", 0, 0 ) == 0 ) diff --git a/common/JackNetOneDriver.h b/common/JackNetOneDriver.h index 5cad7667..b288c91f 100644 --- a/common/JackNetOneDriver.h +++ b/common/JackNetOneDriver.h @@ -55,8 +55,8 @@ render_jack_ports_to_payload (int bitdepth, JSList *playback_ports, JSList *play JackNetOneDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports, int sample_rate, int period_size, int resample_factor, - char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, - int latency, int redundancy, int dont_htonl_floats, int always_deadline ); + const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig, + int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val ); ~JackNetOneDriver(); int Open ( jack_nframes_t frames_per_cycle, jack_nframes_t rate, bool capturing, bool playing, diff --git a/common/netjack.c b/common/netjack.c index fd3635f4..eb5f36b7 100644 --- a/common/netjack.c +++ b/common/netjack.c @@ -164,12 +164,20 @@ int netjack_wait( netjack_driver_state_t *netj ) netj->deadline_goodness = (int)pkthdr->sync_state; netj->packet_data_valid = 1; + int want_deadline; + if( netj->jitter_val != 0 ) + want_deadline = netj->jitter_val; + else if( netj->latency < 4 ) + want_deadline = -netj->period_usecs/2; + else + want_deadline = (netj->period_usecs/4+10*(int)netj->period_usecs*netj->latency/100); + if( netj->deadline_goodness != MASTER_FREEWHEELS ) { - if( netj->deadline_goodness < (int)(netj->period_usecs/4+10*(int)netj->period_usecs*netj->latency/100) ) { + if( netj->deadline_goodness < want_deadline ) { netj->deadline_offset -= netj->period_usecs/100; //jack_log( "goodness: %d, Adjust deadline: --- %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 ); } - if( netj->deadline_goodness > (int)(netj->period_usecs/4+10*(int)netj->period_usecs*netj->latency/100) ) { + if( netj->deadline_goodness > want_deadline ) { netj->deadline_offset += netj->period_usecs/100; //jack_log( "goodness: %d, Adjust deadline: +++ %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 ); } @@ -503,7 +511,8 @@ netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, unsigned int latency, unsigned int redundancy, int dont_htonl_floats, - int always_deadline) + int always_deadline, + int jitter_val ) { // Fill in netj values. @@ -671,6 +680,27 @@ netjack_startup( netjack_driver_state_t *netj ) netj->capture_channels = netj->capture_channels_audio + netj->capture_channels_midi; netj->playback_channels = netj->playback_channels_audio + netj->playback_channels_midi; + if( (netj->capture_channels * netj->period_size * netj->latency * 4) > 100000000 ) { + jack_error( "autoconfig requests more than 100MB packet cache... bailing out" ); + exit(1); + } + + if( netj->playback_channels > 1000 ) { + jack_error( "autoconfig requests more than 1000 playback channels... bailing out" ); + exit(1); + } + + + if( netj->mtu < (2*sizeof( jacknet_packet_header )) ) { + jack_error( "bullshit mtu requested by autoconfig" ); + exit(1); + } + + if( netj->sample_rate == 0 ) { + jack_error( "sample_rate 0 requested by autoconfig" ); + exit(1); + } + // After possible Autoconfig: do all calculations... netj->period_usecs = (jack_time_t) floor ((((float) netj->period_size) / (float)netj->sample_rate) @@ -684,6 +714,9 @@ netjack_startup( netjack_driver_state_t *netj ) if( netj->bitdepth == CELT_MODE ) { // celt mode. // TODO: this is a hack. But i dont want to change the packet header. + netj->resample_factor = (netj->resample_factor * netj->period_size * 1024 / netj->sample_rate / 8)&(~1); + netj->resample_factor_up = (netj->resample_factor_up * netj->period_size * 1024 / netj->sample_rate / 8)&(~1); + netj->net_period_down = netj->resample_factor; netj->net_period_up = netj->resample_factor_up; } else { diff --git a/common/netjack.h b/common/netjack.h index 07e5c269..91c81be5 100644 --- a/common/netjack.h +++ b/common/netjack.h @@ -106,6 +106,7 @@ struct _netjack_driver_state { unsigned int use_autoconfig; unsigned int resample_factor; unsigned int resample_factor_up; + int jitter_val; }; int netjack_wait( netjack_driver_state_t *netj ); @@ -133,7 +134,8 @@ netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, unsigned int latency, unsigned int redundancy, int dont_htonl_floats, - int always_deadline); + int always_deadline, + int jitter_val ); void netjack_release( netjack_driver_state_t *netj ); int netjack_startup( netjack_driver_state_t *netj ); diff --git a/common/netjack_packet.c b/common/netjack_packet.c index 49e31fe4..4edbb2a3 100644 --- a/common/netjack_packet.c +++ b/common/netjack_packet.c @@ -28,9 +28,6 @@ //#include "config.h" -#define _XOPEN_SOURCE 600 -#define _BSD_SOURCE - #ifdef __APPLE__ #define _DARWIN_C_SOURCE #endif @@ -44,7 +41,6 @@ #include #include #include -#include #include #include @@ -369,13 +365,10 @@ int netjack_poll_deadline (int sockfd, jack_time_t deadline) { struct pollfd fds; - int i, poll_err = 0; - sigset_t sigmask; - struct sigaction action; + int poll_err = 0; #if HAVE_PPOLL struct timespec timeout_spec = { 0, 0 }; #else - sigset_t rsigmask; int timeout; #endif @@ -391,35 +384,17 @@ netjack_poll_deadline (int sockfd, jack_time_t deadline) #if HAVE_PPOLL timeout_spec.tv_nsec = (deadline - now) * 1000; #else - timeout = lrintf( (float)(deadline - now) / 1000.0 ); + timeout = (deadline - now + 500) / 1000; #endif - sigemptyset(&sigmask); - sigaddset(&sigmask, SIGHUP); - sigaddset(&sigmask, SIGINT); - sigaddset(&sigmask, SIGQUIT); - sigaddset(&sigmask, SIGPIPE); - sigaddset(&sigmask, SIGTERM); - sigaddset(&sigmask, SIGUSR1); - sigaddset(&sigmask, SIGUSR2); - - action.sa_handler = SIG_DFL; - action.sa_mask = sigmask; - action.sa_flags = SA_RESTART; - - for (i = 1; i < NSIG; i++) - if (sigismember (&sigmask, i)) - sigaction (i, &action, 0); fds.fd = sockfd; fds.events = POLLIN; #if HAVE_PPOLL - poll_err = ppoll (&fds, 1, &timeout_spec, &sigmask); + poll_err = ppoll (&fds, 1, &timeout_spec, NULL); #else - sigprocmask (SIG_UNBLOCK, &sigmask, &rsigmask); poll_err = poll (&fds, 1, timeout); - sigprocmask (SIG_SETMASK, &rsigmask, NULL); #endif if (poll_err == -1) diff --git a/example-clients/netsource.c b/example-clients/netsource.c index fd3387c1..ed4c1af0 100644 --- a/example-clients/netsource.c +++ b/example-clients/netsource.c @@ -32,6 +32,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include +#include #ifdef WIN32 #include @@ -45,9 +46,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. /* These two required by FreeBSD. */ #include -#if HAVE_ALLOCA_H -#include -#endif #include @@ -90,6 +88,8 @@ int state_netxruns = 0; int state_currentframe = 0; int state_recv_packet_queue_time = 0; +int quit=0; + int outsockfd; int insockfd; @@ -266,7 +266,7 @@ process (jack_nframes_t nframes, void *arg) jack_time_t packet_recv_timestamp; if( bitdepth == 1000 ) - net_period = factor; + net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ; else net_period = (float) nframes / (float) factor; @@ -490,9 +490,6 @@ jack_shutdown (void *arg) void init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t port) { -printf( "still here... \n" ); -fflush( stdout ); - name->sin_family = AF_INET ; name->sin_port = htons (port); if (hostname) @@ -516,26 +513,34 @@ fflush( stdout ); void printUsage () { -fprintf (stderr, "usage: jack_netsource -h [options]\n" +fprintf (stderr, "usage: jack_netsource [options]\n" "\n" - " -n - Reports a different name to jack\n" - " -s - The name of the local jack server\n" - " -h - Host name of the slave JACK\n" - " -p - UDP port used by the slave JACK\n" - " -P - Number of audio playback channels\n" - " -C - Number of audio capture channels\n" - " -o - Number of midi playback channels\n" - " -i - Number of midi capture channels\n" - " -l - Network latency in number of NetJack frames\n" - " -r - Local UDP port to use\n" - " -f - Downsample data in the wire by this factor\n" + " -h this help text\n" + " -H - Host name of the slave JACK\n" + " -o - Number of audio playback channels\n" + " -i - Number of audio capture channels\n" + " -O - Number of midi playback channels\n" + " -I - Number of midi capture channels\n" + " -n - Network latency in JACK periods\n" + " -p - UDP port that the slave is listening on\n" + " -r - UDP port that we are listening on\n" + " -B - reply port, for use in NAT environments\n" " -b - Set transport to use 16bit or 8bit\n" + " -c - Use CELT encoding with kbits per channel\n" " -m - Assume this mtu for the link\n" - " -c - Use Celt and encode per channel and packet.\n" - " -R - Send out packets N times.\n" + " -R - Redundancy: send out packets N times.\n" + " -e - skip host-to-network endianness conversion\n" + " -N - Reports a different name to jack\n" + " -s - The name of the local jack server\n" "\n"); } +void +sigterm_handler( int signal ) +{ + quit = 1; +} + int main (int argc, char *argv[]) { @@ -565,83 +570,88 @@ main (int argc, char *argv[]) client_name = (char *) malloc (sizeof (char) * 10); peer_ip = (char *) malloc (sizeof (char) * 10); - sprintf(client_name, "netsource"); + sprintf(client_name, "netjack"); sprintf(peer_ip, "localhost"); - while ((c = getopt (argc, argv, ":H:R:n:s:h:p:C:P:i:o:l:r:f:b:m:c:B:")) != -1) + while ((c = getopt (argc, argv, ":h:H:o:i:O:I:n:p:r:B:b:c:m:R:e:N:s:")) != -1) { switch (c) { - case 'n': - free(client_name); - client_name = (char *) malloc (sizeof (char) * strlen (optarg)+1); - strcpy (client_name, optarg); - break; - case 's': - server_name = (char *) malloc (sizeof (char) * strlen (optarg)+1); - strcpy (server_name, optarg); - options |= JackServerName; - break; case 'h': - free(peer_ip); - peer_ip = (char *) malloc (sizeof (char) * strlen (optarg)+1); - strcpy (peer_ip, optarg); - break; - case 'p': - peer_port = atoi (optarg); - break; - case 'P': - playback_channels_audio = atoi (optarg); - break; - case 'C': - capture_channels_audio = atoi (optarg); - break; + printUsage(); + exit (0); + break; + case 'H': + free(peer_ip); + peer_ip = (char *) malloc (sizeof (char) * strlen (optarg)+1); + strcpy (peer_ip, optarg); + break; case 'o': - playback_channels_midi = atoi (optarg); - break; + playback_channels_audio = atoi (optarg); + break; case 'i': - capture_channels_midi = atoi (optarg); - break; - case 'l': - latency = atoi (optarg); - break; + capture_channels_audio = atoi (optarg); + break; + case 'O': + playback_channels_midi = atoi (optarg); + break; + case 'I': + capture_channels_midi = atoi (optarg); + break; + case 'n': + latency = atoi (optarg); + break; + case 'p': + peer_port = atoi (optarg); + break; case 'r': - reply_port = atoi (optarg); - break; + reply_port = atoi (optarg); + break; case 'B': - bind_port = atoi (optarg); - break; + bind_port = atoi (optarg); + break; case 'f': - factor = atoi (optarg); - break; + factor = atoi (optarg); + printf("This feature is deprecated and will be removed in future netjack versions. CELT offers a superiour way to conserve bandwidth"); + break; case 'b': - bitdepth = atoi (optarg); - break; + bitdepth = atoi (optarg); + break; case 'c': #if HAVE_CELT - bitdepth = 1000; - factor = atoi (optarg); + bitdepth = 1000; + factor = atoi (optarg); #else - printf( "not built with celt supprt\n" ); - exit(10); + printf( "not built with celt supprt\n" ); + exit(10); #endif - break; + break; case 'm': - mtu = atoi (optarg); - break; + mtu = atoi (optarg); + break; case 'R': - redundancy = atoi (optarg); - break; - case 'H': - dont_htonl_floats = atoi (optarg); - break; + redundancy = atoi (optarg); + break; + case 'e': + dont_htonl_floats = 1; + break; + case 'N': + free(client_name); + client_name = (char *) malloc (sizeof (char) * strlen (optarg)+1); + strcpy (client_name, optarg); + break; + case 's': + server_name = (char *) malloc (sizeof (char) * strlen (optarg)+1); + strcpy (server_name, optarg); + options |= JackServerName; + break; case ':': - fprintf (stderr, "Option -%c requires an operand\n", optopt); - errflg++; - break; + fprintf (stderr, "Option -%c requires an operand\n", optopt); + errflg++; + break; case '?': - fprintf (stderr, "Unrecognized option: -%c\n", optopt); - errflg++; + fprintf (stderr, "Unrecognized option: -%c\n", optopt); + errflg++; } } if (errflg) @@ -694,7 +704,7 @@ main (int argc, char *argv[]) alloc_ports (capture_channels_audio, playback_channels_audio, capture_channels_midi, playback_channels_midi); if( bitdepth == 1000 ) - net_period = factor; + net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ; else net_period = ceilf((float) jack_get_buffer_size (client) / (float) factor); @@ -710,11 +720,14 @@ main (int argc, char *argv[]) /* Now sleep forever... and evaluate the state_ vars */ + signal( SIGTERM, sigterm_handler ); + signal( SIGINT, sigterm_handler ); + statecopy_connected = 2; // make it report unconnected on start. statecopy_latency = state_latency; statecopy_netxruns = state_netxruns; - while (1) + while ( !quit ) { #ifdef WIN32 Sleep (1000); @@ -761,8 +774,7 @@ main (int argc, char *argv[]) } } - /* Never reached. Well we will be a GtkApp someday... */ - packet_cache_free (global_packcache); jack_client_close (client); + packet_cache_free (global_packcache); exit (0); }