JackNetTool.h
/*
Copyright (C) 2008-2011 Romain Moret at Grame
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "JackMidiPort.h"
#include "JackTools.h"
#include "types.h"
#include "transport.h"
#ifndef WIN32
#include <netinet/in.h>
#endif
#include <cmath>
using namespace std;
#ifndef htonll
#ifdef __BIG_ENDIAN__
#define htonll(x) (x)
#define ntohll(x) (x)
#else
#define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl(x >> 32))
#define ntohll(x) ((((uint64_t)ntohl(x)) << 32) + ntohl(x >> 32))
#endif
#endif
#define NETWORK_PROTOCOL 8
#define NET_SYNCHING 0
#define SYNC_PACKET_ERROR -2
#define DATA_PACKET_ERROR -3
#define OPTIMIZED_PROTOCOL 1
#define UDP_HEADER_SIZE 64 // 40 bytes for IP header in IPV6, 20 in IPV4, 8 for UDP, so take 64
#define HEADER_SIZE (sizeof(packet_header_t))
// TODO : change PACKET_AVAILABLE_SIZE definition ==> #define PACKET_AVAILABLE_SIZE(params) ((params)->fMtu - UDP_HEADER_SIZE - sizeof(packet_header_t))
#define PACKET_AVAILABLE_SIZE(params) ((params)->fMtu - HEADER_SIZE)
namespace Jack
{
typedef struct _session_params session_params_t;
typedef struct _packet_header packet_header_t;
typedef struct _net_transport_data net_transport_data_t;
typedef struct sockaddr socket_address_t;
typedef struct in_addr address_t;
typedef jack_default_audio_sample_t sample_t;
enum JackNetEncoder {
JackFloatEncoder = 0,
JackIntEncoder = 1,
JackCeltEncoder = 2,
JackOpusEncoder = 3,
};
//session params ******************************************************************************
PRE_PACKED_STRUCTURE
struct _session_params
{
char fPacketType[8]; //packet type ('param')
uint32_t fProtocolVersion; //version
int32_t fPacketID; //indicates the packet type
char fName[JACK_CLIENT_NAME_SIZE]; //slave's name
char fMasterNetName[JACK_SERVER_NAME_SIZE]; //master hostname (network)
char fSlaveNetName[JACK_SERVER_NAME_SIZE]; //slave hostname (network)
uint32_t fMtu; //connection mtu
uint32_t fID; //slave's ID
uint32_t fTransportSync; //is the transport synced ?
int32_t fSendAudioChannels; //number of master->slave channels
int32_t fReturnAudioChannels; //number of slave->master channels
int32_t fSendMidiChannels; //number of master->slave midi channels
int32_t fReturnMidiChannels; //number of slave->master midi channels
uint32_t fSampleRate; //session sample rate
uint32_t fPeriodSize; //period size
uint32_t fSampleEncoder; //samples encoder
uint32_t fKBps; //KB per second for CELT encoder
uint32_t fSlaveSyncMode; //is the slave in sync mode ?
uint32_t fNetworkLatency; //network latency
} POST_PACKED_STRUCTURE;
//net status **********************************************************************************
enum _net_status
{
NET_SOCKET_ERROR = 0,
NET_CONNECT_ERROR,
NET_ERROR,
NET_SEND_ERROR,
NET_RECV_ERROR,
NET_CONNECTED,
NET_ROLLING
};
typedef enum _net_status net_status_t;
//sync packet type ****************************************************************************
enum _sync_packet_type
{
INVALID = 0, //...
SLAVE_AVAILABLE, //a slave is available
SLAVE_SETUP, //slave configuration
START_MASTER, //slave is ready, start master
START_SLAVE, //master is ready, activate slave
KILL_MASTER //master must stop
};
typedef enum _sync_packet_type sync_packet_type_t;
//packet header *******************************************************************************
PRE_PACKED_STRUCTURE
struct _packet_header
{
char fPacketType[8]; //packet type ('headr')
uint32_t fDataType; //'a' for audio, 'm' for midi and 's' for sync
uint32_t fDataStream; //'s' for send, 'r' for return
uint32_t fID; //unique ID of the slave
uint32_t fNumPacket; //number of data packets of the cycle
uint32_t fPacketSize; //packet size in bytes
uint32_t fActivePorts; //number of active ports
uint32_t fCycle; //process cycle counter
uint32_t fSubCycle; //midi/audio subcycle counter
int32_t fFrames; //process cycle size in frames (can be -1 to indicate entire buffer)
uint32_t fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n')
} POST_PACKED_STRUCTURE;
//net timebase master
enum _net_timebase_master
{
NO_CHANGE = 0,
RELEASE_TIMEBASEMASTER = 1,
TIMEBASEMASTER = 2,
CONDITIONAL_TIMEBASEMASTER = 3
};
typedef enum _net_timebase_master net_timebase_master_t;
//transport data ******************************************************************************
PRE_PACKED_STRUCTURE
struct _net_transport_data
{
uint32_t fNewState; //is it a state change
uint32_t fTimebaseMaster; //is there a new timebase master
int32_t fState; //current cycle state
jack_position_t fPosition; //current cycle position
} POST_PACKED_STRUCTURE;
//midi data ***********************************************************************************
class SERVER_EXPORT NetMidiBuffer
{
private:
int fNPorts;
size_t fMaxBufsize;
int fMaxPcktSize;
char* fBuffer;
char* fNetBuffer;
JackMidiBuffer** fPortBuffer;
size_t fCycleBytesSize; // needed size in bytes ofr an entire cycle
public:
NetMidiBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
~NetMidiBuffer();
void Reset();
// needed size in bytes for an entire cycle
size_t GetCycleSize();
int GetNumPackets(int data_sizen, int max_size);
void SetBuffer(int index, JackMidiBuffer* buffer);
JackMidiBuffer* GetBuffer(int index);
//utility
void DisplayEvents();
//jack<->buffer
int RenderFromJackPorts();
void RenderToJackPorts();
//network<->buffer
void RenderFromNetwork(int sub_cycle, size_t copy_size);
int RenderToNetwork(int sub_cycle, size_t total_size);
};
// audio data *********************************************************************************
class SERVER_EXPORT NetAudioBuffer
{
protected:
int fNPorts;
int fLastSubCycle;
int fNumPackets;
char* fNetBuffer;
sample_t** fPortBuffer;
bool* fConnectedPorts;
jack_nframes_t fPeriodSize;
jack_nframes_t fSubPeriodSize;
size_t fSubPeriodBytesSize;
float fCycleDuration; // in sec
size_t fCycleBytesSize; // needed size in bytes for an entire cycle
int CheckPacket(int cycle, int sub_cycle);
void NextCycle();
void Cleanup();
public:
NetAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
virtual ~NetAudioBuffer();
bool GetConnected(int port_index) { return fConnectedPorts[port_index]; }
void SetConnected(int port_index, bool state) { fConnectedPorts[port_index] = state; }
// needed syze in bytes ofr an entire cycle
virtual size_t GetCycleSize() = 0;
// cycle duration in sec
virtual float GetCycleDuration() = 0;
virtual int GetNumPackets(int active_ports) = 0;
virtual void SetBuffer(int index, sample_t* buffer);
virtual sample_t* GetBuffer(int index);
//jack<->buffer
virtual int RenderFromJackPorts(int nframes);
virtual void RenderToJackPorts(int nframes);
//network<->buffer
virtual int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num) = 0;
virtual int RenderToNetwork(int sub_cycle, uint32_t port_num) = 0;
virtual int ActivePortsToNetwork(char* net_buffer);
virtual void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num);
};
class SERVER_EXPORT NetFloatAudioBuffer : public NetAudioBuffer
{
private:
int fPacketSize;
void UpdateParams(int active_ports);
void RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle);
void RenderToNetwork(char* net_buffer, int active_port, int sub_cycle);
public:
NetFloatAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
virtual ~NetFloatAudioBuffer();
// needed size in bytes for an entire cycle
size_t GetCycleSize();
// cycle duration in sec
float GetCycleDuration();
int GetNumPackets(int active_ports);
//jack<->buffer
int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num);
int RenderToNetwork(int sub_cycle, uint32_t port_num);
};
#if HAVE_CELT
#include <celt/celt.h>
class SERVER_EXPORT NetCeltAudioBuffer : public NetAudioBuffer
{
private:
CELTMode** fCeltMode;
CELTEncoder** fCeltEncoder;
CELTDecoder** fCeltDecoder;
int fCompressedSizeByte;
unsigned char** fCompressedBuffer;
size_t fLastSubPeriodBytesSize;
void FreeCelt();
public:
NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps);
virtual ~NetCeltAudioBuffer();
// needed size in bytes for an entire cycle
size_t GetCycleSize();
// cycle duration in sec
float GetCycleDuration();
int GetNumPackets(int active_ports);
//jack<->buffer
int RenderFromJackPorts(int nframes);
void RenderToJackPorts(int nframes);
//network<->buffer
int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num);
int RenderToNetwork(int sub_cycle, uint32_t port_num);
};
#endif
#if HAVE_OPUS
#include <opus/opus.h>
#include <opus/opus_custom.h>
class SERVER_EXPORT NetOpusAudioBuffer : public NetAudioBuffer
{
private:
OpusCustomMode** fOpusMode;
OpusCustomEncoder** fOpusEncoder;
OpusCustomDecoder** fOpusDecoder;
int fCompressedMaxSizeByte;
unsigned short* fCompressedSizesByte;
size_t fLastSubPeriodBytesSize;
unsigned char** fCompressedBuffer;
void FreeOpus();
public:
NetOpusAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps);
virtual ~NetOpusAudioBuffer();
// needed size in bytes for an entire cycle
size_t GetCycleSize();
// cycle duration in sec
float GetCycleDuration();
int GetNumPackets(int active_ports);
//jack<->buffer
int RenderFromJackPorts(int nframes);
void RenderToJackPorts(int nframes);
//network<->buffer
int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num);
int RenderToNetwork(int sub_cycle, uint32_t port_num);
};
#endif
class SERVER_EXPORT NetIntAudioBuffer : public NetAudioBuffer
{
private:
int fCompressedSizeByte;
size_t fLastSubPeriodBytesSize;
short** fIntBuffer;
public:
NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
virtual ~NetIntAudioBuffer();
// needed size in bytes for an entire cycle
size_t GetCycleSize();
// cycle duration in sec
float GetCycleDuration();
int GetNumPackets(int active_ports);
//jack<->buffer
int RenderFromJackPorts(int nframes);
void RenderToJackPorts(int nframes);
//network<->buffer
int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num);
int RenderToNetwork(int sub_cycle, uint32_t port_num);
};
//utility *************************************************************************************
//socket API management
SERVER_EXPORT int SocketAPIInit();
SERVER_EXPORT int SocketAPIEnd();
//n<-->h functions
SERVER_EXPORT void SessionParamsHToN(session_params_t* src_params, session_params_t* dst_params);
SERVER_EXPORT void SessionParamsNToH(session_params_t* src_params, session_params_t* dst_params);
SERVER_EXPORT void PacketHeaderHToN(packet_header_t* src_header, packet_header_t* dst_header);
SERVER_EXPORT void PacketHeaderNToH(packet_header_t* src_header, packet_header_t* dst_header);
SERVER_EXPORT void MidiBufferHToN(JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer);
SERVER_EXPORT void MidiBufferNToH(JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer);
SERVER_EXPORT void TransportDataHToN(net_transport_data_t* src_params, net_transport_data_t* dst_params);
SERVER_EXPORT void TransportDataNToH(net_transport_data_t* src_params, net_transport_data_t* dst_params);
//display session parameters
SERVER_EXPORT void SessionParamsDisplay(session_params_t* params);
//display packet header
SERVER_EXPORT void PacketHeaderDisplay(packet_header_t* header);
//get the packet type from a sesion parameters
SERVER_EXPORT sync_packet_type_t GetPacketType(session_params_t* params);
//set the packet type in a session parameters
SERVER_EXPORT int SetPacketType(session_params_t* params, sync_packet_type_t packet_type);
//transport utility
SERVER_EXPORT const char* GetTransportState(int transport_state);
SERVER_EXPORT void NetTransportDataDisplay(net_transport_data_t* data);
}
_jack_position
Definition: types.h:554
Jack::NetFloatAudioBuffer
Definition: JackNetTool.h:338
Jack
Definition: JackAC3Encoder.cpp:30
std
Jack::_packet_header
Definition: JackNetTool.h:175
Jack::NetIntAudioBuffer
Definition: JackNetTool.h:455
Jack::JackMidiBuffer
Definition: JackMidiPort.h:75
Jack::NetMidiBuffer
Definition: JackNetTool.h:239
Jack::NetAudioBuffer
Definition: JackNetTool.h:282
Jack::_session_params
This structure containes master/slave connection parameters, it's used to setup the whole system...
Definition: JackNetTool.h:92
Jack::_net_transport_data
Definition: JackNetTool.h:214