aboutsummaryrefslogtreecommitdiffhomepage
path: root/backends/rtpmidi.h
blob: a08cf0fb0c270eb234cf9e9a8d9cca18db51de82 (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
#ifndef _WIN32
#include <sys/socket.h>
#endif
#include "midimonster.h"

MM_PLUGIN_API int init();
static int rtpmidi_configure(char* option, char* value);
static int rtpmidi_configure_instance(instance* instance, char* option, char* value);
static int rtpmidi_instance(instance* inst);
static channel* rtpmidi_channel(instance* instance, char* spec, uint8_t flags);
static int rtpmidi_set(instance* inst, size_t num, channel** c, channel_value* v);
static int rtpmidi_handle(size_t num, managed_fd* fds);
static int rtpmidi_start(size_t n, instance** inst);
static int rtpmidi_shutdown(size_t n, instance** inst);

#define RTPMIDI_PACKET_BUFFER 8192
#define RTPMIDI_DEFAULT_HOST "::"
#define RTPMIDI_MDNS_PORT "5353"
#define RTPMIDI_HEADER_MAGIC 0x80
#define RTPMIDI_HEADER_TYPE 0x61
#define RTPMIDI_GET_TYPE(a) ((a) & 0x7F)
#define RTPMIDI_DEFAULT_NAME "MIDIMonster"
#define RTPMIDI_SERVICE_INTERVAL 1000

enum /*_rtpmidi_channel_type*/ {
	none = 0,
	note = 0x90,
	cc = 0xB0,
	pressure = 0xA0,
	aftertouch = 0xD0,
	pitchbend = 0xE0
};

typedef enum /*_rtpmidi_instance_mode*/ {
	unconfigured = 0,
	direct,
	apple
} rtpmidi_instance_mode;

typedef union {
	struct {
		uint8_t pad[5];
		uint8_t type;
		uint8_t channel;
		uint8_t control;
	} fields;
	uint64_t label;
} rtpmidi_channel_ident;

typedef struct /*_rtpmidi_peer*/ {
	struct sockaddr_storage dest;
	socklen_t dest_len;
	//uint32_t ssrc;
	uint8_t active; //marked for reuse
	uint8_t learned; //learned / configured peer
	uint8_t connected; //currently in active session
} rtpmidi_peer;

typedef struct /*_rtmidi_instance_data*/ {
	rtpmidi_instance_mode mode;

	int fd;
	int control_fd;

	size_t peers;
	rtpmidi_peer* peer;
	uint32_t ssrc;
	uint16_t sequence;

	//apple-midi config
	char* session_name; /* initiator only */
	char* accept; /* participant only */

	//direct mode config
	uint8_t learn_peers;
} rtpmidi_instance_data;

typedef struct /*rtpmidi_announced_instance*/ {
	instance* inst;
	size_t invites;
	char** invite;
} rtpmidi_announce;

enum applemidi_command {
	apple_invite = 0x494E, //IN
	apple_accept = 0x4F4B, //OK
	apple_reject = 0x4E4F, //NO
	apple_leave = 0x4259, //BY
	apple_sync = 0x434B, //CK
	apple_feedback = 0x5253 //RS
};

#pragma pack(push, 1)
typedef struct /*_apple_session_command*/ {
	uint16_t res1;
	uint16_t command;
	uint32_t version;
	uint32_t token;
	uint32_t ssrc;
	//char* name
} apple_command;

typedef struct /*_apple_session_sync*/ {
	uint16_t res1;
	uint16_t command;
	uint32_t ssrc;
	uint8_t count;
	uint8_t res2[3];
	uint64_t timestamp[3];
} apple_sync_frame;

typedef struct /*_apple_session_feedback*/ {
	uint16_t res1;
	uint8_t command[2];
	uint32_t ssrc;
	uint32_t sequence;
} apple_journal_feedback;

typedef struct /*_rtp_midi_header*/ {
	uint8_t vpxcc;
	uint8_t mpt;
	uint16_t sequence;
	uint32_t timestamp;
	uint32_t ssrc;
} rtpmidi_header;

typedef struct /*_rtp_midi_command*/ {
	uint8_t flags;
	uint8_t length;
} rtpmidi_command_header;
#pragma pack(pop)