git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2760 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
| @@ -54,7 +54,7 @@ namespace Jack | |||
| 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, char network_master_mode ) | |||
| const char* net_name, uint transport_sync, char network_mode ) | |||
| : JackAudioDriver ( name, alias, engine, table ), fSocket ( ip, port ) | |||
| { | |||
| jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip, port ); | |||
| @@ -67,7 +67,7 @@ namespace Jack | |||
| strcpy ( fParams.fName, net_name ); | |||
| fSocket.GetName ( fParams.fSlaveNetName ); | |||
| fParams.fTransportSync = transport_sync; | |||
| fParams.fNetworkMasterMode = network_master_mode; | |||
| fParams.fNetworkMode = network_mode; | |||
| #ifdef JACK_MONITOR | |||
| fMonitor = NULL; | |||
| fMeasure = NULL; | |||
| @@ -348,7 +348,7 @@ namespace Jack | |||
| string plot_name = string ( fParams.fName ); | |||
| plot_name += string ( "_slave" ); | |||
| plot_name += ( fEngineControl->fSyncMode ) ? string ( "_sync" ) : string ( "_async" ); | |||
| plot_name += ( fParams.fNetworkMasterMode == 'f' ) ? string ( "_fast-network" ) : string ( "_slow-network" ); | |||
| plot_name += ( fParams.fNetworkMode == 'f' ) ? string ( "_fast-network" ) : string ( "" ); | |||
| fMonitor = new JackGnuPlotMonitor<float> ( JackNetDriver::fMeasureCnt, JackNetDriver::fMeasurePoints, plot_name ); | |||
| fMeasure = new float[JackNetDriver::fMeasurePoints]; | |||
| fMonitor->SetPlotFile ( JackNetDriver::fMonitorPlotOptions, JackNetDriver::fMonitorPlotOptionsCnt, | |||
| @@ -400,7 +400,7 @@ namespace Jack | |||
| } | |||
| port = fGraphManager->GetPort ( port_id ); | |||
| port->SetAlias ( alias ); | |||
| port->SetLatency ( fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) ); | |||
| port->SetLatency ( ( fParams.fNetworkMode == 'f' ) ? 0 : fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) ); | |||
| fPlaybackPortList[audio_port_index] = port_id; | |||
| jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() ); | |||
| } | |||
| @@ -434,7 +434,7 @@ namespace Jack | |||
| return -1; | |||
| } | |||
| port = fGraphManager->GetPort ( port_id ); | |||
| port->SetLatency ( fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) ); | |||
| port->SetLatency ( ( fParams.fNetworkMode == 'f' ) ? 0 : fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) ); | |||
| fMidiPlaybackPortList[midi_port_index] = port_id; | |||
| jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() ); | |||
| } | |||
| @@ -614,7 +614,7 @@ namespace Jack | |||
| if ( fEngineControl->fSyncMode ) | |||
| fTxHeader.fCycle = fRxHeader.fCycle; | |||
| else | |||
| fTxHeader.fCycle++; | |||
| fTxHeader.fCycle = fRxHeader.fCycle - 1; | |||
| fTxHeader.fSubCycle = 0; | |||
| fTxHeader.fIsLastPckt = 'n'; | |||
| @@ -777,10 +777,10 @@ namespace Jack | |||
| i++; | |||
| strcpy ( desc->params[i].name, "network_mode" ); | |||
| desc->params[i].character = 'N'; | |||
| desc->params[i].type = JackDriverParamChar; | |||
| desc->params[i].value.ui = 's'; | |||
| strcpy ( desc->params[i].short_desc, "Slow network add 1 cycle latency" ); | |||
| desc->params[i].character = 'f'; | |||
| desc->params[i].type = JackDriverParamString; | |||
| strcpy ( desc->params[i].value.str, "" ); | |||
| strcpy ( desc->params[i].short_desc, "Fast mode allows a zero latency transmission." ); | |||
| strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); | |||
| return desc; | |||
| @@ -806,7 +806,7 @@ namespace Jack | |||
| int midi_input_ports = 0; | |||
| int midi_output_ports = 0; | |||
| bool monitor = false; | |||
| char network_master_mode = 's'; | |||
| char network_mode = 'n'; | |||
| const JSList* node; | |||
| const jack_driver_param_t* param; | |||
| @@ -842,26 +842,15 @@ namespace Jack | |||
| case 't' : | |||
| transport_sync = param->value.ui; | |||
| break; | |||
| case 'N' : | |||
| switch ( param->value.ui ) | |||
| { | |||
| case 's' : | |||
| network_master_mode = 's'; | |||
| break; | |||
| case 'f' : | |||
| network_master_mode = 'f'; | |||
| break; | |||
| default : | |||
| network_master_mode = 's'; | |||
| break; | |||
| } | |||
| case 'f' : | |||
| network_mode = 'f'; | |||
| 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, network_master_mode ) ); | |||
| midi_input_ports, midi_output_ports, name, transport_sync, network_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; | |||
| @@ -125,7 +125,7 @@ namespace Jack | |||
| string plot_name = string ( fParams.fName ); | |||
| plot_name += string ( "_master" ); | |||
| plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" ); | |||
| plot_name += ( fParams.fNetworkMasterMode == 'f' ) ? string ( "_fast-network" ) : string ( "_slow-network" ); | |||
| plot_name += ( fParams.fNetworkMode == 'f' ) ? string ( "_fast-network" ) : string ( "" ); | |||
| fMonitor = new JackGnuPlotMonitor<float> ( JackNetMaster::fMeasureCnt, JackNetMaster::fMeasurePoints, plot_name ); | |||
| fMeasure = new float[JackNetMaster::fMeasurePoints]; | |||
| fMonitor->SetPlotFile ( JackNetMaster::fMonitorPlotOptions, JackNetMaster::fMonitorPlotOptionsCnt, | |||
| @@ -253,7 +253,7 @@ namespace Jack | |||
| sprintf ( name, "from_slave_%d", i+1 ); | |||
| if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0 ) ) == NULL ) | |||
| goto fail; | |||
| jack_port_set_latency ( fAudioPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); | |||
| jack_port_set_latency ( fAudioPlaybackPorts[i], ( fParams.fNetworkMode == 'f' ) ? 0 : port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); | |||
| } | |||
| //midi | |||
| port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; | |||
| @@ -270,7 +270,7 @@ namespace Jack | |||
| sprintf ( name, "midi_from_slave_%d", i+1 ); | |||
| if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, port_flags, 0 ) ) == NULL ) | |||
| goto fail; | |||
| jack_port_set_latency ( fMidiPlaybackPorts[i], port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); | |||
| jack_port_set_latency ( fMidiPlaybackPorts[i], ( fParams.fNetworkMode == 'f' ) ? 0 : port_latency + ( fParams.fSlaveSyncMode ) ? 0 : port_latency ); | |||
| } | |||
| fRunning = true; | |||
| @@ -494,28 +494,34 @@ namespace Jack | |||
| #endif | |||
| //receive -------------------------------------------------------------------------------------------------------------------- | |||
| //sync | |||
| //sync : how much data is available ? | |||
| rx_bytes = Recv ( fParams.fMtu, MSG_PEEK ); | |||
| //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; | |||
| //slow mode : | |||
| if ( fParams.fNetworkMasterMode == 's' ) | |||
| switch ( fParams.fNetworkMode ) | |||
| { | |||
| if ( rx_head->fCycle == fTxHeader.fCycle ) | |||
| return 0; | |||
| else | |||
| rx_bytes = Recv ( rx_head->fPacketSize, 0); | |||
| } | |||
| //fast mode : | |||
| if ( fParams.fNetworkMasterMode == 'f' ) | |||
| { | |||
| if ( fTxHeader.fCycle - fRxHeader.fCycle ) | |||
| jack_log ( "%s : %s = %d", fParams.fName, ( fParams.fSlaveSyncMode ) ? "SyncCycleOffset" : "AsyncCycleOffset", fTxHeader.fCycle - fRxHeader.fCycle ); | |||
| case 'n' : //normal mode | |||
| //normal use of the network : allow to use full bandwith | |||
| // - extra latency is set to one cycle, what corresponds to the time needed to receive streams using full network bandwith | |||
| // - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter | |||
| // - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it | |||
| if ( rx_head->fCycle == fTxHeader.fCycle ) | |||
| return 0; | |||
| else | |||
| { | |||
| rx_bytes = Recv ( rx_head->fPacketSize, 0 ); | |||
| } | |||
| break; | |||
| case 'f' : //fast mode | |||
| //fast mode suppose the network bandwith is larger than required for the transmission (only a few channels for example) | |||
| // - packets can be quickly received, quickly is here relative to the cycle duration | |||
| // - here, receive data, we can't keep it queued on the rx buffer, | |||
| // - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow | |||
| rx_bytes = Recv ( rx_head->fPacketSize, 0 ); | |||
| if ( rx_head->fCycle != fTxHeader.fCycle ) | |||
| jack_error ( "%s, can't stay in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fTxHeader.fCycle - rx_head->fCycle ); | |||
| break; | |||
| } | |||
| #ifdef JACK_MONITOR | |||
| @@ -526,16 +532,20 @@ namespace Jack | |||
| { | |||
| 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 ( ++jumpcnt == fNSubProcess ) | |||
| //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 ) ) | |||
| { | |||
| //read data | |||
| switch ( rx_head->fDataType ) | |||
| { | |||
| case 'm': //midi | |||
| @@ -558,8 +568,8 @@ namespace Jack | |||
| jumpcnt = 0; | |||
| break; | |||
| case 's': //sync | |||
| Recv ( rx_head->fPacketSize, 0 ); | |||
| return 0; | |||
| if ( rx_head->fCycle == fTxHeader.fCycle ) | |||
| return 0; | |||
| } | |||
| } | |||
| } | |||
| @@ -218,7 +218,7 @@ namespace Jack | |||
| jack_info ( "Packet per period : %u", params->fPeriodSize / params->fFramesPerPacket ); | |||
| jack_info ( "Bitdepth : %s", bitdepth ); | |||
| jack_info ( "Slave mode : %s", ( params->fSlaveSyncMode ) ? "sync" : "async" ); | |||
| jack_info ( "Network mode : %s", ( params->fNetworkMasterMode == 'f' ) ? "fast" : "slow" ); | |||
| jack_info ( "Network mode : %s", ( params->fNetworkMode == 'f' ) ? "fast" : "normal" ); | |||
| jack_info ( "****************************************************" ); | |||
| } | |||
| @@ -375,7 +375,7 @@ namespace Jack | |||
| { | |||
| float time; | |||
| //fast mode, wait for the entire cycle duration | |||
| if ( params->fNetworkMasterMode == 'f' ) | |||
| if ( params->fNetworkMode == 'f' ) | |||
| time = 900000.f * ( static_cast<float> ( params->fPeriodSize ) / static_cast<float> ( params->fSampleRate ) ); | |||
| //slow mode, just try recv during two subcycle audio packets | |||
| else | |||
| @@ -73,7 +73,7 @@ namespace Jack | |||
| 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 fNetworkMode; //fast or slow mode | |||
| }; | |||
| //net status ********************************************************************************** | |||