Commit e03d1ddd authored by sletz's avatar sletz
Browse files

Improve error management in JackNetDriver.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4249 0c269be4-1314-0410-8aa9-9f06e86f4224
parent fdcb49c0
......@@ -40,6 +40,7 @@ Valerio Pilo
* Cleanup JackThreadedDriver::Stop.
* Correct JackNetOneDriver::Close.
* Correction in jackdmp.cpp: notify_server_stop should be done after server destruction.
* Improve error management in JackNetDriver.
2011-03-30 Stephane Letz <letz@grame.fr>
......
......@@ -82,6 +82,9 @@ int JackAudioDriver::Open(jack_nframes_t buffer_size,
fCaptureChannels = inchannels;
fPlaybackChannels = outchannels;
fWithMonitorPorts = monitor;
memset(fCapturePortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
memset(fPlaybackPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
memset(fMonitorPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
return JackDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
}
......@@ -98,6 +101,9 @@ int JackAudioDriver::Open(bool capturing,
fCaptureChannels = inchannels;
fPlaybackChannels = outchannels;
fWithMonitorPorts = monitor;
memset(fCapturePortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
memset(fPlaybackPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
memset(fMonitorPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
}
......@@ -389,20 +395,23 @@ void JackAudioDriver::WaitUntilNextCycle()
jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index)
{
assert(fCapturePortList[port_index]);
return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize);
return fCapturePortList[port_index]
? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize)
: NULL;
}
jack_default_audio_sample_t* JackAudioDriver::GetOutputBuffer(int port_index)
{
assert(fPlaybackPortList[port_index]);
return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize);
return fPlaybackPortList[port_index]
? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize)
: NULL;
}
jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index)
{
assert(fPlaybackPortList[port_index]);
return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize);
return fPlaybackPortList[port_index]
? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize)
: NULL;
}
int JackAudioDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
......
......@@ -142,8 +142,10 @@ namespace Jack
( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
//init network
if ( !JackNetSlaveInterface::Init() )
if (!JackNetSlaveInterface::Init()) {
jack_error("Starting network fails...");
return false;
}
//set global parameters
SetParams();
......@@ -163,14 +165,13 @@ namespace Jack
}
//register jack ports
if ( AllocPorts() != 0 )
{
jack_error ( "Can't allocate ports." );
if (AllocPorts() != 0) {
jack_error("Can't allocate ports.");
return false;
}
//init done, display parameters
SessionParamsDisplay ( &fParams );
SessionParamsDisplay(&fParams);
//monitor
#ifdef JACK_MONITOR
......
......@@ -24,9 +24,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
using namespace std;
/*
TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames,
probably also use BUFFER_SIZE_MAX in everything related to MIDI events
/*
TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames,
probably also use BUFFER_SIZE_MAX in everything related to MIDI events
handling (see MidiBufferInit in JackMidiPort.cpp)
*/
......@@ -212,7 +212,7 @@ namespace Jack
//timeout on receive (for init)
if ( fSocket.SetTimeOut ( MASTER_INIT_TIMEOUT ) < 0 )
jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
//connect
if ( fSocket.Connect() == SOCKET_ERROR ) {
jack_error ( "Can't connect : %s", StrError ( NET_ERROR_CODE ) );
......@@ -230,17 +230,17 @@ namespace Jack
memset(&net_params, 0, sizeof ( session_params_t ));
SetPacketType ( &fParams, SLAVE_SETUP );
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 ) );
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 ( &host_params ) != START_MASTER ) && ( ++attempt < SLAVE_SETUP_RETRY ) );
......@@ -315,7 +315,7 @@ namespace Jack
jack_info ( "Exiting '%s'", fParams.fName );
SetPacketType ( &fParams, KILL_MASTER );
JackNetSocket mcast_socket ( fMulticastIP, fSocket.GetPort() );
session_params_t net_params;
memset(&net_params, 0, sizeof ( session_params_t ));
SessionParamsHToN(&fParams, &net_params);
......@@ -324,7 +324,7 @@ namespace Jack
jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
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();
}
......@@ -343,25 +343,25 @@ namespace Jack
jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
//ask to the manager to properly remove the master
Exit();
// UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
ThreadExit();
}
else
jack_error ( "Error in master receive : %s", StrError ( NET_ERROR_CODE ) );
}
packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
PacketHeaderNToH(header, header);
return rx_bytes;
}
int JackNetMasterInterface::Send ( size_t size, int flags )
{
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();
......@@ -370,7 +370,7 @@ namespace Jack
//fatal connection issue, exit
jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
Exit();
// UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
ThreadExit();
}
......@@ -379,7 +379,7 @@ namespace Jack
}
return tx_bytes;
}
bool JackNetMasterInterface::IsSynched()
{
if (fParams.fNetworkMode == 's') {
......@@ -388,7 +388,7 @@ namespace Jack
return true;
}
}
int JackNetMasterInterface::SyncSend()
{
fTxHeader.fCycle++;
......@@ -446,12 +446,12 @@ namespace Jack
{
packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
int rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
return rx_bytes;
fCycleOffset = fTxHeader.fCycle - rx_head->fCycle;
switch ( fParams.fNetworkMode )
{
case 's' :
......@@ -464,7 +464,7 @@ namespace Jack
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);
}
......@@ -479,8 +479,8 @@ namespace Jack
return 0;
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;
......@@ -490,7 +490,7 @@ namespace Jack
// - here, receive data, we can't keep it queued on the rx buffer,
// - 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)
jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
break;
......@@ -499,7 +499,7 @@ namespace Jack
fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
return rx_bytes;
}
int JackNetMasterInterface::DataRecv()
{
int rx_bytes = 0;
......@@ -507,12 +507,12 @@ namespace Jack
uint recvd_midi_pckt = 0;
uint recvd_audio_pckt = 0;
packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
while ( !fRxHeader.fIsLastPckt )
{
//how much data is queued on the rx buffer ?
rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
if ( rx_bytes == SOCKET_ERROR )
return rx_bytes;
//if no data
......@@ -564,7 +564,7 @@ namespace Jack
}
return rx_bytes;
}
void JackNetMasterInterface::EncodeSyncPacket()
{
//this method contains every step of sync packet informations coding
......@@ -632,9 +632,9 @@ namespace Jack
return true;
}
// Separate the connection protocol into two separated step
bool JackNetSlaveInterface::InitConnection()
{
jack_log ( "JackNetSlaveInterface::InitConnection()" );
......@@ -653,10 +653,10 @@ namespace Jack
return false;
}
while (status != NET_CONNECTED);
return true;
}
bool JackNetSlaveInterface::InitRendering()
{
jack_log("JackNetSlaveInterface::InitRendering()");
......@@ -670,8 +670,8 @@ namespace Jack
if (status == NET_ERROR)
return false;
}
while (status != NET_ROLLING);
while (status != NET_ROLLING);
return true;
}
......@@ -695,7 +695,7 @@ namespace Jack
}
//timeout on receive
if ( fSocket.SetTimeOut ( SLAVE_INIT_TIMEOUT ) == SOCKET_ERROR )
if ( fSocket.SetTimeOut ( SLAVE_INIT_TIMEOUT ) == SOCKET_ERROR )
jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
//disable local loop
......@@ -712,7 +712,7 @@ namespace Jack
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
memset(&net_params, 0, sizeof ( session_params_t ));
rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
......@@ -762,7 +762,7 @@ namespace Jack
void JackNetSlaveInterface::SetParams()
{
jack_log ( "JackNetSlaveInterface::SetParams" );
jack_log("JackNetSlaveInterface::SetParams");
JackNetInterface::SetParams();
......@@ -801,7 +801,7 @@ 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;
......@@ -812,7 +812,7 @@ namespace Jack
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 )
{
......@@ -842,7 +842,7 @@ namespace Jack
return rx_bytes;
}
while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's'));
fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
return rx_bytes;
}
......@@ -953,7 +953,7 @@ namespace Jack
}
return 0;
}
//network sync------------------------------------------------------------------------
void JackNetSlaveInterface::EncodeSyncPacket()
{
......@@ -970,7 +970,7 @@ namespace Jack
//then others
//...
}
void JackNetSlaveInterface::DecodeSyncPacket()
{
//this method contains every step of sync packet informations decoding process
......
......@@ -151,11 +151,13 @@ namespace Jack
void NetAudioBuffer::SetBuffer ( int index, sample_t* buffer )
{
assert(fPortBuffer);
fPortBuffer[index] = buffer;
}
sample_t* NetAudioBuffer::GetBuffer ( int index )
{
assert(fPortBuffer);
return fPortBuffer[index];
}
......
......@@ -26,11 +26,11 @@
namespace Jack
{
/*!
\brief To be used as a wrapper of JackNetDriver.
\brief To be used as a wrapper of JackNetDriver.
The idea is to behave as the "dummy" driver, until the network connection is really started and processing starts.
The idea is to behave as the "dummy" driver, until the network connection is really started and processing starts.
The Execute method will call the ProcessNull method until the decorated driver Init method returns.
A helper JackDriverStarter thread is used for that purpose.
*/
......@@ -38,54 +38,57 @@ A helper JackDriverStarter thread is used for that purpose.
class SERVER_EXPORT JackWaitThreadedDriver : public JackThreadedDriver
{
private:
struct SERVER_EXPORT JackDriverStarter : public JackRunnableInterface
struct SERVER_EXPORT JackDriverStarter : public JackRunnableInterface
{
JackDriver* fDriver;
JackThread fThread;
volatile bool fRunning;
JackDriverStarter(JackDriver* driver)
:fDriver(driver),fThread(this),fRunning(false)
{}
~JackDriverStarter()
{
fThread.Kill();
}
int Start()
{
fRunning = false;
return fThread.Start();
}
// JackRunnableInterface interface
bool Execute()
{
// Blocks until decorated driver is started (that is when it's Init method returns).
fDriver->Initialize();
fRunning = true;
if (fDriver->Initialize()) {
fRunning = true;
} else {
jack_error("Initing net driver fails...");
}
return false;
}
};
JackDriverStarter fStarter;
public:
JackWaitThreadedDriver(JackDriver* netdriver)
:JackThreadedDriver(netdriver),fStarter(netdriver)
JackWaitThreadedDriver(JackDriver* net_driver)
:JackThreadedDriver(net_driver), fStarter(net_driver)
{}
virtual ~JackWaitThreadedDriver()
{}
// JackRunnableInterface interface
bool Init();
bool Execute();
};
};
} // end of namespace
......
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