From 3b009644a7dd6fc51c645fb6eb9873121b9e98f5 Mon Sep 17 00:00:00 2001 From: sletz Date: Fri, 5 Mar 2010 10:50:03 +0000 Subject: [PATCH] Raise network protocol, major cleanup. git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3939 0c269be4-1314-0410-8aa9-9f06e86f4224 --- common/JackNetAPI.cpp | 16 ++- common/JackNetDriver.cpp | 5 +- common/JackNetInterface.cpp | 247 ++++++++++++++++-------------------- common/JackNetInterface.h | 14 +- common/JackNetManager.cpp | 9 +- common/JackNetTool.cpp | 68 +++++++--- common/JackNetTool.h | 206 ++++++++++++++++++++++++------ macosx/iphone/main_slave.mm | 9 +- 8 files changed, 357 insertions(+), 217 deletions(-) diff --git a/common/JackNetAPI.cpp b/common/JackNetAPI.cpp index 3ad6e771..90ce515c 100644 --- a/common/JackNetAPI.cpp +++ b/common/JackNetAPI.cpp @@ -262,7 +262,9 @@ struct JackNetExtMaster : public JackNetMasterInterface { return -1; // Set global parameters - SetParams(); + if (!SetParams()) + return -1; + AllocPorts(); return 0; } @@ -465,12 +467,12 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf int Open(jack_master_t* result) { // Init network connection - if (!JackNetSlaveInterface::InitConnection()){ + if (!JackNetSlaveInterface::InitConnection()) return -1; - } // Then set global parameters - SetParams(); + if (!SetParams()) + return -1; // Set result if (result != NULL) { @@ -494,7 +496,8 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf return -1; // Then set global parameters - SetParams(); + if (!SetParams()) + return -1; // We need to notify possibly new buffer size and sample rate (see Execute) if (fBufferSizeCallback) @@ -514,6 +517,7 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf return 0; } + void AllocPorts() { unsigned int port_index; @@ -939,7 +943,7 @@ SERVER_EXPORT void jack_log(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - //jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap); + jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap); va_end(ap); } diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index 5f5af5db..477acb28 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -142,11 +142,12 @@ namespace Jack ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" ); //init network - if ( !JackNetSlaveInterface::Init() ) + if (!JackNetSlaveInterface::Init()) return false; //set global parameters - SetParams(); + if (!SetParams()) + return false; //allocate midi ports lists fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels]; diff --git a/common/JackNetInterface.cpp b/common/JackNetInterface.cpp index 19fe53fe..38584b04 100644 --- a/common/JackNetInterface.cpp +++ b/common/JackNetInterface.cpp @@ -89,88 +89,45 @@ namespace Jack delete fNetMidiPlaybackBuffer; } - void JackNetInterface::SetFramesPerPacket() - { - jack_log ( "JackNetInterface::SetFramesPerPacket" ); - - if (fParams.fSendAudioChannels == 0 && fParams.fReturnAudioChannels == 0) { - fParams.fFramesPerPacket = fParams.fPeriodSize; - } else { - jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float (PACKET_AVAILABLE_SIZE) - / ( max ( fParams.fReturnAudioChannels, fParams.fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2. ) ) ); - fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period; - } - } - int JackNetInterface::SetNetBufferSize() { - float audio_size, midi_size; - int bufsize; //audio - audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket ); + float audio_size = (fNetAudioCaptureBuffer) + ? fNetAudioCaptureBuffer->GetCycleSize() + : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleSize() : 0; + + jack_log ("audio_size %f", audio_size); + //midi - midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) * - fParams.fPeriodSize * sizeof(sample_t) / PACKET_AVAILABLE_SIZE); + float midi_size = (fNetMidiCaptureBuffer) + ? fNetMidiCaptureBuffer->GetCycleSize() + : (fNetMidiPlaybackBuffer) ? fNetMidiPlaybackBuffer->GetCycleSize() : 0; + + jack_log ("midi_size %f", midi_size); + //bufsize = sync + audio + midi - bufsize = MAX_LATENCY * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size); + int bufsize = MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int) midi_size); jack_log("SetNetBufferSize bufsize = %d", bufsize); //tx buffer - if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR ) + if (fSocket.SetOption(SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) return SOCKET_ERROR; //rx buffer - if ( fSocket.SetOption ( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR ) + if (fSocket.SetOption(SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) return SOCKET_ERROR; return 0; } - 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 <= PACKET_AVAILABLE_SIZE) { - return 1; - } else { //get the number of needed packets (simply slice the biiig buffer) - return (fTxHeader.fMidiDataSize % PACKET_AVAILABLE_SIZE) - ? (fTxHeader.fMidiDataSize / PACKET_AVAILABLE_SIZE + 1) - : fTxHeader.fMidiDataSize / PACKET_AVAILABLE_SIZE; - } - } - - 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 0 (first subcyle) - if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) ) { - return true; - } - //else, packet(s) missing, return false - return false; - } - - void JackNetInterface::SetParams() + bool JackNetInterface::SetParams() { - //number of audio subcycles (packets) - fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket; - //TX header init strcpy ( fTxHeader.fPacketType, "header" ); fTxHeader.fID = fParams.fID; fTxHeader.fCycle = 0; fTxHeader.fSubCycle = 0; - fTxHeader.fMidiDataSize = 0; fTxHeader.fBitdepth = fParams.fBitdepth; fTxHeader.fIsLastPckt = 0; @@ -179,7 +136,6 @@ namespace Jack fRxHeader.fID = fParams.fID; fRxHeader.fCycle = 0; fRxHeader.fSubCycle = 0; - fRxHeader.fMidiDataSize = 0; fRxHeader.fBitdepth = fParams.fBitdepth; fRxHeader.fIsLastPckt = 0; @@ -192,6 +148,8 @@ namespace Jack //net audio/midi buffers'addresses fTxData = fTxBuffer + HEADER_SIZE; fRxData = fRxBuffer + HEADER_SIZE; + + return true; } // JackNetMasterInterface ************************************************************************************ @@ -220,11 +178,8 @@ namespace Jack return false; } - //set the number of complete audio frames we can put in a packet - SetFramesPerPacket(); - //send 'SLAVE_SETUP' until 'START_MASTER' received - jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName ); + jack_info ( "Sending parameters to %s...", fParams.fSlaveNetName ); do { session_params_t net_params; @@ -250,18 +205,6 @@ namespace Jack return false; } - //set the new timeout for the socket - if ( SetRxTimeout() == SOCKET_ERROR ) { - jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) ); - return false; - } - - //set the new rx buffer size - if ( SetNetBufferSize() == SOCKET_ERROR ) { - jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) ); - return false; - } - return true; } @@ -270,16 +213,22 @@ namespace Jack jack_log ( "JackNetMasterInterface::SetRxTimeout" ); float time = 0; + //slow or normal mode, short timeout on recv (2 audio subcycles) - if ( ( fParams.fNetworkMode == 's' ) || ( fParams.fNetworkMode == 'n' ) ) - time = 2000000.f * ( static_cast ( fParams.fFramesPerPacket ) / static_cast ( fParams.fSampleRate ) ); + if ((fParams.fNetworkMode == 's') || (fParams.fNetworkMode == 'n')) { + time = 2000000.f * ((fNetAudioCaptureBuffer) + ? fNetAudioCaptureBuffer->GetCycleDuration() + : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleDuration() : 0); + } //fast mode, wait for 75% of 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 ) ); + 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() + bool JackNetMasterInterface::SetParams() { jack_log ( "JackNetMasterInterface::SetParams" ); @@ -303,6 +252,28 @@ namespace Jack assert ( fNetAudioCaptureBuffer ); assert ( fNetAudioPlaybackBuffer ); + + //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 + if ( SetNetBufferSize() == SOCKET_ERROR ) { + jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) ); + goto error; + } + + return true; + + error: + + delete fNetMidiCaptureBuffer; + delete fNetMidiPlaybackBuffer; + delete fNetAudioCaptureBuffer; + delete fNetAudioPlaybackBuffer; + return false; } void JackNetMasterInterface::Exit() @@ -402,18 +373,21 @@ namespace Jack int JackNetMasterInterface::DataSend() { uint subproc; + uint data_size; + //midi if ( fParams.fSendMidiChannels > 0) { //set global header fields and get the number of midi packets fTxHeader.fDataType = 'm'; - fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts(); - fTxHeader.fNMidiPckt = GetNMidiPckt(); - for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ ) + data_size = fNetMidiCaptureBuffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = fNetMidiCaptureBuffer->GetNumPackets(); + + for ( subproc = 0; subproc < fTxHeader.fNumPacket; subproc++ ) { fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = (( subproc == (fTxHeader.fNMidiPckt - 1)) && (fParams.fSendAudioChannels == 0)) ? 1 : 0; - fTxHeader.fPacketSize = HEADER_SIZE + fNetMidiCaptureBuffer->RenderToNetwork(subproc, fTxHeader.fMidiDataSize); + fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && (fParams.fSendAudioChannels == 0)) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + fNetMidiCaptureBuffer->RenderToNetwork(subproc, data_size); memcpy ( fTxBuffer, &fTxHeader, HEADER_SIZE); if (Send (fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; @@ -424,15 +398,15 @@ namespace Jack if ( fParams.fSendAudioChannels > 0) { fTxHeader.fDataType = 'a'; - fTxHeader.fMidiDataSize = 0; - fTxHeader.fNMidiPckt = 0; - for (subproc = 0; subproc < fNSubProcess; subproc++) + data_size = fNetAudioCaptureBuffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = fNetAudioCaptureBuffer->GetNumPackets(); + + for (subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = (subproc == (fNSubProcess - 1)) ? 1 : 0; - fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioPlaybackBuffer->GetSize(); + fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioCaptureBuffer->RenderToNetwork(subproc, data_size); memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - fNetAudioCaptureBuffer->RenderFromJackPorts(subproc); if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; } @@ -506,8 +480,8 @@ namespace Jack int JackNetMasterInterface::DataRecv() { int rx_bytes = 0; - int last_cycle = 0; uint recvd_midi_pckt = 0; + uint recvd_audio_pckt = 0; packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); @@ -530,34 +504,30 @@ namespace Jack fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; fNetMidiPlaybackBuffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); - // Last midi packet is received, so finish rendering... - if ( ++recvd_midi_pckt == rx_head->fNMidiPckt ) + // Last midi packet is received, so finish rendering... + if (++recvd_midi_pckt == rx_head->fNumPacket) fNetMidiPlaybackBuffer->RenderToJackPorts(); break; case 'a': //audio rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - if (!IsNextPacket()) { - jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName); - } fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fSubCycle = rx_head->fSubCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fCycle, rx_head->fSubCycle); - last_cycle = rx_head->fCycle; + fNetAudioPlaybackBuffer->RenderFromNetwork (rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE); + // Last audio packet is received, so finish rendering... + if (fRxHeader.fIsLastPckt) + fNetAudioPlaybackBuffer->RenderToJackPorts(); break; case 's': //sync jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName); - // Finish rendering (copy to JACK ports) - fNetAudioPlaybackBuffer->FinishRenderToJackPorts(last_cycle); + // TODO : finish midi and audio rendering ? return 0; } } } - - // Finish rendering (copy to JACK ports) - fNetAudioPlaybackBuffer->FinishRenderToJackPorts(last_cycle); + return rx_bytes; } @@ -727,18 +697,11 @@ namespace Jack SessionParamsDisplay(&host_params); fParams = host_params; - //set the new buffer sizes - if ( SetNetBufferSize() == SOCKET_ERROR ) { - jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) ); - return NET_SOCKET_ERROR; - } - //connect the socket if ( fSocket.Connect() == SOCKET_ERROR ) { jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) ); return NET_CONNECT_ERROR; } - return NET_CONNECTED; } @@ -759,7 +722,7 @@ namespace Jack return NET_ROLLING; } - void JackNetSlaveInterface::SetParams() + bool JackNetSlaveInterface::SetParams() { jack_log ( "JackNetSlaveInterface::SetParams" ); @@ -783,6 +746,21 @@ namespace Jack assert ( fNetAudioCaptureBuffer ); assert ( fNetAudioPlaybackBuffer ); + + //set the new buffer sizes + if ( SetNetBufferSize() == SOCKET_ERROR ) { + jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) ); + goto error; + } + + return true; + + error: + delete fNetMidiCaptureBuffer; + delete fNetMidiPlaybackBuffer; + delete fNetAudioCaptureBuffer; + delete fNetAudioPlaybackBuffer; + return false; } int JackNetSlaveInterface::Recv ( size_t size, int flags ) @@ -852,8 +830,9 @@ namespace Jack int JackNetSlaveInterface::DataRecv() { int rx_bytes = 0; - int last_cycle = 0; + //int last_cycle = 0; uint recvd_midi_pckt = 0; + uint recvd_audio_pckt = 0; packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); @@ -876,33 +855,29 @@ namespace Jack fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; fNetMidiCaptureBuffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE); // Last midi packet is received, so finish rendering... - if ( ++recvd_midi_pckt == rx_head->fNMidiPckt ) + if ( ++recvd_midi_pckt == rx_head->fNumPacket ) fNetMidiCaptureBuffer->RenderToJackPorts(); break; case 'a': //audio rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - if (!IsNextPacket()) { - jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName); - } fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fSubCycle = rx_head->fSubCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; - fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fCycle, rx_head->fSubCycle); - last_cycle = rx_head->fCycle; + fNetAudioCaptureBuffer->RenderFromNetwork (rx_head->fCycle, rx_head->fSubCycle, rx_bytes - HEADER_SIZE); + if (fRxHeader.fIsLastPckt) { + fNetAudioCaptureBuffer->RenderToJackPorts(); + } break; case 's': //sync jack_info ( "NetSlave : overloaded, skipping receive." ); - // Finish rendering (copy to JACK ports) - fNetAudioCaptureBuffer->FinishRenderToJackPorts(last_cycle); + // TODO : finish midi and audio rendering ? return 0; } } } - // Finish rendering (copy to JACK ports) - fNetAudioCaptureBuffer->FinishRenderToJackPorts(last_cycle); fRxHeader.fCycle = rx_head->fCycle; return 0; } @@ -927,19 +902,20 @@ namespace Jack int JackNetSlaveInterface::DataSend() { uint subproc; + uint data_size; //midi if (fParams.fReturnMidiChannels > 0) { //set global header fields and get the number of midi packets fTxHeader.fDataType = 'm'; - fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts(); - fTxHeader.fNMidiPckt = GetNMidiPckt(); - for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ ) + data_size = fNetMidiPlaybackBuffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = fNetMidiPlaybackBuffer->GetNumPackets(); + for ( subproc = 0; subproc < fTxHeader.fNumPacket; subproc++ ) { fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNMidiPckt - 1)) && !fParams.fReturnAudioChannels) ? 1 : 0; - fTxHeader.fPacketSize = HEADER_SIZE + fNetMidiPlaybackBuffer->RenderToNetwork(subproc, fTxHeader.fMidiDataSize); + fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && !fParams.fReturnAudioChannels) ? 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; @@ -950,15 +926,14 @@ namespace Jack if ( fParams.fReturnAudioChannels > 0) { fTxHeader.fDataType = 'a'; - fTxHeader.fMidiDataSize = 0; - fTxHeader.fNMidiPckt = 0; - for ( subproc = 0; subproc < fNSubProcess; subproc++ ) + data_size = fNetAudioPlaybackBuffer->RenderFromJackPorts(); + fTxHeader.fNumPacket = fNetAudioPlaybackBuffer->GetNumPackets(); + for ( subproc = 0; subproc < fTxHeader.fNumPacket; subproc++ ) { fTxHeader.fSubCycle = subproc; - fTxHeader.fIsLastPckt = (subproc == (fNSubProcess - 1)) ? 1 : 0; - fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioCaptureBuffer->GetSize(); + fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0; + fTxHeader.fPacketSize = HEADER_SIZE + fNetAudioPlaybackBuffer->RenderToNetwork(subproc, data_size); memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE); - fNetAudioPlaybackBuffer->RenderFromJackPorts (subproc); if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) return SOCKET_ERROR; } diff --git a/common/JackNetInterface.h b/common/JackNetInterface.h index 55706cf7..d4214904 100644 --- a/common/JackNetInterface.h +++ b/common/JackNetInterface.h @@ -35,8 +35,7 @@ namespace Jack session_params_t fParams; JackNetSocket fSocket; char fMulticastIP[32]; - uint fNSubProcess; - + //headers packet_header_t fTxHeader; packet_header_t fRxHeader; @@ -58,13 +57,10 @@ namespace Jack NetAudioBuffer* fNetAudioPlaybackBuffer; //utility methods - void SetFramesPerPacket(); int SetNetBufferSize(); - int GetNMidiPckt(); - bool IsNextPacket(); - + //virtual methods : depends on the sub class master/slave - virtual void SetParams(); + virtual bool SetParams(); virtual bool Init() = 0; //transport @@ -103,7 +99,7 @@ namespace Jack bool Init(); int SetRxTimeout(); - void SetParams(); + bool SetParams(); void Exit(); @@ -149,7 +145,7 @@ namespace Jack net_status_t SendAvailableToMaster(); net_status_t SendStartToMaster(); - void SetParams(); + bool SetParams(); int SyncRecv(); int SyncSend(); diff --git a/common/JackNetManager.cpp b/common/JackNetManager.cpp index b42d970e..fb6d855b 100644 --- a/common/JackNetManager.cpp +++ b/common/JackNetManager.cpp @@ -113,11 +113,12 @@ namespace Jack bool JackNetMaster::Init(bool auto_connect) { //network init - if ( !JackNetMasterInterface::Init() ) + if (!JackNetMasterInterface::Init()) return false; //set global parameters - SetParams(); + if (!SetParams()) + return false; //jack client and process jack_status_t status; @@ -415,7 +416,7 @@ namespace Jack for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ ) fNetMidiPlaybackBuffer->SetBuffer ( port_index, static_cast ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index], fParams.fPeriodSize ) ) ); - for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ ) + for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ ) fNetAudioPlaybackBuffer->SetBuffer ( port_index, static_cast ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index], fParams.fPeriodSize ) ) ); @@ -601,7 +602,7 @@ namespace Jack if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR ) jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) ); - jack_info ( "Waiting for a slave..." ); + jack_log ( "sizeof (session_params_t) %d", sizeof (session_params_t) ); //main loop, wait for data, deal with it and wait again do diff --git a/common/JackNetTool.cpp b/common/JackNetTool.cpp index 0eee2474..862216a3 100644 --- a/common/JackNetTool.cpp +++ b/common/JackNetTool.cpp @@ -35,6 +35,9 @@ namespace Jack for ( int port_index = 0; port_index < fNPorts; port_index++ ) fPortBuffer[port_index] = NULL; fNetBuffer = net_buffer; + + fCycleSize = params->fMtu * (max(params->fSendMidiChannels, params->fReturnMidiChannels) * + params->fPeriodSize * sizeof(sample_t) / (params->fMtu - sizeof(packet_header_t))); } NetMidiBuffer::~NetMidiBuffer() @@ -47,6 +50,23 @@ namespace Jack { return fMaxBufsize; } + + size_t NetMidiBuffer::GetCycleSize() + { + return fCycleSize; + } + + int NetMidiBuffer::GetNumPackets() + { + /* + return (data_size % PACKET_AVAILABLE_SIZE) + ? (data_size / PACKET_AVAILABLE_SIZE + 1) + : data_size / PACKET_AVAILABLE_SIZE; + */ + + //TODO + return 0; + } void NetMidiBuffer::SetBuffer ( int index, JackMidiBuffer* buffer ) { @@ -124,10 +144,8 @@ namespace Jack return copy_size; } - // net audio buffer ********************************************************************************* - NetSingleAudioBuffer::NetSingleAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) : fPortBuffer(params, nports), fNetBuffer(net_buffer) {} @@ -139,6 +157,11 @@ namespace Jack { return fPortBuffer.GetSize(); } + + size_t NetSingleAudioBuffer::GetCycleSize() + { + return fPortBuffer.GetCycleSize(); + } void NetSingleAudioBuffer::SetBuffer ( int index, sample_t* buffer ) { @@ -150,18 +173,30 @@ namespace Jack return fPortBuffer.GetBuffer(index); } - void NetSingleAudioBuffer::RenderFromJackPorts (int subcycle) + int NetSingleAudioBuffer::RenderFromJackPorts () { - fPortBuffer.RenderFromJackPorts(fNetBuffer, subcycle); + return fPortBuffer.RenderFromJackPorts(); } - void NetSingleAudioBuffer::RenderToJackPorts (int cycle, int subcycle) + int NetSingleAudioBuffer::RenderToJackPorts () + { + return fPortBuffer.RenderToJackPorts(); + } + + //network<->buffer + int NetSingleAudioBuffer::RenderFromNetwork ( int cycle, int subcycle, size_t copy_size ) + { + return fPortBuffer.RenderFromNetwork(fNetBuffer, cycle, subcycle, copy_size); + } + + int NetSingleAudioBuffer::RenderToNetwork (int subcycle, size_t total_size ) { - fPortBuffer.RenderToJackPorts(fNetBuffer, subcycle); + return fPortBuffer.RenderToNetwork(fNetBuffer, subcycle, total_size); } // Buffered +/* NetBufferedAudioBuffer::NetBufferedAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ) { fMaxCycle = 0; @@ -172,7 +207,7 @@ namespace Jack } fJackPortBuffer = new sample_t* [nports]; - for ( int port_index = 0; port_index < nports; port_index++ ) + for ( uint32_t port_index = 0; port_index < nports; port_index++ ) fJackPortBuffer[port_index] = NULL; } @@ -185,6 +220,11 @@ namespace Jack { return fPortBuffer[0].GetSize(); } + + size_t NetBufferedAudioBuffer::GetCycleSize() + { + return fPortBuffer[0].GetCycleSize(); + } void NetBufferedAudioBuffer::SetBuffer ( int index, sample_t* buffer ) { @@ -214,6 +254,7 @@ namespace Jack fMaxCycle = std::max(fMaxCycle, cycle); fPortBuffer[(cycle + 1) % AUDIO_BUFFER_SIZE].Copy(fJackPortBuffer); // Copy internal buffer in JACK ports } + */ // SessionParams ************************************************************************************ @@ -230,7 +271,6 @@ namespace Jack dst_params->fReturnMidiChannels = htonl ( src_params->fReturnMidiChannels ); dst_params->fSampleRate = htonl ( src_params->fSampleRate ); dst_params->fPeriodSize = htonl ( src_params->fPeriodSize ); - dst_params->fFramesPerPacket = htonl ( src_params->fFramesPerPacket ); dst_params->fBitdepth = htonl ( src_params->fBitdepth ); dst_params->fSlaveSyncMode = htonl ( src_params->fSlaveSyncMode ); } @@ -248,7 +288,6 @@ namespace Jack dst_params->fReturnMidiChannels = ntohl ( src_params->fReturnMidiChannels ); dst_params->fSampleRate = ntohl ( src_params->fSampleRate ); dst_params->fPeriodSize = ntohl ( src_params->fPeriodSize ); - dst_params->fFramesPerPacket = ntohl ( src_params->fFramesPerPacket ); dst_params->fBitdepth = ntohl ( src_params->fBitdepth ); dst_params->fSlaveSyncMode = ntohl ( src_params->fSlaveSyncMode ); } @@ -282,8 +321,6 @@ namespace Jack jack_info ( "Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels ); jack_info ( "Sample rate : %u frames per second", params->fSampleRate ); jack_info ( "Period size : %u frames per period", params->fPeriodSize ); - jack_info ( "Frames per packet : %u", params->fFramesPerPacket ); - jack_info ( "Packet per period : %u", (params->fFramesPerPacket != 0) ? params->fPeriodSize / params->fFramesPerPacket : 0); jack_info ( "Bitdepth : %s", bitdepth ); jack_info ( "Slave mode : %s", ( params->fSlaveSyncMode ) ? "sync" : "async" ); jack_info ( "Network mode : %s", mode ); @@ -338,9 +375,8 @@ namespace Jack { memcpy(dst_header, src_header, sizeof(packet_header_t)); dst_header->fID = htonl ( src_header->fID ); - dst_header->fMidiDataSize = htonl ( src_header->fMidiDataSize ); dst_header->fBitdepth = htonl ( src_header->fBitdepth ); - dst_header->fNMidiPckt = htonl ( src_header->fNMidiPckt ); + dst_header->fNumPacket = htonl ( src_header->fNumPacket ); dst_header->fPacketSize = htonl ( src_header->fPacketSize ); dst_header->fCycle = htonl ( src_header->fCycle ); dst_header->fSubCycle = htonl ( src_header->fSubCycle ); @@ -351,9 +387,8 @@ namespace Jack { memcpy(dst_header, src_header, sizeof(packet_header_t)); dst_header->fID = ntohl ( src_header->fID ); - dst_header->fMidiDataSize = ntohl ( src_header->fMidiDataSize ); dst_header->fBitdepth = ntohl ( src_header->fBitdepth ); - dst_header->fNMidiPckt = ntohl ( src_header->fNMidiPckt ); + dst_header->fNumPacket = ntohl ( src_header->fNumPacket ); dst_header->fPacketSize = ntohl ( src_header->fPacketSize ); dst_header->fCycle = ntohl ( src_header->fCycle ); dst_header->fSubCycle = ntohl ( src_header->fSubCycle ); @@ -370,8 +405,7 @@ namespace Jack jack_info ( "ID : %u", header->fID ); jack_info ( "Cycle : %u", header->fCycle ); jack_info ( "SubCycle : %u", header->fSubCycle ); - jack_info ( "Midi packets : %u", header->fNMidiPckt ); - jack_info ( "Midi data size : %u", header->fMidiDataSize ); + jack_info ( "Midi packets : %u", header->fNumPacket ); jack_info ( "Last packet : '%s'", ( header->fIsLastPckt ) ? "yes" : "no" ); jack_info ( "Bitdepth : %s", bitdepth ); jack_info ( "**********************************************" ); diff --git a/common/JackNetTool.h b/common/JackNetTool.h index 4dae55a7..7c79f9ec 100644 --- a/common/JackNetTool.h +++ b/common/JackNetTool.h @@ -67,8 +67,8 @@ namespace Jack are kept in LITTLE_ENDIAN format (to avoid 2 conversions in the more common LITTLE_ENDIAN <==> LITTLE_ENDIAN connection case). */ - #define MASTER_PROTOCOL 1 - #define SLAVE_PROTOCOL 1 + #define MASTER_PROTOCOL 2 + #define SLAVE_PROTOCOL 2 struct _session_params { @@ -87,7 +87,6 @@ namespace Jack uint32_t fReturnMidiChannels; //number of slave->master midi channels uint32_t fSampleRate; //session sample rate uint32_t fPeriodSize; //period size - uint32_t fFramesPerPacket; //complete frames per packet uint32_t fBitdepth; //samples bitdepth (unused) uint32_t fSlaveSyncMode; //is the slave in sync mode ? char fNetworkMode; //fast, normal or slow mode @@ -159,14 +158,11 @@ namespace Jack char fDataStream; //s for send, r for return uint32_t fID; //unique ID of the slave uint32_t fBitdepth; //bitdepth of the data samples - uint32_t fMidiDataSize; //size of midi data in bytes - uint32_t fNMidiPckt; //number of midi packets of the cycle + uint32_t fNumPacket; //number of data packets of the cycle uint32_t fPacketSize; //packet size in bytes uint32_t fCycle; //process cycle counter uint32_t fSubCycle; //midi/audio subcycle counter uint32_t fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n') - char fASyncWrongCycle; //is the current async cycle wrong (slave's side; 'y' or 'n') - char fFree[26]; //unused }; //net timebase master @@ -199,8 +195,8 @@ namespace Jack int32_t fState; //current cycle state jack_position_t fPosition; //current cycle position }; - -//midi data *********************************************************************************** + + //midi data *********************************************************************************** /** \Brief Midi buffer and operations class @@ -226,6 +222,8 @@ namespace Jack char* fBuffer; char* fNetBuffer; JackMidiBuffer** fPortBuffer; + + size_t fCycleSize; // needed size in bytes ofr an entire cycle public: NetMidiBuffer ( session_params_t* params, uint32_t nports, char* net_buffer ); @@ -234,6 +232,11 @@ namespace Jack void Reset(); size_t GetSize(); + // needed size in bytes for an entire cycle + size_t GetCycleSize(); + + int GetNumPackets(); + //utility void DisplayEvents(); @@ -262,14 +265,21 @@ namespace Jack virtual size_t GetSize() = 0; + // needed syze in bytes ofr an entire cycle + virtual size_t GetCycleSize() = 0; + + // cycle duration in sec + virtual float GetCycleDuration() = 0; + + virtual int GetNumPackets() = 0; + //jack<->buffer - virtual void RenderFromJackPorts (int subcycle ) = 0; - virtual void RenderToJackPorts ( int cycle, int subcycle) = 0; - virtual void FinishRenderToJackPorts (int cycle) = 0; + virtual int RenderFromJackPorts () = 0; + virtual int RenderToJackPorts () = 0; //network<->buffer - //int RenderFromNetwork ( int subcycle, size_t copy_size ) = 0; - //int RenderToNetwork ( int subcycle, size_t total_size ) = 0; + virtual int RenderFromNetwork ( int cycle, int subcycle, size_t copy_size ) = 0; + virtual int RenderToNetwork (int subcycle, size_t total_size ) = 0; virtual void SetBuffer ( int index, sample_t* buffer ) = 0; virtual sample_t* GetBuffer ( int index ) = 0; @@ -292,16 +302,39 @@ namespace Jack size_t fSubPeriodBytesSize; sample_t** fPortBuffer; int fNPorts; + size_t fCycleSize; // needed size in bytes for an entire cycle + float fCycleDuration; // in dec + + int fLastSubCycle; JackPortList(session_params_t* params, uint32_t nports) { fNPorts = nports; fPeriodSize = params->fPeriodSize; - fSubPeriodSize = params->fFramesPerPacket; + + if (params->fSendAudioChannels == 0 && params->fReturnAudioChannels == 0) { + fSubPeriodSize = params->fPeriodSize; + } else { + jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float ((params->fMtu - sizeof(packet_header_t))) + / ( max ( params->fReturnAudioChannels, params->fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2. ) ) ); + fSubPeriodSize = ( period > params->fPeriodSize ) ? params->fPeriodSize : period; + } + fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t ); + fPortBuffer = new sample_t* [fNPorts]; for ( int port_index = 0; port_index < fNPorts; port_index++ ) fPortBuffer[port_index] = NULL; + + fCycleDuration = float(fSubPeriodSize) / float(params->fSampleRate); + fCycleSize = params->fMtu * ( fPeriodSize / fSubPeriodBytesSize ); + + fLastSubCycle = -1; + } + + int GetNumPackets() + { + return fPeriodSize / fSubPeriodSize; } JackPortList() @@ -338,7 +371,19 @@ namespace Jack { return fNPorts * fSubPeriodBytesSize; } - + + // needed syze in bytes ofr an entire cycle + size_t GetCycleSize() + { + return fCycleSize; + } + + // cycle duration in sec + float GetCycleDuration() + { + return fCycleDuration; + } + #ifdef __BIG_ENDIAN__ static inline float SwapFloat(float f) @@ -357,40 +402,75 @@ namespace Jack return dat2.f; } - void RenderFromJackPorts (char* net_buffer, int subcycle ) + int RenderFromJackPorts () { - for ( int port_index = 0; port_index < fNPorts; port_index++ ) { - float* src = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); - float* dst = (float*)(net_buffer + port_index * fSubPeriodBytesSize); - for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { - dst[sample] = SwapFloat(src[sample]); - } - } + return fNPorts * fSubPeriodBytesSize; // in bytes } - void RenderToJackPorts (char* net_buffer, int subcycle) + int RenderToJackPorts () { - for ( int port_index = 0; port_index < fNPorts; port_index++ ) { + return fPeriodSize * sizeof(sample_t); // in bytes TODO + } + + //network<->buffer + int RenderFromNetwork (char* net_buffer, int cycle, int subcycle, size_t copy_size ) + { + for ( int port_index = 0; port_index < fNPorts; port_index++ ) { float* src = (float*)(net_buffer + port_index * fSubPeriodBytesSize); float* dst = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { dst[sample] = SwapFloat(src[sample]); } - } + } + + return copy_size; + } + + int RenderToNetwork (char* net_buffer, int subcycle, size_t total_size ) + { + + for ( int port_index = 0; port_index < fNPorts; port_index++ ) { + float* src = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); + float* dst = (float*)(net_buffer + port_index * fSubPeriodBytesSize); + for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { + dst[sample] = SwapFloat(src[sample]); + } + } + + return fNPorts * fSubPeriodBytesSize; } #else - void RenderFromJackPorts (char* net_buffer, int subcycle ) + int RenderFromJackPorts () { - for ( int port_index = 0; port_index < fNPorts; port_index++ ) - memcpy ( net_buffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize ); + return fNPorts * fSubPeriodBytesSize; // in bytes } - void RenderToJackPorts (char* net_buffer, int subcycle) + int RenderToJackPorts () + { + fLastSubCycle = -1; + return fPeriodSize * sizeof(sample_t); // in bytes; TODO + } + + //network<->buffer + int RenderFromNetwork (char* net_buffer, int cycle, int subcycle, size_t copy_size ) { for ( int port_index = 0; port_index < fNPorts; port_index++ ) memcpy ( fPortBuffer[port_index] + subcycle * fSubPeriodSize, net_buffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize ); + if (subcycle != fLastSubCycle + 1) { + jack_error("Packet(s) missing from... %d %d", fLastSubCycle, subcycle); + } + fLastSubCycle = subcycle; + return copy_size; + } + + int RenderToNetwork (char* net_buffer,int subcycle, size_t total_size ) + { + for ( int port_index = 0; port_index < fNPorts; port_index++ ) + memcpy ( net_buffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize ); + + return fNPorts * fSubPeriodBytesSize; } #endif @@ -419,7 +499,15 @@ namespace Jack { fNPorts = nports; fPeriodSize = params->fPeriodSize; - fSubPeriodSize = params->fFramesPerPacket; + + if (params->fSendAudioChannels == 0 && params->fReturnAudioChannels == 0) { + fSubPeriodSize = params->fPeriodSize; + } else { + jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float ((params->fMtu - sizeof(packet_header_t))) + / ( max ( params->fReturnAudioChannels, params->fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2. ) ) ); + fSubPeriodSize = ( period > params->fPeriodSize ) ? params->fPeriodSize : period; + } + fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t ); fPortBuffer = new sample_t* [fNPorts]; for ( int port_index = 0; port_index < fNPorts; port_index++ ) @@ -439,18 +527,36 @@ namespace Jack ~NetSingleAudioBuffer(); size_t GetSize(); + + // needed size in bytes for an entire cycle + size_t GetCycleSize(); + + // cycle duration in sec + float GetCycleDuration() + { + return fPortBuffer.GetCycleDuration(); + } + + int GetNumPackets() + { + return fPortBuffer.GetNumPackets(); + } + //jack<->buffer - void RenderFromJackPorts (int subcycle ); - void RenderToJackPorts (int cycle, int subcycle); + int RenderFromJackPorts (); + int RenderToJackPorts (); void SetBuffer ( int index, sample_t* buffer ); sample_t* GetBuffer ( int index ); - - void FinishRenderToJackPorts (int cycle) {} + + //network<->buffer + int RenderFromNetwork ( int cycle, int subcycle, size_t copy_size ); + int RenderToNetwork (int subcycle, size_t total_size ); }; #define AUDIO_BUFFER_SIZE 8 + /* class SERVER_EXPORT NetBufferedAudioBuffer : public NetAudioBuffer { @@ -465,14 +571,36 @@ namespace Jack ~NetBufferedAudioBuffer(); size_t GetSize(); + // needed syze in bytes ofr an entire cycle + size_t GetCycleSize(); + + // cycle duration in sec + float GetCycleDuration() + { + return fPortBuffer[0].GetCycleDuration(); + } + //jack<->buffer - void RenderFromJackPorts (int subcycle ); - void RenderToJackPorts ( int cycle, int subcycle); - void FinishRenderToJackPorts (int cycle); + int RenderFromJackPorts (int subcycle ); + int RenderToJackPorts ( int cycle, int subcycle); + //void FinishRenderToJackPorts (int cycle); + + //network<->buffer + int RenderFromNetwork ( int subcycle, size_t copy_size ) + { + // TODO + return 0; + } + int RenderToNetwork ( int subcycle, size_t total_size ) + { + // TODO + return 0; + } void SetBuffer ( int index, sample_t* buffer ); sample_t* GetBuffer ( int index ); }; + */ //utility ************************************************************************************* diff --git a/macosx/iphone/main_slave.mm b/macosx/iphone/main_slave.mm index b3435fec..8e400563 100644 --- a/macosx/iphone/main_slave.mm +++ b/macosx/iphone/main_slave.mm @@ -33,7 +33,7 @@ static int net_process(jack_nframes_t buffer_size, void* data) { - //jack_adapter_pull_and_push(adapter, audio_output_buffer, audio_input_buffer, buffer_size); + jack_adapter_pull_and_push(adapter, audio_output_buffer, audio_input_buffer, buffer_size); // Process input, produce output if (audio_input == audio_output) { @@ -47,7 +47,7 @@ static int net_process(jack_nframes_t buffer_size, static void SlaveAudioCallback(int frames, float** inputs, float** outputs, void* arg) { - //jack_adapter_push_and_pull(adapter, inputs, outputs, frames); + jack_adapter_push_and_pull(adapter, inputs, outputs, frames); } //http://www.securityfocus.com/infocus/1884 @@ -62,8 +62,8 @@ int main(int argc, char *argv[]) { jack_slave_t request = { NUM_INPUT, NUM_OUTPUT, 0, 0, WIFI_MTU, -1, JackSlowMode }; jack_master_t result; - //if ((net = jack_net_slave_open("169.254.121.189", DEFAULT_PORT, "iPhone", &request, &result)) == 0) { - if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPhone", &request, &result)) == 0) { + if ((net = jack_net_slave_open("169.254.46.132", DEFAULT_PORT, "iPhone", &request, &result)) == 0) { + //if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPhone", &request, &result)) == 0) { return -1; } @@ -77,6 +77,7 @@ int main(int argc, char *argv[]) { return -1; } + TiPhoneCoreAudioRenderer audio_device(NUM_INPUT, NUM_OUTPUT); jack_set_net_slave_process_callback(net, net_process, NULL);