From 21164db0b1ac556241beb0f59a4b57a94e78d7da Mon Sep 17 00:00:00 2001 From: sletz Date: Mon, 1 Mar 2010 11:39:21 +0000 Subject: [PATCH] Cleanup. git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3926 0c269be4-1314-0410-8aa9-9f06e86f4224 --- common/JackAudioAdapterInterface.cpp | 2 - common/JackNetInterface.cpp | 71 +++++++++--------- .../iPhoneNet.xcodeproj/project.pbxproj | 34 ++++++--- macosx/iphone/icon.png | Bin 0 -> 5297 bytes 4 files changed, 60 insertions(+), 47 deletions(-) create mode 100644 macosx/iphone/icon.png diff --git a/common/JackAudioAdapterInterface.cpp b/common/JackAudioAdapterInterface.cpp index b8df9dd3..fed62e03 100644 --- a/common/JackAudioAdapterInterface.cpp +++ b/common/JackAudioAdapterInterface.cpp @@ -181,8 +181,6 @@ namespace Jack { if (fRingbufferCurSize > DEFAULT_RB_SIZE) fRingbufferCurSize = DEFAULT_RB_SIZE; - - jack_log("JackAudioAdapterInterface::ResetRingBuffers new_size = %ld", fRingbufferCurSize); for (int i = 0; i < fCaptureChannels; i++) fCaptureRingBuffer[i]->Reset(fRingbufferCurSize); diff --git a/common/JackNetInterface.cpp b/common/JackNetInterface.cpp index 1ecc04ca..6d287258 100644 --- a/common/JackNetInterface.cpp +++ b/common/JackNetInterface.cpp @@ -24,6 +24,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. using namespace std; +#define PACKET_AVAILABLE_SIZE (fParams.fMtu - sizeof(packet_header_t)) + /* TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames, probably also use BUFFER_SIZE_MAX in everything related to MIDI events @@ -61,6 +63,7 @@ namespace Jack JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket ) { + jack_log("JackNetInterface ( session_params_t& params...)"); fParams = params; strcpy(fMulticastIP, multicast_ip); fTxBuffer = NULL; @@ -93,7 +96,7 @@ namespace Jack if (fParams.fSendAudioChannels == 0 && fParams.fReturnAudioChannels == 0) { fParams.fFramesPerPacket = fParams.fPeriodSize; } else { - jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float ( fParams.fMtu - sizeof ( packet_header_t ) ) + 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; } @@ -109,7 +112,7 @@ namespace Jack audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket ); //midi midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) * - fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) ); + fParams.fPeriodSize * sizeof(sample_t) / PACKET_AVAILABLE_SIZE); //bufsize = sync + audio + midi bufsize = MAX_LATENCY * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size); @@ -128,13 +131,14 @@ namespace Jack { //even if there is no midi data, jack need an empty buffer to know there is no event to read //99% of the cases : all data in one packet - if ( fTxHeader.fMidiDataSize <= ( fParams.fMtu - sizeof ( packet_header_t ) ) ) + + if (fTxHeader.fMidiDataSize <= PACKET_AVAILABLE_SIZE) { return 1; - //else, get the number of needed packets (simply slice the biiig buffer) - int npckt = fTxHeader.fMidiDataSize / ( fParams.fMtu - sizeof ( packet_header_t ) ); - if ( fTxHeader.fMidiDataSize % ( fParams.fMtu - sizeof ( packet_header_t ) ) ) - return ++npckt; - return npckt; + } 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() @@ -162,7 +166,7 @@ namespace Jack fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket; //payload size - fPayloadSize = fParams.fMtu - sizeof ( packet_header_t ); + fPayloadSize = PACKET_AVAILABLE_SIZE; //TX header init strcpy ( fTxHeader.fPacketType, "header" ); @@ -460,10 +464,11 @@ namespace Jack // - if the network is two fast, just wait the next cycle, this mode allows a shorter cycle duration for the master // - this mode will skip the two first cycles, thus it lets time for data to be processed and queued on the socket rx buffer //the slow mode is the safest mode because it wait twice the bandwidth relative time (send/return + process) - if (fCycleOffset < 2) - return 0; - else + if (fCycleOffset < 2) { + return 0; + } else { rx_bytes = Recv ( rx_head->fPacketSize, 0 ); + } if (fCycleOffset > 2) { jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); @@ -475,13 +480,15 @@ namespace Jack // - extra latency is set to one cycle, what is the time needed to receive streams using full network bandwidth // - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter // - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it - if (fCycleOffset < 1) + if (fCycleOffset < 1) { return 0; - else + } else { rx_bytes = Recv ( rx_head->fPacketSize, 0 ); + } - if (fCycleOffset != 1) + if (fCycleOffset != 1) { jack_info("'%s' can't run in normal network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); + } break; case 'f' : @@ -491,8 +498,9 @@ namespace Jack // - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - if (fCycleOffset != 0) + if (fCycleOffset != 0) { jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset); + } break; } @@ -539,9 +547,6 @@ namespace Jack case 'a': //audio rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - // SL: 25/01/09 - // if ( !IsNextPacket() ) - // jack_error ( "Packet(s) missing from '%s'...", fParams.fName ); if (recvd_audio_pckt++ != rx_head->fSubCycle) { jack_error("Packet(s) missing from '%s'...", fParams.fSlaveNetName); } @@ -553,10 +558,6 @@ namespace Jack break; case 's': //sync - /* SL: 25/01/09 - if ( rx_head->fCycle == fTxHeader.fCycle ) - return 0; - */ jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName); return 0; } @@ -805,16 +806,15 @@ namespace Jack { net_error_t error = fSocket.GetError(); //no data isn't really an error in realtime processing, so just return 0 - if ( error == NET_NO_DATA ) + 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 - else if ( error == NET_CONN_ERROR ) - { + } else if ( error == NET_CONN_ERROR ) { jack_error ( "Connection lost." ); throw JackNetException(); - } - else + } else { jack_error ( "Fatal error in slave receive : %s", StrError ( NET_ERROR_CODE ) ); + } } packet_header_t* header = reinterpret_cast(fRxBuffer); @@ -833,13 +833,12 @@ namespace Jack { net_error_t error = fSocket.GetError(); //if a network error occurs, this exception will restart the driver - if ( error == NET_CONN_ERROR ) - { + if ( error == NET_CONN_ERROR ) { jack_error ( "Connection lost." ); throw JackNetException(); - } - else + } else { jack_error ( "Fatal error in slave send : %s", StrError ( NET_ERROR_CODE ) ); + } } return tx_bytes; } @@ -848,6 +847,7 @@ namespace Jack { int rx_bytes = 0; packet_header_t* rx_head = reinterpret_cast ( fRxBuffer ); + //receive sync (launch the cycle) do { @@ -885,17 +885,16 @@ namespace Jack fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) ); + // Last midi packet is received, so finish rendering... if ( ++recvd_midi_pckt == rx_head->fNMidiPckt ) fNetMidiCaptureBuffer->RenderToJackPorts(); break; case 'a': //audio rx_bytes = Recv ( rx_head->fPacketSize, 0 ); - //SL: 25/01/09 - // if ( !IsNextPacket() ) - // jack_error ( "Packet(s) missing..." ); if (recvd_audio_pckt++ != rx_head->fSubCycle) { - jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName); + //jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName); + jack_error("Packet(s) missing from '%s'... %d %d %d", fParams.fMasterNetName, rx_head->fCycle, recvd_audio_pckt, rx_head->fSubCycle); } fRxHeader.fCycle = rx_head->fCycle; fRxHeader.fSubCycle = rx_head->fSubCycle; diff --git a/macosx/iphone/iPhoneNet.xcodeproj/project.pbxproj b/macosx/iphone/iPhoneNet.xcodeproj/project.pbxproj index 7463ae57..5ea267ea 100755 --- a/macosx/iphone/iPhoneNet.xcodeproj/project.pbxproj +++ b/macosx/iphone/iPhoneNet.xcodeproj/project.pbxproj @@ -71,6 +71,12 @@ 4B4146AA10BD3C4300C12F0C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 4B4146AB10BD3C4300C12F0C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; 4B4146AC10BD3C4300C12F0C /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; }; + 4B9CB1371136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB1381136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB1391136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB13A1136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB13B1136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; + 4B9CB13C1136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; }; 4BBDC8FA0F5420C000465F9C /* freeverb.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BBDC8F90F5420C000465F9C /* freeverb.mm */; }; 4BC9C1F71135AB2800D22670 /* main_master.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B0772500F54022D000DC657 /* main_master.mm */; }; 4BCB37B6112D647C008C7BC1 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; @@ -160,12 +166,13 @@ 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; }; 4B2791870F72570C000536B7 /* JackGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobals.cpp; path = ../../common/JackGlobals.cpp; sourceTree = SOURCE_ROOT; }; 4B4146B010BD3C4300C12F0C /* iPhoneFaustNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaustNet.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B9CB1361136CA99007DE01A /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = SOURCE_ROOT; }; 4BBDC8F90F5420C000465F9C /* freeverb.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = freeverb.mm; sourceTree = SOURCE_ROOT; }; 4BC9C1D31135AA1800D22670 /* iPhoneNetMasterAppl-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iPhoneNetMasterAppl-Info.plist"; sourceTree = ""; }; 4BCB37CE112D647C008C7BC1 /* iPhoneFaust.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaust.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4BCB37D5112D64B4008C7BC1 /* HardwareClock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HardwareClock.cpp; sourceTree = SOURCE_ROOT; }; 4BCB37D8112D64D8008C7BC1 /* iphone-faust.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "iphone-faust.mm"; sourceTree = SOURCE_ROOT; }; - 4BCF75F210BC2FD90082C526 /* iPhoneFaustNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaustNet.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BCF75F210BC2FD90082C526 /* iPhoneThruNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneThruNet.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4BCF75F610BC30140082C526 /* audio_thru.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = audio_thru.mm; sourceTree = SOURCE_ROOT; }; 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioAdapterInterface.cpp; path = ../../common/JackAudioAdapterInterface.cpp; sourceTree = SOURCE_ROOT; }; 4BF136120F4B0B5E00218A3F /* JackAudioAdapterInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackAudioAdapterInterface.h; path = ../../common/JackAudioAdapterInterface.h; sourceTree = SOURCE_ROOT; }; @@ -263,7 +270,7 @@ 4BFF45120F4D59DB00106083 /* libjacknet.a */, 4BFF45770F4D5D9700106083 /* iPhoneFaustNet.app */, 4B0772380F54018C000DC657 /* iPhoneNetMaster.app */, - 4BCF75F210BC2FD90082C526 /* iPhoneFaustNet.app */, + 4BCF75F210BC2FD90082C526 /* iPhoneThruNet.app */, 4B4146B010BD3C4300C12F0C /* iPhoneFaustNet.app */, 4BCB37CE112D647C008C7BC1 /* iPhoneFaust.app */, ); @@ -318,6 +325,7 @@ 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( + 4B9CB1361136CA99007DE01A /* icon.png */, 28AD733E0D9D9553002E5188 /* MainWindow.xib */, 8D1107310486CEB800E47090 /* Info.plist */, 4BC9C1D31135AA1800D22670 /* iPhoneNetMasterAppl-Info.plist */, @@ -389,9 +397,9 @@ productReference = 4B0772380F54018C000DC657 /* iPhoneNetMaster.app */; productType = "com.apple.product-type.application"; }; - 4B1A940F0F49BDE000D3626B /* jacknet */ = { + 4B1A940F0F49BDE000D3626B /* libjacknet */ = { isa = PBXNativeTarget; - buildConfigurationList = 4B1A94130F49BDFF00D3626B /* Build configuration list for PBXNativeTarget "jacknet" */; + buildConfigurationList = 4B1A94130F49BDFF00D3626B /* Build configuration list for PBXNativeTarget "libjacknet" */; buildPhases = ( 4B1A940C0F49BDE000D3626B /* Headers */, 4B1A940D0F49BDE000D3626B /* Sources */, @@ -401,7 +409,7 @@ ); dependencies = ( ); - name = jacknet; + name = libjacknet; productName = jacknet; productReference = 4BFF45120F4D59DB00106083 /* libjacknet.a */; productType = "com.apple.product-type.library.static"; @@ -454,7 +462,7 @@ ); name = iPhoneThruNet; productName = iPhoneNet; - productReference = 4BCF75F210BC2FD90082C526 /* iPhoneFaustNet.app */; + productReference = 4BCF75F210BC2FD90082C526 /* iPhoneThruNet.app */; productType = "com.apple.product-type.application"; }; 4BFF455E0F4D5D9700106083 /* iPhoneFaustNet */ = { @@ -492,7 +500,7 @@ 4BCF75D810BC2FD90082C526 /* iPhoneThruNet */, 4B41469610BD3C4300C12F0C /* iPhoneFaustNet Distribution */, 4BCB37B4112D647C008C7BC1 /* iPhoneFaust */, - 4B1A940F0F49BDE000D3626B /* jacknet */, + 4B1A940F0F49BDE000D3626B /* libjacknet */, ); }; /* End PBXProject section */ @@ -503,6 +511,7 @@ buildActionMask = 2147483647; files = ( 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */, + 4B9CB1381136CA99007DE01A /* icon.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -511,6 +520,7 @@ buildActionMask = 2147483647; files = ( 4B0772210F54018C000DC657 /* MainWindow.xib in Resources */, + 4B9CB1371136CA99007DE01A /* icon.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -519,6 +529,7 @@ buildActionMask = 2147483647; files = ( 4B41469810BD3C4300C12F0C /* MainWindow.xib in Resources */, + 4B9CB13B1136CA99007DE01A /* icon.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -527,6 +538,7 @@ buildActionMask = 2147483647; files = ( 4BCB37B6112D647C008C7BC1 /* MainWindow.xib in Resources */, + 4B9CB13C1136CA99007DE01A /* icon.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -535,6 +547,7 @@ buildActionMask = 2147483647; files = ( 4BCF75DA10BC2FD90082C526 /* MainWindow.xib in Resources */, + 4B9CB13A1136CA99007DE01A /* icon.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -543,6 +556,7 @@ buildActionMask = 2147483647; files = ( 4BFF45600F4D5D9700106083 /* MainWindow.xib in Resources */, + 4B9CB1391136CA99007DE01A /* icon.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -737,7 +751,7 @@ "$(inherited)", "\"$(SRCROOT)/build/Debug-iphonesimulator\"", ); - PRODUCT_NAME = iPhoneNetSlave; + PRODUCT_NAME = NetJackSlave; }; name = Release; }; @@ -808,6 +822,7 @@ MACH_O_TYPE = staticlib; PREBINDING = NO; PRODUCT_NAME = jacknet; + SDKROOT = iphoneos3.1.3; STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = static; }; name = Debug; @@ -828,6 +843,7 @@ ); PREBINDING = NO; PRODUCT_NAME = jacknet; + SDKROOT = iphoneos3.1.3; ZERO_LINK = NO; }; name = Release; @@ -1083,7 +1099,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4B1A94130F49BDFF00D3626B /* Build configuration list for PBXNativeTarget "jacknet" */ = { + 4B1A94130F49BDFF00D3626B /* Build configuration list for PBXNativeTarget "libjacknet" */ = { isa = XCConfigurationList; buildConfigurations = ( 4B1A94110F49BDE100D3626B /* Debug */, diff --git a/macosx/iphone/icon.png b/macosx/iphone/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9e312ea68368e826171b0212a15a548c4e34a78a GIT binary patch literal 5297 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 DmEt5- literal 0 HcmV?d00001