@@ -369,29 +369,33 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
void FreePorts() | |||
{ | |||
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; | |||
fAudioPlaybackBuffer = NULL; | |||
} | |||
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; | |||
fMidiPlaybackBuffer = NULL; | |||
} | |||
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; | |||
fAudioCaptureBuffer = NULL; | |||
} | |||
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; | |||
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) | |||
{ | |||
try { | |||
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]); | |||
} | |||
/* | |||
// TODO : use with netmaster/netdriver code | |||
//receive sync | |||
int res = SyncRecv(); | |||
if ((res == 0) || (res == SOCKET_ERROR)) { | |||
return res; | |||
} | |||
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(); | |||
} catch (JackNetException& e) { | |||
jack_error("Connection lost."); | |||
jack_error("Lost connection"); | |||
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 { | |||
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]); | |||
} | |||
if (IsSynched()) { // only send if connection is "synched" | |||
EncodeSyncPacket(); | |||
// send sync | |||
if (SyncSend() == SOCKET_ERROR) { | |||
return SOCKET_ERROR; | |||
} | |||
@@ -462,7 +486,7 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||
return 0; | |||
} catch (JackNetException& e) { | |||
jack_error("Connection lost."); | |||
jack_error("Lost connection"); | |||
return -1; | |||
} | |||
} | |||
@@ -749,13 +773,34 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||
int Read() | |||
{ | |||
// TODO : use with netmaster/netdriver code | |||
//receive sync (launch the cycle) | |||
/* | |||
if (SyncRecv() == SOCKET_ERROR) { | |||
return SOCKET_ERROR; | |||
} | |||
DecodeSyncPacket(); | |||
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() | |||
@@ -351,11 +351,31 @@ namespace Jack | |||
{ | |||
//don't return -1 in case of sync recv failure | |||
//we need the process to continue for network error detection | |||
/* | |||
if (SyncRecv() == SOCKET_ERROR) { | |||
return 0; | |||
} | |||
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(); | |||
} | |||
@@ -507,10 +507,25 @@ namespace Jack | |||
fNetTimeMon->New(); | |||
#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) { | |||
return SOCKET_ERROR; | |||
} | |||
*/ | |||
#ifdef JACK_MONITOR | |||
// For timing | |||
@@ -519,19 +534,30 @@ namespace Jack | |||
//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(); | |||
//DecodeSyncPacket(); | |||
#ifdef JACK_MONITOR | |||
fNetTimeMon->Add(float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f); | |||
#endif | |||
//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) { | |||
return SOCKET_ERROR; | |||
} else if (res == NET_PACKET_ERROR) { | |||
jack_time_t cur_time = GetMicroSeconds(); | |||
NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing... | |||
} | |||
*/ | |||
//take the time at the beginning of the cycle | |||
JackDriver::CycleTakeBeginTime(); | |||
@@ -553,12 +579,9 @@ namespace Jack | |||
for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { | |||
#ifdef OPTIMIZED_PROTOCOL | |||
// 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 { | |||
fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL); | |||
} | |||
@@ -381,7 +381,7 @@ namespace Jack | |||
fRunning = false; | |||
// 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); | |||
JackNetSocket mcast_socket(fMulticastIP, fSocket.GetPort()); | |||
@@ -488,8 +488,8 @@ namespace Jack | |||
while (strcmp(rx_head->fPacketType, "header") != 0); | |||
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; | |||
@@ -532,7 +532,7 @@ namespace Jack | |||
break; | |||
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); | |||
} | |||
} | |||
@@ -866,7 +866,7 @@ namespace Jack | |||
// receive sync (launch the cycle) | |||
do { | |||
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) { | |||
return rx_bytes; | |||
} | |||
@@ -874,8 +874,8 @@ namespace Jack | |||
while (strcmp(rx_head->fPacketType, "header") != 0); | |||
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; | |||
@@ -894,7 +894,7 @@ namespace Jack | |||
// how much data is queued on the rx buffer ? | |||
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) { | |||
return rx_bytes; | |||
} | |||
@@ -912,7 +912,7 @@ namespace Jack | |||
break; | |||
case 's': // sync | |||
jack_info("NetSlave : overloaded, skipping receive"); | |||
jack_info("NetSlave : missing last data packet"); | |||
return FinishRecv(fNetAudioCaptureBuffer); | |||
} | |||
} | |||
@@ -510,19 +510,39 @@ namespace Jack | |||
} | |||
//receive sync | |||
/* | |||
int res = SyncRecv(); | |||
if ((res == 0) || (res == SOCKET_ERROR)) { | |||
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 | |||
fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f); | |||
#endif | |||
//decode sync | |||
DecodeSyncPacket(); | |||
//DecodeSyncPacket(); | |||
//receive data | |||
/* | |||
res = DataRecv(); | |||
if ((res == 0) || (res == SOCKET_ERROR)) { | |||
return res; | |||
@@ -530,6 +550,21 @@ namespace Jack | |||
// Well not a real XRun... | |||
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 | |||
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; | |||
OSStatus status = MIDIDestinationCreate(client, name, HandleInputEvent, | |||
this, &destination); | |||
/* | |||
SInt32 value; | |||
status = MIDIObjectGetIntegerProperty(destination, kMIDIPropertyUniqueID, &value); | |||
if (status == noErr) { | |||
jack_info("kMIDIPropertyUniqueID %d", value); | |||
} | |||
*/ | |||
CFRelease(name); | |||
if (status != noErr) { | |||
throw std::runtime_error(GetMacOSErrorString(status)); | |||
@@ -44,6 +44,15 @@ JackCoreMidiVirtualOutputPort(const char *alias_name, const char *client_name, | |||
} | |||
MIDIEndpointRef source; | |||
OSStatus status = MIDISourceCreate(client, name, &source); | |||
/* | |||
SInt32 value; | |||
status = MIDIObjectGetIntegerProperty(source, kMIDIPropertyUniqueID, &value); | |||
if (status == noErr) { | |||
jack_info("kMIDIPropertyUniqueID %d", value); | |||
} | |||
*/ | |||
CFRelease(name); | |||
if (status != noErr) { | |||
throw std::runtime_error(GetMacOSErrorString(status)); | |||
@@ -335,12 +335,12 @@ namespace Jack | |||
jack_log("JackNetUnixSocket::SetTimeout %d usecs", us); | |||
struct timeval timeout; | |||
//less than 1sec | |||
//less than 1 sec | |||
if (us < 1000000) { | |||
timeout.tv_sec = 0; | |||
timeout.tv_usec = us; | |||
} else { | |||
//more than 1sec | |||
//more than 1 sec | |||
float sec = float(us) / 1000000.f; | |||
timeout.tv_sec = (int)sec; | |||
float usec = (sec - float(timeout.tv_sec)) * 1000000; | |||