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(); | |||