@@ -369,29 +369,33 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
void FreePorts() | void FreePorts() | ||||
{ | { | ||||
if (fAudioPlaybackBuffer) { | if (fAudioPlaybackBuffer) { | ||||
for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) | |||||
for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) { | |||||
delete[] fAudioPlaybackBuffer[audio_port_index]; | delete[] fAudioPlaybackBuffer[audio_port_index]; | ||||
} | |||||
delete[] fAudioPlaybackBuffer; | delete[] fAudioPlaybackBuffer; | ||||
fAudioPlaybackBuffer = NULL; | fAudioPlaybackBuffer = NULL; | ||||
} | } | ||||
if (fMidiPlaybackBuffer) { | if (fMidiPlaybackBuffer) { | ||||
for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) | |||||
for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | |||||
delete[] (fMidiPlaybackBuffer[midi_port_index]); | delete[] (fMidiPlaybackBuffer[midi_port_index]); | ||||
} | |||||
delete[] fMidiPlaybackBuffer; | delete[] fMidiPlaybackBuffer; | ||||
fMidiPlaybackBuffer = NULL; | fMidiPlaybackBuffer = NULL; | ||||
} | } | ||||
if (fAudioCaptureBuffer) { | if (fAudioCaptureBuffer) { | ||||
for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) | |||||
for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) { | |||||
delete[] fAudioCaptureBuffer[audio_port_index]; | delete[] fAudioCaptureBuffer[audio_port_index]; | ||||
} | |||||
delete[] fAudioCaptureBuffer; | delete[] fAudioCaptureBuffer; | ||||
fAudioCaptureBuffer = NULL; | fAudioCaptureBuffer = NULL; | ||||
} | } | ||||
if (fMidiCaptureBuffer) { | if (fMidiCaptureBuffer) { | ||||
for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) | |||||
for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | |||||
delete[] fMidiCaptureBuffer[midi_port_index]; | delete[] fMidiCaptureBuffer[midi_port_index]; | ||||
} | |||||
delete[] fMidiCaptureBuffer; | delete[] fMidiCaptureBuffer; | ||||
fMidiCaptureBuffer = NULL; | fMidiCaptureBuffer = NULL; | ||||
} | } | ||||
@@ -399,7 +403,6 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) | int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) | ||||
{ | { | ||||
try { | try { | ||||
assert(audio_input == fParams.fReturnAudioChannels); | assert(audio_input == fParams.fReturnAudioChannels); | ||||
@@ -412,23 +415,44 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]); | fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]); | ||||
} | } | ||||
/* | |||||
// TODO : use with netmaster/netdriver code | |||||
//receive sync | //receive sync | ||||
int res = SyncRecv(); | int res = SyncRecv(); | ||||
if ((res == 0) || (res == SOCKET_ERROR)) { | if ((res == 0) || (res == SOCKET_ERROR)) { | ||||
return res; | return res; | ||||
} | } | ||||
DecodeSyncPacket(); | DecodeSyncPacket(); | ||||
*/ | |||||
int res = SyncRecv(); | |||||
switch (res) { | |||||
case 0: | |||||
case SOCKET_ERROR: | |||||
return res; | |||||
case NET_PACKET_ERROR: | |||||
// Since sync packet is incorrect, don't decode it and continue with data | |||||
break; | |||||
default: | |||||
//decode sync | |||||
DecodeSyncPacket(); | |||||
break; | |||||
} | |||||
return DataRecv(); | return DataRecv(); | ||||
} catch (JackNetException& e) { | } catch (JackNetException& e) { | ||||
jack_error("Connection lost."); | |||||
jack_error("Lost connection"); | |||||
return -1; | return -1; | ||||
} | } | ||||
} | |||||
} | |||||
int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) | |||||
{ | |||||
int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) | |||||
{ | |||||
try { | try { | ||||
assert(audio_output == fParams.fSendAudioChannels); | assert(audio_output == fParams.fSendAudioChannels); | ||||
@@ -441,11 +465,11 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); | fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]); | ||||
} | } | ||||
if (IsSynched()) { // only send if connection is "synched" | if (IsSynched()) { // only send if connection is "synched" | ||||
EncodeSyncPacket(); | EncodeSyncPacket(); | ||||
// send sync | |||||
if (SyncSend() == SOCKET_ERROR) { | if (SyncSend() == SOCKET_ERROR) { | ||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
} | } | ||||
@@ -462,7 +486,7 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
return 0; | return 0; | ||||
} catch (JackNetException& e) { | } catch (JackNetException& e) { | ||||
jack_error("Connection lost."); | |||||
jack_error("Lost connection"); | |||||
return -1; | return -1; | ||||
} | } | ||||
} | } | ||||
@@ -749,13 +773,34 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
int Read() | int Read() | ||||
{ | { | ||||
// TODO : use with netmaster/netdriver code | |||||
//receive sync (launch the cycle) | //receive sync (launch the cycle) | ||||
/* | |||||
if (SyncRecv() == SOCKET_ERROR) { | if (SyncRecv() == SOCKET_ERROR) { | ||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
} | } | ||||
DecodeSyncPacket(); | DecodeSyncPacket(); | ||||
return DataRecv(); | return DataRecv(); | ||||
*/ | |||||
switch (SyncRecv()) { | |||||
case SOCKET_ERROR: | |||||
return SOCKET_ERROR; | |||||
case NET_PACKET_ERROR: | |||||
// Since sync packet is incorrect, don't decode it and continue with data | |||||
break; | |||||
default: | |||||
//decode sync | |||||
//if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified | |||||
DecodeSyncPacket(); | |||||
break; | |||||
} | |||||
return DataRecv(); | |||||
} | } | ||||
int Write() | int Write() | ||||
@@ -351,11 +351,31 @@ namespace Jack | |||||
{ | { | ||||
//don't return -1 in case of sync recv failure | //don't return -1 in case of sync recv failure | ||||
//we need the process to continue for network error detection | //we need the process to continue for network error detection | ||||
/* | |||||
if (SyncRecv() == SOCKET_ERROR) { | if (SyncRecv() == SOCKET_ERROR) { | ||||
return 0; | return 0; | ||||
} | } | ||||
DecodeSyncPacket(); | DecodeSyncPacket(); | ||||
*/ | |||||
//don't return -1 in case of sync recv failure | |||||
//we need the process to continue for network error detection | |||||
switch (SyncRecv()) { | |||||
case SOCKET_ERROR: | |||||
return 0; | |||||
case NET_PACKET_ERROR: | |||||
// Since sync packet is incorrect, don't decode it and continue with data | |||||
break; | |||||
default: | |||||
//decode sync | |||||
DecodeSyncPacket(); | |||||
break; | |||||
} | |||||
return DataRecv(); | return DataRecv(); | ||||
} | } | ||||
@@ -507,10 +507,25 @@ namespace Jack | |||||
fNetTimeMon->New(); | fNetTimeMon->New(); | ||||
#endif | #endif | ||||
//receive sync (launch the cycle) | |||||
switch (SyncRecv()) { | |||||
case SOCKET_ERROR: | |||||
return SOCKET_ERROR; | |||||
case NET_PACKET_ERROR: | |||||
// Since sync packet is incorrect, don't decode it and continue with data | |||||
break; | |||||
default: | |||||
//decode sync | |||||
DecodeSyncPacket(); | |||||
break; | |||||
} | |||||
/* | |||||
if (SyncRecv() == SOCKET_ERROR) { | if (SyncRecv() == SOCKET_ERROR) { | ||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
} | } | ||||
*/ | |||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
// For timing | // For timing | ||||
@@ -519,19 +534,30 @@ namespace Jack | |||||
//decode sync | //decode sync | ||||
//if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified | //if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified | ||||
DecodeSyncPacket(); | |||||
//DecodeSyncPacket(); | |||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
fNetTimeMon->Add(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | fNetTimeMon->Add(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | ||||
#endif | #endif | ||||
//audio, midi or sync if driver is late | //audio, midi or sync if driver is late | ||||
int res = DataRecv(); | |||||
switch (DataRecv()) { | |||||
case SOCKET_ERROR: | |||||
return SOCKET_ERROR; | |||||
case NET_PACKET_ERROR: | |||||
jack_time_t cur_time = GetMicroSeconds(); | |||||
NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing... | |||||
break; | |||||
} | |||||
/* | |||||
if (res == SOCKET_ERROR) { | if (res == SOCKET_ERROR) { | ||||
return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
} else if (res == NET_PACKET_ERROR) { | } else if (res == NET_PACKET_ERROR) { | ||||
jack_time_t cur_time = GetMicroSeconds(); | jack_time_t cur_time = GetMicroSeconds(); | ||||
NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing... | NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing... | ||||
} | } | ||||
*/ | |||||
//take the time at the beginning of the cycle | //take the time at the beginning of the cycle | ||||
JackDriver::CycleTakeBeginTime(); | JackDriver::CycleTakeBeginTime(); | ||||
@@ -553,12 +579,9 @@ namespace Jack | |||||
for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { | for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { | ||||
#ifdef OPTIMIZED_PROTOCOL | #ifdef OPTIMIZED_PROTOCOL | ||||
// Port is connected on other side... | // Port is connected on other side... | ||||
if (fNetAudioPlaybackBuffer->GetConnected(audio_port_index)) { | |||||
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[audio_port_index]) > 0) { | |||||
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index)); | |||||
} else { | |||||
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL); | |||||
} | |||||
if (fNetAudioPlaybackBuffer->GetConnected(audio_port_index) | |||||
&& (fGraphManager->GetConnectionsNum(fPlaybackPortList[audio_port_index]) > 0)) { | |||||
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index)); | |||||
} else { | } else { | ||||
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL); | fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL); | ||||
} | } | ||||
@@ -381,7 +381,7 @@ namespace Jack | |||||
fRunning = false; | fRunning = false; | ||||
// send a 'multicast euthanasia request' - new socket is required on macosx | // send a 'multicast euthanasia request' - new socket is required on macosx | ||||
jack_info("Exiting '%s'", fParams.fName); | |||||
jack_info("Exiting '%s' %s", fParams.fName, fMulticastIP); | |||||
SetPacketType(&fParams, KILL_MASTER); | SetPacketType(&fParams, KILL_MASTER); | ||||
JackNetSocket mcast_socket(fMulticastIP, fSocket.GetPort()); | JackNetSocket mcast_socket(fMulticastIP, fSocket.GetPort()); | ||||
@@ -488,8 +488,8 @@ namespace Jack | |||||
while (strcmp(rx_head->fPacketType, "header") != 0); | while (strcmp(rx_head->fPacketType, "header") != 0); | ||||
if (rx_head->fDataType != 's') { | if (rx_head->fDataType != 's') { | ||||
jack_error("Wrong packet type : %c\n", rx_head->fDataType); | |||||
return -1; | |||||
jack_error("Wrong packet type : %c", rx_head->fDataType); | |||||
return NET_PACKET_ERROR; | |||||
} | } | ||||
fCurrentCycleOffset = fTxHeader.fCycle - rx_head->fCycle; | fCurrentCycleOffset = fTxHeader.fCycle - rx_head->fCycle; | ||||
@@ -532,7 +532,7 @@ namespace Jack | |||||
break; | break; | ||||
case 's': // sync | case 's': // sync | ||||
jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName); | |||||
jack_info("NetMaster : missing last data packet from '%s'", fParams.fName); | |||||
return FinishRecv(fNetAudioPlaybackBuffer); | return FinishRecv(fNetAudioPlaybackBuffer); | ||||
} | } | ||||
} | } | ||||
@@ -866,7 +866,7 @@ namespace Jack | |||||
// receive sync (launch the cycle) | // receive sync (launch the cycle) | ||||
do { | do { | ||||
rx_bytes = Recv(fParams.fMtu, 0); | rx_bytes = Recv(fParams.fMtu, 0); | ||||
// connection issue, send will detect it, so don't skip the cycle (return 0) | |||||
// connection issue (return -1) | |||||
if (rx_bytes == SOCKET_ERROR) { | if (rx_bytes == SOCKET_ERROR) { | ||||
return rx_bytes; | return rx_bytes; | ||||
} | } | ||||
@@ -874,8 +874,8 @@ namespace Jack | |||||
while (strcmp(rx_head->fPacketType, "header") != 0); | while (strcmp(rx_head->fPacketType, "header") != 0); | ||||
if (rx_head->fDataType != 's') { | if (rx_head->fDataType != 's') { | ||||
jack_error("Wrong packet type : %c\n", rx_head->fDataType); | |||||
return -1; | |||||
jack_error("Wrong packet type : %c", rx_head->fDataType); | |||||
return NET_PACKET_ERROR; | |||||
} | } | ||||
fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | fRxHeader.fIsLastPckt = rx_head->fIsLastPckt; | ||||
@@ -894,7 +894,7 @@ namespace Jack | |||||
// how much data is queued on the rx buffer ? | // how much data is queued on the rx buffer ? | ||||
rx_bytes = Recv(fParams.fMtu, MSG_PEEK); | rx_bytes = Recv(fParams.fMtu, MSG_PEEK); | ||||
// error here, problem with recv, just skip the cycle (return -1) | |||||
// error here, just skip the cycle (return -1) | |||||
if (rx_bytes == SOCKET_ERROR) { | if (rx_bytes == SOCKET_ERROR) { | ||||
return rx_bytes; | return rx_bytes; | ||||
} | } | ||||
@@ -912,7 +912,7 @@ namespace Jack | |||||
break; | break; | ||||
case 's': // sync | case 's': // sync | ||||
jack_info("NetSlave : overloaded, skipping receive"); | |||||
jack_info("NetSlave : missing last data packet"); | |||||
return FinishRecv(fNetAudioCaptureBuffer); | return FinishRecv(fNetAudioCaptureBuffer); | ||||
} | } | ||||
} | } | ||||
@@ -510,19 +510,39 @@ namespace Jack | |||||
} | } | ||||
//receive sync | //receive sync | ||||
/* | |||||
int res = SyncRecv(); | int res = SyncRecv(); | ||||
if ((res == 0) || (res == SOCKET_ERROR)) { | if ((res == 0) || (res == SOCKET_ERROR)) { | ||||
return res; | return res; | ||||
} | } | ||||
*/ | |||||
int res = SyncRecv(); | |||||
switch (res) { | |||||
case 0: | |||||
case SOCKET_ERROR: | |||||
return res; | |||||
case NET_PACKET_ERROR: | |||||
// Since sync packet is incorrect, don't decode it and continue with data | |||||
break; | |||||
default: | |||||
//decode sync | |||||
DecodeSyncPacket(); | |||||
break; | |||||
} | |||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | ||||
#endif | #endif | ||||
//decode sync | //decode sync | ||||
DecodeSyncPacket(); | |||||
//DecodeSyncPacket(); | |||||
//receive data | //receive data | ||||
/* | |||||
res = DataRecv(); | res = DataRecv(); | ||||
if ((res == 0) || (res == SOCKET_ERROR)) { | if ((res == 0) || (res == SOCKET_ERROR)) { | ||||
return res; | return res; | ||||
@@ -530,6 +550,21 @@ namespace Jack | |||||
// Well not a real XRun... | // Well not a real XRun... | ||||
JackServerGlobals::fInstance->GetEngine()->NotifyClientXRun(ALL_CLIENTS); | JackServerGlobals::fInstance->GetEngine()->NotifyClientXRun(ALL_CLIENTS); | ||||
} | } | ||||
*/ | |||||
//receive data | |||||
res = DataRecv(); | |||||
switch (res) { | |||||
case 0: | |||||
case SOCKET_ERROR: | |||||
return res; | |||||
case NET_PACKET_ERROR: | |||||
// Well not a real XRun... | |||||
JackServerGlobals::fInstance->GetEngine()->NotifyClientXRun(ALL_CLIENTS); | |||||
break; | |||||
} | |||||
#ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
fNetTimeMon->AddLast((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | fNetTimeMon->AddLast((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | ||||
@@ -59,6 +59,15 @@ JackCoreMidiVirtualInputPort(const char *alias_name, const char *client_name, | |||||
MIDIEndpointRef destination; | MIDIEndpointRef destination; | ||||
OSStatus status = MIDIDestinationCreate(client, name, HandleInputEvent, | OSStatus status = MIDIDestinationCreate(client, name, HandleInputEvent, | ||||
this, &destination); | this, &destination); | ||||
/* | |||||
SInt32 value; | |||||
status = MIDIObjectGetIntegerProperty(destination, kMIDIPropertyUniqueID, &value); | |||||
if (status == noErr) { | |||||
jack_info("kMIDIPropertyUniqueID %d", value); | |||||
} | |||||
*/ | |||||
CFRelease(name); | CFRelease(name); | ||||
if (status != noErr) { | if (status != noErr) { | ||||
throw std::runtime_error(GetMacOSErrorString(status)); | throw std::runtime_error(GetMacOSErrorString(status)); | ||||
@@ -44,6 +44,15 @@ JackCoreMidiVirtualOutputPort(const char *alias_name, const char *client_name, | |||||
} | } | ||||
MIDIEndpointRef source; | MIDIEndpointRef source; | ||||
OSStatus status = MIDISourceCreate(client, name, &source); | OSStatus status = MIDISourceCreate(client, name, &source); | ||||
/* | |||||
SInt32 value; | |||||
status = MIDIObjectGetIntegerProperty(source, kMIDIPropertyUniqueID, &value); | |||||
if (status == noErr) { | |||||
jack_info("kMIDIPropertyUniqueID %d", value); | |||||
} | |||||
*/ | |||||
CFRelease(name); | CFRelease(name); | ||||
if (status != noErr) { | if (status != noErr) { | ||||
throw std::runtime_error(GetMacOSErrorString(status)); | throw std::runtime_error(GetMacOSErrorString(status)); | ||||
@@ -335,12 +335,12 @@ namespace Jack | |||||
jack_log("JackNetUnixSocket::SetTimeout %d usecs", us); | jack_log("JackNetUnixSocket::SetTimeout %d usecs", us); | ||||
struct timeval timeout; | struct timeval timeout; | ||||
//less than 1sec | |||||
//less than 1 sec | |||||
if (us < 1000000) { | if (us < 1000000) { | ||||
timeout.tv_sec = 0; | timeout.tv_sec = 0; | ||||
timeout.tv_usec = us; | timeout.tv_usec = us; | ||||
} else { | } else { | ||||
//more than 1sec | |||||
//more than 1 sec | |||||
float sec = float(us) / 1000000.f; | float sec = float(us) / 1000000.f; | ||||
timeout.tv_sec = (int)sec; | timeout.tv_sec = (int)sec; | ||||
float usec = (sec - float(timeout.tv_sec)) * 1000000; | float usec = (sec - float(timeout.tv_sec)) * 1000000; | ||||