Browse Source

Cleanup.

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2805 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.90
moret 16 years ago
parent
commit
2509baae32
9 changed files with 261 additions and 116 deletions
  1. +101
    -94
      Readme_NetJack2.txt
  2. +120
    -4
      common/JackNetAdapter.cpp
  3. +16
    -2
      common/JackNetAdapter.h
  4. +6
    -6
      common/JackNetDriver.cpp
  5. +1
    -1
      common/JackNetDriver.h
  6. +8
    -0
      common/JackNetInterface.h
  7. +7
    -7
      common/JackNetManager.cpp
  8. +1
    -1
      common/JackNetManager.h
  9. +1
    -1
      common/JackNetTool.h

+ 101
- 94
Readme_NetJack2.txt View File

@@ -1,94 +1,101 @@
-------------------------------
NetJack for Jackmp
-------------------------------
This branche includes a version of netjack designed for jackmp.
This prerelease is far from being complete and doesn't include some of the features proposed by netjack (transport isn't completely working yet).
Indeed, the original concept has been completely redesigned to better fit to the jackmp architecture, but also in order to provide additional capabilities, and ultimately a greater robustness.
This document describes the major changes between those two systems, then a simple how-to for setting up a basic usage of 'netjackmp'.
-------------------------------
Major changes and architecture
-------------------------------
The biggest difference between netjack and netjackmp is the way of slicing audio and midi streams into network packets.
For one audio cycle, netjack used to take all audio and midi buffers (one per channel), put butt all of them, then send it over the network.
The problem is that a network packet has a fixed maximum size, depending on the network infrastructure (for 100mb, it reaches 1500bytes - MTU of the network).
The solution is then to slice those buffers into smaller ones, and then send as many packets as we need. This cutting up can be done by network equipments, but it's more efficient and secure to include it in the software data management.
Still this slicing brings another issue : all the packets are not pleased with any emission order and are unfortunately received in a random order, thanks to UDP.
So we can't deal with data as it comes, we need to re-bufferize incoming streams in order to rebuild complete audio buffers.
With netjackmp, the main idea is to make this slicing depending on the network capabilities.
If we can put only 128 complete audio frames (128 samples for all audio channels) in a network packet, the elementary packet will so carry 128 frames, and in one cycle, we will transmit as many packet as we need. We take the example of 128 frames because it's the current value for 2 channels. This value is determinated by taking the maximum 'power of 2' frames we can put in a packet.
If we take 2 channels, 4 bytes per sample (float values), we get 8 bytes per frame, with 128 frames, we now have 1024 bytes, so we can put these 1024 bytes in one packet, and add a small header which identify the packet.
This technique allows to separate the packets (in time) so they can be received in the order they have been emitted.
If the master is running at 512 frames per second, four audio packets are sent per cycle and the slave deals with them as they arrive.
With gigabytes networks, the MTU is larger, so we can put more data in one packet (in this example, we can even put the complete cycle in one packet).
For midi data, netjack used to send the whole buffer, in this example, 512 frames * 4 bytes per sample and per midi port. Those 2048 bytes are in 99% of the time filled to a few bytes, but rarely more. This means that if we have 2 audio and 2 midi channels to transmit, everything happens as if we had 4 audio channels, which is quite a waste of bandwidth.
In netjackmp, the idea is to take into account that fact, by sending only the useful bytes, and not more. It's completely unappropriate to overload the network with useless data.
So we now have : 99% of the time one midi packet (of a few dozen of bytes), followed by four audio packets (in this example).
Those five packets are preceded by a synchronization packet, which will make the slave directly synched on the master's cycle rythm.
This way of separating audio and midi is quite important. We deal here with network transmissions, and also need to be 'realtime'. We need a system which allow to carry as many audio and midi data streams as we need and can, as if the distant computer was in fact a simple jack client. With all those constraints, we can't avoid packets loss. The better thing to do is to deal with it.
But to loose an audio packet is different from skipping a midi one. Indeed, an audio loss leads to audio click, or undesirable, but very short side effect. Whereas a midi data loss can be completely disastrous. Imagine that we play some notes, with sustain, and we loose the sustain 0 value, which stops the effect. The sustain keeps going on on all following notes until the next 'sustain off' event. A simple missing byte can put all the midi system offside (that's the purpose of all the big PANIC buttons on midi softwares...).
That's why we need to separate audio (more than one per cycle) from midi (one packet at 99% of the time). If we loose an audio packet, we probably still have an available midi packet, so we can use what we received, even if some audio is missing.
The second main difference between netjack and netjackmp is the way the two computers (master and slave) synchronise their parametering and launch.
In netjack, once the slave configured (by the command line) and launched, it was waiting for the first incoming packet to synchronize (launch its first audio cycle) then run.
The two computers needed to be configured separately but with the same parameters to run correctly.
In netjackmp, the only thing you have to set for the slave is its number of in/out midi and audio channels. No more need to choose and set parameters depending on the master, they are automatically determinated and communicated to the slave.
This first synchronization step uses a multicast communication, no more need to know by advance all the IP addresses. The slave says on a multicast address "hey, I'm available". A master get the message, and communicate parametering to the slave. Once synchronization done, audio transfers can start. Moreover, the master being still listening on the multicast address, it can catch other slaves and manage them (create a jack client to communicate with the slave, and neatily close everything when the slave is gone).
The loaded internal client is no longer only an interface for the slave, like in netjack. It's now called 'network manager', it doesn't deal with audio or midi, just with some kind of 'network logistical messages'. The manager automatically create a new internal client as soon as a new slave is seen on the network (by sending messages on the multicast address the manager is listening on). This manager is also able to remove one of its internal client as soon as a slave has left the network. This conception allow a complete separation of audio exchanges from parametering and management.
The 'unloading' of the internal client (the manager) will cause a full cleaning of the infrastructure. The jack clients are all removed from the server, the slave are all turned available again, ready to be cought by another master etc. When a slave quits, it's also automatically removed from the manager's slaves list.
-------------------------------
Current limitations
-------------------------------
The netjackmp's development has just started. This prerelease is operational, but involve some serious limitations :
- You can't set the bitdepth of the transmitted audio samples. Floating point values are used for now. The possibility to use 16 or 24bits data will be included soon, like in netjack. It's important to notice that change the bitdepth id very expensive in processing ressources (because it is a sample to sample operation).
- The 'inter-slave' communication is not optimized yet. If you connect one slave to another, the network streams go through the master. While sending network addresses to the slaves when they are inter-jack-connected, we could make the slave possibly independant of the master (except for the synchronization, sent over the network). This is the next step of the netjackmp development.
- Unlike netjack, this version doesn't include transport, this is naturally planned for the fully operational version.
- The 'Audio Adapter' is not completely working, there are several improvements to do.
-------------------------------
How-to use this ?
-------------------------------
Netjackmp is very simple to use. On the master's side, an internal client deals with the slaves, and the slaves themselves are classical jack servers running under a 'network audio driver'.
The difference between the two versions is that the master now has a manager, which takes care of the slaves, while listening on the multicast address and create a new master as soon as a slave is available. But everything is transparent to the user, that's why it uses multicast (someone says "hello", and anyone who wants to hear it just has to listen).
So, just compile and install jackmp as you are used to, on linux, using './waf configure', './waf' and './waf install' as root. On macosx, you can use the xcode project.
On Windows, you can use the Code::Blocks workspace (you also have a small script to make an all in one installer).
On the master, just launch a classical jack server, the period size doesn't matter.
Then, load the network manager using jack_load :
'jack_load netmanager'
This will load the internal client, which will wait for an available slave (see the message window on qjackctl - or the console output).
If you want to listen to a specific multicast socket, you can add some options. To spicify a complete command line, you can use :
'jack_load netmanager -i"-a xxx.xxx.xxx.xxx -p udp_port"'
If you set another multicast address or port, you have to set the same on the slave's side. The default value should be working in many cases.
On the slave, just launch a new jack server using :
'jackd -R -d net'
As in a standard backend in Jackmp, you can use '-S' (synchronous mode).
The asynchronous mode (without '-S') allows to send the computed data during the next cycle. You loose a one cycle extra latency, but you improve the masters while allowing it to receive data just after having sent some. In synchronous mode, data are sent back at the end of the cycle, that means after the process.
You can specify some options, like '-n name' (will give a name to the slave, default is the network hostname), '-C input_ports' (the number of master-->slave channels), '-P output_ports' (the number of slave-->master channels), default is 2 ; or '-i midi_in_ports' and '-o midi_out_ports', default is 0.
If you set multicast address or port on the master, you can add '-a xxx.xxx.xxx.xxx' and '-p udp_port'.
-------------------------------
What's next ?
-------------------------------
The development of 'netjackmp' continues and some things are going to change soon (see the 'actual limitations' section).
If you use it, please report encountered bugs, ideas or anything you think about.
If you have any question, you can subscribe the jackaudio developers mailing list at http://www.jackaudio.org/ or join the IRC channel 'jack' on FreeNode.
-------------------------------
NetJack for Jackmp
-------------------------------


This release includes a version of netjack designed for jackmp.
Indeed, the original concept has been completely redesigned to better fit to the jackmp architecture, but also in order to provide additional capabilities, and ultimately a greater robustness.

This document describes the major changes between those two systems, then a simple how-to for setting up a basic usage of 'netjack2'.


-------------------------------
Major changes and architecture
-------------------------------


The biggest difference between netjack and netjack2 is the way of slicing audio and midi streams into network packets.
For one audio cycle, netjack used to take all audio and midi buffers (one per channel), put butt all of them, then send it over the network.
The problem is that a network packet has a fixed maximum size, depending on the network infrastructure (for 100mb, it reaches 1500bytes - MTU of the network).
The solution is then to slice those buffers into smaller ones, and then send as many packets as we need. This cutting up can be done by network equipments, but it's more efficient and secure to include it in the software data management.
Still this slicing brings another issue : all the packets are not pleased with any emission order and are unfortunately received in a random order, thanks to UDP.
So we can't deal with data as it comes, we need to re-bufferize incoming streams in order to rebuild complete audio buffers.

In netjack2, the main idea is to make this slicing depending on the network capabilities.
If we can put only 128 complete audio frames (128 samples for all audio channels) in a network packet, the elementary packet will so carry 128 frames, and in one cycle, we will transmit as many packet as we need. We take the example of 128 frames because it's the current value for 2 channels. This value is determinated by taking the maximum 'power of 2' frames we can put in a packet.
If we take 2 channels, 4 bytes per sample (float values), we get 8 bytes per frame, with 128 frames, we now have 1024 bytes, so we can put these 1024 bytes in one packet, and add a small header which identify the packet.
This technique allows to separate the packets (in time) so they can be received in the order they have been emitted.
If the master is running at 512 frames per second, four audio packets are sent per cycle and the slave deals with them as they arrive.
With gigabytes networks, the MTU is larger, so we can put more data in one packet (in this example, we can even put the complete cycle in one packet).
For midi data, netjack used to send the whole buffer, in this example, 512 frames * 4 bytes per sample and per midi port. Those 2048 bytes are in 99% of the time filled to a few bytes, but rarely more. This means that if we have 2 audio and 2 midi channels to transmit, everything happens as if we had 4 audio channels, which is quite a waste of bandwidth.
In netjack2, the idea is to take into account that fact, by sending only the useful bytes, and not more. It's completely unappropriate to overload the network with useless data.
So we now have : 99% of the time one midi packet (of a few dozen of bytes), followed by four audio packets (in this example).

This way of separating audio and midi is quite important. We deal here with network transmissions, and also need to be 'realtime'. We need a system which allow to carry as many audio and midi data streams as we need and can, as if the distant computer was in fact a simple jack client. With all those constraints, we can't avoid packets loss. The better thing to do is to deal with it.
But to loose an audio packet is different from skipping a midi one. Indeed, an audio loss leads to audio click, or undesirable, but very short side effect. Whereas a midi data loss can be completely disastrous. Imagine that we play some notes, with sustain, and we loose the sustain 0 value, which stops the effect. The sustain keeps going on on all following notes until the next 'sustain off' event. A simple missing byte can put all the midi system offside (that's the purpose of all the big PANIC buttons on midi softwares...).
That's why we need to separate audio (more than one per cycle) from midi (one packet at 99% of the time). If we loose an audio packet, we probably still have an available midi packet, so we can use what we received, even if some audio is missing.

Those audio and midi packets are preceded by a synchronization packet, which will make the slave directly synchronized on the master's cycle rythm.
This packet also carries transport data. Thus it's actually possible to synchronize also transport.
This feature goes a little further than in netjack. The idea here is to make every computer of the network fully synchronized on the master's transport. That means the master needs to know the state of every slow sync clients of each of its slaves.
The master can now manage the transport state (especially the 'rolling' state) of each slave thus the main transport waits for the last slow sync client before turning 'rolling'.
By doing this, the transport can start (roll) in the same cycle for every computers managed by the master.


The second main difference between netjack and netjack2 is the way the two computers (master and slave) synchronise their parametering and launch.
In netjack, once the slave configured (by the command line) and launched, it was waiting for the first incoming packet to synchronize (launch its first audio cycle) then run.
The two computers needed to be configured separately but with the same parameters to run correctly.

In netjack2, the only thing you have to set for the slave is its number of in/out midi and audio channels. No more need to choose and set parameters depending on the master, they are automatically determinated and communicated to the slave.
This first synchronization step uses a multicast communication, no more need to know by advance all the IP addresses. The slave says on a multicast address "hey, I'm available". A master get the message, and communicate parametering to the slave. Once synchronization done, data transfers can start. Moreover, the master being still listening on the multicast address, it can catch other slaves and manage them (create a jack client to communicate with the slave, and neatily close everything when the slave is gone).
The loaded internal client is no longer only an interface for the slave, like in netjack. It's now called 'network manager', it doesn't deal with audio or midi, just with some kind of 'network logistical messages'. The manager automatically create a new internal client as soon as a new slave is seen on the network (by sending messages on the multicast address the manager is listening on). This manager is also able to remove one of its internal client as soon as a slave has left the network. This conception allow a complete separation of audio exchanges from parametering and management.
The 'unloading' of the internal client (the manager) will cause a full cleaning of the infrastructure. The jack clients are all removed from the server, the slave are all turned available again, ready to be cought by another master etc. When a slave quits, it's also automatically removed from the manager's slaves list.


-------------------------------
How-to use this ?
-------------------------------


Netjackmp is very simple to use. On the master's side, an internal client deals with the slaves, and the slaves themselves are classical jack servers running under a 'network audio driver'.
The difference between the two versions is that the master now has a manager, which takes care of the slaves, while listening on the multicast address and create a new master as soon as a slave is available. But everything is transparent to the user, that's why it uses multicast (someone says "hello", and anyone who wants to hear it just has to listen).

So, just compile and install jackmp as you are used to, on linux, using './waf configure', './waf' and './waf install' as root. On macosx, you can use the xcode project.
On Windows, you can use the Code::Blocks workspace (you also have a small script to make an all in one installer).

On the master, just launch a classical jack server, the period size doesn't matter.
Then, load the network manager using jack_load :

'jack_load netmanager'

This will load the internal client, which will wait for an available slave (see the message window on qjackctl - or the console output).
If you want to listen to a specific multicast socket, you can add some options. To spicify a complete command line, you can use :
'jack_load netmanager -i"-a xxx.xxx.xxx.xxx -p udp_port"'
If you set another multicast address or port, you have to set the same on the slave's side. The default value should be working in many cases.

On the slave, just launch a new jack server using :

'jackd -R -d net'

As in a standard backend in Jackmp, you can use '-S' (synchronous mode).
The asynchronous mode (without '-S') allows to send the computed data during the next cycle. In synchronous mode, data are sent back at the end of the cycle, that means after the process.
You can specify some options, like '-n name' (will give a name to the slave, default is the network hostname), '-C input_ports' (the number of master-->slave channels), '-P output_ports' (the number of slave-->master channels), default is 2 ; or '-i midi_in_ports' and '-o midi_out_ports', default is 0.
If you set multicast address or port on the master, you can add '-a xxx.xxx.xxx.xxx' and '-p udp_port'.

You can also use others network mode, with '-m' option (fast, normal or slow).
Fast mode allow a zero latency transmission. This mode means the master waits for its returned data from the slave in the current cycle. This mode is appropriated for 'small' transmissions (only a few channels with a light process on the slave).
Normal (default) mode brings one cycle latency. It allow a normal use of the network.
Slow mode allow a full usage of the whole system. Slow mode brings a two cycles additional latency. This mode allows to send a lot of data on the network, but it also takes into account some process time on the slave, thus the data aren't expected on the master before two cycles, so it's not necessary to wait for them.

For additional informations, you can go to the NetJack2 Wiki at : http://trac.jackaudio.org/wiki/WalkThrough/User/NetJack2.


-------------------------------
What's next ?
-------------------------------


The development of netjack continues and some things are always moving...
If you use it, please report encountered bugs, ideas or anything you think about.

If you have any question, you can subscribe the jackaudio developers mailing list at http://www.jackaudio.org/ or join the IRC channel '#jack' on FreeNode.

+ 120
- 4
common/JackNetAdapter.cpp View File

@@ -27,7 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

namespace Jack
{
JackNetAdapter::JackNetAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params )
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" );
@@ -42,7 +42,7 @@ namespace Jack
GetHostName ( fParams.fName, JACK_CLIENT_NAME_SIZE );
fSocket.GetName ( fParams.fSlaveNetName );
fParams.fMtu = 1500;
fParams.fTransportSync = 1;
fParams.fTransportSync = 0;
fParams.fSendAudioChannels = 2;
fParams.fReturnAudioChannels = 2;
fParams.fSendMidiChannels = 0;
@@ -51,6 +51,7 @@ namespace Jack
fParams.fPeriodSize = buffer_size;
fParams.fSlaveSyncMode = 1;
fParams.fNetworkMode = 'n';
fJackClient = jack_client;

//options parsing
const JSList* node;
@@ -82,7 +83,7 @@ namespace Jack
strncpy ( fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE );
break;
case 't' :
fParams.fTransportSync = param->value.ui;
//fParams.fTransportSync = param->value.ui;
break;
case 'm' :
if ( strcmp ( param->value.str, "normal" ) == 0 )
@@ -129,6 +130,7 @@ namespace Jack
}
}

//open/close--------------------------------------------------------------------------
int JackNetAdapter::Open()
{
jack_log ( "JackNetAdapter::Open" );
@@ -182,6 +184,7 @@ namespace Jack
return 0;
}

//thread------------------------------------------------------------------------------
bool JackNetAdapter::Init()
{
jack_log ( "JackNetAdapter::Init" );
@@ -245,22 +248,134 @@ namespace Jack
}
}

//transport---------------------------------------------------------------------------
int JackNetAdapter::DecodeTransportData()
{
//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 ?
if ( fSendTransportData.fNewState && ( fSendTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
{
switch ( fSendTransportData.fState )
{
case JackTransportStopped :
jack_transport_stop ( fJackClient );
jack_info ( "NetMaster : transport stops." );
break;
case JackTransportStarting :
jack_transport_reposition ( fJackClient, &fSendTransportData.fPosition );
jack_transport_start ( fJackClient );
jack_info ( "NetMaster : transport starts." );
break;
case JackTransportRolling :
//TODO , we need to :
// - find a way to call TransportEngine->SetNetworkSync()
// - turn the transport state to JackTransportRolling
jack_info ( "NetMaster : transport rolls." );
break;
}
}

return 0;
}

int JackNetAdapter::EncodeTransportData()
{
//is there a timebase master change ?
int refnum = -1;
bool conditional = 0;
//TODO : get the actual timebase master
if ( refnum != fLastTimebaseMaster )
{
//timebase master has released its function
if ( refnum == -1 )
{
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" );
}
fLastTimebaseMaster = refnum;
}
else
fReturnTransportData.fTimebaseMaster = NO_CHANGE;

//update transport state and position
fReturnTransportData.fState = jack_transport_query ( fJackClient, &fReturnTransportData.fPosition );

//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 ) );
fLastTransportState = fReturnTransportData.fState;

return 0;
}

//network sync------------------------------------------------------------------------
int JackNetAdapter::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 ( &fSendTransportData, fRxData, sizeof ( net_transport_data_t ) );
if ( DecodeTransportData() < 0 )
return -1;
}
//then others
//...
return 0;
}

int JackNetAdapter::EncodeSyncPacket()
{
//this method contains every step of sync packet informations coding
//first of all, reset sync packet
memset ( fTxData, 0, fPayloadSize );
//then first step : transport
if ( fParams.fTransportSync )
{
if ( EncodeTransportData() < 0 )
return -1;
//copy to TxBuffer
memcpy ( fTxData, &fReturnTransportData, sizeof ( net_transport_data_t ) );
}
//then others
//...
return 0;
}

//read/write operations---------------------------------------------------------------
int JackNetAdapter::Read()
{
if ( SyncRecv() == SOCKET_ERROR )
return 0;

if ( DecodeSyncPacket() < 0 )
return 0;

return DataRecv();
}

int JackNetAdapter::Write()
{
if ( EncodeSyncPacket() < 0 )
return 0;

if ( SyncSend() == SOCKET_ERROR )
return SOCKET_ERROR;

return DataSend();
}

//process-----------------------------------------------------------------------------
int JackNetAdapter::Process()
{
bool failure = false;
@@ -306,6 +421,7 @@ namespace Jack
}
} // namespace Jack

//loader------------------------------------------------------------------------------
#ifdef __cplusplus
extern "C"
{
@@ -406,7 +522,7 @@ extern "C"
jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client );
jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client );

adapter = new Jack::JackAudioAdapter ( jack_client, new Jack::JackNetAdapter ( buffer_size, sample_rate, params ) );
adapter = new Jack::JackAudioAdapter ( jack_client, new Jack::JackNetAdapter ( jack_client, buffer_size, sample_rate, params ) );
assert ( adapter );

if ( adapter->Open() == 0 )


+ 16
- 2
common/JackNetAdapter.h View File

@@ -36,7 +36,13 @@ namespace Jack
{
private:
//jack data
net_transport_data_t fTransportData;
jack_client_t* fJackClient;

//transport data
int fLastTransportState;
int fLastTimebaseMaster;
net_transport_data_t fSendTransportData;
net_transport_data_t fReturnTransportData;

//sample buffers
sample_t** fSoftCaptureBuffer;
@@ -45,9 +51,17 @@ namespace Jack
//adapter thread
JackThread fThread;

//transport
int EncodeTransportData();
int DecodeTransportData();

//sync packet
int EncodeSyncPacket();
int DecodeSyncPacket();

public:

JackNetAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params );
JackNetAdapter ( jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params );
~JackNetAdapter();

int Open();


+ 6
- 6
common/JackNetDriver.cpp View File

@@ -338,26 +338,26 @@ namespace Jack
fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
if ( refnum != -1 )
fEngineControl->fTransport.ResetTimebase ( refnum );
jack_info ( "NetMaster is now the new timebase master." );
jack_info ( "The NetMaster is now the new timebase master." );
}

//is there a tranport state change to handle ?
if ( fSendTransportData.fNewState && ( fSendTransportData.fState != ( uint ) fEngineControl->fTransport.GetState() ) )
if ( fSendTransportData.fNewState && ( fSendTransportData.fState != fEngineControl->fTransport.GetState() ) )
{
switch ( fSendTransportData.fState )
{
case JackTransportStopped :
fEngineControl->fTransport.SetCommand ( TransportCommandStop );
jack_info ( "NetMaster : transport stops." );
jack_info ( "Master stops transport." );
break;
case JackTransportStarting :
fEngineControl->fTransport.RequestNewPos ( &fSendTransportData.fPosition );
fEngineControl->fTransport.SetCommand ( TransportCommandStart );
jack_info ( "NetMaster : transport starts." );
jack_info ( "Master starts transport." );
break;
case JackTransportRolling :
fEngineControl->fTransport.SetState ( JackTransportRolling );
jack_info ( "NetMaster : transport rolls." );
jack_info ( "Master is rolling." );
break;
}
}
@@ -397,7 +397,7 @@ namespace Jack
fReturnTransportData.fNewState = ( ( fReturnTransportData.fState != fLastTransportState ) &&
( fReturnTransportData.fState != fSendTransportData.fState ) );
if ( fReturnTransportData.fNewState )
jack_info ( "Sending transport state '%s'.", GetTransportState ( fReturnTransportData.fState ) );
jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData.fState ) );
fLastTransportState = fReturnTransportData.fState;

return 0;


+ 1
- 1
common/JackNetDriver.h View File

@@ -42,7 +42,7 @@ namespace Jack
jack_port_id_t* fMidiPlaybackPortList;

//transport
uint fLastTransportState;
int fLastTransportState;
int fLastTimebaseMaster;
net_transport_data_t fSendTransportData;
net_transport_data_t fReturnTransportData;


+ 8
- 0
common/JackNetInterface.h View File

@@ -68,6 +68,14 @@ namespace Jack
virtual void SetParams();
virtual bool Init() = 0;

//transport
virtual int EncodeTransportData() = 0;
virtual int DecodeTransportData() = 0;

//sync packet
virtual int EncodeSyncPacket() = 0;
virtual int DecodeSyncPacket() = 0;

virtual int SyncRecv() = 0;
virtual int SyncSend() = 0;
virtual int DataRecv() = 0;


+ 7
- 7
common/JackNetManager.cpp View File

@@ -148,7 +148,7 @@ namespace Jack
goto fail;
}

jack_info ( "NetJack new master started." );
jack_info ( "New NetMaster started." );

return true;

@@ -238,7 +238,7 @@ namespace Jack
fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) &&
( fSendTransportData.fState != fReturnTransportData.fState ) );
if ( fSendTransportData.fNewState )
jack_info ( "'%s' : sending transport state '%s'.", fParams.fName, GetTransportState ( fSendTransportData.fState ) );
jack_info ( "Sending '%s' to '%s'.", GetTransportState ( fSendTransportData.fState ), fParams.fName );
fLastTransportState = fSendTransportData.fState;

return 0;
@@ -280,24 +280,24 @@ namespace Jack
}

//is the slave in a new transport state and is this state different from master's ?
if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != ( uint ) jack_transport_query ( fJackClient, NULL ) ) )
if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
{
switch ( fReturnTransportData.fState )
{
case JackTransportStopped :
jack_transport_stop ( fJackClient );
jack_info ( "'%s' : transport stops.", fParams.fName );
jack_info ( "'%s' stops transport.", fParams.fName );
break;
case JackTransportStarting :
if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) < 0 )
jack_error ( "Can't set new position." );
jack_transport_start ( fJackClient );
jack_info ( "'%s' : transport starts.", fParams.fName );
jack_info ( "'%s' starts transport.", fParams.fName );
break;
case JackTransportNetStarting :
jack_info ( "'%s' : transport is ready to roll.", fParams.fName );
jack_info ( "'%s' is ready to roll..", fParams.fName );
case JackTransportRolling :
jack_info ( "'%s' : transport is rolling.", fParams.fName );
jack_info ( "'%s' is rolling.", fParams.fName );
break;
}
}


+ 1
- 1
common/JackNetManager.h View File

@@ -52,7 +52,7 @@ namespace Jack
jack_port_t** fMidiPlaybackPorts;

//sync and transport
uint32_t fLastTransportState;
int fLastTransportState;
net_transport_data_t fSendTransportData;
net_transport_data_t fReturnTransportData;



+ 1
- 1
common/JackNetTool.h View File

@@ -178,7 +178,7 @@ namespace Jack
{
uint32_t fNewState; //is it a state change
uint32_t fTimebaseMaster; //is there a new timebase master
uint32_t fState; //current cycle state
int32_t fState; //current cycle state
jack_position_t fPosition; //current cycle position
};



Loading…
Cancel
Save