From 8a7739e0d68590f012575ed57b1d2d8d97c215c6 Mon Sep 17 00:00:00 2001 From: sletz Date: Wed, 28 Jan 2009 14:59:15 +0000 Subject: [PATCH] Support for BIG_ENDIAN machines in NetJack2. git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3272 0c269be4-1314-0410-8aa9-9f06e86f4224 --- ChangeLog | 4 ++ common/JackNetInterface.cpp | 87 ++++++++++++++-------- common/JackNetManager.cpp | 12 ++-- common/JackNetTool.cpp | 140 ++++++++++++++++++++++++------------ common/JackNetTool.h | 11 +-- posix/JackPosixThread.cpp | 4 +- 6 files changed, 173 insertions(+), 85 deletions(-) diff --git a/ChangeLog b/ChangeLog index b98083ab..65dc7ed2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,10 @@ Michael Voigt Jackdmp changes log --------------------------- +2009-01-28 Stephane Letz + + * Support for BIG_ENDIAN machines in NetJack2. + 2009-01-27 Stephane Letz * Better recovery of network overload situations, now "resynchronize" by skipping cycles." diff --git a/common/JackNetInterface.cpp b/common/JackNetInterface.cpp index 970324a7..b2f79811 100644 --- a/common/JackNetInterface.cpp +++ b/common/JackNetInterface.cpp @@ -195,7 +195,7 @@ namespace Jack { jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID ); - session_params_t params; + session_params_t host_params; uint attempt = 0; int rx_bytes = 0; @@ -224,16 +224,23 @@ namespace Jack jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName ); do { + session_params_t net_params; SetPacketType ( &fParams, SLAVE_SETUP ); - if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR ) + SessionParamsHToN(&fParams, &net_params); + + if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR ) jack_error ( "Error in send : ", StrError ( NET_ERROR_CODE ) ); - if ( ( ( rx_bytes = fSocket.Recv ( ¶ms, sizeof ( session_params_t ), 0 ) ) == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) ) + + memset(&net_params, 0, sizeof ( session_params_t )); + if ( ( ( rx_bytes = fSocket.Recv ( &net_params, sizeof ( session_params_t ), 0 ) ) == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) ) { jack_error ( "Problem with network." ); return false; } + + SessionParamsNToH(&net_params, &host_params); } - while ( ( GetPacketType ( ¶ms ) != START_MASTER ) && ( ++attempt < SLAVE_SETUP_RETRY ) ); + while ( ( GetPacketType ( &host_params ) != START_MASTER ) && ( ++attempt < SLAVE_SETUP_RETRY ) ); if ( attempt == SLAVE_SETUP_RETRY ) { jack_error ( "Slave doesn't respond, exiting." ); @@ -308,54 +315,65 @@ namespace Jack jack_info ( "Exiting '%s'", fParams.fName ); SetPacketType ( &fParams, KILL_MASTER ); JackNetSocket mcast_socket ( fMulticastIP, fSocket.GetPort() ); + + session_params_t net_params; + SessionParamsHToN(&fParams, &net_params); + if ( mcast_socket.NewSocket() == SOCKET_ERROR ) jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) ); - if ( mcast_socket.SendTo ( &fParams, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR ) + if ( mcast_socket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR ) jack_error ( "Can't send suicide request : %s", StrError ( NET_ERROR_CODE ) ); + mcast_socket.Close(); // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine. ThreadExit(); } - int JackNetMasterInterface::Send ( size_t size, int flags ) + int JackNetMasterInterface::Recv ( size_t size, int flags ) { - int tx_bytes; - if ( ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning ) + int rx_bytes; + if ( ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning ) { net_error_t error = fSocket.GetError(); - if ( error == NET_CONN_ERROR ) + //no data isn't really a network error, so just return 0 avalaible read bytes + if ( error == NET_NO_DATA ) + return 0; + else if ( error == NET_CONN_ERROR ) { //fatal connection issue, exit jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) ); + //ask to the manager to properly remove the master Exit(); } else - jack_error ( "Error in master send : %s", StrError ( NET_ERROR_CODE ) ); + jack_error ( "Error in master receive : %s", StrError ( NET_ERROR_CODE ) ); } - return tx_bytes; + + packet_header_t* header = reinterpret_cast(fRxBuffer); + PacketHeaderNToH(header, header); + return rx_bytes; } - - int JackNetMasterInterface::Recv ( size_t size, int flags ) + + int JackNetMasterInterface::Send ( size_t size, int flags ) { - int rx_bytes; - if ( ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning ) + int tx_bytes; + packet_header_t* header = reinterpret_cast(fTxBuffer); + PacketHeaderHToN(header, header); + + if ( ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning ) { net_error_t error = fSocket.GetError(); - //no data isn't really a network error, so just return 0 avalaible read bytes - if ( error == NET_NO_DATA ) - return 0; - else if ( error == NET_CONN_ERROR ) + if ( error == NET_CONN_ERROR ) { //fatal connection issue, exit jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) ); - //ask to the manager to properly remove the master Exit(); } else - jack_error ( "Error in master receive : %s", StrError ( NET_ERROR_CODE ) ); + jack_error ( "Error in master send : %s", StrError ( NET_ERROR_CODE ) ); } - return rx_bytes; + return tx_bytes; } bool JackNetMasterInterface::IsSynched() @@ -582,7 +600,7 @@ namespace Jack { jack_log ( "JackNetSlaveInterface::GetNetMaster()" ); //utility - session_params_t params; + session_params_t host_params; int rx_bytes = 0; //socket @@ -609,20 +627,25 @@ namespace Jack do { //send 'available' - if ( fSocket.SendTo ( &fParams, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR ) + session_params_t net_params; + 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 - rx_bytes = fSocket.CatchHost ( ¶ms, sizeof ( session_params_t ), 0 ); + memset(&net_params, 0, sizeof ( session_params_t )); + rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 ); + SessionParamsNToH(&net_params, &host_params); if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) ) { jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) ); return NET_RECV_ERROR; } } - while ( strcmp ( params.fPacketType, fParams.fPacketType ) && ( GetPacketType ( ¶ms ) != SLAVE_SETUP ) ); + while ( strcmp ( host_params.fPacketType, fParams.fPacketType ) && ( GetPacketType ( &host_params ) != SLAVE_SETUP ) ); //everything is OK, copy parameters - fParams = params; + fParams = host_params; //set the new buffer sizes if ( SetNetBufferSize() == SOCKET_ERROR ) @@ -643,8 +666,10 @@ namespace Jack jack_log ( "JackNetSlaveInterface::SendStartToMaster" ); //tell the master to start + session_params_t net_params; SetPacketType ( &fParams, START_MASTER ); - if ( fSocket.Send ( &fParams, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR ) + SessionParamsHToN(&fParams, &net_params); + if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR ) { jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) ); return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR; @@ -693,12 +718,18 @@ namespace Jack else jack_error ( "Fatal error in slave receive : %s", StrError ( NET_ERROR_CODE ) ); } + + packet_header_t* header = reinterpret_cast(fRxBuffer); + PacketHeaderNToH(header, header); return rx_bytes; } int JackNetSlaveInterface::Send ( size_t size, int flags ) { + packet_header_t* header = reinterpret_cast(fTxBuffer); + PacketHeaderHToN(header, header); int tx_bytes = fSocket.Send ( fTxBuffer, size, flags ); + //handle errors if ( tx_bytes == SOCKET_ERROR ) { diff --git a/common/JackNetManager.cpp b/common/JackNetManager.cpp index 313d4f67..23104eac 100644 --- a/common/JackNetManager.cpp +++ b/common/JackNetManager.cpp @@ -551,7 +551,7 @@ namespace Jack int attempt = 0; //data - session_params_t params; + session_params_t host_params; int rx_bytes = 0; JackNetMaster* net_master; @@ -594,7 +594,9 @@ namespace Jack //main loop, wait for data, deal with it and wait again do { - rx_bytes = fSocket.CatchHost ( ¶ms, sizeof ( session_params_t ), 0 ); + session_params_t net_params; + rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 ); + SessionParamsNToH(&net_params, &host_params); if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) ) { jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) ); @@ -606,17 +608,17 @@ namespace Jack } if ( rx_bytes == sizeof ( session_params_t ) ) { - switch ( GetPacketType ( ¶ms ) ) + switch ( GetPacketType ( &host_params ) ) { case SLAVE_AVAILABLE: - if ( ( net_master = MasterInit ( params ) ) ) + if ( ( net_master = MasterInit ( host_params ) ) ) SessionParamsDisplay ( &net_master->fParams ); else jack_error ( "Can't init new net master..." ); jack_info ( "Waiting for a slave..." ); break; case KILL_MASTER: - if ( KillMaster ( ¶ms ) ) + if ( KillMaster ( &host_params ) ) jack_info ( "Waiting for a slave..." ); break; default: diff --git a/common/JackNetTool.cpp b/common/JackNetTool.cpp index 8210aecd..713118eb 100644 --- a/common/JackNetTool.cpp +++ b/common/JackNetTool.cpp @@ -150,6 +150,48 @@ namespace Jack return fPortBuffer[index]; } +#ifdef BIG_ENDIAN + + static inline float SwapFloat(float f) + { + union + { + float f; + unsigned char b[4]; + } dat1, dat2; + + dat1.f = f; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; + } + + void NetAudioBuffer::RenderFromJackPorts ( int subcycle ) + { + for ( int port_index = 0; port_index < fNPorts; port_index++ ) { + float* src = (float*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize); + float* dst = (float*)(fNetBuffer + port_index * fSubPeriodBytesSize); + for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(float); sample++) { + dst[sample] = SwapFloat(src[sample]); + } + } + } + + void NetAudioBuffer::RenderToJackPorts ( int subcycle ) + { + for ( int port_index = 0; port_index < fNPorts; port_index++ ) { + float* src = (float*)(fNetBuffer + 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]); + } + } + } + +#else + void NetAudioBuffer::RenderFromJackPorts ( int subcycle ) { for ( int port_index = 0; port_index < fNPorts; port_index++ ) @@ -162,40 +204,44 @@ namespace Jack memcpy ( fPortBuffer[port_index] + subcycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize ); } +#endif + // SessionParams ************************************************************************************ - SERVER_EXPORT void SessionParamsHToN ( session_params_t* params ) + SERVER_EXPORT void SessionParamsHToN ( session_params_t* src_params, session_params_t* dst_params ) { - params->fPacketID = htonl ( params->fPacketID ); - params->fMtu = htonl ( params->fMtu ); - params->fID = htonl ( params->fID ); - params->fTransportSync = htonl ( params->fTransportSync ); - params->fSendAudioChannels = htonl ( params->fSendAudioChannels ); - params->fReturnAudioChannels = htonl ( params->fReturnAudioChannels ); - params->fSendMidiChannels = htonl ( params->fSendMidiChannels ); - params->fReturnMidiChannels = htonl ( params->fReturnMidiChannels ); - params->fSampleRate = htonl ( params->fSampleRate ); - params->fPeriodSize = htonl ( params->fPeriodSize ); - params->fFramesPerPacket = htonl ( params->fFramesPerPacket ); - params->fBitdepth = htonl ( params->fBitdepth ); - params->fSlaveSyncMode = htonl ( params->fSlaveSyncMode ); + memcpy(dst_params, src_params, sizeof(session_params_t)); + dst_params->fPacketID = htonl ( src_params->fPacketID ); + dst_params->fMtu = htonl ( src_params->fMtu ); + dst_params->fID = htonl ( src_params->fID ); + dst_params->fTransportSync = htonl ( src_params->fTransportSync ); + dst_params->fSendAudioChannels = htonl ( src_params->fSendAudioChannels ); + dst_params->fReturnAudioChannels = htonl ( src_params->fReturnAudioChannels ); + dst_params->fSendMidiChannels = htonl ( src_params->fSendMidiChannels ); + 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 ); } - SERVER_EXPORT void SessionParamsNToH ( session_params_t* params ) + SERVER_EXPORT void SessionParamsNToH ( session_params_t* src_params, session_params_t* dst_params ) { - params->fPacketID = ntohl ( params->fPacketID ); - params->fMtu = ntohl ( params->fMtu ); - params->fID = ntohl ( params->fID ); - params->fTransportSync = ntohl ( params->fTransportSync ); - params->fSendAudioChannels = ntohl ( params->fSendAudioChannels ); - params->fReturnAudioChannels = ntohl ( params->fReturnAudioChannels ); - params->fSendMidiChannels = ntohl ( params->fSendMidiChannels ); - params->fReturnMidiChannels = ntohl ( params->fReturnMidiChannels ); - params->fSampleRate = ntohl ( params->fSampleRate ); - params->fPeriodSize = ntohl ( params->fPeriodSize ); - params->fFramesPerPacket = ntohl ( params->fFramesPerPacket ); - params->fBitdepth = ntohl ( params->fBitdepth ); - params->fSlaveSyncMode = ntohl ( params->fSlaveSyncMode ); + memcpy(dst_params, src_params, sizeof(session_params_t)); + dst_params->fPacketID = ntohl ( src_params->fPacketID ); + dst_params->fMtu = ntohl ( src_params->fMtu ); + dst_params->fID = ntohl ( src_params->fID ); + dst_params->fTransportSync = ntohl ( src_params->fTransportSync ); + dst_params->fSendAudioChannels = ntohl ( src_params->fSendAudioChannels ); + dst_params->fReturnAudioChannels = ntohl ( src_params->fReturnAudioChannels ); + dst_params->fSendMidiChannels = ntohl ( src_params->fSendMidiChannels ); + 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 ); } SERVER_EXPORT void SessionParamsDisplay ( session_params_t* params ) @@ -279,28 +325,30 @@ namespace Jack // Packet header ********************************************************************************** - SERVER_EXPORT void PacketHeaderHToN ( packet_header_t* header ) + SERVER_EXPORT void PacketHeaderHToN ( packet_header_t* src_header, packet_header_t* dst_header ) { - header->fID = htonl ( header->fID ); - header->fMidiDataSize = htonl ( header->fMidiDataSize ); - header->fBitdepth = htonl ( header->fBitdepth ); - header->fNMidiPckt = htonl ( header->fNMidiPckt ); - header->fPacketSize = htonl ( header->fPacketSize ); - header->fCycle = ntohl ( header->fCycle ); - header->fSubCycle = htonl ( header->fSubCycle ); - header->fIsLastPckt = htonl ( header->fIsLastPckt ); + 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->fPacketSize = htonl ( src_header->fPacketSize ); + dst_header->fCycle = htonl ( src_header->fCycle ); + dst_header->fSubCycle = htonl ( src_header->fSubCycle ); + dst_header->fIsLastPckt = htonl ( src_header->fIsLastPckt ); } - SERVER_EXPORT void PacketHeaderNToH ( packet_header_t* header ) + SERVER_EXPORT void PacketHeaderNToH ( packet_header_t* src_header, packet_header_t* dst_header ) { - header->fID = ntohl ( header->fID ); - header->fMidiDataSize = ntohl ( header->fMidiDataSize ); - header->fBitdepth = ntohl ( header->fBitdepth ); - header->fNMidiPckt = ntohl ( header->fNMidiPckt ); - header->fPacketSize = ntohl ( header->fPacketSize ); - header->fCycle = ntohl ( header->fCycle ); - header->fSubCycle = ntohl ( header->fSubCycle ); - header->fIsLastPckt = ntohl ( header->fIsLastPckt ); + 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->fPacketSize = ntohl ( src_header->fPacketSize ); + dst_header->fCycle = ntohl ( src_header->fCycle ); + dst_header->fSubCycle = ntohl ( src_header->fSubCycle ); + dst_header->fIsLastPckt = ntohl ( src_header->fIsLastPckt ); } SERVER_EXPORT void PacketHeaderDisplay ( packet_header_t* header ) diff --git a/common/JackNetTool.h b/common/JackNetTool.h index a378c0b3..867cb1f3 100644 --- a/common/JackNetTool.h +++ b/common/JackNetTool.h @@ -51,6 +51,9 @@ namespace Jack - number of audio frames in one network packet (depends on the channel number) - is the NetDriver in Sync or ASync mode ? - is the NetDriver linked with the master's transport + + Data encoding : headers (session_params and packet_header) are encoded using HTN kind of functions but float data + are kept in LITLE_ENDIAN formet (to avoing 2 conversion in the more common LITLE_ENDIAN <==> LITLE_ENDIAN connection scheme. */ struct _session_params @@ -269,10 +272,10 @@ namespace Jack SERVER_EXPORT int SocketAPIInit(); SERVER_EXPORT int SocketAPIEnd(); //n<-->h functions - SERVER_EXPORT void SessionParamsHToN ( session_params_t* params ); - SERVER_EXPORT void SessionParamsNToH ( session_params_t* params ); - SERVER_EXPORT void PacketHeaderHToN ( packet_header_t* header ); - SERVER_EXPORT void PacketHeaderNToH ( packet_header_t* header ); + SERVER_EXPORT void SessionParamsHToN ( session_params_t* src_params, session_params_t* dst_params ); + SERVER_EXPORT void SessionParamsNToH ( session_params_t* src_params, session_params_t* dst_params ); + SERVER_EXPORT void PacketHeaderHToN ( packet_header_t* src_header, packet_header_t* dst_header ); + SERVER_EXPORT void PacketHeaderNToH ( packet_header_t* src_header, packet_header_t* dst_header ); //display session parameters SERVER_EXPORT void SessionParamsDisplay ( session_params_t* params ); //display packet header diff --git a/posix/JackPosixThread.cpp b/posix/JackPosixThread.cpp index 6f6ba14c..807b0868 100644 --- a/posix/JackPosixThread.cpp +++ b/posix/JackPosixThread.cpp @@ -220,7 +220,7 @@ int JackPosixThread::AcquireRealTimeImp(pthread_t thread, int priority) rtparam.sched_priority = priority; if ((res = pthread_setschedparam(thread, JACK_SCHED_POLICY, &rtparam)) != 0) { - jack_error("Cannot use real-time scheduling (RR/%d) " + jack_error("Cannot use real-time scheduling (RR/%d)" "(%d: %s)", rtparam.sched_priority, res, strerror(res)); return -1; @@ -241,7 +241,7 @@ int JackPosixThread::DropRealTimeImp(pthread_t thread) rtparam.sched_priority = 0; if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) { - jack_error("Cannot switch to normal scheduling priority(%s)\n", strerror(errno)); + jack_error("Cannot switch to normal scheduling priority(%s)", strerror(errno)); return -1; } return 0;