Commit 8a7739e0 authored by sletz's avatar sletz
Browse files

Support for BIG_ENDIAN machines in NetJack2.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3272 0c269be4-1314-0410-8aa9-9f06e86f4224
parent 0a45edf0
......@@ -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."
......
......@@ -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 )
{
......
......@@ -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:
......
......@@ -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 )
{
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 );
}
SERVER_EXPORT void SessionParamsNToH ( session_params_t* 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 );
SERVER_EXPORT void SessionParamsHToN ( session_params_t* src_params, session_params_t* dst_params )
{
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* src_params, session_params_t* dst_params )
{
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 )
{
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 );
}
SERVER_EXPORT void PacketHeaderNToH ( packet_header_t* 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 );
SERVER_EXPORT void PacketHeaderHToN ( packet_header_t* src_header, packet_header_t* dst_header )
{
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* src_header, packet_header_t* dst_header )
{
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 )
......
......@@ -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
......
......@@ -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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment