Browse Source

Support for BIG_ENDIAN machines in NetJack2.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3272 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.9.1
sletz 17 years ago
parent
commit
8a7739e0d6
6 changed files with 173 additions and 85 deletions
  1. +4
    -0
      ChangeLog
  2. +59
    -28
      common/JackNetInterface.cpp
  3. +7
    -5
      common/JackNetManager.cpp
  4. +94
    -46
      common/JackNetTool.cpp
  5. +7
    -4
      common/JackNetTool.h
  6. +2
    -2
      posix/JackPosixThread.cpp

+ 4
- 0
ChangeLog View File

@@ -23,6 +23,10 @@ Michael Voigt
Jackdmp changes log
---------------------------

2009-01-28 Stephane Letz <letz@grame.fr>

* Support for BIG_ENDIAN machines in NetJack2.

2009-01-27 Stephane Letz <letz@grame.fr>

* Better recovery of network overload situations, now "resynchronize" by skipping cycles."


+ 59
- 28
common/JackNetInterface.cpp View File

@@ -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 ( &params, 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 ( &params ) != 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<packet_header_t*>(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<packet_header_t*>(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 ( &params, 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 ( &params ) != 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<packet_header_t*>(fRxBuffer);
PacketHeaderNToH(header, header);
return rx_bytes;
}

int JackNetSlaveInterface::Send ( size_t size, int flags )
{
packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
PacketHeaderHToN(header, header);
int tx_bytes = fSocket.Send ( fTxBuffer, size, flags );
//handle errors
if ( tx_bytes == SOCKET_ERROR )
{


+ 7
- 5
common/JackNetManager.cpp View File

@@ -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 ( &params, 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 ( &params ) )
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 ( &params ) )
if ( KillMaster ( &host_params ) )
jack_info ( "Waiting for a slave..." );
break;
default:


+ 94
- 46
common/JackNetTool.cpp View File

@@ -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 )


+ 7
- 4
common/JackNetTool.h View File

@@ -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


+ 2
- 2
posix/JackPosixThread.cpp View File

@@ -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;


Loading…
Cancel
Save