git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4511 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
@@ -23,8 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
using namespace std; | |||
#define PACKET_AVAILABLE_SIZE (fParams.fMtu - sizeof(packet_header_t)) | |||
#define HEADER_SIZE (sizeof(packet_header_t)) | |||
/* | |||
TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames, | |||
@@ -157,7 +155,7 @@ namespace Jack | |||
// set global header fields and get the number of midi packets | |||
fTxHeader.fDataType = 'm'; | |||
uint data_size = buffer->RenderFromJackPorts(); | |||
fTxHeader.fNumPacket = buffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE); | |||
fTxHeader.fNumPacket = buffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE(&fParams)); | |||
for (uint subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) { | |||
fTxHeader.fSubCycle = subproc; | |||
@@ -408,10 +406,20 @@ namespace Jack | |||
mcast_socket.Close(); | |||
} | |||
void JackNetMasterInterface::FatalError() | |||
void JackNetMasterInterface::FatalRecvError() | |||
{ | |||
// fatal connection issue, exit | |||
jack_error("'%s' : %s, exiting", fParams.fName, StrError(NET_ERROR_CODE)); | |||
jack_error("Recv connection lost error = %s, '%s' exiting", StrError(NET_ERROR_CODE), fParams.fName); | |||
// 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(); | |||
} | |||
void JackNetMasterInterface::FatalSendError() | |||
{ | |||
// fatal connection issue, exit | |||
jack_error("Send connection lost error = %s, '%s' exiting", StrError(NET_ERROR_CODE), fParams.fName); | |||
// 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. | |||
@@ -430,13 +438,13 @@ namespace Jack | |||
if (error == NET_NO_DATA) { | |||
return 0; | |||
} else if (error == NET_CONN_ERROR) { | |||
FatalError(); | |||
FatalRecvError(); | |||
} else { | |||
jack_error("Error in master receive : %s", StrError(NET_ERROR_CODE)); | |||
} | |||
*/ | |||
FatalError(); | |||
FatalRecvError(); | |||
} | |||
packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer); | |||
@@ -454,12 +462,12 @@ namespace Jack | |||
/* | |||
net_error_t error = fSocket.GetError(); | |||
if (error == NET_CONN_ERROR) { | |||
FatalError(); | |||
FatalSendError(); | |||
} else { | |||
jack_error("Error in master send : %s", StrError(NET_ERROR_CODE)); | |||
} | |||
*/ | |||
FatalError(); | |||
FatalSendError(); | |||
} | |||
return tx_bytes; | |||
} | |||
@@ -563,7 +571,7 @@ namespace Jack | |||
{ | |||
// This method contains every step of sync packet informations coding | |||
// first of all, reset sync packet | |||
memset(fTxData, 0, PACKET_AVAILABLE_SIZE); | |||
memset(fTxData, 0, PACKET_AVAILABLE_SIZE(&fParams)); | |||
// then, first step : transport | |||
if (fParams.fTransportSync) { | |||
@@ -845,12 +853,12 @@ namespace Jack | |||
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) { | |||
FatalError(); | |||
FatalRecvError(); | |||
} else { | |||
jack_error("Fatal error in slave receive : %s", StrError(NET_ERROR_CODE)); | |||
} | |||
*/ | |||
FatalError(); | |||
FatalRecvError(); | |||
} | |||
packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer); | |||
@@ -858,9 +866,15 @@ namespace Jack | |||
return rx_bytes; | |||
} | |||
void JackNetSlaveInterface::FatalError() | |||
void JackNetSlaveInterface::FatalRecvError() | |||
{ | |||
jack_error("Recv connection lost error = %s", StrError(NET_ERROR_CODE)); | |||
throw JackNetException(); | |||
} | |||
void JackNetSlaveInterface::FatalSendError() | |||
{ | |||
jack_error("Send connection lost"); | |||
jack_error("Send connection lost error = %s", StrError(NET_ERROR_CODE)); | |||
throw JackNetException(); | |||
} | |||
@@ -876,12 +890,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) { | |||
FatalError(); | |||
FatalSendError(); | |||
} else { | |||
jack_error("Fatal error in slave send : %s", StrError(NET_ERROR_CODE)); | |||
} | |||
*/ | |||
FatalError(); | |||
FatalSendError(); | |||
} | |||
return tx_bytes; | |||
} | |||
@@ -984,7 +998,7 @@ namespace Jack | |||
{ | |||
// This method contains every step of sync packet informations coding | |||
// first of all, reset sync packet | |||
memset(fTxData, 0, PACKET_AVAILABLE_SIZE); | |||
memset(fTxData, 0, PACKET_AVAILABLE_SIZE(&fParams)); | |||
// then first step : transport | |||
if (fParams.fTransportSync) { | |||
// desactivated... | |||
@@ -95,7 +95,8 @@ namespace Jack | |||
virtual int Send(size_t size, int flags) = 0; | |||
virtual int Recv(size_t size, int flags) = 0; | |||
virtual void FatalError() = 0; | |||
virtual void FatalRecvError() = 0; | |||
virtual void FatalSendError() = 0; | |||
int MidiSend(NetMidiBuffer* buffer, int midi_channnels, int audio_channels); | |||
int AudioSend(NetAudioBuffer* buffer, int audio_channels); | |||
@@ -150,7 +151,8 @@ namespace Jack | |||
bool IsSynched(); | |||
void FatalError(); | |||
void FatalRecvError(); | |||
void FatalSendError(); | |||
public: | |||
@@ -197,7 +199,8 @@ namespace Jack | |||
int Recv(size_t size, int flags); | |||
int Send(size_t size, int flags); | |||
void FatalError(); | |||
void FatalRecvError(); | |||
void FatalSendError(); | |||
void InitAPI() | |||
{ | |||
@@ -575,7 +575,7 @@ namespace Jack | |||
} | |||
//set sync callback | |||
jack_set_sync_callback ( fManagerClient, SetSyncCallback, this ); | |||
jack_set_sync_callback(fManagerClient, SetSyncCallback, this); | |||
//activate the client (for sync callback) | |||
if (jack_activate(fManagerClient) != 0) { | |||
@@ -583,20 +583,21 @@ namespace Jack | |||
} | |||
//launch the manager thread | |||
if (jack_client_create_thread ( fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this)) { | |||
if (jack_client_create_thread(fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this)) { | |||
jack_error("Can't create the network manager control thread"); | |||
} | |||
} | |||
JackNetMasterManager::~JackNetMasterManager() | |||
{ | |||
jack_log ( "JackNetMasterManager::~JackNetMasterManager" ); | |||
jack_info ( "Exiting net manager..." ); | |||
jack_log("JackNetMasterManager::~JackNetMasterManager"); | |||
jack_info("Exiting net manager..."); | |||
fRunning = false; | |||
jack_client_kill_thread ( fManagerClient, fManagerThread ); | |||
jack_client_kill_thread(fManagerClient, fManagerThread); | |||
master_list_t::iterator it; | |||
for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) | |||
delete ( *it ); | |||
for (it = fMasterList.begin(); it != fMasterList.end(); it++) { | |||
delete (*it); | |||
} | |||
fSocket.Close(); | |||
SocketAPIEnd(); | |||
} | |||
@@ -629,10 +630,11 @@ namespace Jack | |||
//check if each slave is ready to roll | |||
int ret = 1; | |||
master_list_it_t it; | |||
for (it = fMasterList.begin(); it != fMasterList.end(); it++) | |||
for (it = fMasterList.begin(); it != fMasterList.end(); it++) { | |||
if (!(*it)->IsSlaveReadyToRoll()) { | |||
ret = 0; | |||
} | |||
} | |||
jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" ); | |||
return ret; | |||
} | |||
@@ -321,19 +321,21 @@ namespace Jack | |||
} | |||
fPortBuffer = new sample_t* [fNPorts]; | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
fPortBuffer[port_index] = NULL; | |||
} | |||
fCompressedSizeByte = (kbps * params->fPeriodSize * 1024) / (params->fSampleRate * 8); | |||
fCompressedBuffer = new unsigned char* [fNPorts]; | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
fCompressedBuffer[port_index] = new unsigned char[fCompressedSizeByte]; | |||
} | |||
jack_log("NetCeltAudioBuffer fCompressedSizeByte %d", fCompressedSizeByte); | |||
res1 = (fNPorts * fCompressedSizeByte) % (params->fMtu - sizeof(packet_header_t)); | |||
res2 = (fNPorts * fCompressedSizeByte) / (params->fMtu - sizeof(packet_header_t)); | |||
res1 = (fNPorts * fCompressedSizeByte) % PACKET_AVAILABLE_SIZE(params); | |||
res2 = (fNPorts * fCompressedSizeByte) / PACKET_AVAILABLE_SIZE(params); | |||
fNumPackets = (res1) ? (res2 + 1) : res2; | |||
@@ -360,8 +362,9 @@ namespace Jack | |||
{ | |||
FreeCelt(); | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
delete [] fCompressedBuffer[port_index]; | |||
} | |||
delete [] fCompressedBuffer; | |||
delete [] fPortBuffer; | |||
@@ -370,12 +373,15 @@ namespace Jack | |||
void NetCeltAudioBuffer::FreeCelt() | |||
{ | |||
for (int i = 0; i < fNPorts; i++) { | |||
if (fCeltEncoder[i]) | |||
if (fCeltEncoder[i]) { | |||
celt_encoder_destroy(fCeltEncoder[i]); | |||
if (fCeltDecoder[i]) | |||
} | |||
if (fCeltDecoder[i]) { | |||
celt_decoder_destroy(fCeltDecoder[i]); | |||
if (fCeltMode[i]) | |||
} | |||
if (fCeltMode[i]) { | |||
celt_mode_destroy(fCeltMode[i]); | |||
} | |||
} | |||
delete [] fCeltMode; | |||
@@ -422,7 +428,7 @@ namespace Jack | |||
int res = celt_encode_float(fCeltEncoder[port_index], floatbuf, NULL, fCompressedBuffer[port_index], fCompressedSizeByte); | |||
#endif | |||
if (res != fCompressedSizeByte) { | |||
jack_error("celt_encode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res); | |||
jack_error("celt_encode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res); | |||
} | |||
} | |||
} | |||
@@ -436,7 +442,7 @@ namespace Jack | |||
int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index]); | |||
#endif | |||
if (res != CELT_OK) { | |||
jack_error("celt_decode_float error res = %d", fCompressedSizeByte, res); | |||
jack_error("celt_decode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res); | |||
} | |||
} | |||
@@ -449,12 +455,15 @@ namespace Jack | |||
{ | |||
int res = 0; | |||
// Last packet of the cycle | |||
if (sub_cycle == fNumPackets - 1) { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize); | |||
} | |||
} else { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize); | |||
} | |||
} | |||
if (sub_cycle != fLastSubCycle + 1) { | |||
@@ -470,13 +479,16 @@ namespace Jack | |||
{ | |||
port_num = fNPorts; | |||
// Last packet of the cycle | |||
if (sub_cycle == fNumPackets - 1) { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fLastSubPeriodBytesSize); | |||
} | |||
return fNPorts * fLastSubPeriodBytesSize; | |||
} else { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fSubPeriodBytesSize); | |||
} | |||
return fNPorts * fSubPeriodBytesSize; | |||
} | |||
} | |||
@@ -492,19 +504,21 @@ namespace Jack | |||
fPeriodSize = params->fPeriodSize; | |||
fPortBuffer = new sample_t* [fNPorts]; | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
fPortBuffer[port_index] = NULL; | |||
} | |||
fIntBuffer = new short* [fNPorts]; | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
fIntBuffer[port_index] = new short[fPeriodSize]; | |||
} | |||
fCompressedSizeByte = (params->fPeriodSize * sizeof(short)); | |||
jack_log("fCompressedSizeByte %d", fCompressedSizeByte); | |||
res1 = (fNPorts * fCompressedSizeByte) % (params->fMtu - sizeof(packet_header_t)); | |||
res2 = (fNPorts * fCompressedSizeByte) / (params->fMtu - sizeof(packet_header_t)); | |||
res1 = (fNPorts * fCompressedSizeByte) % PACKET_AVAILABLE_SIZE(params); | |||
res2 = (fNPorts * fCompressedSizeByte) / PACKET_AVAILABLE_SIZE(params); | |||
jack_log("res1 = %d res2 = %d", res1, res2); | |||
@@ -527,8 +541,9 @@ namespace Jack | |||
NetIntAudioBuffer::~NetIntAudioBuffer() | |||
{ | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
delete [] fIntBuffer[port_index]; | |||
} | |||
delete [] fIntBuffer; | |||
delete [] fPortBuffer; | |||
@@ -562,17 +577,19 @@ namespace Jack | |||
void NetIntAudioBuffer::RenderFromJackPorts() | |||
{ | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
for (unsigned int frame = 0; frame < fPeriodSize; frame++) | |||
for (unsigned int frame = 0; frame < fPeriodSize; frame++) { | |||
fIntBuffer[port_index][frame] = short(fPortBuffer[port_index][frame] * 32768.f); | |||
} | |||
} | |||
} | |||
void NetIntAudioBuffer::RenderToJackPorts() | |||
{ | |||
float coef = 1.f / 32768.f; | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
float coef = 1.f / 32768.f; | |||
for (unsigned int frame = 0; frame < fPeriodSize; frame++) | |||
for (unsigned int frame = 0; frame < fPeriodSize; frame++) { | |||
fPortBuffer[port_index][frame] = float(fIntBuffer[port_index][frame] * coef); | |||
} | |||
} | |||
// reset for next cycle | |||
@@ -585,11 +602,13 @@ namespace Jack | |||
int res = 0; | |||
if (sub_cycle == fNumPackets - 1) { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize); | |||
} | |||
} else { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize); | |||
} | |||
} | |||
if (sub_cycle != fLastSubCycle + 1) { | |||
@@ -605,13 +624,16 @@ namespace Jack | |||
{ | |||
port_num = fNPorts; | |||
// Last packet of the cycle | |||
if (sub_cycle == fNumPackets - 1) { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fLastSubPeriodBytesSize); | |||
} | |||
return fNPorts * fLastSubPeriodBytesSize; | |||
} else { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize); | |||
} | |||
return fNPorts * fSubPeriodBytesSize; | |||
} | |||
} | |||
@@ -46,6 +46,9 @@ using namespace std; | |||
#define OPTIMIZED_PROTOCOL | |||
#define HEADER_SIZE (sizeof(packet_header_t)) | |||
#define PACKET_AVAILABLE_SIZE(params) ((params)->fMtu - sizeof(packet_header_t)) | |||
namespace Jack | |||
{ | |||
typedef struct _session_params session_params_t; | |||
@@ -562,8 +565,9 @@ namespace Jack | |||
// Cleanup all JACK ports at the beginning of the cycle | |||
if (sub_cycle == 0) { | |||
for (int port_index = 0; port_index < fNPorts; port_index++) { | |||
if (fPortBuffer[port_index]) | |||
if (fPortBuffer[port_index]) { | |||
memset(fPortBuffer[port_index], 0, fPeriodSize * sizeof(sample_t)); | |||
} | |||
} | |||
} | |||
@@ -583,8 +587,9 @@ namespace Jack | |||
// Only copy to active ports : read the active port number then audio data | |||
int* active_port_address = (int*)(net_buffer + port_index * sub_period_bytes_size); | |||
int active_port = (int)(*active_port_address); | |||
if (fPortBuffer[port_index]) | |||
if (fPortBuffer[port_index]) { | |||
memcpy(fPortBuffer[active_port] + sub_cycle * sub_period_size, (char*)(active_port_address + 1), sub_period_bytes_size - sizeof(int)); | |||
} | |||
} | |||
if (sub_cycle != fLastSubCycle + 1) { | |||
@@ -715,6 +720,7 @@ namespace Jack | |||
int fCompressedSizeByte; | |||
jack_nframes_t fPeriodSize; | |||
int fNumPackets; | |||
float fCycleDuration; // in sec | |||
size_t fCycleSize; // needed size in bytes for an entire cycle | |||
@@ -734,7 +740,7 @@ namespace Jack | |||
public: | |||
NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps); | |||
~NetCeltAudioBuffer(); | |||
virtual ~NetCeltAudioBuffer(); | |||
// needed size in bytes for an entire cycle | |||
size_t GetCycleSize(); | |||
@@ -770,12 +776,12 @@ namespace Jack | |||
size_t fSubPeriodSize; | |||
size_t fSubPeriodBytesSize; | |||
size_t fLastSubPeriodSize;; | |||
size_t fLastSubPeriodSize; | |||
size_t fLastSubPeriodBytesSize; | |||
sample_t** fPortBuffer; | |||
char* fNetBuffer; | |||
short ** fIntBuffer; | |||
short** fIntBuffer; | |||
int fNPorts; | |||
int fLastSubCycle; | |||
@@ -783,7 +789,7 @@ namespace Jack | |||
public: | |||
NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer); | |||
~NetIntAudioBuffer(); | |||
virtual ~NetIntAudioBuffer(); | |||
// needed size in bytes for an entire cycle | |||
size_t GetCycleSize(); | |||