diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index 0ee6c8c6..5cbf6c06 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -497,8 +497,6 @@ namespace Jack EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params ) { - jack_log ( "driver_initialize : net" ); - if ( SocketAPIInit() < 0 ) { jack_error ( "Can't init Socket API, exiting..." ); @@ -564,8 +562,6 @@ namespace Jack } } - jack_info ( "mode : %c", network_mode ); - 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, network_mode ) ); diff --git a/common/JackNetInterface.cpp b/common/JackNetInterface.cpp index d63b497c..4791758c 100644 --- a/common/JackNetInterface.cpp +++ b/common/JackNetInterface.cpp @@ -58,8 +58,71 @@ namespace Jack delete fNetMidiPlaybackBuffer; } + jack_nframes_t JackNetInterface::SetFramesPerPacket() + { + if ( !fParams.fSendAudioChannels && !fParams.fReturnAudioChannels ) + return ( fParams.fFramesPerPacket = fParams.fPeriodSize ); + jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log ( ( fParams.fMtu - sizeof ( packet_header_t ) ) + / ( max ( fParams.fReturnAudioChannels, fParams.fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2 ) ) ); + ( period > fParams.fPeriodSize ) ? fParams.fFramesPerPacket = fParams.fPeriodSize : fParams.fFramesPerPacket = period; + return fParams.fFramesPerPacket; + } + + int JackNetInterface::SetNetBufferSize() + { + float audio_size, midi_size; + int bufsize, res = 0; + //audio + audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket ); + //midi + midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) * + fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) ); + //size of sync + audio + midi + bufsize = 2 * ( fParams.fMtu + ( int ) audio_size + ( int ) midi_size ); + + //tx buffer + if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR ) + res = SOCKET_ERROR; + + //rx buffer + if ( fSocket.SetOption ( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR ) + res = SOCKET_ERROR; + + return res; + } + + int JackNetInterface::GetNMidiPckt() + { + //even if there is no midi data, jack need an empty buffer to know there is no event to read + //99% of the cases : all data in one packet + if ( fTxHeader.fMidiDataSize <= ( fParams.fMtu - sizeof ( packet_header_t ) ) ) + return 1; + //else, get the number of needed packets (simply slice the biiig buffer) + int npckt = fTxHeader.fMidiDataSize / ( fParams.fMtu - sizeof ( packet_header_t ) ); + if ( fTxHeader.fMidiDataSize % ( fParams.fMtu - sizeof ( packet_header_t ) ) ) + return ++npckt; + return npckt; + } + + bool JackNetInterface::IsNextPacket() + { + packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); + //ignore first cycle + if ( fRxHeader.fCycle <= 1 ) + return true; + //same PcktID (cycle), next SubPcktID (subcycle) + if ( ( fRxHeader.fSubCycle < ( fNSubProcess - 1 ) ) && ( rx_head->fCycle == fRxHeader.fCycle ) && ( rx_head->fSubCycle == ( fRxHeader.fSubCycle + 1 ) ) ) + return true; + //next PcktID (cycle), SubPcktID reset to 1 (first subcyle) + if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) ) + return true; + //else, next is'nt next, return false + return false; + } + void JackNetInterface::SetParams() { + SetFramesPerPacket(); fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket; //TX header init @@ -99,7 +162,6 @@ namespace Jack session_params_t params; uint attempt = 0; int rx_bytes = 0; - int rx_bufsize = 0; //socket if ( fSocket.NewSocket() == SOCKET_ERROR ) @@ -140,23 +202,37 @@ namespace Jack } //set the new timeout for the socket - if ( SetRxTimeout ( &fSocket, &fParams ) == SOCKET_ERROR ) + if ( SetRxTimeout() == SOCKET_ERROR ) { jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) ); return false; } //set the new rx buffer size - rx_bufsize = GetNetBufferSize ( &fParams ); - if ( fSocket.SetOption ( SOL_SOCKET, SO_RCVBUF, &rx_bufsize, sizeof ( rx_bufsize ) ) == SOCKET_ERROR ) + if ( SetNetBufferSize() == SOCKET_ERROR ) { - jack_error ( "Can't set rx buffer size : %s", StrError ( NET_ERROR_CODE ) ); + jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) ); return false; } return true; } + int JackNetMasterInterface::SetRxTimeout() + { + float time = 0; + //slow mode, very short timeout on recv + if ( fParams.fNetworkMode == 's' ) + time = 1000000.f * ( static_cast ( fParams.fFramesPerPacket ) / static_cast ( fParams.fSampleRate ) ); + //normal mode, short timeout on recv + else if ( fParams.fNetworkMode == 'n' ) + time = 2000000.f * ( static_cast ( fParams.fFramesPerPacket ) / static_cast ( fParams.fSampleRate ) ); + //fast mode, wait for the entire cycle duration + else if ( fParams.fNetworkMode == 'f' ) + time = 750000.f * ( static_cast ( fParams.fPeriodSize ) / static_cast ( fParams.fSampleRate ) ); + return fSocket.SetTimeOut ( static_cast ( time ) ); + } + void JackNetMasterInterface::SetParams() { jack_log ( "JackNetMasterInterface::SetParams" ); @@ -256,7 +332,7 @@ namespace Jack //set global header fields and get the number of midi packets fTxHeader.fDataType = 'm'; fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts(); - fTxHeader.fNMidiPckt = GetNMidiPckt ( &fParams, fTxHeader.fMidiDataSize ); + fTxHeader.fNMidiPckt = GetNMidiPckt(); for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ ) { //fill the packet header fields @@ -351,50 +427,46 @@ namespace Jack uint midi_recvd_pckt = 0; packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); - if ( fParams.fReturnMidiChannels || fParams.fReturnAudioChannels ) + while ( rx_head->fIsLastPckt != 'y' ) { - do + //how much data is queued on the rx buffer ? + rx_bytes = Recv ( fParams.fMtu, MSG_PEEK ); + if ( rx_bytes == SOCKET_ERROR ) + return rx_bytes; + //if no data, + if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) ) { - //how much data is queued on the rx buffer ? - rx_bytes = Recv ( fParams.fMtu, MSG_PEEK ); - if ( rx_bytes == SOCKET_ERROR ) - return rx_bytes; - //if no data, - if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) ) - { - jack_error ( "No data from %s...", fParams.fName ); - jumpcnt = 0; - } - //else if data is valid, - if ( rx_bytes && ( rx_head->fDataStream == 'r' ) && ( rx_head->fID == fParams.fID ) ) + jack_error ( "No data from %s...", fParams.fName ); + jumpcnt = 0; + } + //else if data is valid, + if ( rx_bytes && ( rx_head->fDataStream == 'r' ) && ( rx_head->fID == fParams.fID ) ) + { + //read data + switch ( rx_head->fDataType ) { - //read data - switch ( rx_head->fDataType ) - { - case 'm': //midi - Recv ( rx_head->fPacketSize, 0 ); - fRxHeader.fCycle = rx_head->fCycle; - fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) ); - if ( ++midi_recvd_pckt == rx_head->fNMidiPckt ) - fNetMidiPlaybackBuffer->RenderToJackPorts(); - jumpcnt = 0; - break; - case 'a': //audio - Recv ( rx_head->fPacketSize, 0 ); - if ( !IsNextPacket ( &fRxHeader, rx_head, fNSubProcess ) ) - jack_error ( "Packet(s) missing from '%s'...", fParams.fName ); - fRxHeader.fCycle = rx_head->fCycle; - fRxHeader.fSubCycle = rx_head->fSubCycle; - fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle ); - jumpcnt = 0; - break; - case 's': //sync - if ( rx_head->fCycle == fTxHeader.fCycle ) - return 0; - } + case 'm': //midi + Recv ( rx_head->fPacketSize, 0 ); + fRxHeader.fCycle = rx_head->fCycle; + fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) ); + if ( ++midi_recvd_pckt == rx_head->fNMidiPckt ) + fNetMidiPlaybackBuffer->RenderToJackPorts(); + jumpcnt = 0; + break; + case 'a': //audio + Recv ( rx_head->fPacketSize, 0 ); + if ( !IsNextPacket() ) + jack_error ( "Packet(s) missing from '%s'...", fParams.fName ); + fRxHeader.fCycle = rx_head->fCycle; + fRxHeader.fSubCycle = rx_head->fSubCycle; + fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle ); + jumpcnt = 0; + break; + case 's': //sync + if ( rx_head->fCycle == fTxHeader.fCycle ) + return 0; } } - while ( rx_head->fIsLastPckt != 'y' ); } return rx_bytes; } @@ -462,6 +534,10 @@ namespace Jack if ( fSocket.SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof ( loop ) ) == SOCKET_ERROR ) jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) ); + //set the new rx buffer size + if ( SetNetBufferSize() == SOCKET_ERROR ) + jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) ); + //send 'AVAILABLE' until 'SLAVE_SETUP' received jack_info ( "Waiting for a master..." ); do @@ -590,41 +666,36 @@ namespace Jack int rx_bytes = 0; packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); - //audio, midi or sync if driver is late - if ( fParams.fSendMidiChannels || fParams.fSendAudioChannels ) + while ( rx_head->fIsLastPckt != 'y' ); { - do + rx_bytes = Recv ( fParams.fMtu, MSG_PEEK ); + //error here, problem with recv, just skip the cycle (return -1) + if ( rx_bytes == SOCKET_ERROR ) + return rx_bytes; + if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) ) { - rx_bytes = Recv ( fParams.fMtu, MSG_PEEK ); - //error here, problem with recv, just skip the cycle (return -1) - if ( rx_bytes == SOCKET_ERROR ) - return rx_bytes; - if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) ) + switch ( rx_head->fDataType ) { - switch ( rx_head->fDataType ) - { - case 'm': //midi - rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - fRxHeader.fCycle = rx_head->fCycle; - fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) ); - if ( ++recvd_midi_pckt == rx_head->fNMidiPckt ) - fNetMidiCaptureBuffer->RenderToJackPorts(); - break; - case 'a': //audio - rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - if ( !IsNextPacket ( &fRxHeader, rx_head, fNSubProcess ) ) - jack_error ( "Packet(s) missing..." ); - fRxHeader.fCycle = rx_head->fCycle; - fRxHeader.fSubCycle = rx_head->fSubCycle; - fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle ); - break; - case 's': //sync - jack_info ( "NetSlave : overloaded, skipping receive." ); - return 0; - } + case 'm': //midi + rx_bytes = Recv ( rx_head->fPacketSize, 0 ); + fRxHeader.fCycle = rx_head->fCycle; + fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) ); + if ( ++recvd_midi_pckt == rx_head->fNMidiPckt ) + fNetMidiCaptureBuffer->RenderToJackPorts(); + break; + case 'a': //audio + rx_bytes = Recv ( rx_head->fPacketSize, 0 ); + if ( !IsNextPacket() ) + jack_error ( "Packet(s) missing..." ); + fRxHeader.fCycle = rx_head->fCycle; + fRxHeader.fSubCycle = rx_head->fSubCycle; + fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle ); + break; + case 's': //sync + jack_info ( "NetSlave : overloaded, skipping receive." ); + return 0; } } - while ( rx_head->fIsLastPckt != 'y' ); } fRxHeader.fCycle = rx_head->fCycle; return 0; @@ -654,7 +725,7 @@ namespace Jack { fTxHeader.fDataType = 'm'; fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts(); - fTxHeader.fNMidiPckt = GetNMidiPckt ( &fParams, fTxHeader.fMidiDataSize ); + fTxHeader.fNMidiPckt = GetNMidiPckt(); for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ ) { fTxHeader.fSubCycle = subproc; @@ -687,4 +758,3 @@ namespace Jack return 0; } } - diff --git a/common/JackNetInterface.h b/common/JackNetInterface.h index 040d430c..2c12a9ff 100644 --- a/common/JackNetInterface.h +++ b/common/JackNetInterface.h @@ -58,9 +58,14 @@ namespace Jack int fAudioTxLen; int fPayloadSize; - virtual void SetParams(); + //utility methods + jack_nframes_t SetFramesPerPacket(); + int SetNetBufferSize(); + int GetNMidiPckt(); + bool IsNextPacket(); //virtual methods : depends on the sub class master/slave + virtual void SetParams(); virtual bool Init() = 0; virtual int SyncRecv() = 0; @@ -81,63 +86,64 @@ namespace Jack }; /** - \Brief This class describes the Net Interface for slaves (NetDriver and NetAdapter) + \Brief This class describes the Net Interface for masters (NetMaster) */ - class EXPORT JackNetSlaveInterface : public JackNetInterface + class EXPORT JackNetMasterInterface : public JackNetInterface { protected: + bool fRunning; + bool Init(); - net_status_t GetNetMaster(); - net_status_t SendMasterStartSync(); + int SetRxTimeout(); void SetParams(); + void Exit(); int SyncRecv(); int SyncSend(); int DataRecv(); int DataSend(); - int Recv ( size_t size, int flags ); int Send ( size_t size, int flags ); + int Recv ( size_t size, int flags ); public: - JackNetSlaveInterface() + JackNetMasterInterface() : fRunning ( false ) {} - JackNetSlaveInterface ( const char* ip, int port ) : JackNetInterface ( ip, port ) + JackNetMasterInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) + : JackNetInterface ( params, socket, multicast_ip ) + {} + ~JackNetMasterInterface() {} - ~JackNetSlaveInterface() - { - SocketAPIEnd(); - } }; /** - \Brief This class describes the Net Interface for masters (NetMaster) + \Brief This class describes the Net Interface for slaves (NetDriver and NetAdapter) */ - class EXPORT JackNetMasterInterface : public JackNetInterface + class EXPORT JackNetSlaveInterface : public JackNetInterface { protected: - bool fRunning; - bool Init(); + net_status_t GetNetMaster(); + net_status_t SendMasterStartSync(); void SetParams(); - void Exit(); int SyncRecv(); int SyncSend(); int DataRecv(); int DataSend(); - int Send ( size_t size, int flags ); int Recv ( size_t size, int flags ); + int Send ( size_t size, int flags ); public: - JackNetMasterInterface() : fRunning ( false ) - {} - JackNetMasterInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) - : JackNetInterface ( params, socket, multicast_ip ) + JackNetSlaveInterface() {} - ~JackNetMasterInterface() + JackNetSlaveInterface ( const char* ip, int port ) : JackNetInterface ( ip, port ) {} + ~JackNetSlaveInterface() + { + SocketAPIEnd(); + } }; } diff --git a/common/JackNetManager.cpp b/common/JackNetManager.cpp index 374ea47c..573dcf20 100644 --- a/common/JackNetManager.cpp +++ b/common/JackNetManager.cpp @@ -69,15 +69,15 @@ namespace Jack plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" ); switch ( fParams.fNetworkMode ) { - case 's' : - plot_name += string ( "_slow" ); - break; - case 'n' : - plot_name += string ( "_normal" ); - break; - case 'f' : - plot_name += string ( "_fast" ); - break; + case 's' : + plot_name += string ( "_slow" ); + break; + case 'n' : + plot_name += string ( "_normal" ); + break; + case 'f' : + plot_name += string ( "_fast" ); + break; } fNetTimeMon = new JackGnuPlotMonitor ( 128, 4, plot_name ); string net_time_mon_fields[] = @@ -482,7 +482,6 @@ namespace Jack params.fSampleRate = jack_get_sample_rate ( fManagerClient ); params.fPeriodSize = jack_get_buffer_size ( fManagerClient ); params.fBitdepth = 0; - SetFramesPerPacket ( ¶ms ); SetSlaveName ( params ); //create a new master and add it to the list diff --git a/common/JackNetTool.cpp b/common/JackNetTool.cpp index c86f41ec..95b32ada 100644 --- a/common/JackNetTool.cpp +++ b/common/JackNetTool.cpp @@ -205,15 +205,15 @@ namespace Jack char mode[8]; switch ( params->fNetworkMode ) { - case 's' : - strcpy ( mode, "slow" ); - break; - case 'n' : - strcpy ( mode, "normal" ); - break; - case 'f' : - strcpy ( mode, "fast" ); - break; + case 's' : + strcpy ( mode, "slow" ); + break; + case 'n' : + strcpy ( mode, "normal" ); + break; + case 'f' : + strcpy ( mode, "fast" ); + break; } jack_info ( "**************** Network parameters ****************" ); jack_info ( "Name : %s", params->fName ); @@ -349,67 +349,4 @@ namespace Jack #endif return 0; } - - EXPORT jack_nframes_t SetFramesPerPacket ( session_params_t* params ) - { - if ( !params->fSendAudioChannels && !params->fReturnAudioChannels ) - return ( params->fFramesPerPacket = params->fPeriodSize ); - jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log ( ( params->fMtu - sizeof ( packet_header_t ) ) - / ( max ( params->fReturnAudioChannels, params->fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2 ) ) ); - ( period > params->fPeriodSize ) ? params->fFramesPerPacket = params->fPeriodSize : params->fFramesPerPacket = period; - return params->fFramesPerPacket; - } - - EXPORT int GetNetBufferSize ( session_params_t* params ) - { - //audio - float audio_size = params->fMtu * ( params->fPeriodSize / params->fFramesPerPacket ); - //midi - float midi_size = params->fMtu * ( max ( params->fSendMidiChannels, params->fReturnMidiChannels ) * - params->fPeriodSize * sizeof ( sample_t ) / ( params->fMtu - sizeof ( packet_header_t ) ) ); - //return : sizes of sync + audio + midi - return ( params->fMtu + ( int ) audio_size + ( int ) midi_size ); - } - - EXPORT int GetNMidiPckt ( session_params_t* params, size_t data_size ) - { - //even if there is no midi data, jack need an empty buffer to know there is no event to read - //99% of the cases : all data in one packet - if ( data_size <= ( params->fMtu - sizeof ( packet_header_t ) ) ) - return 1; - //else, get the number of needed packets (simply slice the biiig buffer) - int npckt = data_size / ( params->fMtu - sizeof ( packet_header_t ) ); - if ( data_size % ( params->fMtu - sizeof ( packet_header_t ) ) ) - return ++npckt; - return npckt; - } - - EXPORT int SetRxTimeout ( JackNetSocket* socket, session_params_t* params ) - { - float time; - //fast mode, wait for the entire cycle duration - if ( params->fNetworkMode == 'f' ) - time = 900000.f * ( static_cast ( params->fPeriodSize ) / static_cast ( params->fSampleRate ) ); - //normal or slow mode, short timeout on recv - else - time = 4000000.f * ( static_cast ( params->fFramesPerPacket ) / static_cast ( params->fSampleRate ) ); - return socket->SetTimeOut ( static_cast ( time ) ); - } - -// Packet ******************************************************************************************************* - - EXPORT bool IsNextPacket ( packet_header_t* previous, packet_header_t* next, uint subcycles ) - { - //ignore first cycle - if ( previous->fCycle <= 1 ) - return true; - //same PcktID (cycle), next SubPcktID (subcycle) - if ( ( previous->fSubCycle < ( subcycles - 1 ) ) && ( next->fCycle == previous->fCycle ) && ( next->fSubCycle == ( previous->fSubCycle + 1 ) ) ) - return true; - //next PcktID (cycle), SubPcktID reset to 1 (first subcyle) - if ( ( next->fCycle == ( previous->fCycle + 1 ) ) && ( previous->fSubCycle == ( subcycles - 1 ) ) && ( next->fSubCycle == 0 ) ) - return true; - //else, next is'nt next, return false - return false; - } } diff --git a/common/JackNetTool.h b/common/JackNetTool.h index 4d5dd4b6..d5d5ab07 100644 --- a/common/JackNetTool.h +++ b/common/JackNetTool.h @@ -260,14 +260,4 @@ namespace Jack EXPORT sync_packet_type_t GetPacketType ( session_params_t* params ); //set the packet type in a session parameters EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type ); - //step of network initialization - EXPORT jack_nframes_t SetFramesPerPacket ( session_params_t* params ); - //step of network initialization - EXPORT int GetNetBufferSize ( session_params_t* params ); - //get the midi packet number for a given cycle - EXPORT int GetNMidiPckt ( session_params_t* params, size_t data_size ); - //set the recv timeout on a socket - EXPORT int SetRxTimeout ( JackNetSocket* socket, session_params_t* params ); - //check if 'next' packet is really the next after 'previous' - EXPORT bool IsNextPacket ( packet_header_t* previous, packet_header_t* next, uint subcycles ); }