aboutsummaryrefslogtreecommitdiffhomepage
path: root/backends/artnet.h
blob: 8bf83f52bc51d652edd4db6d9ea5faac4111028c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#ifndef _WIN32
#include <sys/socket.h>
#endif
#include "midimonster.h"

MM_PLUGIN_API int init();
static uint32_t artnet_interval();
static int artnet_configure(char* option, char* value);
static int artnet_configure_instance(instance* instance, char* option, char* value);
static int artnet_instance(instance* inst);
static channel* artnet_channel(instance* instance, char* spec, uint8_t flags);
static int artnet_set(instance* inst, size_t num, channel** c, channel_value* v);
static int artnet_handle(size_t num, managed_fd* fds);
static int artnet_start(size_t n, instance** inst);
static int artnet_shutdown(size_t n, instance** inst);

#define ARTNET_PORT "6454"
#define ARTNET_VERSION 14
#define ARTNET_ESTA_MANUFACTURER 0x4653 //"FS" as registered with ESTA
#define ARTNET_OEM 0x2B93 //as registered with artistic license
#define ARTNET_RECV_BUF 4096

#define ARTNET_KEEPALIVE_INTERVAL 1000
//limit transmit rate to at most 44 packets per second (1000/44 ~= 22)
#define ARTNET_FRAME_TIMEOUT 20
#define ARTNET_SYNTHESIZE_MARGIN 10

#define MAP_COARSE 0x0200
#define MAP_FINE 0x0400
#define MAP_SINGLE 0x0800
#define MAP_MARK 0x1000
#define MAPPED_CHANNEL(a) ((a) & 0x01FF)
#define IS_ACTIVE(a) ((a) & 0xFE00)
#define IS_WIDE(a) ((a) & (MAP_FINE | MAP_COARSE))
#define IS_SINGLE(a) ((a) & MAP_SINGLE)

typedef struct /*_artnet_universe_model*/ {
	uint8_t seq;
	uint8_t in[512];
	uint8_t out[512];
	uint16_t map[512];
	channel channel[512];
} artnet_universe;

typedef struct /*_artnet_instance_model*/ {
	uint8_t net;
	uint8_t uni;
	struct sockaddr_storage dest_addr;
	socklen_t dest_len;
	artnet_universe data;
	size_t fd_index;
	uint64_t last_input;
	uint8_t realtime;
} artnet_instance_data;

typedef union /*_artnet_instance_id*/ {
	struct {
		uint8_t fd_index;
		uint8_t net;
		uint8_t uni;
	} fields;
	uint64_t label;
} artnet_instance_id;

typedef struct /*_artnet_fd_universe*/ {
	uint64_t label;
	uint64_t last_frame;
	uint8_t mark;
} artnet_output_universe;

typedef struct /*_artnet_fd*/ {
	int fd;
	size_t output_instances;
	artnet_output_universe* output_instance;
	struct sockaddr_storage announce_addr; //used for pollreplies if ss_family == AF_INET, port is always valid
} artnet_descriptor;

#pragma pack(push, 1)
typedef struct /*_artnet_hdr*/ {
	uint8_t magic[8];
	uint16_t opcode;
	uint16_t version;
} artnet_hdr;

typedef struct /*_artnet_dmx*/ {
	uint8_t magic[8];
	uint16_t opcode;
	uint16_t version;
	uint8_t sequence;
	uint8_t port;
	uint8_t universe;
	uint8_t net;
	uint16_t length;
	uint8_t data[512];
} artnet_dmx;

typedef struct /*_artnet_poll*/ {
	uint8_t magic[8];
	uint16_t opcode;
	uint16_t version;
	uint8_t flags;
	uint8_t priority;
} artnet_poll;

typedef struct /*_artnet_poll_reply*/ {
	uint8_t magic[8];
	uint16_t opcode; //little-endian
	uint8_t ip4[4]; //stop including l2/3 addresses in the payload, just use the sender address ffs
	uint16_t port; //little-endian, who does that?
	uint16_t firmware; //big-endian
	uint16_t port_address; //big-endian
	uint16_t oem; //big-endian
	uint8_t bios_version;
	uint8_t status;
	uint16_t manufacturer; //little-endian
	uint8_t shortname[18];
	uint8_t longname[64];
	uint8_t report[64];
	uint16_t ports; //big-endian
	uint8_t port_types[4]; //only use the first member, we report every universe in it's own reply
	uint8_t port_in[4];
	uint8_t port_out[4];
	uint8_t subaddr_in[4];
	uint8_t subaddr_out[4];
	uint8_t video; //deprecated
	uint8_t macro; //deprecatd
	uint8_t remote; //deprecated
	uint8_t spare[3];
	uint8_t style;
	uint8_t mac[6]; //come on
	uint8_t parent_ip[4]; //COME ON
	uint8_t parent_index; //i don't even know
	uint8_t status2;
	uint8_t port_out_b[4];
	uint8_t status3;
	uint8_t spare2[21];
} artnet_poll_reply;
#pragma pack(pop)

enum artnet_pkt_opcode {
	OpPoll = 0x0020,
	OpPollReply = 0x0021,
	OpDmx = 0x0050
};