|
@@ -25,19 +25,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
|
|
|
|
|
|
|
namespace Jack |
|
|
namespace Jack |
|
|
{ |
|
|
{ |
|
|
JackNetAdapter::JackNetAdapter ( jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params ) |
|
|
|
|
|
: JackAudioAdapterInterface ( buffer_size, sample_rate), JackNetSlaveInterface(), fThread ( this ) |
|
|
|
|
|
|
|
|
JackNetAdapter::JackNetAdapter(jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) |
|
|
|
|
|
: JackAudioAdapterInterface(buffer_size, sample_rate), JackNetSlaveInterface(), fThread(this) |
|
|
{ |
|
|
{ |
|
|
jack_log ( "JackNetAdapter::JackNetAdapter" ); |
|
|
|
|
|
|
|
|
jack_log("JackNetAdapter::JackNetAdapter"); |
|
|
|
|
|
|
|
|
//global parametering |
|
|
//global parametering |
|
|
//we can't call JackNetSlaveInterface constructor with some parameters before |
|
|
//we can't call JackNetSlaveInterface constructor with some parameters before |
|
|
//because we don't have full parametering right now |
|
|
//because we don't have full parametering right now |
|
|
//parameters will be parsed from the param list, and then JackNetSlaveInterface will be filled with proper values |
|
|
//parameters will be parsed from the param list, and then JackNetSlaveInterface will be filled with proper values |
|
|
strcpy ( fMulticastIP, DEFAULT_MULTICAST_IP ); |
|
|
|
|
|
|
|
|
strcpy(fMulticastIP, DEFAULT_MULTICAST_IP); |
|
|
uint port = DEFAULT_PORT; |
|
|
uint port = DEFAULT_PORT; |
|
|
GetHostName ( fParams.fName, JACK_CLIENT_NAME_SIZE ); |
|
|
|
|
|
fSocket.GetName ( fParams.fSlaveNetName ); |
|
|
|
|
|
|
|
|
GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE); |
|
|
|
|
|
fSocket.GetName(fParams.fSlaveNetName); |
|
|
fParams.fMtu = DEFAULT_MTU; |
|
|
fParams.fMtu = DEFAULT_MTU; |
|
|
fParams.fTransportSync = 0; |
|
|
fParams.fTransportSync = 0; |
|
|
int send_audio = -1; |
|
|
int send_audio = -1; |
|
@@ -53,19 +53,19 @@ namespace Jack |
|
|
//options parsing |
|
|
//options parsing |
|
|
const JSList* node; |
|
|
const JSList* node; |
|
|
const jack_driver_param_t* param; |
|
|
const jack_driver_param_t* param; |
|
|
for ( node = params; node; node = jack_slist_next ( node ) ) |
|
|
|
|
|
|
|
|
for (node = params; node; node = jack_slist_next(node)) |
|
|
{ |
|
|
{ |
|
|
param = ( const jack_driver_param_t* ) node->data; |
|
|
|
|
|
switch ( param->character ) |
|
|
|
|
|
|
|
|
param = (const jack_driver_param_t*) node->data; |
|
|
|
|
|
switch (param->character) |
|
|
{ |
|
|
{ |
|
|
case 'a' : |
|
|
case 'a' : |
|
|
if (strlen (param->value.str) < 32) |
|
|
|
|
|
|
|
|
if (strlen(param->value.str) < 32) |
|
|
strcpy(fMulticastIP, param->value.str); |
|
|
strcpy(fMulticastIP, param->value.str); |
|
|
else |
|
|
else |
|
|
jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP); |
|
|
jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP); |
|
|
break; |
|
|
break; |
|
|
case 'p' : |
|
|
case 'p' : |
|
|
fSocket.SetPort ( param->value.ui ); |
|
|
|
|
|
|
|
|
fSocket.SetPort(param->value.ui); |
|
|
break; |
|
|
break; |
|
|
case 'M' : |
|
|
case 'M' : |
|
|
fParams.fMtu = param->value.i; |
|
|
fParams.fMtu = param->value.i; |
|
@@ -77,20 +77,30 @@ namespace Jack |
|
|
return_audio = param->value.i; |
|
|
return_audio = param->value.i; |
|
|
break; |
|
|
break; |
|
|
case 'n' : |
|
|
case 'n' : |
|
|
strncpy ( fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE ); |
|
|
|
|
|
|
|
|
strncpy(fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE); |
|
|
break; |
|
|
break; |
|
|
case 't' : |
|
|
case 't' : |
|
|
//fParams.fTransportSync = param->value.ui; |
|
|
//fParams.fTransportSync = param->value.ui; |
|
|
break; |
|
|
break; |
|
|
|
|
|
#if HAVE_CELT |
|
|
|
|
|
case 'c': |
|
|
|
|
|
if (param->value.i > 0) { |
|
|
|
|
|
fParams.fSampleEncoder = JackCeltEncoder; |
|
|
|
|
|
fParams.fKBps = param->value.i; |
|
|
|
|
|
} else { |
|
|
|
|
|
fParams.fSampleEncoder = JackFloatEncoder; |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
#endif |
|
|
case 'm' : |
|
|
case 'm' : |
|
|
if ( strcmp ( param->value.str, "normal" ) == 0 ) |
|
|
|
|
|
|
|
|
if (strcmp(param->value.str, "normal") == 0) |
|
|
fParams.fNetworkMode = 'n'; |
|
|
fParams.fNetworkMode = 'n'; |
|
|
else if ( strcmp ( param->value.str, "slow" ) == 0 ) |
|
|
|
|
|
|
|
|
else if (strcmp(param->value.str, "slow") == 0) |
|
|
fParams.fNetworkMode = 's'; |
|
|
fParams.fNetworkMode = 's'; |
|
|
else if ( strcmp ( param->value.str, "fast" ) == 0 ) |
|
|
|
|
|
|
|
|
else if (strcmp(param->value.str, "fast") == 0) |
|
|
fParams.fNetworkMode = 'f'; |
|
|
fParams.fNetworkMode = 'f'; |
|
|
else |
|
|
else |
|
|
jack_error ( "Unknown network mode, using 'normal' mode." ); |
|
|
|
|
|
|
|
|
jack_error("Unknown network mode, using 'normal' mode."); |
|
|
break; |
|
|
break; |
|
|
case 'q': |
|
|
case 'q': |
|
|
fQuality = param->value.ui; |
|
|
fQuality = param->value.ui; |
|
@@ -103,18 +113,18 @@ namespace Jack |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//set the socket parameters |
|
|
//set the socket parameters |
|
|
fSocket.SetPort ( port ); |
|
|
|
|
|
fSocket.SetAddress ( fMulticastIP, port ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fSocket.SetPort(port); |
|
|
|
|
|
fSocket.SetAddress(fMulticastIP, port); |
|
|
|
|
|
|
|
|
// If not set, takes deafault |
|
|
// If not set, takes deafault |
|
|
fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio; |
|
|
fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If not set, takes deafault |
|
|
// If not set, takes deafault |
|
|
fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio; |
|
|
fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//set the audio adapter interface channel values |
|
|
//set the audio adapter interface channel values |
|
|
SetInputs ( fParams.fSendAudioChannels ); |
|
|
|
|
|
SetOutputs ( fParams.fReturnAudioChannels ); |
|
|
|
|
|
|
|
|
SetInputs(fParams.fSendAudioChannels); |
|
|
|
|
|
SetOutputs(fParams.fReturnAudioChannels); |
|
|
|
|
|
|
|
|
//soft buffers will be allocated later (once network initialization done) |
|
|
//soft buffers will be allocated later (once network initialization done) |
|
|
fSoftCaptureBuffer = NULL; |
|
|
fSoftCaptureBuffer = NULL; |
|
@@ -123,18 +133,16 @@ namespace Jack |
|
|
|
|
|
|
|
|
JackNetAdapter::~JackNetAdapter() |
|
|
JackNetAdapter::~JackNetAdapter() |
|
|
{ |
|
|
{ |
|
|
jack_log ("JackNetAdapter::~JackNetAdapter"); |
|
|
|
|
|
|
|
|
jack_log("JackNetAdapter::~JackNetAdapter"); |
|
|
|
|
|
|
|
|
int port_index; |
|
|
int port_index; |
|
|
if (fSoftCaptureBuffer) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
if (fSoftCaptureBuffer) { |
|
|
for (port_index = 0; port_index < fCaptureChannels; port_index++) |
|
|
for (port_index = 0; port_index < fCaptureChannels; port_index++) |
|
|
delete[] fSoftCaptureBuffer[port_index]; |
|
|
delete[] fSoftCaptureBuffer[port_index]; |
|
|
delete[] fSoftCaptureBuffer; |
|
|
delete[] fSoftCaptureBuffer; |
|
|
} |
|
|
} |
|
|
if (fSoftPlaybackBuffer) |
|
|
|
|
|
{ |
|
|
|
|
|
for ( port_index = 0; port_index < fPlaybackChannels; port_index++) |
|
|
|
|
|
|
|
|
if (fSoftPlaybackBuffer) { |
|
|
|
|
|
for (port_index = 0; port_index < fPlaybackChannels; port_index++) |
|
|
delete[] fSoftPlaybackBuffer[port_index]; |
|
|
delete[] fSoftPlaybackBuffer[port_index]; |
|
|
delete[] fSoftPlaybackBuffer; |
|
|
delete[] fSoftPlaybackBuffer; |
|
|
} |
|
|
} |
|
@@ -143,14 +151,13 @@ namespace Jack |
|
|
//open/close-------------------------------------------------------------------------- |
|
|
//open/close-------------------------------------------------------------------------- |
|
|
int JackNetAdapter::Open() |
|
|
int JackNetAdapter::Open() |
|
|
{ |
|
|
{ |
|
|
jack_log ( "JackNetAdapter::Open" ); |
|
|
|
|
|
|
|
|
jack_log("JackNetAdapter::Open"); |
|
|
|
|
|
|
|
|
jack_info ( "NetAdapter started in %s mode %s Master's transport sync.", |
|
|
|
|
|
( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" ); |
|
|
|
|
|
|
|
|
jack_info("NetAdapter started in %s mode %s Master's transport sync.", |
|
|
|
|
|
(fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without"); |
|
|
|
|
|
|
|
|
if ( fThread.StartSync() < 0 ) |
|
|
|
|
|
{ |
|
|
|
|
|
jack_error ( "Cannot start netadapter thread" ); |
|
|
|
|
|
|
|
|
if (fThread.StartSync() < 0) { |
|
|
|
|
|
jack_error("Cannot start netadapter thread"); |
|
|
return -1; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -159,30 +166,28 @@ namespace Jack |
|
|
|
|
|
|
|
|
int JackNetAdapter::Close() |
|
|
int JackNetAdapter::Close() |
|
|
{ |
|
|
{ |
|
|
jack_log ( "JackNetAdapter::Close" ); |
|
|
|
|
|
|
|
|
jack_log("JackNetAdapter::Close"); |
|
|
|
|
|
|
|
|
#ifdef JACK_MONITOR |
|
|
#ifdef JACK_MONITOR |
|
|
fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); |
|
|
fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize); |
|
|
#endif |
|
|
#endif |
|
|
fSocket.Close(); |
|
|
fSocket.Close(); |
|
|
|
|
|
|
|
|
switch ( fThread.GetStatus() ) |
|
|
|
|
|
|
|
|
switch (fThread.GetStatus()) |
|
|
{ |
|
|
{ |
|
|
// Kill the thread in Init phase |
|
|
// Kill the thread in Init phase |
|
|
case JackThread::kStarting: |
|
|
case JackThread::kStarting: |
|
|
case JackThread::kIniting: |
|
|
case JackThread::kIniting: |
|
|
if ( fThread.Kill() < 0 ) |
|
|
|
|
|
{ |
|
|
|
|
|
jack_error ( "Cannot kill thread" ); |
|
|
|
|
|
|
|
|
if (fThread.Kill() < 0) { |
|
|
|
|
|
jack_error("Cannot kill thread"); |
|
|
return -1; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
// Stop when the thread cycle is finished |
|
|
// Stop when the thread cycle is finished |
|
|
|
|
|
|
|
|
case JackThread::kRunning: |
|
|
case JackThread::kRunning: |
|
|
if ( fThread.Stop() < 0 ) |
|
|
|
|
|
{ |
|
|
|
|
|
jack_error ( "Cannot stop thread" ); |
|
|
|
|
|
|
|
|
if (fThread.Stop() < 0) { |
|
|
|
|
|
jack_error ("Cannot stop thread"); |
|
|
return -1; |
|
|
return -1; |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
@@ -194,55 +199,55 @@ namespace Jack |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
int JackNetAdapter::SetBufferSize ( jack_nframes_t buffer_size ) |
|
|
|
|
|
|
|
|
int JackNetAdapter::SetBufferSize(jack_nframes_t buffer_size) |
|
|
{ |
|
|
{ |
|
|
JackAudioAdapterInterface::SetHostBufferSize ( buffer_size ); |
|
|
|
|
|
|
|
|
JackAudioAdapterInterface::SetHostBufferSize(buffer_size); |
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//thread------------------------------------------------------------------------------ |
|
|
//thread------------------------------------------------------------------------------ |
|
|
// TODO : if failure, thread exist... need to restart ? |
|
|
// TODO : if failure, thread exist... need to restart ? |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool JackNetAdapter::Init() |
|
|
bool JackNetAdapter::Init() |
|
|
{ |
|
|
{ |
|
|
jack_log ( "JackNetAdapter::Init" ); |
|
|
|
|
|
|
|
|
jack_log("JackNetAdapter::Init"); |
|
|
|
|
|
|
|
|
int port_index; |
|
|
int port_index; |
|
|
|
|
|
|
|
|
//init network connection |
|
|
//init network connection |
|
|
if (!JackNetSlaveInterface::Init()) { |
|
|
if (!JackNetSlaveInterface::Init()) { |
|
|
jack_error("JackNetSlaveInterface::Init() error..." ); |
|
|
|
|
|
|
|
|
jack_error("JackNetSlaveInterface::Init() error..."); |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//then set global parameters |
|
|
//then set global parameters |
|
|
if (!SetParams()) { |
|
|
if (!SetParams()) { |
|
|
jack_error("SetParams error..." ); |
|
|
|
|
|
|
|
|
jack_error("SetParams error..."); |
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//set buffers |
|
|
//set buffers |
|
|
if (fCaptureChannels > 0) { |
|
|
if (fCaptureChannels > 0) { |
|
|
fSoftCaptureBuffer = new sample_t*[fCaptureChannels]; |
|
|
fSoftCaptureBuffer = new sample_t*[fCaptureChannels]; |
|
|
for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) |
|
|
|
|
|
|
|
|
for (port_index = 0; port_index < fCaptureChannels; port_index++) |
|
|
{ |
|
|
{ |
|
|
fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize]; |
|
|
fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize]; |
|
|
fNetAudioCaptureBuffer->SetBuffer ( port_index, fSoftCaptureBuffer[port_index] ); |
|
|
|
|
|
|
|
|
fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fPlaybackChannels > 0) { |
|
|
if (fPlaybackChannels > 0) { |
|
|
fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels]; |
|
|
fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels]; |
|
|
for ( port_index = 0; port_index < fPlaybackChannels; port_index++ ) |
|
|
|
|
|
|
|
|
for (port_index = 0; port_index < fPlaybackChannels; port_index++) |
|
|
{ |
|
|
{ |
|
|
fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize]; |
|
|
fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize]; |
|
|
fNetAudioPlaybackBuffer->SetBuffer ( port_index, fSoftPlaybackBuffer[port_index] ); |
|
|
|
|
|
|
|
|
fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//set audio adapter parameters |
|
|
//set audio adapter parameters |
|
|
SetAdaptedBufferSize ( fParams.fPeriodSize ); |
|
|
|
|
|
SetAdaptedSampleRate ( fParams.fSampleRate ); |
|
|
|
|
|
|
|
|
SetAdaptedBufferSize(fParams.fPeriodSize); |
|
|
|
|
|
SetAdaptedSampleRate(fParams.fSampleRate); |
|
|
|
|
|
|
|
|
// Will do "something" on OSX only... |
|
|
// Will do "something" on OSX only... |
|
|
fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); |
|
|
fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); |
|
@@ -254,7 +259,7 @@ namespace Jack |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//init done, display parameters |
|
|
//init done, display parameters |
|
|
SessionParamsDisplay ( &fParams ); |
|
|
|
|
|
|
|
|
SessionParamsDisplay(&fParams); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -287,26 +292,25 @@ namespace Jack |
|
|
//TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver) |
|
|
//TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver) |
|
|
|
|
|
|
|
|
//is there a new transport state ? |
|
|
//is there a new transport state ? |
|
|
if ( fSendTransportData.fNewState && ( fSendTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) ) |
|
|
|
|
|
{ |
|
|
|
|
|
switch ( fSendTransportData.fState ) |
|
|
|
|
|
|
|
|
if (fSendTransportData.fNewState &&(fSendTransportData.fState != jack_transport_query(fJackClient, NULL))) { |
|
|
|
|
|
switch (fSendTransportData.fState) |
|
|
{ |
|
|
{ |
|
|
case JackTransportStopped : |
|
|
case JackTransportStopped : |
|
|
jack_transport_stop ( fJackClient ); |
|
|
|
|
|
jack_info ( "NetMaster : transport stops." ); |
|
|
|
|
|
|
|
|
jack_transport_stop(fJackClient); |
|
|
|
|
|
jack_info("NetMaster : transport stops."); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case JackTransportStarting : |
|
|
case JackTransportStarting : |
|
|
jack_transport_reposition ( fJackClient, &fSendTransportData.fPosition ); |
|
|
|
|
|
jack_transport_start ( fJackClient ); |
|
|
|
|
|
jack_info ( "NetMaster : transport starts." ); |
|
|
|
|
|
|
|
|
jack_transport_reposition(fJackClient, &fSendTransportData.fPosition); |
|
|
|
|
|
jack_transport_start(fJackClient); |
|
|
|
|
|
jack_info("NetMaster : transport starts."); |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case JackTransportRolling : |
|
|
case JackTransportRolling : |
|
|
//TODO , we need to : |
|
|
//TODO , we need to : |
|
|
// - find a way to call TransportEngine->SetNetworkSync() |
|
|
// - find a way to call TransportEngine->SetNetworkSync() |
|
|
// - turn the transport state to JackTransportRolling |
|
|
// - turn the transport state to JackTransportRolling |
|
|
jack_info ( "NetMaster : transport rolls." ); |
|
|
|
|
|
|
|
|
jack_info("NetMaster : transport rolls."); |
|
|
break; |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@@ -318,33 +322,29 @@ namespace Jack |
|
|
int refnum = -1; |
|
|
int refnum = -1; |
|
|
bool conditional = 0; |
|
|
bool conditional = 0; |
|
|
//TODO : get the actual timebase master |
|
|
//TODO : get the actual timebase master |
|
|
if ( refnum != fLastTimebaseMaster ) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
if (refnum != fLastTimebaseMaster) { |
|
|
//timebase master has released its function |
|
|
//timebase master has released its function |
|
|
if ( refnum == -1 ) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
if (refnum == -1) { |
|
|
fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER; |
|
|
fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER; |
|
|
jack_info ( "Sending a timebase master release request." ); |
|
|
|
|
|
} |
|
|
|
|
|
//there is a new timebase master |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
fReturnTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER; |
|
|
|
|
|
jack_info ( "Sending a %s timebase master request.", ( conditional ) ? "conditional" : "non-conditional" ); |
|
|
|
|
|
|
|
|
jack_info("Sending a timebase master release request."); |
|
|
|
|
|
} else { |
|
|
|
|
|
//there is a new timebase master |
|
|
|
|
|
fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER; |
|
|
|
|
|
jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional"); |
|
|
} |
|
|
} |
|
|
fLastTimebaseMaster = refnum; |
|
|
fLastTimebaseMaster = refnum; |
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
|
|
|
} else { |
|
|
fReturnTransportData.fTimebaseMaster = NO_CHANGE; |
|
|
fReturnTransportData.fTimebaseMaster = NO_CHANGE; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
//update transport state and position |
|
|
//update transport state and position |
|
|
fReturnTransportData.fState = jack_transport_query ( fJackClient, &fReturnTransportData.fPosition ); |
|
|
|
|
|
|
|
|
fReturnTransportData.fState = jack_transport_query(fJackClient, &fReturnTransportData.fPosition); |
|
|
|
|
|
|
|
|
//is it a new state (that the master need to know...) ? |
|
|
//is it a new state (that the master need to know...) ? |
|
|
fReturnTransportData.fNewState = ( ( fReturnTransportData.fState != fLastTransportState ) && |
|
|
|
|
|
( fReturnTransportData.fState != fSendTransportData.fState ) ); |
|
|
|
|
|
if ( fReturnTransportData.fNewState ) |
|
|
|
|
|
jack_info ( "Sending transport state '%s'.", GetTransportState ( fReturnTransportData.fState ) ); |
|
|
|
|
|
|
|
|
fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) && |
|
|
|
|
|
(fReturnTransportData.fState != fSendTransportData.fState)); |
|
|
|
|
|
if (fReturnTransportData.fNewState) |
|
|
|
|
|
jack_info("Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState)); |
|
|
fLastTransportState = fReturnTransportData.fState; |
|
|
fLastTransportState = fReturnTransportData.fState; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@@ -353,7 +353,7 @@ 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(); |
|
@@ -364,7 +364,7 @@ namespace Jack |
|
|
{ |
|
|
{ |
|
|
EncodeSyncPacket(); |
|
|
EncodeSyncPacket(); |
|
|
|
|
|
|
|
|
if ( SyncSend() == SOCKET_ERROR ) |
|
|
|
|
|
|
|
|
if (SyncSend() == SOCKET_ERROR) |
|
|
return SOCKET_ERROR; |
|
|
return SOCKET_ERROR; |
|
|
|
|
|
|
|
|
return DataSend(); |
|
|
return DataSend(); |
|
@@ -403,77 +403,87 @@ extern "C" |
|
|
|
|
|
|
|
|
SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() |
|
|
SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() |
|
|
{ |
|
|
{ |
|
|
jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) ); |
|
|
|
|
|
|
|
|
jack_driver_desc_t* desc = (jack_driver_desc_t*) calloc(1, sizeof(jack_driver_desc_t)); |
|
|
|
|
|
|
|
|
strcpy(desc->name, "netadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 |
|
|
strcpy(desc->name, "netadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 |
|
|
strcpy(desc->desc, "netjack net <==> audio backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 |
|
|
strcpy(desc->desc, "netjack net <==> audio backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 |
|
|
|
|
|
|
|
|
desc->nparams = 11; |
|
|
|
|
|
desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); |
|
|
|
|
|
|
|
|
desc->nparams = 12; |
|
|
|
|
|
desc->params = (jack_driver_param_desc_t*) calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); |
|
|
|
|
|
|
|
|
int i = 0; |
|
|
int i = 0; |
|
|
strcpy ( desc->params[i].name, "multicast_ip" ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].name, "multicast_ip"); |
|
|
desc->params[i].character = 'a'; |
|
|
desc->params[i].character = 'a'; |
|
|
desc->params[i].type = JackDriverParamString; |
|
|
desc->params[i].type = JackDriverParamString; |
|
|
strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP ); |
|
|
|
|
|
strcpy ( desc->params[i].short_desc, "Multicast Address" ); |
|
|
|
|
|
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].value.str, DEFAULT_MULTICAST_IP); |
|
|
|
|
|
strcpy(desc->params[i].short_desc, "Multicast Address"); |
|
|
|
|
|
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
|
|
|
i++; |
|
|
i++; |
|
|
strcpy ( desc->params[i].name, "udp_net_port" ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].name, "udp_net_port"); |
|
|
desc->params[i].character = 'p'; |
|
|
desc->params[i].character = 'p'; |
|
|
desc->params[i].type = JackDriverParamInt; |
|
|
desc->params[i].type = JackDriverParamInt; |
|
|
desc->params[i].value.i = DEFAULT_PORT; |
|
|
desc->params[i].value.i = DEFAULT_PORT; |
|
|
strcpy ( desc->params[i].short_desc, "UDP port" ); |
|
|
|
|
|
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].short_desc, "UDP port"); |
|
|
|
|
|
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
|
|
|
i++; |
|
|
i++; |
|
|
strcpy ( desc->params[i].name, "mtu" ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].name, "mtu"); |
|
|
desc->params[i].character = 'M'; |
|
|
desc->params[i].character = 'M'; |
|
|
desc->params[i].type = JackDriverParamInt; |
|
|
desc->params[i].type = JackDriverParamInt; |
|
|
desc->params[i].value.i = DEFAULT_MTU; |
|
|
desc->params[i].value.i = DEFAULT_MTU; |
|
|
strcpy ( desc->params[i].short_desc, "MTU to the master" ); |
|
|
|
|
|
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].short_desc, "MTU to the master"); |
|
|
|
|
|
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
|
|
|
i++; |
|
|
i++; |
|
|
strcpy ( desc->params[i].name, "input-ports" ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].name, "input-ports"); |
|
|
desc->params[i].character = 'C'; |
|
|
desc->params[i].character = 'C'; |
|
|
desc->params[i].type = JackDriverParamInt; |
|
|
desc->params[i].type = JackDriverParamInt; |
|
|
desc->params[i].value.i = 2; |
|
|
desc->params[i].value.i = 2; |
|
|
strcpy ( desc->params[i].short_desc, "Number of audio input ports" ); |
|
|
|
|
|
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].short_desc, "Number of audio input ports"); |
|
|
|
|
|
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
|
|
|
i++; |
|
|
i++; |
|
|
strcpy ( desc->params[i].name, "output-ports" ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].name, "output-ports"); |
|
|
desc->params[i].character = 'P'; |
|
|
desc->params[i].character = 'P'; |
|
|
desc->params[i].type = JackDriverParamInt; |
|
|
desc->params[i].type = JackDriverParamInt; |
|
|
desc->params[i].value.i = 2; |
|
|
desc->params[i].value.i = 2; |
|
|
strcpy ( desc->params[i].short_desc, "Number of audio output ports" ); |
|
|
|
|
|
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].short_desc, "Number of audio output ports"); |
|
|
|
|
|
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_CELT |
|
|
i++; |
|
|
i++; |
|
|
strcpy ( desc->params[i].name, "client-name" ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].name, "celt"); |
|
|
|
|
|
desc->params[i].character = 'c'; |
|
|
|
|
|
desc->params[i].type = JackDriverParamInt; |
|
|
|
|
|
desc->params[i].value.i = -1; |
|
|
|
|
|
strcpy(desc->params[i].short_desc, "Set CELT encoding and number of kBits per channel"); |
|
|
|
|
|
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
i++; |
|
|
|
|
|
strcpy(desc->params[i].name, "client-name"); |
|
|
desc->params[i].character = 'n'; |
|
|
desc->params[i].character = 'n'; |
|
|
desc->params[i].type = JackDriverParamString; |
|
|
desc->params[i].type = JackDriverParamString; |
|
|
strcpy ( desc->params[i].value.str, "'hostname'" ); |
|
|
|
|
|
strcpy ( desc->params[i].short_desc, "Name of the jack client" ); |
|
|
|
|
|
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].value.str, "'hostname'"); |
|
|
|
|
|
strcpy(desc->params[i].short_desc, "Name of the jack client"); |
|
|
|
|
|
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
|
|
|
i++; |
|
|
i++; |
|
|
strcpy ( desc->params[i].name, "transport-sync" ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].name, "transport-sync"); |
|
|
desc->params[i].character = 't'; |
|
|
desc->params[i].character = 't'; |
|
|
desc->params[i].type = JackDriverParamUInt; |
|
|
desc->params[i].type = JackDriverParamUInt; |
|
|
desc->params[i].value.ui = 1U; |
|
|
desc->params[i].value.ui = 1U; |
|
|
strcpy ( desc->params[i].short_desc, "Sync transport with master's" ); |
|
|
|
|
|
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].short_desc, "Sync transport with master's"); |
|
|
|
|
|
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
|
|
|
i++; |
|
|
i++; |
|
|
strcpy ( desc->params[i].name, "mode" ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].name, "mode"); |
|
|
desc->params[i].character = 'm'; |
|
|
desc->params[i].character = 'm'; |
|
|
desc->params[i].type = JackDriverParamString; |
|
|
desc->params[i].type = JackDriverParamString; |
|
|
strcpy ( desc->params[i].value.str, "slow" ); |
|
|
|
|
|
strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." ); |
|
|
|
|
|
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); |
|
|
|
|
|
|
|
|
strcpy(desc->params[i].value.str, "slow"); |
|
|
|
|
|
strcpy(desc->params[i].short_desc, "Slow, Normal or Fast mode."); |
|
|
|
|
|
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
|
|
|
i++; |
|
|
i++; |
|
|
strcpy(desc->params[i].name, "quality"); |
|
|
strcpy(desc->params[i].name, "quality"); |
|
@@ -492,28 +502,28 @@ extern "C" |
|
|
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); |
|
|
strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); |
|
|
|
|
|
|
|
|
i++; |
|
|
i++; |
|
|
strcpy ( desc->params[i].name, "auto-connect" ); |
|
|
|
|
|
|
|
|
strcpy (desc->params[i].name, "auto-connect"); |
|
|
desc->params[i].character = 'c'; |
|
|
desc->params[i].character = 'c'; |
|
|
desc->params[i].type = JackDriverParamBool; |
|
|
desc->params[i].type = JackDriverParamBool; |
|
|
desc->params[i].value.i = false; |
|
|
desc->params[i].value.i = false; |
|
|
strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" ); |
|
|
|
|
|
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); |
|
|
|
|
|
|
|
|
strcpy (desc->params[i].short_desc, "Auto connect netmaster to system ports"); |
|
|
|
|
|
strcpy (desc->params[i].long_desc, desc->params[i].short_desc); |
|
|
|
|
|
|
|
|
return desc; |
|
|
return desc; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params ) |
|
|
|
|
|
|
|
|
SERVER_EXPORT int jack_internal_initialize(jack_client_t* jack_client, const JSList* params) |
|
|
{ |
|
|
{ |
|
|
jack_log ( "Loading netadapter" ); |
|
|
|
|
|
|
|
|
jack_log("Loading netadapter"); |
|
|
|
|
|
|
|
|
Jack::JackAudioAdapter* adapter; |
|
|
Jack::JackAudioAdapter* adapter; |
|
|
jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client ); |
|
|
|
|
|
jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client ); |
|
|
|
|
|
|
|
|
jack_nframes_t buffer_size = jack_get_buffer_size(jack_client); |
|
|
|
|
|
jack_nframes_t sample_rate = jack_get_sample_rate(jack_client); |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
|
|
|
|
|
|
adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackNetAdapter(jack_client, buffer_size, sample_rate, params), params, false); |
|
|
adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackNetAdapter(jack_client, buffer_size, sample_rate, params), params, false); |
|
|
assert ( adapter ); |
|
|
|
|
|
|
|
|
assert(adapter); |
|
|
|
|
|
|
|
|
if (adapter->Open() == 0) { |
|
|
if (adapter->Open() == 0) { |
|
|
return 0; |
|
|
return 0; |
|
@@ -527,30 +537,30 @@ extern "C" |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init ) |
|
|
|
|
|
|
|
|
SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init) |
|
|
{ |
|
|
{ |
|
|
JSList* params = NULL; |
|
|
JSList* params = NULL; |
|
|
bool parse_params = true; |
|
|
bool parse_params = true; |
|
|
int res = 1; |
|
|
int res = 1; |
|
|
jack_driver_desc_t* desc = jack_get_descriptor(); |
|
|
jack_driver_desc_t* desc = jack_get_descriptor(); |
|
|
|
|
|
|
|
|
Jack::JackArgParser parser ( load_init ); |
|
|
|
|
|
if ( parser.GetArgc() > 0 ) |
|
|
|
|
|
parse_params = parser.ParseParams ( desc, ¶ms ); |
|
|
|
|
|
|
|
|
Jack::JackArgParser parser(load_init); |
|
|
|
|
|
if (parser.GetArgc() > 0) |
|
|
|
|
|
parse_params = parser.ParseParams(desc, ¶ms); |
|
|
|
|
|
|
|
|
if (parse_params) { |
|
|
if (parse_params) { |
|
|
res = jack_internal_initialize ( jack_client, params ); |
|
|
|
|
|
parser.FreeParams ( params ); |
|
|
|
|
|
|
|
|
res = jack_internal_initialize(jack_client, params); |
|
|
|
|
|
parser.FreeParams(params); |
|
|
} |
|
|
} |
|
|
return res; |
|
|
return res; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
SERVER_EXPORT void jack_finish ( void* arg ) |
|
|
|
|
|
|
|
|
SERVER_EXPORT void jack_finish(void* arg) |
|
|
{ |
|
|
{ |
|
|
Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*> ( arg ); |
|
|
|
|
|
|
|
|
Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*>(arg); |
|
|
|
|
|
|
|
|
if (adapter) { |
|
|
if (adapter) { |
|
|
jack_log ( "Unloading netadapter" ); |
|
|
|
|
|
|
|
|
jack_log("Unloading netadapter"); |
|
|
adapter->Close(); |
|
|
adapter->Close(); |
|
|
delete adapter; |
|
|
delete adapter; |
|
|
} |
|
|
} |
|
|