diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index e226bd64..328c5948 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -53,7 +53,8 @@ namespace Jack #endif JackNetDriver::JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, - const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, const char* net_name, uint transport_sync ) + const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, + const char* net_name, uint transport_sync, char network_master_mode, char network_slave_mode ) : JackAudioDriver ( name, alias, engine, table ), fSocket ( ip, port ) { jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip, port ); @@ -66,6 +67,8 @@ namespace Jack strcpy ( fParams.fName, net_name ); fSocket.GetName ( fParams.fSlaveNetName ); fParams.fTransportSync = transport_sync; + fParams.fNetworkMasterMode = network_master_mode; + fParams.fNetworkSlaveMode = network_slave_mode; #ifdef JACK_MONITOR fMonitor = NULL; fMeasure = NULL; @@ -523,6 +526,10 @@ namespace Jack int JackNetDriver::Read() { + //slow mode and first cycle : skip read + if ( ( fParams.fNetworkSlaveMode == 's' ) && ( fRxHeader.fCycle == 0 ) ) + return 0; + int rx_bytes; uint recvd_midi_pckt = 0; packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); @@ -690,7 +697,7 @@ namespace Jack { jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) ); strcpy ( desc->name, "net" ); - desc->nparams = 9; + desc->nparams = 11; desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); int i = 0; @@ -765,6 +772,24 @@ namespace Jack strcpy ( desc->params[i].short_desc, "Sync transport with master's" ); strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); + i++; + strcpy ( desc->params[i].name, "network_master_mode" ); + desc->params[i].character = 'm'; + desc->params[i].type = JackDriverParamChar; + desc->params[i].value.ui = 's'; + strcpy ( desc->params[i].short_desc, "Slow network add 1 cycle latency" ); + strcpy ( desc->params[i].long_desc, "'s' for slow, 'f' for fast, default is slow.\ + Fast network will make the master waiting for the current cycle return data." ); + + i++; + strcpy ( desc->params[i].name, "network_slave_mode" ); + desc->params[i].character = 's'; + desc->params[i].type = JackDriverParamChar; + desc->params[i].value.ui = 's'; + strcpy ( desc->params[i].short_desc, "Slow network add 1 cycle latency" ); + strcpy ( desc->params[i].long_desc, "'s' for slow, 'f' for fast, default is slow.\ + Fast network will make the slave waiting for the first cycle data." ); + return desc; } @@ -788,6 +813,8 @@ namespace Jack int midi_input_ports = 0; int midi_output_ports = 0; bool monitor = false; + char network_master_mode = 's'; + char network_slave_mode = 's'; const JSList* node; const jack_driver_param_t* param; @@ -819,14 +846,44 @@ namespace Jack break; case 'n' : strncpy ( name, param->value.str, JACK_CLIENT_NAME_SIZE ); + break; case 't' : transport_sync = param->value.ui; + break; + case 'm' : + switch ( param->value.ui ) + { + case 's' : + network_master_mode = 's'; + break; + case 'f' : + network_master_mode = 'f'; + break; + default : + network_master_mode = 's'; + break; + } + break; + case 's' : + switch ( param->value.ui ) + { + case 's' : + network_slave_mode = 's'; + break; + case 'f' : + network_slave_mode = 'f'; + break; + default : + network_slave_mode = 's'; + break; + } + break; } } Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver ( new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, mtu, - midi_input_ports, midi_output_ports, name, transport_sync ) ); + midi_input_ports, midi_output_ports, name, transport_sync, network_master_mode, network_slave_mode ) ); if ( driver->Open ( period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports, monitor, "from_master_", "to_master_", 0, 0 ) == 0 ) return driver; diff --git a/common/JackNetDriver.h b/common/JackNetDriver.h index de00eed2..9c7e2a05 100644 --- a/common/JackNetDriver.h +++ b/common/JackNetDriver.h @@ -99,7 +99,8 @@ namespace Jack public: JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, - const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, const char* master_name, uint transport_sync ); + const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports, + const char* master_name, uint transport_sync, char network_master_mode, char network_slave_mode ); ~JackNetDriver(); int Open ( jack_nframes_t frames_per_cycle, jack_nframes_t rate, bool capturing, bool playing, diff --git a/common/JackNetManager.cpp b/common/JackNetManager.cpp index 238a4811..72bdb8d1 100644 --- a/common/JackNetManager.cpp +++ b/common/JackNetManager.cpp @@ -477,8 +477,9 @@ namespace Jack //receive -------------------------------------------------------------------------------------------------------------------- //sync rx_bytes == Recv ( sizeof ( packet_header_t ), 0 ); - //if there is no data to be read, there could be stg wron with the slave, so just finish the cycle while returning 0 to start a new one - //if it's a network error, just return SOCKET_ERROR + //wait here for sync, switch network mode : + // -fast : this recv will wait for a long time (90% of cycle duration) + // -slow : just wait for a short time, then return, the data will be available at the next cycle if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) ) return rx_bytes; diff --git a/common/JackNetTool.cpp b/common/JackNetTool.cpp index c456b338..0135cf09 100644 --- a/common/JackNetTool.cpp +++ b/common/JackNetTool.cpp @@ -359,7 +359,13 @@ namespace Jack EXPORT int SetRxTimeout ( JackNetSocket* socket, session_params_t* params ) { - float time = 1250000.f * ( static_cast ( params->fFramesPerPacket ) / static_cast ( params->fSampleRate ) ); + float time; + //fast mode, wait for the entire cycle duration + if ( params->fNetworkMasterMode == 'f' ) + time = 900000.f * ( static_cast ( params->fPeriodSize ) / static_cast ( params->fSampleRate ) ); + //slow mode, just try recv during a subcycle audio packet + else + time = 1250000.f * ( static_cast ( params->fFramesPerPacket ) / static_cast ( params->fSampleRate ) ); int usec = ( int ) time; return socket->SetTimeOut ( usec ); } diff --git a/common/JackNetTool.h b/common/JackNetTool.h index 851be48b..298fd903 100644 --- a/common/JackNetTool.h +++ b/common/JackNetTool.h @@ -73,6 +73,8 @@ We have : uint32_t fFramesPerPacket; //complete frames per packet uint32_t fBitdepth; //samples bitdepth (unused) uint32_t fSlaveSyncMode; //is the slave in sync mode ? + char fNetworkMasterMode; //fast or slow mode + char fNetworkSlaveMode; //fast or slow mode }; //net status ********************************************************************************** diff --git a/windows/JackNetWinSocket.cpp b/windows/JackNetWinSocket.cpp index 08bf71a6..55c1ce78 100644 --- a/windows/JackNetWinSocket.cpp +++ b/windows/JackNetWinSocket.cpp @@ -266,8 +266,8 @@ namespace Jack int JackNetWinSocket::SetTimeOut ( int& usec ) { //negative timeout, or exceeding 10s, return - if ( ( msec < 0 ) || ( usec > 10000000 ) ) - return -1; + if ( ( usec < 0 ) || ( usec > 10000000 ) ) + return SOCKET_ERROR; int time = usec / 1000; return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &time, sizeof ( time ) ); } diff --git a/windows/jack_netadapter.cbp b/windows/jack_netadapter.cbp index b78e1c92..0ce92c5c 100644 --- a/windows/jack_netadapter.cbp +++ b/windows/jack_netadapter.cbp @@ -17,6 +17,7 @@ + @@ -47,6 +48,7 @@ + @@ -77,6 +79,7 @@ + @@ -101,6 +104,7 @@ +