diff --git a/common/JackLibClient.cpp b/common/JackLibClient.cpp index ffcd633b..4ba58c9c 100644 --- a/common/JackLibClient.cpp +++ b/common/JackLibClient.cpp @@ -100,11 +100,8 @@ int JackLibClient::Open(const char* server_name, const char* name, int uuid, jac JackLibGlobals::fGlobals->fGraphManager.SetShmIndex(shared_graph, fServerName); fClientControl.SetShmIndex(shared_client, fServerName); JackGlobals::fVerbose = GetEngineControl()->fVerbose; - } catch (int n) { - jack_error("Map shared memory segments exception %d", n); - goto error; } catch (...) { - jack_error("Unknown error..."); + jack_error("Map shared memory segments exception"); goto error; } diff --git a/common/JackNetAPI.cpp b/common/JackNetAPI.cpp index 38e4a2be..9d0d030b 100644 --- a/common/JackNetAPI.cpp +++ b/common/JackNetAPI.cpp @@ -40,6 +40,7 @@ extern "C" JackFloatEncoder = 0, JackIntEncoder = 1, JackCeltEncoder = 2, + JackMaxEncoder = 3 }; typedef struct { @@ -50,9 +51,9 @@ extern "C" int midi_output; int mtu; int time_out; // in millisecond, -1 means in infinite - int encoder; + int encoder; // one of JackNetEncoder int kbps; // KB per second for CELT encoder - int latency; + int latency; // network cycles } jack_slave_t; @@ -183,16 +184,19 @@ struct JackNetExtMaster : public JackNetMasterInterface { } // Join multicast group - if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) - fprintf(stderr, "Can't join multicast group : %s\n", StrError(NET_ERROR_CODE)); + if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) { + fprintf(stderr, "Can't join multicast group : %s\n", StrError(NET_ERROR_CODE)); + } // Local loop - if (fSocket.SetLocalLoop() == SOCKET_ERROR) + if (fSocket.SetLocalLoop() == SOCKET_ERROR) { fprintf(stderr, "Can't set local loop : %s\n", StrError(NET_ERROR_CODE)); + } // Set a timeout on the multicast receive (the thread can now be cancelled) - if (fSocket.SetTimeOut(2000000) == SOCKET_ERROR) + if (fSocket.SetTimeOut(2000000) == SOCKET_ERROR) { fprintf(stderr, "Can't set timeout : %s\n", StrError(NET_ERROR_CODE)); + } //main loop, wait for data, deal with it and wait again //utility variables @@ -271,12 +275,14 @@ struct JackNetExtMaster : public JackNetMasterInterface { fSocket.Close(); // Network slave init - if (!JackNetMasterInterface::Init()) + if (!JackNetMasterInterface::Init()) { return -1; + } // Set global parameters - if (!SetParams()) + if (!SetParams()) { return -1; + } AllocPorts(); return 0; @@ -369,8 +375,9 @@ struct JackNetExtMaster : public JackNetMasterInterface { fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]); } - if (SyncRecv() == SOCKET_ERROR) + if (SyncRecv() == SOCKET_ERROR) { return 0; + } DecodeSyncPacket(); return DataRecv(); @@ -384,22 +391,23 @@ struct JackNetExtMaster : public JackNetMasterInterface { int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) { try { - assert(audio_output == fParams.fSendAudioChannels); + assert(audio_output == fParams.fSendAudioChannels); - for (int audio_port_index = 0; audio_port_index < audio_output; audio_port_index++) { - fNetAudioCaptureBuffer->SetBuffer(audio_port_index, audio_output_buffer[audio_port_index]); - } + for (int audio_port_index = 0; audio_port_index < audio_output; audio_port_index++) { + fNetAudioCaptureBuffer->SetBuffer(audio_port_index, audio_output_buffer[audio_port_index]); + } - for (int midi_port_index = 0; midi_port_index < midi_output; midi_port_index++) { - fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); - } + for (int midi_port_index = 0; midi_port_index < midi_output; midi_port_index++) { + fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); + } - EncodeSyncPacket(); + EncodeSyncPacket(); - if (SyncSend() == SOCKET_ERROR) - return SOCKET_ERROR; + if (SyncSend() == SOCKET_ERROR) { + return SOCKET_ERROR; + } - return DataSend(); + return DataSend(); } catch (JackNetException& e) { jack_error("Connection lost."); @@ -486,13 +494,20 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf int Open(jack_master_t* result) { + if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) { + printf("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY); + return -1; + } + // Init network connection - if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) + if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) { return -1; + } // Then set global parameters - if (!SetParams()) + if (!SetParams()) { return -1; + } // Set result if (result != NULL) { @@ -512,23 +527,28 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf int Restart() { // If shutdown cb is set, then call it - if (fShutdownCallback) + if (fShutdownCallback) { fShutdownCallback(fShutdownArg); + } // Init network connection - if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) + if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) { return -1; + } // Then set global parameters - if (!SetParams()) + if (!SetParams()) { return -1; + } // We need to notify possibly new buffer size and sample rate (see Execute) - if (fBufferSizeCallback) + if (fBufferSizeCallback) { fBufferSizeCallback(fParams.fPeriodSize, fBufferSizeArg); + } - if (fSampleRateCallback) + if (fSampleRateCallback) { fSampleRateCallback(fParams.fSampleRate, fSampleRateArg); + } AllocPorts(); return 0; @@ -543,62 +563,58 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf void AllocPorts() { - int port_index; - // Set buffers fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels]; - for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) { - fAudioCaptureBuffer[port_index] = new float[fParams.fPeriodSize]; - fNetAudioCaptureBuffer->SetBuffer(port_index, fAudioCaptureBuffer[port_index]); + for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) { + fAudioCaptureBuffer[audio_port_index] = new float[fParams.fPeriodSize]; + fNetAudioCaptureBuffer->SetBuffer(audio_port_index, fAudioCaptureBuffer[audio_port_index]); } fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels]; - for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) { - fMidiCaptureBuffer[port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; - fNetMidiCaptureBuffer->SetBuffer(port_index, fMidiCaptureBuffer[port_index]); + for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { + fMidiCaptureBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; + fNetMidiCaptureBuffer->SetBuffer(midi_port_index, fMidiCaptureBuffer[midi_port_index]); } fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels]; - for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) { - fAudioPlaybackBuffer[port_index] = new float[fParams.fPeriodSize]; - fNetAudioPlaybackBuffer->SetBuffer(port_index, fAudioPlaybackBuffer[port_index]); + for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) { + fAudioPlaybackBuffer[audio_port_index] = new float[fParams.fPeriodSize]; + fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, fAudioPlaybackBuffer[audio_port_index]); } fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels]; - for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) { - fMidiPlaybackBuffer[port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; - fNetMidiPlaybackBuffer->SetBuffer(port_index, fMidiPlaybackBuffer[port_index]); + for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { + fMidiPlaybackBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize]; + fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, fMidiPlaybackBuffer[midi_port_index]); } } void FreePorts() { - int port_index; - if (fAudioCaptureBuffer) { - for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) - delete[] fAudioCaptureBuffer[port_index]; + for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) + delete[] fAudioCaptureBuffer[audio_port_index]; delete[] fAudioCaptureBuffer; fAudioCaptureBuffer = NULL; } if (fMidiCaptureBuffer) { - for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) - delete[] (fMidiCaptureBuffer[port_index]); + for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) + delete[] (fMidiCaptureBuffer[midi_port_index]); delete[] fMidiCaptureBuffer; fMidiCaptureBuffer = NULL; } if (fAudioPlaybackBuffer) { - for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) - delete[] fAudioPlaybackBuffer[port_index]; + for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) + delete[] fAudioPlaybackBuffer[audio_port_index]; delete[] fAudioPlaybackBuffer; fAudioPlaybackBuffer = NULL; } if (fMidiPlaybackBuffer) { - for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) - delete[] fMidiPlaybackBuffer[port_index]; + for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) + delete[] fMidiPlaybackBuffer[midi_port_index]; delete[] fMidiPlaybackBuffer; fMidiPlaybackBuffer = NULL; } @@ -647,8 +663,9 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf { // Don't return -1 in case of sync recv failure // we need the process to continue for network error detection - if (SyncRecv() == SOCKET_ERROR) + if (SyncRecv() == SOCKET_ERROR) { return 0; + } DecodeSyncPacket(); return DataRecv(); @@ -658,8 +675,9 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf { EncodeSyncPacket(); - if (SyncSend() == SOCKET_ERROR) + if (SyncSend() == SOCKET_ERROR) { return SOCKET_ERROR; + } return DataSend(); } @@ -668,8 +686,9 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf { // Read data from the network // in case of fatal network error, stop the process - if (Read() == SOCKET_ERROR) + if (Read() == SOCKET_ERROR) { return SOCKET_ERROR; + } fProcessCallback(fParams.fPeriodSize, fParams.fSendAudioChannels, @@ -684,8 +703,9 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf // Then write data to network // in case of failure, stop process - if (Write() == SOCKET_ERROR) + if (Write() == SOCKET_ERROR) { return SOCKET_ERROR; + } return 0; } @@ -770,10 +790,12 @@ struct JackNetAdapter : public JackAudioAdapterInterface { { //ringbuffers - if (fCaptureChannels > 0) + if (fCaptureChannels > 0) { fCaptureRingBuffer = new JackResampler*[fCaptureChannels]; - if (fPlaybackChannels > 0) + } + if (fPlaybackChannels > 0) { fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels]; + } if (fAdaptative) { AdaptRingBufferSize(); @@ -793,10 +815,12 @@ struct JackNetAdapter : public JackAudioAdapterInterface { fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize); } - if (fCaptureChannels > 0) + if (fCaptureChannels > 0) { jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace()); - if (fPlaybackChannels > 0) + } + if (fPlaybackChannels > 0) { jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace()); + } } virtual ~JackNetAdapter() @@ -916,7 +940,11 @@ SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output, jack_nframes_t adapted_buffer_size, jack_nframes_t adapted_sample_rate) { - return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate); + try { + return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate); + } catch (...) { + return NULL; + } } SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter) diff --git a/common/JackNetAdapter.cpp b/common/JackNetAdapter.cpp index 438936c0..a41953f4 100644 --- a/common/JackNetAdapter.cpp +++ b/common/JackNetAdapter.cpp @@ -96,6 +96,10 @@ namespace Jack #endif case 'l' : fParams.fNetworkLatency = param->value.i; + if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) { + jack_error("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY); + throw std::bad_alloc(); + } break; case 'q': fQuality = param->value.ui; @@ -268,20 +272,20 @@ namespace Jack { case JackTransportStopped : jack_transport_stop(fJackClient); - jack_info("NetMaster : transport stops."); + jack_info("NetMaster : transport stops"); break; case JackTransportStarting : jack_transport_reposition(fJackClient, &fSendTransportData.fPosition); jack_transport_start(fJackClient); - jack_info("NetMaster : transport starts."); + jack_info("NetMaster : transport starts"); break; case JackTransportRolling : // TODO, we need to : // - find a way to call TransportEngine->SetNetworkSync() // - turn the transport state to JackTransportRolling - jack_info("NetMaster : transport rolls."); + jack_info("NetMaster : transport rolls"); break; } } @@ -404,8 +408,8 @@ extern "C" value.ui = 1U; jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL); - strcpy(value.str, "slow"); - jack_driver_descriptor_add_parameter(desc, &filler, "mode", 'm', JackDriverParamString, &value, NULL, "Slow, Normal or Fast mode.", NULL); + value.ui = 2U; + jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL); value.i = 0; jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL); @@ -440,6 +444,7 @@ extern "C" } } catch (...) { + jack_info("NetAdapter allocation error"); return 1; } } diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index aa9d7468..e0bccde4 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -35,8 +35,9 @@ namespace Jack jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port); // Use the hostname if no name parameter was given - if (strcmp(net_name, "") == 0) + if (strcmp(net_name, "") == 0) { GetHostName(net_name, JACK_CLIENT_NAME_SIZE); + } fParams.fMtu = mtu; fParams.fSendMidiChannels = midi_input_ports; @@ -94,8 +95,9 @@ namespace Jack int JackNetDriver::Close() { #ifdef JACK_MONITOR - if (fNetTimeMon) + if (fNetTimeMon) { fNetTimeMon->Save(); + } #endif FreeAll(); return JackDriver::Close(); @@ -420,8 +422,9 @@ namespace Jack bool conditional; if (fSendTransportData.fTimebaseMaster == TIMEBASEMASTER) { fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional); - if (refnum != -1) + if (refnum != -1) { fEngineControl->fTransport.ResetTimebase(refnum); + } jack_info("The NetMaster is now the new timebase master."); } @@ -503,8 +506,9 @@ namespace Jack #endif //receive sync (launch the cycle) - if (SyncRecv() == SOCKET_ERROR) + if (SyncRecv() == SOCKET_ERROR) { return 0; + } #ifdef JACK_MONITOR // For timing @@ -564,16 +568,18 @@ namespace Jack EncodeSyncPacket(); //send sync - if (SyncSend() == SOCKET_ERROR) + if (SyncSend() == SOCKET_ERROR) { return SOCKET_ERROR; + } #ifdef JACK_MONITOR fNetTimeMon->Add(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); #endif //send data - if (DataSend() == SOCKET_ERROR) + if (DataSend() == SOCKET_ERROR) { return SOCKET_ERROR; + } #ifdef JACK_MONITOR fNetTimeMon->AddLast(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f); @@ -699,16 +705,10 @@ namespace Jack break; case 'l' : network_latency = param->value.ui; - /* - if (strcmp(param->value.str, "normal") == 0) - network_mode = 'n'; - else if (strcmp(param->value.str, "slow") == 0) - network_mode = 's'; - else if (strcmp(param->value.str, "fast") == 0) - network_mode = 'f'; - else - jack_error("Unknown network mode, using 'normal' mode."); - */ + if (network_latency > NETWORK_MAX_LATENCY) { + printf("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY); + return NULL; + } break; } } diff --git a/common/JackNetInterface.cpp b/common/JackNetInterface.cpp index 525b36c9..80caa0fc 100644 --- a/common/JackNetInterface.cpp +++ b/common/JackNetInterface.cpp @@ -94,27 +94,27 @@ namespace Jack int JackNetInterface::SetNetBufferSize() { - //audio + // audio float audio_size = (fNetAudioCaptureBuffer) - ? fNetAudioCaptureBuffer->GetCycleSize() - : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleSize() : 0; + ? fNetAudioCaptureBuffer->GetCycleSize() + : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleSize() : 0; jack_log("audio_size %f", audio_size); - //midi + // midi float midi_size = (fNetMidiCaptureBuffer) - ? fNetMidiCaptureBuffer->GetCycleSize() - : (fNetMidiPlaybackBuffer) ? fNetMidiPlaybackBuffer->GetCycleSize() : 0; + ? fNetMidiCaptureBuffer->GetCycleSize() + : (fNetMidiPlaybackBuffer) ? fNetMidiPlaybackBuffer->GetCycleSize() : 0; jack_log("midi_size %f", midi_size); - //bufsize = sync + audio + midi - int bufsize = NETWORK_MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int) midi_size); + // bufsize = sync + audio + midi + int bufsize = NETWORK_MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int)midi_size); jack_log("SetNetBufferSize bufsize = %d", bufsize); - //tx buffer + // tx buffer if (fSocket.SetOption(SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) return SOCKET_ERROR; - //rx buffer + // rx buffer if (fSocket.SetOption(SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) return SOCKET_ERROR; @@ -123,33 +123,108 @@ namespace Jack bool JackNetInterface::SetParams() { - //TX header init + // TX header init strcpy(fTxHeader.fPacketType, "header"); fTxHeader.fID = fParams.fID; fTxHeader.fCycle = 0; fTxHeader.fSubCycle = 0; fTxHeader.fIsLastPckt = 0; - //RX header init + // RX header init strcpy(fRxHeader.fPacketType, "header"); fRxHeader.fID = fParams.fID; fRxHeader.fCycle = 0; fRxHeader.fSubCycle = 0; fRxHeader.fIsLastPckt = 0; - //network buffers + // network buffers fTxBuffer = new char[fParams.fMtu]; fRxBuffer = new char[fParams.fMtu]; assert(fTxBuffer); assert(fRxBuffer); - //net audio/midi buffers'addresses + // net audio/midi buffers'addresses fTxData = fTxBuffer + HEADER_SIZE; fRxData = fRxBuffer + HEADER_SIZE; return true; } + int JackNetInterface::MidiSend(NetMidiBuffer* buffer, int midi_channnels, int audio_channels) + { + if (midi_channnels > 0) { + // set global header fields and get the number of midi packets + fTxHeader.fDataType = 'm'; + uint data_size = buffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = buffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE); + + for (uint subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { + fTxHeader.fSubCycle = subproc; + // fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && !fParams.fReturnAudioChannels) ? 1 : 0; + fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && audio_channels == 0) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + buffer->RenderToNetwork(subproc, data_size); + memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) + return SOCKET_ERROR; + } + } + return 0; + } + + int JackNetInterface::AudioSend(NetAudioBuffer* buffer, int audio_channels) + { + // audio + if (audio_channels > 0) { + fTxHeader.fDataType = 'a'; + buffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = buffer->GetNumPackets(); + + for (uint subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { + fTxHeader.fSubCycle = subproc; + fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + buffer->RenderToNetwork(subproc, fTxHeader.fActivePorts); + memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + // PacketHeaderDisplay(&fTxHeader); + if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) + return SOCKET_ERROR; + } + } + return 0; + } + + int JackNetInterface::MidiRecv(packet_header_t* rx_head, NetMidiBuffer* buffer, uint& recvd_midi_pckt) + { + int rx_bytes = Recv(rx_head->fPacketSize, 0); + fRxHeader.fCycle = rx_head->fCycle; + fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; + buffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); + // Last midi packet is received, so finish rendering... + if (++recvd_midi_pckt == rx_head->fNumPacket) + buffer->RenderToJackPorts(); + return rx_bytes; + } + + int JackNetInterface::AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer) + { + int rx_bytes = Recv(rx_head->fPacketSize, 0); + fRxHeader.fCycle = rx_head->fCycle; + fRxHeader.fSubCycle = rx_head->fSubCycle; + fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; + fRxHeader.fActivePorts = rx_head->fActivePorts; + rx_bytes = buffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE, fRxHeader.fActivePorts); + // Last audio packet is received, so finish rendering... + if (fRxHeader.fIsLastPckt) + buffer->RenderToJackPorts(); + return rx_bytes; + } + + int JackNetInterface::FinishRecv(NetAudioBuffer* buffer) + { + // TODO : finish midi and audio rendering ? + buffer->RenderToJackPorts(); + return NET_PACKET_ERROR; + } + // JackNetMasterInterface ************************************************************************************ bool JackNetMasterInterface::Init() @@ -160,23 +235,23 @@ namespace Jack uint attempt = 0; int rx_bytes = 0; - //socket + // socket if (fSocket.NewSocket() == SOCKET_ERROR) { jack_error("Can't create socket : %s", StrError(NET_ERROR_CODE)); return false; } - //timeout on receive (for init) + // timeout on receive (for init) if (fSocket.SetTimeOut(MASTER_INIT_TIMEOUT) < 0) jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE)); - //connect + // connect if (fSocket.Connect() == SOCKET_ERROR) { jack_error("Can't connect : %s", StrError(NET_ERROR_CODE)); return false; } - //send 'SLAVE_SETUP' until 'START_MASTER' received + // send 'SLAVE_SETUP' until 'START_MASTER' received jack_info("Sending parameters to %s...", fParams.fSlaveNetName); do { @@ -223,7 +298,9 @@ namespace Jack fTxHeader.fDataStream = 's'; fRxHeader.fDataStream = 'r'; - //midi net buffers + fMaxCycleOffset = fParams.fNetworkLatency; + + // midi net buffers if (fParams.fSendMidiChannels > 0) fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fTxData); @@ -232,7 +309,7 @@ namespace Jack try { - //audio net buffers + // audio net buffers if (fParams.fSendAudioChannels > 0) { switch (fParams.fSampleEncoder) { @@ -282,13 +359,13 @@ namespace Jack return false; } - //set the new timeout for the socket + // set the new timeout for the socket if (SetRxTimeout() == SOCKET_ERROR) { jack_error("Can't set rx timeout : %s", StrError(NET_ERROR_CODE)); goto error; } - //set the new rx buffer size + // set the new rx buffer size if (SetNetBufferSize() == SOCKET_ERROR) { jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE)); goto error; @@ -305,10 +382,10 @@ namespace Jack { jack_log("JackNetMasterInterface::Exit, ID %u", fParams.fID); - //stop process + // stop process fRunning = false; - //send a 'multicast euthanasia request' - new socket is required on macosx + // send a 'multicast euthanasia request' - new socket is required on macosx jack_info("Exiting '%s'", fParams.fName); SetPacketType(&fParams, KILL_MASTER); JackNetSocket mcast_socket(fMulticastIP, fSocket.GetPort()); @@ -327,9 +404,9 @@ namespace Jack void JackNetMasterInterface::FatalError() { - //fatal connection issue, exit + // fatal connection issue, exit jack_error("'%s' : %s, exiting", fParams.fName, StrError(NET_ERROR_CODE)); - //ask to the manager to properly remove the master + // ask to the manager to properly remove the master Exit(); // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine. ThreadExit(); @@ -343,7 +420,7 @@ namespace Jack /* net_error_t error = fSocket.GetError(); - //no data isn't really a network error, so just return 0 available read bytes + // no data isn't really a network error, so just return 0 available read bytes if (error == NET_NO_DATA) { return 0; } else if (error == NET_CONN_ERROR) { @@ -399,18 +476,19 @@ namespace Jack fNetAudioPlaybackBuffer->ActivePortsToNetwork(fTxData, fTxHeader.fActivePorts); memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - //PacketHeaderDisplay(&fTxHeader); + // PacketHeaderDisplay(&fTxHeader); return Send(fTxHeader.fPacketSize, 0); } int JackNetMasterInterface::DataSend() { + /* uint subproc; uint data_size; - //midi + // midi if (fParams.fSendMidiChannels > 0) { - //set global header fields and get the number of midi packets + // set global header fields and get the number of midi packets fTxHeader.fDataType = 'm'; data_size = fNetMidiCaptureBuffer->RenderFromJackPorts(); fTxHeader.fNumPacket = fNetMidiCaptureBuffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE); @@ -424,8 +502,13 @@ namespace Jack return SOCKET_ERROR; } } + */ + + if (MidiSend(fNetMidiCaptureBuffer, fParams.fSendMidiChannels, fParams.fSendAudioChannels) == SOCKET_ERROR) + return SOCKET_ERROR; - //audio + /* + // audio if (fParams.fSendAudioChannels > 0) { fTxHeader.fDataType = 'a'; fNetAudioCaptureBuffer->RenderFromJackPorts(); @@ -436,13 +519,14 @@ namespace Jack fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioCaptureBuffer->RenderToNetwork(subproc, fTxHeader.fActivePorts); memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - //PacketHeaderDisplay(&fTxHeader); + // PacketHeaderDisplay(&fTxHeader); if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; } } - return 0; + */ + return AudioSend(fNetAudioPlaybackBuffer, fParams.fSendAudioChannels); } int JackNetMasterInterface::SyncRecv() @@ -477,21 +561,20 @@ namespace Jack uint recvd_midi_pckt = 0; packet_header_t* rx_head = reinterpret_cast(fRxBuffer); - while (!fRxHeader.fIsLastPckt) - { - //how much data is queued on the rx buffer ? + while (!fRxHeader.fIsLastPckt) { + // how much data is queued on the rx buffer ? rx_bytes = Recv(fParams.fMtu, MSG_PEEK); - //error here, problem with recv, just skip the cycle (return -1) + // 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 == 'r') && (rx_head->fID == fParams.fID)) - { - //read data - switch (rx_head->fDataType) - { - case 'm': //midi + if (rx_bytes && (rx_head->fDataStream == 'r') && (rx_head->fID == fParams.fID)) { + // read data + switch (rx_head->fDataType) { + + case 'm': // midi + /* rx_bytes = Recv(rx_head->fPacketSize, 0); fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; @@ -499,9 +582,12 @@ namespace Jack // Last midi packet is received, so finish rendering... if (++recvd_midi_pckt == rx_head->fNumPacket) fNetMidiPlaybackBuffer->RenderToJackPorts(); + */ + rx_bytes = MidiRecv(rx_head, fNetMidiPlaybackBuffer, recvd_midi_pckt); break; - case 'a': //audio + case 'a': // audio + /* rx_bytes = Recv(rx_head->fPacketSize, 0); fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fSubCycle = rx_head->fSubCycle; @@ -511,13 +597,18 @@ namespace Jack // Last audio packet is received, so finish rendering... if (fRxHeader.fIsLastPckt) fNetAudioPlaybackBuffer->RenderToJackPorts(); + */ + rx_bytes = AudioRecv(rx_head, fNetAudioPlaybackBuffer); break; - case 's': //sync + case 's': // sync jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName); + /* // TODO : finish midi and audio rendering ? fNetAudioPlaybackBuffer->RenderToJackPorts(); return NET_PACKET_ERROR; + */ + return FinishRecv(fNetAudioPlaybackBuffer); } } } @@ -527,35 +618,35 @@ namespace Jack void JackNetMasterInterface::EncodeSyncPacket() { - //this method contains every step of sync packet informations coding - //first of all, reset sync packet + // This method contains every step of sync packet informations coding + // first of all, reset sync packet memset(fTxData, 0, PACKET_AVAILABLE_SIZE); - //then, first step : transport + // then, first step : transport if (fParams.fTransportSync) { // desactivated... - //EncodeTransportData(); + // EncodeTransportData(); TransportDataHToN(&fSendTransportData, &fSendTransportData); - //copy to TxBuffer + // copy to TxBuffer memcpy(fTxData, &fSendTransportData, sizeof(net_transport_data_t)); } - //then others (freewheel etc.) - //... + // then others (freewheel etc.) + // ... } void JackNetMasterInterface::DecodeSyncPacket() { - //this method contains every step of sync packet informations decoding process - //first : transport + // This method contains every step of sync packet informations decoding process + // first : transport if (fParams.fTransportSync) { - //copy received transport data to transport data structure + // copy received transport data to transport data structure memcpy(&fReturnTransportData, fRxData, sizeof(net_transport_data_t)); TransportDataNToH(&fReturnTransportData, &fReturnTransportData); // desactivated... - //DecodeTransportData(); + // DecodeTransportData(); } - //then others - //... + // then others + // ... } // JackNetSlaveInterface ************************************************************************************************ @@ -566,15 +657,15 @@ namespace Jack { jack_log("JackNetSlaveInterface::Init()"); - //set the parameters to send + // set the parameters to send strcpy(fParams.fPacketType, "params"); fParams.fProtocolVersion = SLAVE_PROTOCOL; SetPacketType(&fParams, SLAVE_AVAILABLE); - //init loop : get a master and start, do it until connection is ok + // init loop : get a master and start, do it until connection is ok net_status_t status; do { - //first, get a master, do it until a valid connection is running + // first, get a master, do it until a valid connection is running do { status = SendAvailableToMaster(); if (status == NET_SOCKET_ERROR) @@ -582,7 +673,7 @@ namespace Jack } while (status != NET_CONNECTED); - //then tell the master we are ready + // then tell the master we are ready jack_info("Initializing connection with %s...", fParams.fMasterNetName); status = SendStartToMaster(); if (status == NET_ERROR) @@ -597,16 +688,16 @@ namespace Jack bool JackNetSlaveInterface::InitConnection(int time_out) { jack_log("JackNetSlaveInterface::InitConnection()"); - unsigned int try_count = (time_out > 0) ? ((1000000 * time_out) / SLAVE_INIT_TIMEOUT) : LONG_MAX; + uint try_count = (time_out > 0) ? ((1000000 * time_out) / SLAVE_INIT_TIMEOUT) : LONG_MAX; - //set the parameters to send + // set the parameters to send strcpy(fParams.fPacketType, "params"); fParams.fProtocolVersion = SLAVE_PROTOCOL; SetPacketType(&fParams, SLAVE_AVAILABLE); net_status_t status; do { - //get a master + // get a master status = SendAvailableToMaster(try_count); if (status == NET_SOCKET_ERROR) return false; @@ -622,7 +713,7 @@ namespace Jack net_status_t status; do { - //then tell the master we are ready + // then tell the master we are ready jack_info("Initializing connection with %s...", fParams.fMasterNetName); status = SendStartToMaster(); if (status == NET_ERROR) @@ -636,41 +727,41 @@ namespace Jack net_status_t JackNetSlaveInterface::SendAvailableToMaster(long try_count) { jack_log("JackNetSlaveInterface::SendAvailableToMaster()"); - //utility + // utility session_params_t host_params; int rx_bytes = 0; - //socket + // socket if (fSocket.NewSocket() == SOCKET_ERROR) { jack_error("Fatal error : network unreachable - %s", StrError(NET_ERROR_CODE)); return NET_SOCKET_ERROR; } - //bind the socket + // bind the socket if (fSocket.Bind() == SOCKET_ERROR) { jack_error("Can't bind the socket : %s", StrError(NET_ERROR_CODE)); return NET_SOCKET_ERROR; } - //timeout on receive + // timeout on receive if (fSocket.SetTimeOut(SLAVE_INIT_TIMEOUT) == SOCKET_ERROR) jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE)); - //disable local loop + // disable local loop if (fSocket.SetLocalLoop() == SOCKET_ERROR) jack_error("Can't disable multicast loop : %s", StrError(NET_ERROR_CODE)); - //send 'AVAILABLE' until 'SLAVE_SETUP' received + // send 'AVAILABLE' until 'SLAVE_SETUP' received jack_info("Waiting for a master..."); do { - //send 'available' + // send 'available' session_params_t net_params; memset(&net_params, 0, sizeof(session_params_t)); SessionParamsHToN(&fParams, &net_params); if (fSocket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR) jack_error("Error in data send : %s", StrError(NET_ERROR_CODE)); - //filter incoming packets : don't exit while no error is detected + // filter incoming packets : don't exit while no error is detected memset(&net_params, 0, sizeof(session_params_t)); rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0); SessionParamsNToH(&net_params, &host_params); @@ -687,10 +778,10 @@ namespace Jack return NET_CONNECT_ERROR; } - //everything is OK, copy parameters + // everything is OK, copy parameters fParams = host_params; - //connect the socket + // connect the socket if (fSocket.Connect() == SOCKET_ERROR) { jack_error("Error in connect : %s", StrError(NET_ERROR_CODE)); return NET_CONNECT_ERROR; @@ -702,7 +793,7 @@ namespace Jack { jack_log("JackNetSlaveInterface::SendStartToMaster"); - //tell the master to start + // tell the master to start session_params_t net_params; memset(&net_params, 0, sizeof(session_params_t)); SetPacketType(&fParams, START_MASTER); @@ -724,7 +815,7 @@ namespace Jack fTxHeader.fDataStream = 'r'; fRxHeader.fDataStream = 's'; - //midi net buffers + // midi net buffers if (fParams.fSendMidiChannels > 0) fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fRxData); @@ -733,7 +824,7 @@ namespace Jack try { - //audio net buffers + // audio net buffers if (fParams.fSendAudioChannels > 0) { switch (fParams.fSampleEncoder) { @@ -783,7 +874,7 @@ namespace Jack return false; } - //set the new buffer sizes + // set the new buffer sizes if (SetNetBufferSize() == SOCKET_ERROR) { jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE)); goto error; @@ -799,14 +890,14 @@ namespace Jack int JackNetSlaveInterface::Recv(size_t size, int flags) { int rx_bytes = fSocket.Recv(fRxBuffer, size, flags); - //handle errors + // handle errors if (rx_bytes == SOCKET_ERROR) { /* net_error_t error = fSocket.GetError(); - //no data isn't really an error in realtime processing, so just return 0 + // no data isn't really an error in realtime processing, so just return 0 if (error == NET_NO_DATA) { jack_error("No data, is the master still running ?"); - //if a network error occurs, this exception will restart the driver + // if a network error occurs, this exception will restart the driver } else if (error == NET_CONN_ERROR) { FatalError(); } else { @@ -833,11 +924,11 @@ namespace Jack PacketHeaderHToN(header, header); int tx_bytes = fSocket.Send(fTxBuffer, size, flags); - //handle errors + // handle errors if (tx_bytes == SOCKET_ERROR) { /* net_error_t error = fSocket.GetError(); - //if a network error occurs, this exception will restart the driver + // if a network error occurs, this exception will restart the driver if (error == NET_CONN_ERROR) { FatalError(); } else { @@ -854,10 +945,10 @@ namespace Jack int rx_bytes = 0; packet_header_t* rx_head = reinterpret_cast(fRxBuffer); - //receive sync (launch the cycle) + // receive sync (launch the cycle) do { rx_bytes = Recv(fParams.fMtu, 0); - //connection issue, send will detect it, so don't skip the cycle (return 0) + // connection issue, send will detect it, so don't skip the cycle (return 0) if (rx_bytes == SOCKET_ERROR) return rx_bytes; } @@ -878,17 +969,19 @@ namespace Jack packet_header_t* rx_head = reinterpret_cast(fRxBuffer); while (!fRxHeader.fIsLastPckt) { - //how much data is queued on the rx buffer ? + // how much data is queued on the rx buffer ? rx_bytes = Recv(fParams.fMtu, MSG_PEEK); - //error here, problem with recv, just skip the cycle (return -1) + // 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) - { - case 'm': //midi + // read data + switch (rx_head->fDataType) { + + case 'm': // midi + /* rx_bytes = Recv(rx_head->fPacketSize, 0); fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; @@ -896,9 +989,12 @@ namespace Jack // Last midi packet is received, so finish rendering... if (++recvd_midi_pckt == rx_head->fNumPacket) fNetMidiCaptureBuffer->RenderToJackPorts(); + */ + rx_bytes = MidiRecv(rx_head, fNetMidiCaptureBuffer, recvd_midi_pckt); break; - case 'a': //audio + case 'a': // audio + /* rx_bytes = Recv(rx_head->fPacketSize, 0); fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fSubCycle = rx_head->fSubCycle; @@ -908,13 +1004,18 @@ namespace Jack // Last audio packet is received, so finish rendering... if (fRxHeader.fIsLastPckt) fNetAudioCaptureBuffer->RenderToJackPorts(); + */ + rx_bytes = AudioRecv(rx_head, fNetAudioCaptureBuffer); break; - case 's': //sync + case 's': // sync jack_info("NetSlave : overloaded, skipping receive"); + /* // TODO : finish midi and audio rendering ? fNetAudioCaptureBuffer->RenderToJackPorts(); return NET_PACKET_ERROR; + */ + return FinishRecv(fNetAudioCaptureBuffer); } } } @@ -925,7 +1026,7 @@ namespace Jack int JackNetSlaveInterface::SyncSend() { - //tx header + // tx header if (fParams.fSlaveSyncMode) { fTxHeader.fCycle = fRxHeader.fCycle; } else { @@ -941,33 +1042,39 @@ namespace Jack fNetAudioCaptureBuffer->ActivePortsToNetwork(fTxData, fTxHeader.fActivePorts); memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); + // PacketHeaderDisplay(&fTxHeader); return Send(fTxHeader.fPacketSize, 0); } int JackNetSlaveInterface::DataSend() { + /* uint subproc, data_size; - //midi + // midi if (fParams.fReturnMidiChannels > 0) { - //set global header fields and get the number of midi packets + // set global header fields and get the number of midi packets fTxHeader.fDataType = 'm'; data_size = fNetMidiPlaybackBuffer->RenderFromJackPorts(); fTxHeader.fNumPacket = fNetMidiPlaybackBuffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE); for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && !fParams.fReturnAudioChannels) ? 1 : 0; + // fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && !fParams.fReturnAudioChannels) ? 1 : 0; + fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && fParams.fReturnAudioChannels == 0) ? 1 : 0; fTxHeader.fPacketSize = HEADER_SIZE + fNetMidiPlaybackBuffer->RenderToNetwork(subproc, data_size); memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; } } + */ + if (MidiSend(fNetMidiPlaybackBuffer, fParams.fReturnMidiChannels, fParams.fReturnAudioChannels) == SOCKET_ERROR) + return SOCKET_ERROR; - //audio + /* + // audio if (fParams.fReturnAudioChannels > 0) { - fTxHeader.fDataType = 'a'; fNetAudioPlaybackBuffer->RenderFromJackPorts(); fTxHeader.fNumPacket = fNetAudioPlaybackBuffer->GetNumPackets(); @@ -977,45 +1084,48 @@ namespace Jack fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioPlaybackBuffer->RenderToNetwork(subproc, fTxHeader.fActivePorts); memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - //PacketHeaderDisplay(&fTxHeader); + // PacketHeaderDisplay(&fTxHeader); if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; } } return 0; + */ + + return AudioSend(fNetAudioPlaybackBuffer, fParams.fReturnAudioChannels); } - //network sync------------------------------------------------------------------------ + // network sync------------------------------------------------------------------------ void JackNetSlaveInterface::EncodeSyncPacket() { - //this method contains every step of sync packet informations coding - //first of all, reset sync packet + // This method contains every step of sync packet informations coding + // first of all, reset sync packet memset(fTxData, 0, PACKET_AVAILABLE_SIZE); - //then first step : transport + // then first step : transport if (fParams.fTransportSync) { // desactivated... - //EncodeTransportData(); + // EncodeTransportData(); TransportDataHToN(&fReturnTransportData, &fReturnTransportData); - //copy to TxBuffer + // copy to TxBuffer memcpy(fTxData, &fReturnTransportData, sizeof(net_transport_data_t)); } - //then others - //... + // then others + // ... } void JackNetSlaveInterface::DecodeSyncPacket() { - //this method contains every step of sync packet informations decoding process - //first : transport + // This method contains every step of sync packet informations decoding process + // first : transport if (fParams.fTransportSync) { - //copy received transport data to transport data structure + // copy received transport data to transport data structure memcpy(&fSendTransportData, fRxData, sizeof(net_transport_data_t)); TransportDataNToH(&fSendTransportData, &fSendTransportData); // desactivated... - //DecodeTransportData(); + // DecodeTransportData(); } - //then others - //... + // then others + // ... } } diff --git a/common/JackNetInterface.h b/common/JackNetInterface.h index 04943160..a13292e6 100644 --- a/common/JackNetInterface.h +++ b/common/JackNetInterface.h @@ -25,6 +25,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. namespace Jack { + +#define DEFAULT_MULTICAST_IP "225.3.19.154" +#define DEFAULT_PORT 19000 +#define DEFAULT_MTU 1500 + +#define SLAVE_SETUP_RETRY 5 + +#define MASTER_INIT_TIMEOUT 1000000 // in usec +#define SLAVE_INIT_TIMEOUT 1000000 // in usec + +#define NETWORK_MAX_LATENCY 10 + /** \Brief This class describes the basic Net Interface, used by both master and slave */ @@ -40,7 +52,7 @@ namespace Jack JackNetSocket fSocket; char fMulticastIP[32]; - //headers + // headers packet_header_t fTxHeader; packet_header_t fRxHeader; @@ -48,31 +60,31 @@ namespace Jack net_transport_data_t fSendTransportData; net_transport_data_t fReturnTransportData; - //network buffers + // network buffers char* fTxBuffer; char* fRxBuffer; char* fTxData; char* fRxData; - //jack buffers + // jack buffers NetMidiBuffer* fNetMidiCaptureBuffer; NetMidiBuffer* fNetMidiPlaybackBuffer; NetAudioBuffer* fNetAudioCaptureBuffer; NetAudioBuffer* fNetAudioPlaybackBuffer; - //utility methods + // utility methods int SetNetBufferSize(); void FreeNetworkBuffers(); - //virtual methods : depends on the sub class master/slave + // virtual methods : depends on the sub class master/slave virtual bool SetParams(); virtual bool Init() = 0; - //transport + // transport virtual void EncodeTransportData() = 0; virtual void DecodeTransportData() = 0; - //sync packet + // sync packet virtual void EncodeSyncPacket() = 0; virtual void DecodeSyncPacket() = 0; @@ -86,12 +98,20 @@ namespace Jack virtual void FatalError() = 0; + int MidiSend(NetMidiBuffer* buffer, int midi_channnels, int audio_channels); + int AudioSend(NetAudioBuffer* buffer, int audio_channels); + + int MidiRecv(packet_header_t* rx_head, NetMidiBuffer* buffer, uint& recvd_midi_pckt); + int AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer); + + int FinishRecv(NetAudioBuffer* buffer); + + public: + JackNetInterface(); JackNetInterface(const char* multicast_ip, int port); JackNetInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip); - public: - virtual ~JackNetInterface(); }; @@ -122,7 +142,7 @@ namespace Jack int DataRecv(); int DataSend(); - //sync packet + // sync packet void EncodeSyncPacket(); void DecodeSyncPacket(); @@ -134,12 +154,14 @@ namespace Jack void FatalError(); public: + JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCycleOffset(0), fMaxCycleOffset(0), fLastfCycleOffset(0) {} - JackNetMasterInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) - : JackNetInterface ( params, socket, multicast_ip ) + JackNetMasterInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip) + : JackNetInterface(params, socket, multicast_ip) {} - ~JackNetMasterInterface() + + virtual~JackNetMasterInterface() {} }; @@ -169,62 +191,46 @@ namespace Jack int DataRecv(); int DataSend(); - //sync packet + // sync packet void EncodeSyncPacket(); void DecodeSyncPacket(); - int Recv ( size_t size, int flags ); - int Send ( size_t size, int flags ); + int Recv(size_t size, int flags); + int Send(size_t size, int flags); void FatalError(); + void InitAPI() + { + // open Socket API with the first slave + if (fSlaveCounter++ == 0) { + if (SocketAPIInit() < 0) { + jack_error("Can't init Socket API, exiting..."); + throw std::bad_alloc(); + } + } + } + public: JackNetSlaveInterface() : JackNetInterface() { - //open Socket API with the first slave - if ( fSlaveCounter++ == 0 ) - { - if ( SocketAPIInit() < 0 ) - { - jack_error ( "Can't init Socket API, exiting..." ); - throw -1; - } - } + InitAPI(); } - JackNetSlaveInterface ( const char* ip, int port ) : JackNetInterface ( ip, port ) + JackNetSlaveInterface(const char* ip, int port) : JackNetInterface(ip, port) { - //open Socket API with the first slave - if ( fSlaveCounter++ == 0 ) - { - if ( SocketAPIInit() < 0 ) - { - jack_error ( "Can't init Socket API, exiting..." ); - throw -1; - } - } + InitAPI(); } - ~JackNetSlaveInterface() + virtual ~JackNetSlaveInterface() { - //close Socket API with the last slave - if ( --fSlaveCounter == 0 ) + // close Socket API with the last slave + if (--fSlaveCounter == 0) { SocketAPIEnd(); + } } }; } -#define DEFAULT_MULTICAST_IP "225.3.19.154" -#define DEFAULT_PORT 19000 -#define DEFAULT_MTU 1500 - -#define SLAVE_SETUP_RETRY 5 - -#define MASTER_INIT_TIMEOUT 1000000 // in usec -#define SLAVE_INIT_TIMEOUT 1000000 // in usec - -#define CYCLE_OFFSET_SLOW 10 -#define NETWORK_MAX_LATENCY CYCLE_OFFSET_SLOW - #endif diff --git a/common/JackShmMem.h b/common/JackShmMem.h index 619e81f6..13d1c43a 100644 --- a/common/JackShmMem.h +++ b/common/JackShmMem.h @@ -156,11 +156,12 @@ class JackShmReadWritePtr { if (fInfo.index < 0 && index >= 0) { jack_log("JackShmReadWritePtr::Init %ld %ld", index, fInfo.index); - if (jack_initialize_shm(server_name) < 0) - throw - 1; + if (jack_initialize_shm(server_name) < 0) { + throw std::bad_alloc(); + } fInfo.index = index; if (jack_attach_lib_shm(&fInfo)) { - throw - 2; + throw std::bad_alloc(); } GetShmAddress()->LockMemory(); } @@ -237,11 +238,12 @@ class JackShmReadWritePtr1 { if (fInfo.index < 0 && index >= 0) { jack_log("JackShmReadWritePtr1::Init %ld %ld", index, fInfo.index); - if (jack_initialize_shm(server_name) < 0) - throw - 1; + if (jack_initialize_shm(server_name) < 0) { + throw std::bad_alloc(); + } fInfo.index = index; if (jack_attach_lib_shm(&fInfo)) { - throw - 2; + throw std::bad_alloc(); } /* nobody else needs to access this shared memory any more, so @@ -324,11 +326,12 @@ class JackShmReadPtr { if (fInfo.index < 0 && index >= 0) { jack_log("JackShmPtrRead::Init %ld %ld", index, fInfo.index); - if (jack_initialize_shm(server_name) < 0) - throw - 1; + if (jack_initialize_shm(server_name) < 0) { + throw std::bad_alloc(); + } fInfo.index = index; if (jack_attach_lib_shm_read(&fInfo)) { - throw - 2; + throw std::bad_alloc(); } GetShmAddress()->LockMemory(); } diff --git a/macosx/coreaudio/JackCoreAudioAdapter.cpp b/macosx/coreaudio/JackCoreAudioAdapter.cpp index fef7d4d8..319e1ddf 100644 --- a/macosx/coreaudio/JackCoreAudioAdapter.cpp +++ b/macosx/coreaudio/JackCoreAudioAdapter.cpp @@ -391,27 +391,35 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra fPlaying = true; } - if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0) - throw -1; + if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0) { + throw std::bad_alloc(); + } - if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0) - throw -1; + if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0) { + throw std::bad_alloc(); + } - if (SetupBufferSize(fAdaptedBufferSize) < 0) - throw -1; + if (SetupBufferSize(fAdaptedBufferSize) < 0) { + throw std::bad_alloc(); + } - if (SetupSampleRate(fAdaptedSampleRate) < 0) - throw -1; + if (SetupSampleRate(fAdaptedSampleRate) < 0) { + throw std::bad_alloc(); + } - if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) - throw -1; + if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) { + throw std::bad_alloc(); + } - if (fCapturing && fCaptureChannels > 0) - if (SetupBuffers(fCaptureChannels) < 0) - throw -1; + if (fCapturing && fCaptureChannels > 0) { + if (SetupBuffers(fCaptureChannels) < 0) { + throw std::bad_alloc(); + } + } - if (AddListeners() < 0) - throw -1; + if (AddListeners() < 0) { + throw std::bad_alloc(); + } } OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id)