| @@ -149,6 +149,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| JackMidiBuffer** fMidiPlaybackBuffer; | |||
| jack_master_t fRequest; | |||
| int fPacketTimeOut; | |||
| JackNetExtMaster(const char* ip, | |||
| int port, | |||
| @@ -472,7 +474,7 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
| return SOCKET_ERROR; | |||
| } | |||
| //send data | |||
| // send data | |||
| if (DataSend() == SOCKET_ERROR) { | |||
| return SOCKET_ERROR; | |||
| } | |||
| @@ -521,7 +523,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| JackMidiBuffer** fMidiPlaybackBuffer; | |||
| int fConnectTimeOut; | |||
| JackNetExtSlave(const char* ip, | |||
| int port, | |||
| const char* name, | |||
| @@ -767,6 +769,12 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| bool Execute() | |||
| { | |||
| try { | |||
| /* | |||
| Fist cycle use an INT_MAX time out, so that connection | |||
| is considered established (with PACKET_TIMEOUT later on) | |||
| when the first cycle has been done. | |||
| */ | |||
| DummyProcess(); | |||
| // keep running even in case of error | |||
| while (fThread.GetStatus() == JackThread::kRunning) { | |||
| if (Process() == SOCKET_ERROR) { | |||
| @@ -821,6 +829,18 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
| return DataSend(); | |||
| } | |||
| void DummyProcess() | |||
| { | |||
| // First cycle with INT_MAX time out | |||
| SetPackedTimeOut(INT_MAX); | |||
| // One cycle | |||
| Process(); | |||
| // Then use PACKET_TIMEOUT for next cycles | |||
| SetPackedTimeOut(PACKET_TIMEOUT); | |||
| } | |||
| int Process() | |||
| { | |||
| @@ -52,7 +52,7 @@ namespace Jack | |||
| fParams.fNetworkLatency = 2; | |||
| fParams.fSampleEncoder = JackFloatEncoder; | |||
| fClient = jack_client; | |||
| // Possibly use env variable | |||
| const char* default_udp_port = getenv("JACK_NETJACK_PORT"); | |||
| udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT; | |||
| @@ -262,10 +262,11 @@ namespace Jack | |||
| { | |||
| try { | |||
| // Keep running even in case of error | |||
| while (fThread.GetStatus() == JackThread::kRunning) | |||
| while (fThread.GetStatus() == JackThread::kRunning) { | |||
| if (Process() == SOCKET_ERROR) { | |||
| return false; | |||
| } | |||
| } | |||
| return false; | |||
| } catch (JackNetException& e) { | |||
| // Otherwise just restart... | |||
| @@ -50,7 +50,7 @@ namespace Jack | |||
| //adapter thread | |||
| JackThread fThread; | |||
| //transport | |||
| void EncodeTransportData(); | |||
| void DecodeTransportData(); | |||
| @@ -185,17 +185,20 @@ namespace Jack | |||
| delete[] fMidiCapturePortList; | |||
| delete[] fMidiPlaybackPortList; | |||
| fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels]; | |||
| fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels]; | |||
| assert(fMidiCapturePortList); | |||
| assert(fMidiPlaybackPortList); | |||
| for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | |||
| fMidiCapturePortList[midi_port_index] = 0; | |||
| if (fParams.fSendMidiChannels > 0) { | |||
| fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels]; | |||
| assert(fMidiCapturePortList); | |||
| for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | |||
| fMidiCapturePortList[midi_port_index] = 0; | |||
| } | |||
| } | |||
| for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | |||
| fMidiPlaybackPortList[midi_port_index] = 0; | |||
| if (fParams.fReturnMidiChannels > 0) { | |||
| fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels]; | |||
| assert(fMidiPlaybackPortList); | |||
| for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | |||
| fMidiPlaybackPortList[midi_port_index] = 0; | |||
| } | |||
| } | |||
| // Register jack ports | |||
| @@ -504,17 +507,17 @@ namespace Jack | |||
| void JackNetDriver::EncodeTransportData() | |||
| { | |||
| //is there a timebase master change ? | |||
| // is there a timebase master change ? | |||
| int refnum; | |||
| bool conditional; | |||
| fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional); | |||
| if (refnum != fLastTimebaseMaster) { | |||
| //timebase master has released its function | |||
| // timebase master has released its function | |||
| if (refnum == -1) { | |||
| fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER; | |||
| jack_info("Sending a timebase master release request."); | |||
| } else { | |||
| //there is a new timebase master | |||
| // there is a new timebase master | |||
| fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER; | |||
| jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional"); | |||
| } | |||
| @@ -523,10 +526,10 @@ namespace Jack | |||
| fReturnTransportData.fTimebaseMaster = NO_CHANGE; | |||
| } | |||
| //update transport state and position | |||
| // update transport state and position | |||
| fReturnTransportData.fState = fEngineControl->fTransport.Query(&fReturnTransportData.fPosition); | |||
| //is it a new state (that the master need to know...) ? | |||
| // is it a new state (that the master need to know...) ? | |||
| fReturnTransportData.fNewState = ((fReturnTransportData.fState == JackTransportNetStarting) && | |||
| (fReturnTransportData.fState != fLastTransportState) && | |||
| (fReturnTransportData.fState != fSendTransportData.fState)); | |||
| @@ -540,7 +543,7 @@ namespace Jack | |||
| int JackNetDriver::Read() | |||
| { | |||
| //buffers | |||
| // buffers | |||
| for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | |||
| fNetMidiCaptureBuffer->SetBuffer(midi_port_index, GetMidiInputBuffer(midi_port_index)); | |||
| } | |||
| @@ -584,7 +587,7 @@ namespace Jack | |||
| #ifdef JACK_MONITOR | |||
| fNetTimeMon->Add(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||
| #endif | |||
| //audio, midi or sync if driver is late | |||
| // audio, midi or sync if driver is late | |||
| switch (DataRecv()) { | |||
| case SOCKET_ERROR: | |||
| @@ -596,7 +599,7 @@ namespace Jack | |||
| break; | |||
| } | |||
| //take the time at the beginning of the cycle | |||
| // take the time at the beginning of the cycle | |||
| JackDriver::CycleTakeBeginTime(); | |||
| #ifdef JACK_MONITOR | |||
| @@ -608,7 +611,7 @@ namespace Jack | |||
| int JackNetDriver::Write() | |||
| { | |||
| //buffers | |||
| // buffers | |||
| for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | |||
| fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, GetMidiOutputBuffer(midi_port_index)); | |||
| } | |||
| @@ -631,10 +634,9 @@ namespace Jack | |||
| fNetTimeMon->AddLast(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||
| #endif | |||
| //sync | |||
| EncodeSyncPacket(); | |||
| //send sync | |||
| // send sync | |||
| if (SyncSend() == SOCKET_ERROR) { | |||
| return SOCKET_ERROR; | |||
| } | |||
| @@ -643,7 +645,7 @@ namespace Jack | |||
| fNetTimeMon->Add(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); | |||
| #endif | |||
| //send data | |||
| // send data | |||
| if (DataSend() == SOCKET_ERROR) { | |||
| return SOCKET_ERROR; | |||
| } | |||
| @@ -52,7 +52,7 @@ namespace Jack | |||
| int fWantedMIDIPlaybackChannels; | |||
| bool fAutoSave; | |||
| //monitoring | |||
| #ifdef JACK_MONITOR | |||
| JackGnuPlotMonitor<float>* fNetTimeMon; | |||
| @@ -63,6 +63,7 @@ namespace Jack | |||
| fNetMidiPlaybackBuffer = NULL; | |||
| memset(&fSendTransportData, 0, sizeof(net_transport_data_t)); | |||
| memset(&fReturnTransportData, 0, sizeof(net_transport_data_t)); | |||
| fPacketTimeOut = PACKET_TIMEOUT; | |||
| } | |||
| void JackNetInterface::FreeNetworkBuffers() | |||
| @@ -255,7 +256,7 @@ namespace Jack | |||
| void JackNetInterface::SetRcvTimeOut() | |||
| { | |||
| if (!fSetTimeOut) { | |||
| if (fSocket.SetTimeOut(PACKET_TIMEOUT) == SOCKET_ERROR) { | |||
| if (fSocket.SetTimeOut(fPacketTimeOut) == SOCKET_ERROR) { | |||
| jack_error("Can't set rx timeout : %s", StrError(NET_ERROR_CODE)); | |||
| return; | |||
| } | |||
| @@ -854,6 +855,8 @@ namespace Jack | |||
| int JackNetSlaveInterface::SyncRecv() | |||
| { | |||
| SetRcvTimeOut(); | |||
| int rx_bytes = 0; | |||
| packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer); | |||
| @@ -875,8 +878,6 @@ namespace Jack | |||
| } | |||
| fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | |||
| SetRcvTimeOut(); | |||
| return rx_bytes; | |||
| } | |||
| @@ -49,6 +49,7 @@ namespace Jack | |||
| protected: | |||
| bool fSetTimeOut; | |||
| int fPacketTimeOut; | |||
| void Initialize(); | |||
| @@ -112,6 +113,12 @@ namespace Jack | |||
| int FinishRecv(NetAudioBuffer* buffer); | |||
| void SetRcvTimeOut(); | |||
| void SetPackedTimeOut(int time_out) | |||
| { | |||
| // New time out | |||
| fPacketTimeOut = time_out; | |||
| fSetTimeOut = false; | |||
| } | |||
| NetAudioBuffer* AudioBufferFactory(int nports, char* buffer); | |||
| @@ -62,7 +62,7 @@ namespace Jack | |||
| for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) { | |||
| fMidiPlaybackPorts[port_index] = NULL; | |||
| } | |||
| //monitor | |||
| #ifdef JACK_MONITOR | |||
| fPeriodUsecs = (int)(1000000.f * ((float) fParams.fPeriodSize / (float) fParams.fSampleRate)); | |||
| @@ -509,7 +509,7 @@ namespace Jack | |||
| #endif | |||
| } | |||
| //encode the first packet | |||
| // encode the first packet | |||
| EncodeSyncPacket(); | |||
| if (SyncSend() == SOCKET_ERROR) { | |||
| @@ -520,7 +520,7 @@ namespace Jack | |||
| fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | |||
| #endif | |||
| //send data | |||
| // send data | |||
| if (DataSend() == SOCKET_ERROR) { | |||
| return SOCKET_ERROR; | |||
| } | |||
| @@ -529,7 +529,7 @@ namespace Jack | |||
| fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | |||
| #endif | |||
| //receive sync | |||
| // receive sync | |||
| int res = SyncRecv(); | |||
| switch (res) { | |||
| @@ -542,7 +542,7 @@ namespace Jack | |||
| break; | |||
| default: | |||
| //decode sync | |||
| // Decode sync | |||
| DecodeSyncPacket(); | |||
| break; | |||
| } | |||
| @@ -551,7 +551,7 @@ namespace Jack | |||
| fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | |||
| #endif | |||
| //receive data | |||
| // receive data | |||
| res = DataRecv(); | |||
| switch (res) { | |||
| @@ -60,7 +60,7 @@ namespace Jack | |||
| //sync and transport | |||
| int fLastTransportState; | |||
| //monitoring | |||
| #ifdef JACK_MONITOR | |||
| jack_time_t fPeriodUsecs; | |||
| @@ -148,6 +148,10 @@ main (int argc, char *argv[]) | |||
| */ | |||
| //usleep(5*1000000); | |||
| printf("Wait...\n"); | |||
| //sleep(10); | |||
| usleep(1000000); | |||
| printf("Wait...OK\n"); | |||
| while (1) { | |||
| @@ -161,6 +165,8 @@ main (int argc, char *argv[]) | |||
| printf("jack_net_master_send failure, exiting\n"); | |||
| break; | |||
| } | |||
| usleep(10000); | |||
| if (jack_net_master_recv(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) { | |||
| printf("jack_net_master_recv failure, exiting\n"); | |||