Commit 611d5c4f authored by moret's avatar moret
Browse files

Add first version of transport in NetJack2

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2801 0c269be4-1314-0410-8aa9-9f06e86f4224
parent a280d1f3
......@@ -47,6 +47,7 @@ namespace Jack
fSocket.GetName ( fParams.fSlaveNetName );
fParams.fTransportSync = transport_sync;
fParams.fNetworkMode = network_mode;
fLastTimebaseMaster = -1;
#ifdef JACK_MONITOR
fNetTimeMon = NULL;
#endif
......@@ -126,6 +127,9 @@ namespace Jack
JackDriver::NotifyBufferSize ( fParams.fPeriodSize );
JackDriver::NotifySampleRate ( fParams.fSampleRate );
//transport engine parametering
fEngineControl->fTransport.SetNetworkSync ( true );
//allocate midi ports lists
fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels];
fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels];
......@@ -318,15 +322,90 @@ namespace Jack
return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize ) );
}
int JackNetDriver::SetSyncPacket()
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
if ( fTransportData.fTimebaseMaster == TIMEBASEMASTER )
{
fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
if ( refnum != -1 )
fEngineControl->fTransport.ResetTimebase ( refnum );
}
//is there a tranport state change to handle ?
if ( fTransportData.fNewState )
{
switch ( fTransportData.fState )
{
case JackTransportStopped :
fEngineControl->fTransport.SetState ( JackTransportStopped );
break;
case JackTransportRolling :
fEngineControl->fTransport.SetState ( JackTransportRolling);
break;
case JackTransportStarting :
fEngineControl->fTransport.SetCommand ( TransportCommandStart );
break;
}
}
return 0;
}
int JackNetDriver::SetTransportData()
{
//is there a new timebase master ?
int refnum;
bool conditional;
fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
if ( refnum != fLastTimebaseMaster )
{
fTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
fLastTimebaseMaster = refnum;
}
//update transport state and position
fTransportData.fState = fEngineControl->fTransport.Query ( &fTransportData.fPosition );
//is it a new state ?
fTransportData.fNewState = ( fTransportData.fState != fLastTransportState );
fLastTransportState = fTransportData.fState;
return 0;
}
int JackNetDriver::DecodeSyncPacket()
{
//this method contains every step of sync packet informations decoding process
//first : transport
if ( fParams.fTransportSync )
{
//set the TransportData
//copy received transport data to transport data structure
memcpy ( &fTransportData, fRxData, sizeof ( net_transport_data_t ) );
if ( DecodeTransportData() < 0 )
return -1;
}
//then others
//...
return 0;
}
int JackNetDriver::SetSyncPacket()
{
//this method contains every step of sync packet informations coding
//first : transport
if ( fParams.fTransportSync )
{
if ( SetTransportData() < 0 )
return -1;
//copy to TxBuffer
memcpy ( fTxData, &fTransportData, sizeof ( net_transport_data_t ) );
}
//then others
//...
return 0;
}
......@@ -354,6 +433,9 @@ namespace Jack
//take the time at the beginning of the cycle
JackDriver::CycleTakeBeginTime();
//decode transport info
//audio, midi or sync if driver is late
if ( DataRecv() == SOCKET_ERROR )
return SOCKET_ERROR;
......
......@@ -39,12 +39,13 @@ namespace Jack
private:
//jack data
net_transport_data_t fTransportData;
uint fLastTransportState;
int fLastTimebaseMaster;
jack_port_id_t* fMidiCapturePortList;
jack_port_id_t* fMidiPlaybackPortList;
//monitoring
#ifdef JACK_MONITOR
//time measurment
JackGnuPlotMonitor<float>* fNetTimeMon;
#endif
......@@ -52,13 +53,18 @@ namespace Jack
void Restart();
int AllocPorts();
int FreePorts();
//transport
int SetTransportData();
int DecodeTransportData();
//sync packet
int SetSyncPacket();
int TransportSync();
int DecodeSyncPacket();
JackMidiBuffer* GetMidiInputBuffer ( int port_index );
JackMidiBuffer* GetMidiOutputBuffer ( int port_index );
public:
JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports,
......@@ -79,7 +85,7 @@ namespace Jack
int Read();
int Write();
// BufferSize can be changed
// BufferSize can't be changed
bool IsFixedBufferSize()
{
return true;
......
......@@ -40,7 +40,6 @@ namespace Jack
//settings
fClientName = const_cast<char*> ( fParams.fName );
fJackClient = NULL;
fSyncState = 1;
uint port_index;
//jack audio ports
......@@ -113,7 +112,7 @@ namespace Jack
delete fNetTimeMon;
#endif
}
//init--------------------------------------------------------------------------------
bool JackNetMaster::Init()
{
//network init
......@@ -160,6 +159,7 @@ namespace Jack
return false;
}
//jack ports--------------------------------------------------------------------------
int JackNetMaster::AllocPorts()
{
jack_log ( "JackNetMaster::AllocPorts" );
......@@ -224,22 +224,121 @@ namespace Jack
jack_port_unregister ( fJackClient, fMidiPlaybackPorts[port_index] );
}
//transport---------------------------------------------------------------------------
int JackNetMaster::SetTransportData()
{
//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...
fTransportData.fTimebaseMaster = NO_TIMEBASEMASTER;
//update state and position
fTransportData.fState = static_cast<uint32_t> ( jack_transport_query ( fJackClient, &fTransportData.fPosition ) );
//is it a new state ?
fTransportData.fNewState = ( fTransportData.fState != fLastTransportState );
fLastTransportState = fTransportData.fState;
return 0;
}
int JackNetMaster::DecodeTransportData()
{
//is the slave a new timebase master ?
switch ( fTransportData.fTimebaseMaster )
{
case NO_TIMEBASEMASTER :
break;
case TIMEBASEMASTER :
jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this );
break;
case CONDITIONAL_TIMEBASEMASTER :
jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this );
break;
}
//is there a transport state change to handle ?
if ( fTransportData.fNewState )
{
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." );
break;
case JackTransportStarting :
if ( jack_transport_reposition ( fJackClient, &fTransportData.fPosition ) < 0 )
return -1;
jack_transport_start ( fJackClient );
jack_info ( "%s start transport.", fParams.fName );
break;
}
}
return 0;
}
void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg )
{
static_cast<JackNetMaster*> ( arg )->TimebaseCallback ( pos );
}
void JackNetMaster::TimebaseCallback ( jack_position_t* pos )
{
pos->bar = fTransportData.fPosition.bar;
pos->beat = fTransportData.fPosition.beat;
pos->tick = fTransportData.fPosition.tick;
pos->bar_start_tick = fTransportData.fPosition.bar_start_tick;
pos->beats_per_bar = fTransportData.fPosition.beats_per_bar;
pos->beat_type = fTransportData.fPosition.beat_type;
pos->ticks_per_beat = fTransportData.fPosition.ticks_per_beat;
pos->beats_per_minute = fTransportData.fPosition.beats_per_minute;
}
//sync--------------------------------------------------------------------------------
int JackNetMaster::SetSyncPacket()
{
//this method contains every step of sync packet informations coding
//first : transport
if ( fParams.fTransportSync )
{
//TODO : set the TransportData
if ( SetTransportData() < 0 )
return -1;
//copy to TxBuffer
memcpy ( fTxData, &fTransportData, sizeof ( net_transport_data_t ) );
}
//then others
//...
return 0;
}
int JackNetMaster::DecodeSyncPacket()
{
//this method contains every step of sync packet informations decoding process
//first : transport
if ( fParams.fTransportSync )
{
//copy received transport data to transport data structure
memcpy ( &fTransportData, fRxData, sizeof ( net_transport_data_t ) );
if ( DecodeTransportData() < 0 )
return -1;
}
//then others
//...
return 0;
}
bool JackNetMaster::IsSlaveReadyToRoll()
{
return ( fTransportData.fState == JackTransportNetStarting );
}
//process-----------------------------------------------------------------------------
int JackNetMaster::SetProcess ( jack_nframes_t nframes, void* arg )
{
JackNetMaster* master = static_cast<JackNetMaster*> ( arg );
return master->Process();
return static_cast<JackNetMaster*> ( arg )->Process();
}
int JackNetMaster::Process()
......@@ -298,6 +397,10 @@ namespace Jack
fNetTimeMon->Add ( ( ( ( float ) ( jack_get_time() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
#endif
//decode sync
if ( DecodeSyncPacket() < 0 )
return 0;
//receive data
res = DataRecv();
if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
......@@ -365,8 +468,7 @@ namespace Jack
int JackNetMasterManager::SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg )
{
JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*> ( arg );
return master_manager->SyncCallback ( state, pos );
return static_cast<JackNetMasterManager*> ( arg )->SyncCallback ( state, pos );
}
int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos )
......@@ -375,7 +477,7 @@ namespace Jack
int ret = 1;
master_list_it_t it;
for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
if ( ( *it )->fSyncState == 0 )
if ( !( *it )->IsSlaveReadyToRoll())
ret = 0;
jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" );
return ret;
......
......@@ -39,6 +39,7 @@ namespace Jack
friend class JackNetMasterManager;
private:
static int SetProcess ( jack_nframes_t nframes, void* arg );
static void SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg );
//jack client
jack_client_t* fJackClient;
......@@ -51,7 +52,7 @@ namespace Jack
jack_port_t** fMidiPlaybackPorts;
//sync and transport
int fSyncState;
uint32_t fLastTransportState;
net_transport_data_t fTransportData;
//monitoring
......@@ -65,12 +66,22 @@ namespace Jack
void FreePorts();
void Exit();
//transport
int SetTransportData();
int DecodeTransportData();
//sync packet
int SetSyncPacket();
int DecodeSyncPacket();
int Process();
void TimebaseCallback ( jack_position_t* pos);
public:
JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip );
~JackNetMaster ();
bool IsSlaveReadyToRoll();
};
typedef std::list<JackNetMaster*> master_list_t;
......
......@@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackTools.h"
#include "JackPlatformNetSocket.h"
#include "types.h"
#include "transport.h"
#include <cmath>
using namespace std;
......@@ -150,16 +151,34 @@ namespace Jack
char fFree[26]; //unused
};
//net timebase master
/**
\Brief This enum describes timebase master's type
*/
enum _net_timebase_master
{
NO_TIMEBASEMASTER = 0,
TIMEBASEMASTER = 1,
CONDITIONAL_TIMEBASEMASTER = 2
};
typedef enum _net_timebase_master net_timebase_master_t;
//transport data ******************************************************************************
/**
\Brief This structure contains transport info
\Brief This structure contains transport data to be sent over the network
*/
struct _net_transport_data
{
jack_position_t fCurPos;
jack_transport_state_t fCurState;
uint32_t fNewState; //is it a state change
uint32_t fTimebaseMaster; //is there a new timebase master
uint32_t fState; //current cycle state
jack_position_t fPosition; //current cycle position
};
//midi data ***********************************************************************************
......
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