Commit 6c05d125 authored by moret's avatar moret
Browse files

Transport is now working over the network with NetJack2

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2802 0c269be4-1314-0410-8aa9-9f06e86f4224
parent 611d5c4f
......@@ -62,8 +62,7 @@ namespace Jack
#endif
}
//*************************************initialization***********************************************************************
//open, close, attach and detach------------------------------------------------------
int JackNetDriver::Open ( jack_nframes_t buffer_size, jack_nframes_t samplerate, bool capturing, bool playing,
int inchannels, int outchannels, bool monitor,
const char* capture_driver_name, const char* playback_driver_name,
......@@ -96,6 +95,7 @@ namespace Jack
return 0;
}
//init and restart--------------------------------------------------------------------
bool JackNetDriver::Init()
{
jack_log ( "JackNetDriver::Init()" );
......@@ -163,9 +163,10 @@ namespace Jack
plot_name += string ( "_fast" );
break;
}
fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name );
fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 5, plot_name );
string net_time_mon_fields[] =
{
string ( "sync decoded" ),
string ( "end of read" ),
string ( "start of write" ),
string ( "sync send" ),
......@@ -176,7 +177,7 @@ namespace Jack
string ( "set xlabel \"audio cycles\"" ),
string ( "set ylabel \"% of audio cycle\"" )
};
fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 );
fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 5 );
#endif
return true;
......@@ -210,6 +211,7 @@ namespace Jack
#endif
}
//jack ports and buffers--------------------------------------------------------------
int JackNetDriver::AllocPorts()
{
jack_log ( "JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate );
......@@ -322,32 +324,40 @@ namespace Jack
return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize ) );
}
//transport---------------------------------------------------------------------------
int JackNetDriver::DecodeTransportData()
{
//is there a new timebase master on the master ?
int refnum;
bool conditional;
//release timebase master only if it's a non-conditional request
//no request (NO_TIMEBASEMASTER) : don't do anything
//conditional request : don't change anything to, master will know if this slave is actually the timebase master
if ( fTransportData.fTimebaseMaster == TIMEBASEMASTER )
{
fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
if ( refnum != -1 )
fEngineControl->fTransport.ResetTimebase ( refnum );
jack_info ( "NetMaster is now the new timebase master." );
}
//is there a tranport state change to handle ?
if ( fTransportData.fNewState )
if ( fTransportData.fNewState && ( fTransportData.fState != (uint)fEngineControl->fTransport.GetState() ) )
{
switch ( fTransportData.fState )
{
case JackTransportStopped :
fEngineControl->fTransport.SetState ( JackTransportStopped );
break;
case JackTransportRolling :
fEngineControl->fTransport.SetState ( JackTransportRolling);
fEngineControl->fTransport.SetCommand ( TransportCommandStop );
jack_info ( "NetMaster : transport stops." );
break;
case JackTransportStarting :
fEngineControl->fTransport.RequestNewPos ( &fTransportData.fPosition );
fEngineControl->fTransport.SetCommand ( TransportCommandStart );
jack_info ( "NetMaster : transport starts." );
break;
case JackTransportRolling :
fEngineControl->fTransport.SetState ( JackTransportRolling );
jack_info ( "NetMaster : transport rolls." );
break;
}
}
......@@ -355,7 +365,7 @@ namespace Jack
return 0;
}
int JackNetDriver::SetTransportData()
int JackNetDriver::EncodeTransportData()
{
//is there a new timebase master ?
int refnum;
......@@ -366,17 +376,22 @@ namespace Jack
fTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
fLastTimebaseMaster = refnum;
}
else
fTransportData.fTimebaseMaster = NO_TIMEBASEMASTER;
//update transport state and position
fTransportData.fState = fEngineControl->fTransport.Query ( &fTransportData.fPosition );
//is it a new state ?
fTransportData.fNewState = ( fTransportData.fState != fLastTransportState );
if ( fTransportData.fNewState )
jack_info ( "Sending transport state '%s'.", GetTransportState ( fTransportData.fState ) );
fLastTransportState = fTransportData.fState;
return 0;
}
//network sync------------------------------------------------------------------------
int JackNetDriver::DecodeSyncPacket()
{
//this method contains every step of sync packet informations decoding process
......@@ -393,13 +408,15 @@ namespace Jack
return 0;
}
int JackNetDriver::SetSyncPacket()
int JackNetDriver::EncodeSyncPacket()
{
//this method contains every step of sync packet informations coding
//first : transport
//first of all, reset sync packet
memset ( fTxData, 0, fPayloadSize );
//then first step : transport
if ( fParams.fTransportSync )
{
if ( SetTransportData() < 0 )
if ( EncodeTransportData() < 0 )
return -1;
//copy to TxBuffer
memcpy ( fTxData, &fTransportData, sizeof ( net_transport_data_t ) );
......@@ -409,8 +426,7 @@ namespace Jack
return 0;
}
//*************************************process************************************************************************
//driver processes--------------------------------------------------------------------
int JackNetDriver::Read()
{
uint midi_port_index;
......@@ -433,9 +449,13 @@ namespace Jack
//take the time at the beginning of the cycle
JackDriver::CycleTakeBeginTime();
//decode transport info
//decode sync
if ( DecodeSyncPacket() < 0 )
return 0;
#ifdef JACK_MONITOR
fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
#endif
//audio, midi or sync if driver is late
if ( DataRecv() == SOCKET_ERROR )
return SOCKET_ERROR;
......@@ -463,8 +483,8 @@ namespace Jack
#endif
//sync
memset ( fTxData, 0, fPayloadSize );
SetSyncPacket();
if ( EncodeSyncPacket() < 0 )
return 0;
//send sync
if ( SyncSend() == SOCKET_ERROR )
......@@ -485,7 +505,7 @@ namespace Jack
return 0;
}
//*************************************loader*******************************************************
//driver loader-----------------------------------------------------------------------
#ifdef __cplusplus
extern "C"
......
......@@ -38,12 +38,14 @@ namespace Jack
{
private:
//jack data
net_transport_data_t fTransportData;
uint fLastTransportState;
int fLastTimebaseMaster;
jack_port_id_t* fMidiCapturePortList;
jack_port_id_t* fMidiPlaybackPortList;
//transport
uint fLastTransportState;
int fLastTimebaseMaster;
net_transport_data_t fTransportData;
//monitoring
#ifdef JACK_MONITOR
JackGnuPlotMonitor<float>* fNetTimeMon;
......@@ -55,11 +57,11 @@ namespace Jack
int FreePorts();
//transport
int SetTransportData();
int EncodeTransportData();
int DecodeTransportData();
//sync packet
int SetSyncPacket();
int EncodeSyncPacket();
int DecodeSyncPacket();
JackMidiBuffer* GetMidiInputBuffer ( int port_index );
......
......@@ -225,7 +225,7 @@ namespace Jack
}
//transport---------------------------------------------------------------------------
int JackNetMaster::SetTransportData()
int JackNetMaster::EncodeTransportData()
{
//is there a new timebase master ?
//TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value...
......@@ -236,6 +236,8 @@ namespace Jack
//is it a new state ?
fTransportData.fNewState = ( fTransportData.fState != fLastTransportState );
if ( fTransportData.fNewState )
jack_info ( "'%s' : sending transport state '%s'.", fParams.fName, GetTransportState ( fTransportData.fState ) );
fLastTransportState = fTransportData.fState;
return 0;
......@@ -244,36 +246,51 @@ namespace Jack
int JackNetMaster::DecodeTransportData()
{
//is the slave a new timebase master ?
int timebase;
switch ( fTransportData.fTimebaseMaster )
{
case NO_TIMEBASEMASTER :
break;
case TIMEBASEMASTER :
jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this );
timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this );
if ( timebase < 0 )
jack_error ( "Can't set a new timebase master." );
else
jack_info ( "'%s' is the new timebase master.", fParams.fName );
break;
case CONDITIONAL_TIMEBASEMASTER :
jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this );
timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this );
if ( timebase < 0 )
{
if ( timebase == EBUSY )
jack_error ( "'%s' is already the timebase master.", fParams.fName );
else
jack_error ( "Can't set a new timebase master." );
}
else
jack_info ( "'%s' is the new timebase master.", fParams.fName );
break;
}
//is there a transport state change to handle ?
if ( fTransportData.fNewState )
//is the slave in a new transport state and is this state different from master's ?
if ( fTransportData.fNewState && ( fTransportData.fState != (uint)jack_transport_query ( fJackClient, NULL ) ) )
{
switch ( fTransportData.fState )
{
case JackTransportStopped :
jack_transport_stop ( fJackClient );
jack_info ( "%s stops transport.", fParams.fName );
break;
case JackTransportRolling :
if ( jack_transport_query ( fJackClient, &fTransportData.fPosition ) != JackTransportRolling )
jack_error ( "Problem with transport." );
jack_info ( "'%s' : transport stops.", fParams.fName );
break;
case JackTransportStarting :
if ( jack_transport_reposition ( fJackClient, &fTransportData.fPosition ) < 0 )
return -1;
jack_error ( "Can't set new position." );
jack_transport_start ( fJackClient );
jack_info ( "%s start transport.", fParams.fName );
jack_info ( "'%s' : transport starts.", fParams.fName );
break;
case JackTransportNetStarting :
jack_info ( "'%s' : transport is ready to roll.", fParams.fName );
case JackTransportRolling :
jack_info ( "'%s' : transport is rolling.", fParams.fName );
break;
}
}
......@@ -298,13 +315,16 @@ namespace Jack
}
//sync--------------------------------------------------------------------------------
int JackNetMaster::SetSyncPacket()
int JackNetMaster::EncodeSyncPacket()
{
//this method contains every step of sync packet informations coding
//first : transport
//first of all, reset sync packet
memset ( fTxData, 0, fPayloadSize );
//then, first step : transport
if ( fParams.fTransportSync )
{
if ( SetTransportData() < 0 )
if ( EncodeTransportData() < 0 )
return -1;
//copy to TxBuffer
memcpy ( fTxData, &fTransportData, sizeof ( net_transport_data_t ) );
......@@ -368,9 +388,9 @@ namespace Jack
fNetAudioPlaybackBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index],
fParams.fPeriodSize ) ) );
//Set the first packet to send
memset ( fTxData, 0, fPayloadSize );
SetSyncPacket();
//encode the first packet
if ( EncodeSyncPacket() < 0 )
return 0;
//send sync
if ( SyncSend() == SOCKET_ERROR )
......@@ -473,11 +493,11 @@ namespace Jack
int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos )
{
//check sync state for every master in the list
//check if each slave is ready to roll
int ret = 1;
master_list_it_t it;
for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
if ( !( *it )->IsSlaveReadyToRoll())
if ( !( *it )->IsSlaveReadyToRoll() )
ret = 0;
jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" );
return ret;
......
......@@ -67,11 +67,11 @@ namespace Jack
void Exit();
//transport
int SetTransportData();
int EncodeTransportData();
int DecodeTransportData();
//sync packet
int SetSyncPacket();
int EncodeSyncPacket();
int DecodeSyncPacket();
int Process();
......
......@@ -351,4 +351,20 @@ namespace Jack
#endif
return 0;
}
EXPORT const char* GetTransportState ( int transport_state )
{
switch ( transport_state )
{
case JackTransportRolling :
return "rolling";
case JackTransportStarting :
return "starting";
case JackTransportStopped :
return "stopped";
case JackTransportNetStarting :
return "netstarting";
}
return NULL;
}
}
......@@ -279,4 +279,6 @@ namespace Jack
EXPORT sync_packet_type_t GetPacketType ( session_params_t* params );
//set the packet type in a session parameters
EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type );
//transport utility
EXPORT const char* GetTransportState ( int transport_state );
}
......@@ -228,6 +228,9 @@ void JackTransportEngine::CycleEnd(JackClientInterface** table, jack_nframes_t f
}
break;
case JackTransportNetStarting:
break;
default:
jack_error("Invalid JACK transport state: %d", fTransportState);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment