pipewire/src/modules/module-netjack2/packets.h
Wim Taymans d0a2e6316b spa: small cleanups
Initialize result variable.
Use strncpy to avoid warnings about using non-NULL terminaded strings.
2024-01-10 15:51:01 +01:00

194 lines
7.7 KiB
C

/* PipeWire */
/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */
/* SPDX-License-Identifier: MIT */
#ifndef PIPEWIRE_NETJACK2_H
#define PIPEWIRE_NETJACK2_H
#ifdef __cplusplus
extern "C" {
#endif
#define JACK_CLIENT_NAME_SIZE 64
#define JACK_SERVER_NAME_SIZE 256
struct nj2_session_params {
char type[8]; /* packet type ('param') */
#define NJ2_NETWORK_PROTOCOL 8
uint32_t version; /* version */
#define NJ2_ID_FOLLOWER_AVAILABLE 0 /* a follower is available */
#define NJ2_ID_FOLLOWER_SETUP 1 /* follower configuration */
#define NJ2_ID_START_DRIVER 2 /* follower is ready, start driver */
#define NJ2_ID_START_FOLLOWER 3 /* driver is ready, activate follower */
#define NJ2_ID_STOP_DRIVER 4 /* driver must stop */
int32_t packet_id; /* indicates the packet type */
char name[JACK_CLIENT_NAME_SIZE]; /* follower's name */
char driver_name[JACK_SERVER_NAME_SIZE]; /* driver hostname (network) */
char follower_name[JACK_SERVER_NAME_SIZE]; /* follower hostname (network) */
uint32_t mtu; /* connection mtu */
uint32_t id; /* follower's ID */
uint32_t transport_sync; /* is the transport synced ? */
int32_t send_audio_channels; /* number of driver->follower channels */
int32_t recv_audio_channels; /* number of follower->driver channels */
int32_t send_midi_channels; /* number of driver->follower midi channels */
int32_t recv_midi_channels; /* number of follower->driver midi channels */
uint32_t sample_rate; /* session sample rate */
uint32_t period_size; /* period size */
#define NJ2_ENCODER_FLOAT 0
#define NJ2_ENCODER_INT 1
#define NJ2_ENCODER_CELT 2
#define NJ2_ENCODER_OPUS 3
uint32_t sample_encoder; /* samples encoder */
uint32_t kbps; /* KB per second for CELT encoder */
uint32_t follower_sync_mode; /* is the follower in sync mode ? */
uint32_t network_latency; /* network latency */
} __attribute__ ((packed));
static inline void nj2_dump_session_params(struct nj2_session_params *params)
{
pw_log_info("Type: '%s'", params->type);
pw_log_info("Version: %u", ntohl(params->version));
pw_log_info("packet ID: %d", ntohl(params->packet_id));
pw_log_info("Name: '%s'", params->name);
pw_log_info("Driver Name: '%s'", params->driver_name);
pw_log_info("Follower Name: '%s'", params->follower_name);
pw_log_info("MTU: %u", ntohl(params->mtu));
pw_log_info("ID: %u", ntohl(params->id));
pw_log_info("TransportSync: %u", ntohl(params->transport_sync));
pw_log_info("Audio Send: %d", ntohl(params->send_audio_channels));
pw_log_info("Audio Recv: %d", ntohl(params->recv_audio_channels));
pw_log_info("MIDI Send: %d", ntohl(params->send_midi_channels));
pw_log_info("MIDI Recv: %d", ntohl(params->recv_midi_channels));
pw_log_info("Sample Rate: %u", ntohl(params->sample_rate));
pw_log_info("Period Size: %u", ntohl(params->period_size));
pw_log_info("Encoder: %u", ntohl(params->sample_encoder));
pw_log_info("KBps: %u", ntohl(params->kbps));
pw_log_info("Follower Sync: %u", ntohl(params->follower_sync_mode));
pw_log_info("Latency: %u", ntohl(params->network_latency));
}
static inline void nj2_session_params_ntoh(struct nj2_session_params *host,
const struct nj2_session_params *net)
{
memcpy(host, net, sizeof(*host));
host->version = ntohl(net->version);
host->packet_id = ntohl(net->packet_id);
host->mtu = ntohl(net->mtu);
host->id = ntohl(net->id);
host->transport_sync = ntohl(net->transport_sync);
host->send_audio_channels = ntohl(net->send_audio_channels);
host->recv_audio_channels = ntohl(net->recv_audio_channels);
host->send_midi_channels = ntohl(net->send_midi_channels);
host->recv_midi_channels = ntohl(net->recv_midi_channels);
host->sample_rate = ntohl(net->sample_rate);
host->period_size = ntohl(net->period_size);
host->sample_encoder = ntohl(net->sample_encoder);
host->kbps = ntohl(net->kbps);
host->follower_sync_mode = ntohl(net->follower_sync_mode);
host->network_latency = ntohl(net->network_latency);
}
static inline void nj2_session_params_hton(struct nj2_session_params *net,
const struct nj2_session_params *host)
{
memcpy(net, host, sizeof(*net));
net->version = htonl(host->version);
net->packet_id = htonl(host->packet_id);
net->mtu = htonl(host->mtu);
net->id = htonl(host->id);
net->transport_sync = htonl(host->transport_sync);
net->send_audio_channels = htonl(host->send_audio_channels);
net->recv_audio_channels = htonl(host->recv_audio_channels);
net->send_midi_channels = htonl(host->send_midi_channels);
net->recv_midi_channels = htonl(host->recv_midi_channels);
net->sample_rate = htonl(host->sample_rate);
net->period_size = htonl(host->period_size);
net->sample_encoder = htonl(host->sample_encoder);
net->kbps = htonl(host->kbps);
net->follower_sync_mode = htonl(host->follower_sync_mode);
net->network_latency = htonl(host->network_latency);
}
struct nj2_packet_header {
char type[8]; /* packet type ('header') */
uint32_t data_type; /* 'a' for audio, 'm' for midi and 's' for sync */
uint32_t data_stream; /* 's' for send, 'r' for return */
uint32_t id; /* unique ID of the follower */
uint32_t num_packets; /* number of data packets of the cycle */
uint32_t packet_size; /* packet size in bytes */
uint32_t active_ports; /* number of active ports */
uint32_t cycle; /* process cycle counter */
uint32_t sub_cycle; /* midi/audio subcycle counter */
int32_t frames; /* process cycle size in frames (can be -1 to indicate entire buffer) */
uint32_t is_last; /* is it the last packet of a given cycle ('y' or 'n') */
} __attribute__ ((packed));
#define UDP_HEADER_SIZE 64 /* 40 bytes for IP header in IPV6, 20 in IPV4, 8 for UDP, so take 64 */
#define PACKET_AVAILABLE_SIZE(mtu) (mtu - UDP_HEADER_SIZE - sizeof(struct nj2_packet_header))
static inline void nj2_dump_packet_header(struct nj2_packet_header *header)
{
pw_log_info("Type: %s", header->type);
pw_log_info("Data Type: %c", ntohl(header->data_type));
pw_log_info("Data Stream: %c", ntohl(header->data_stream));
pw_log_info("ID: %u", ntohl(header->id));
pw_log_info("Num Packets: %u", ntohl(header->num_packets));
pw_log_info("Packet Size: %u", ntohl(header->packet_size));
pw_log_info("Active Ports: %u", ntohl(header->active_ports));
pw_log_info("Cycle: %u", ntohl(header->cycle));
pw_log_info("Sub Cycle: %u", ntohl(header->sub_cycle));
pw_log_info("Frames %d", ntohl(header->frames));
pw_log_info("Is Last: %u", ntohl(header->is_last));
}
#define MIDI_INLINE_MAX 4
struct nj2_midi_event {
uint32_t time; /**< Sample index at which event is valid */
uint32_t size; /**< Number of bytes of data in the event */
union {
uint32_t offset; /**< offset in buffer */
uint8_t buffer[MIDI_INLINE_MAX]; /**< Raw inline data */
};
};
struct nj2_midi_buffer {
#define MIDI_BUFFER_MAGIC 0x900df00d
uint32_t magic;
uint32_t buffer_size;
uint32_t nframes;
uint32_t write_pos;
uint32_t event_count;
uint32_t lost_events;
struct nj2_midi_event event[1];
};
static inline void nj2_midi_buffer_hton(struct nj2_midi_buffer *net,
const struct nj2_midi_buffer *host)
{
net->magic = htonl(host->magic);
net->buffer_size = htonl(host->buffer_size);
net->nframes = htonl(host->nframes);
net->write_pos = htonl(host->write_pos);
net->event_count = htonl(host->event_count);
net->lost_events = htonl(host->lost_events);
}
static inline void nj2_midi_buffer_ntoh(struct nj2_midi_buffer *host,
const struct nj2_midi_buffer *net)
{
host->magic = ntohl(net->magic);
host->buffer_size = ntohl(net->buffer_size);
host->nframes = ntohl(net->nframes);
host->write_pos = ntohl(net->write_pos);
host->event_count = ntohl(net->event_count);
host->lost_events = ntohl(net->lost_events);
}
#ifdef __cplusplus
}
#endif
#endif /* PIPEWIRE_NETJACK2_H */