Real Time Open Sound Control librtosc
Loading...
Searching...
No Matches
rtosc-0.3.1
include
rtosc
port-sugar.h
1
/*
2
* Copyright (c) 2016 Mark McCurry
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is furnished to do so, subject to the following conditions:
10
*
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
13
* Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
* DEALINGS IN THE SOFTWARE.
23
*/
24
25
#include <assert.h>
26
#include <type_traits>
27
#include <cstring>
28
29
#ifndef RTOSC_PORT_SUGAR
30
#define RTOSC_PORT_SUGAR
31
32
//Hack to workaround old incomplete decltype implementations
33
#ifdef __GNUC__
34
#ifndef __clang__
35
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ <= 7)
36
template
<
typename
T>
37
struct
rtosc_hack_decltype_t
38
{
39
typedef
T type;
40
};
41
42
#define decltype(expr) rtosc_hack_decltype_t<decltype(expr)>::type
43
#endif
44
#endif
45
#endif
46
47
//General macro utilities
48
#define STRINGIFY2(a) #a
49
#define STRINGIFY(a) STRINGIFY2(a)
50
51
//Helper for documenting varargs
52
#define IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,N, ...) N
53
#define LAST_IMP(...) IMPL(__VA_ARGS__,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
54
#define DOC_IMP24(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x) \
55
a b c d e f g h i j k l m n o p q r s t u v w rDoc(x)
56
#define DOC_IMP23(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w) \
57
a b c d e f g h i j k l m n o p q r s t u v rDoc(w)
58
#define DOC_IMP22(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v) \
59
a b c d e f g h i j k l m n o p q r s t u rDoc(v)
60
#define DOC_IMP21(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u) \
61
a b c d e f g h i j k l m n o p q r s t rDoc(u)
62
#define DOC_IMP20(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) \
63
a b c d e f g h i j k l m n o p q r s rDoc(t)
64
#define DOC_IMP19(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s) \
65
a b c d e f g h i j k l m n o p q r rDoc(s)
66
#define DOC_IMP18(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) \
67
a b c d e f g h i j k l m n o p q rDoc(r)
68
#define DOC_IMP17(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) \
69
a b c d e f g h i j k l m n o p rDoc(q)
70
#define DOC_IMP16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \
71
a b c d e f g h i j k l m n o rDoc(p)
72
#define DOC_IMP15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \
73
a b c d e f g h i j k l m n rDoc(o)
74
#define DOC_IMP14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) \
75
a b c d e f g h i j k l m rDoc(n)
76
#define DOC_IMP13(a,b,c,d,e,f,g,h,i,j,k,l,m) \
77
a b c d e f g h i j k l rDoc(m)
78
#define DOC_IMP12(a,b,c,d,e,f,g,h,i,j,k,l) a b c d e f g h i j k rDoc(l)
79
#define DOC_IMP11(a,b,c,d,e,f,g,h,i,j,k) a b c d e f g h i j rDoc(k)
80
#define DOC_IMP10(a,b,c,d,e,f,g,h,i,j) a b c d e f g h i rDoc(j)
81
#define DOC_IMP9(a,b,c,d,e,f,g,h,i) a b c d e f g h rDoc(i)
82
#define DOC_IMP8(a,b,c,d,e,f,g,h) a b c d e f g rDoc(h)
83
#define DOC_IMP7(a,b,c,d,e,f,g) a b c d e f rDoc(g)
84
#define DOC_IMP6(a,b,c,d,e,f) a b c d e rDoc(f)
85
#define DOC_IMP5(a,b,c,d,e) a b c d rDoc(e)
86
#define DOC_IMP4(a,b,c,d) a b c rDoc(d)
87
#define DOC_IMP3(a,b,c) a b rDoc(c)
88
#define DOC_IMP2(a,b) a rDoc(b)
89
#define DOC_IMP1(a) rDoc(a)
90
#define DOC_IMP0() YOU_MUST_DOCUMENT_YOUR_PORTS
91
#define DOC_IMP(count, ...) DOC_IMP ##count(__VA_ARGS__)
92
#define DOC_I(count, ...) DOC_IMP(count,__VA_ARGS__)
93
#define DOC(...) DOC_I(LAST_IMP(__VA_ARGS__), __VA_ARGS__)
94
95
96
#define rINC(x) rINC_ ## x
97
#define rINC_0 1
98
#define rINC_1 2
99
#define rINC_2 3
100
#define rINC_3 4
101
#define rINC_4 5
102
#define rINC_5 6
103
#define rINC_6 7
104
#define rINC_7 8
105
#define rINC_8 9
106
#define rINC_9 10
107
#define rINC_10 11
108
#define rINC_11 12
109
#define rINC_12 13
110
#define rINC_13 14
111
#define rINC_14 15
112
#define rINC_15 16
113
#define rINC_16 17
114
115
//Helper for applying macro on varargs
116
//arguments: counting offset, macro, macro args
117
#define MAC_EACH_0(o,m,d,x, ...) INSUFFICIENT_ARGUMENTS_PROVIDED_TO_MAC_EACH
118
#define MAC_EACH_1(o,m,d,x, ...) m(o,d,x)
119
#define MAC_EACH_2(o,m,d,x, ...) m(o,d,x) MAC_EACH_1(rINC(o),m,d, __VA_ARGS__)
120
#define MAC_EACH_3(o,m,d,x, ...) m(o,d,x) MAC_EACH_2(rINC(o),m,d, __VA_ARGS__)
121
#define MAC_EACH_4(o,m,d,x, ...) m(o,d,x) MAC_EACH_3(rINC(o),m,d, __VA_ARGS__)
122
#define MAC_EACH_5(o,m,d,x, ...) m(o,d,x) MAC_EACH_4(rINC(o),m,d, __VA_ARGS__)
123
#define MAC_EACH_6(o,m,d,x, ...) m(o,d,x) MAC_EACH_5(rINC(o),m,d, __VA_ARGS__)
124
#define MAC_EACH_7(o,m,d,x, ...) m(o,d,x) MAC_EACH_6(rINC(o),m,d, __VA_ARGS__)
125
#define MAC_EACH_8(o,m,d,x, ...) m(o,d,x) MAC_EACH_7(rINC(o),m,d, __VA_ARGS__)
126
#define MAC_EACH_9(o,m,d,x, ...) m(o,d,x) MAC_EACH_8(rINC(o),m,d, __VA_ARGS__)
127
#define MAC_EACH_10(o,m,d,x, ...) m(o,d,x) MAC_EACH_9(rINC(o),m,d, __VA_ARGS__)
128
#define MAC_EACH_11(o,m,d,x, ...) m(o,d,x) MAC_EACH_10(rINC(o),m,d, __VA_ARGS__)
129
#define MAC_EACH_12(o,m,d,x, ...) m(o,d,x) MAC_EACH_11(rINC(o),m,d, __VA_ARGS__)
130
#define MAC_EACH_13(o,m,d,x, ...) m(o,d,x) MAC_EACH_12(rINC(o),m,d, __VA_ARGS__)
131
#define MAC_EACH_14(o,m,d,x, ...) m(o,d,x) MAC_EACH_13(rINC(o),m,d, __VA_ARGS__)
132
#define MAC_EACH_15(o,m,d,x, ...) m(o,d,x) MAC_EACH_14(rINC(o),m,d, __VA_ARGS__)
133
#define MAC_EACH_16(o,m,d,x, ...) m(o,d,x) MAC_EACH_15(rINC(o),m,d, __VA_ARGS__)
134
135
#define MAC_EACH_IMP(off, mac, data, count, ...) \
136
MAC_EACH_ ##count(off, mac, data, __VA_ARGS__)
137
#define MAC_EACH_I(off, mac, data, count, ...) \
138
MAC_EACH_IMP(off, mac, data, count, __VA_ARGS__)
139
#define MAC_EACH_OFF(off, mac, data, ...) \
140
MAC_EACH_I(off, mac, data, LAST_IMP(__VA_ARGS__), __VA_ARGS__)
141
#define MAC_EACH(mac, data, ...) MAC_EACH_OFF(0, mac, data, __VA_ARGS__)
142
143
// 1 2 3 4 5 6 7 8 9101112131415161718192021222324
144
#define OPTIONS_IMP24(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x) \
145
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
146
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
147
rOpt(14,o)rOpt(15,p)rOpt(16,q)rOpt(17,r)rOpt(18,s)rOpt(19,t)rOpt(20,u)\
148
rOpt(21,v)rOpt(22,w)rOpt(23,x)
149
// 1 2 3 4 5 6 7 8 91011121314151617181920212223
150
#define OPTIONS_IMP23(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w) \
151
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
152
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
153
rOpt(14,o)rOpt(15,p)rOpt(16,q)rOpt(17,r)rOpt(18,s)rOpt(19,t)rOpt(20,u)\
154
rOpt(21,v)rOpt(22,w)
155
// 1 2 3 4 5 6 7 8 910111213141516171819202122
156
#define OPTIONS_IMP22(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v) \
157
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
158
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
159
rOpt(14,o)rOpt(15,p)rOpt(16,q)rOpt(17,r)rOpt(18,s)rOpt(19,t)rOpt(20,u)\
160
rOpt(21,v)
161
// 1 2 3 4 5 6 7 8 9101112131415161718192021
162
#define OPTIONS_IMP21(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u) \
163
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
164
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
165
rOpt(14,o)rOpt(15,p)rOpt(16,q)rOpt(17,r)rOpt(18,s)rOpt(19,t)rOpt(20,u)
166
// 1 2 3 4 5 6 7 8 91011121314151617181920
167
#define OPTIONS_IMP20(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) \
168
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
169
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
170
rOpt(14,o)rOpt(15,p)rOpt(16,q)rOpt(17,r)rOpt(18,s)rOpt(19,t)
171
// 1 2 3 4 5 6 7 8 910111213141516171819
172
#define OPTIONS_IMP19(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s) \
173
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
174
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
175
rOpt(14,o)rOpt(15,p)rOpt(16,q)rOpt(17,r)rOpt(18,s)
176
// 1 2 3 4 5 6 7 8 9101112131415161718
177
#define OPTIONS_IMP18(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) \
178
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
179
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
180
rOpt(14,o)rOpt(15,p)rOpt(16,q)rOpt(17,r)
181
#define OPTIONS_IMP17(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) \
182
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
183
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
184
rOpt(14,o)rOpt(15,p)rOpt(16,q)
185
#define OPTIONS_IMP16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \
186
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
187
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
188
rOpt(14,o)rOpt(15,p)
189
#define OPTIONS_IMP15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \
190
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
191
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)\
192
rOpt(14,o)
193
#define OPTIONS_IMP14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) \
194
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
195
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)rOpt(13,n)
196
#define OPTIONS_IMP13(a,b,c,d,e,f,g,h,i,j,k,l,m) \
197
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
198
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)rOpt(12,m)
199
#define OPTIONS_IMP12(a,b,c,d,e,f,g,h,i,j,k,l) \
200
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
201
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)rOpt(11,l)
202
#define OPTIONS_IMP11(a,b,c,d,e,f,g,h,i,j,k) \
203
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
204
rOpt(7,h) rOpt(8,i) rOpt(9,j) rOpt(10,k)
205
#define OPTIONS_IMP10(a,b,c,d,e,f,g,h,i,j) \
206
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
207
rOpt(7,h) rOpt(8,i) rOpt(9,j)
208
#define OPTIONS_IMP9(a,b,c,d,e,f,g,h,i) \
209
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
210
rOpt(7,h) rOpt(8,i)
211
#define OPTIONS_IMP8(a,b,c,d,e,f,g,h) \
212
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g) \
213
rOpt(7,h)
214
#define OPTIONS_IMP7(a,b,c,d,e,f,g) \
215
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f) rOpt(6,g)
216
#define OPTIONS_IMP6(a,b,c,d,e,f) \
217
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e) rOpt(5,f)
218
#define OPTIONS_IMP5(a,b,c,d,e) \
219
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d) rOpt(4,e)
220
#define OPTIONS_IMP4(a,b,c,d) \
221
rOpt(0,a) rOpt(1,b) rOpt(2,c) rOpt(3,d)
222
#define OPTIONS_IMP3(a,b,c) \
223
rOpt(0,a) rOpt(1,b) rOpt(2,c)
224
#define OPTIONS_IMP2(a,b) \
225
rOpt(0,a) rOpt(1,b)
226
#define OPTIONS_IMP1(a) \
227
rOpt(0,a)
228
#define OPTIONS_IMP0() YOU_MUST_PROVIDE_OPTIONS
229
#define OPTIONS_IMP(count, ...) OPTIONS_IMP ##count(__VA_ARGS__)
230
#define OPTIONS_I(count, ...) OPTIONS_IMP(count, __VA_ARGS__)
231
#define OPTIONS(...) OPTIONS_I(LAST_IMP(__VA_ARGS__), __VA_ARGS__)
232
233
//Additional Change Callback (after parameters have been changed)
234
//This can be used to queue up interpolation or parameter regen
235
#define rChangeCb
236
237
#define rCrossBroadcast(loc, cross) \
238
char part_loc[128]; \
239
strncpy(part_loc, loc, sizeof(part_loc)); \
240
part_loc[sizeof(part_loc) - 1] = '\0'; \
241
char *end = strrchr(part_loc, '/'); \
242
if(end) { \
243
strcpy(&end[1], STRINGIFY(cross)); \
244
data.broadcast(part_loc, "f", obj->cross); \
245
}
246
247
//Normal parameters
248
#define rParam(name, ...) \
249
{STRINGIFY(name) "::c", rProp(parameter) rMap(min, 0) rMap(max, 127) DOC(__VA_ARGS__), NULL, rParamCb(name)}
250
#define rParamF(name, ...) \
251
{STRINGIFY(name) "::f", rProp(parameter) DOC(__VA_ARGS__), NULL, rParamFCb(name)}
252
#define rParamI(name, ...) \
253
{STRINGIFY(name) "::i", rProp(parameter) DOC(__VA_ARGS__), NULL, rParamICb(name)}
254
#define rToggle(name, ...) \
255
{STRINGIFY(name) "::T:F",rProp(parameter) DOC(__VA_ARGS__), NULL, rToggleCb(name)}
256
#define rOption(name, ...) \
257
{STRINGIFY(name) "::i:c:S",rProp(parameter) rProp(enumerated) DOC(__VA_ARGS__), NULL, rOptionCb(name)}
258
259
//Array operators
260
#define rArrayF(name, length, ...) \
261
{STRINGIFY(name) "#" STRINGIFY(length) "::f", rProp(parameter) DOC(__VA_ARGS__), NULL, rArrayFCb(name)}
262
#define rArrayT(name, length, ...) \
263
{STRINGIFY(name) "#" STRINGIFY(length) "::T:F", rProp(parameter) DOC(__VA_ARGS__), NULL, rArrayTCb(name)}
264
#define rArrayI(name, length, ...) \
265
{STRINGIFY(name) "#" STRINGIFY(length) "::i", rProp(parameter) DOC(__VA_ARGS__), NULL, rArrayICb(name)}
266
#define rArrayOption(name, length, ...) \
267
{STRINGIFY(name) "#" STRINGIFY(length) "::i:c:S", rProp(parameter) DOC(__VA_ARGS__), NULL, rArrayOptionCb(name)}
268
#define rArray rArrayI
269
270
//Method callback Actions
271
#define rAction(name, ...) \
272
{STRINGIFY(name) ":", DOC(__VA_ARGS__), NULL, rActionCb(name)}
273
#define rActioni(name, ...) \
274
{STRINGIFY(name) ":i", DOC(__VA_ARGS__), NULL, rActioniCb(name)}
275
276
277
//Alias operators
278
#define rParams(name, length, ...) \
279
rArray(name, length, __VA_ARGS__), \
280
{STRINGIFY(name) ":", rProp(alias) rDoc("get all data from aliased array"), NULL, rParamsCb(name, length)}
281
282
283
template
<
class
T>
constexpr
T spice(T*t) {
return
*t;}
284
285
//Recursion [two ports in one for pointer manipulation]
286
#define rRecur(name, ...) \
287
{STRINGIFY(name) "/", DOC(__VA_ARGS__), &decltype(rObject::name)::ports, rRecurCb(name)}, \
288
{STRINGIFY(name) ":", rProp(internal) rDoc("get obj pointer"), NULL, rRecurPtrCb(name)}
289
290
#define rRecurp(name, ...) \
291
{STRINGIFY(name) "/", DOC(__VA_ARGS__), \
292
&decltype(spice(rObject::name))::ports, \
293
rRecurpCb(name)}
294
295
#define rRecurs(name, length, ...) \
296
{STRINGIFY(name) "#" STRINGIFY(length)"/", DOC(__VA_ARGS__), \
297
&decltype(spice(&rObject::name[0]))::ports, \
298
rRecursCb(name, length)}
299
300
//Technically this is a pointer pointer method...
301
#define rRecursp(name, length, ...) \
302
{STRINGIFY(name)"#" STRINGIFY(length) "/", DOC(__VA_ARGS__), \
303
&decltype(spice(rObject::name[0]))::ports, \
304
rRecurspCb(name)}
305
306
//{STRINGIFY(name) ":", rProp(internal), NULL, rRecurPtrCb(name)}
307
308
//let this recurring parameter depend on another port
309
//the path of the other port must be at the current level or one level above
310
#define rEnabledBy(portname) rMap(enabled by, portname)
311
#define rEnabledByCondition(cond_name) rEnabledBy(cond_name)
312
#define rEnabledCondition(cond_name, condition) \
313
{STRINGIFY(cond_name) ":", rProp(internal), NULL, rEnabledIfCb(condition)}
314
#define rEnabledIfCb(condition) rBOIL_BEGIN \
315
assert(!rtosc_narguments(msg)); \
316
data.reply(loc, (condition)?"T":"F"); \
317
rBOIL_END \
318
319
#define rSelf(type, ...) \
320
{"self:", rProp(internal) rMap(class, type) __VA_ARGS__ rDoc("port metadata"), 0, \
321
[](const char *, rtosc::RtData &d){ \
322
d.reply(d.loc, "b", sizeof(d.obj), &d.obj);}}\
323
324
//Misc
325
#define rDummy(name, ...) {STRINGIFY(name), rProp(dummy), NULL, [](msg_t, rtosc::RtData &){}}
326
#define rString(name, len, ...) \
327
{STRINGIFY(name) "::s", rMap(length, len) rProp(parameter) DOC(__VA_ARGS__), NULL, rStringCb(name,len)}
328
329
//General property operators
330
#define rMap(name, value) ":" STRINGIFY(name) "\0=" STRINGIFY(value) "\0"
331
#define rProp(name) ":" STRINGIFY(name) "\0"
332
333
//Scaling property
334
//This property describes the variable's input scale, which is in most cases
335
//(not always) equal to the perception. Thus, if 0 is in the input scale, and
336
//has no special meaning, rLinear shall be used.
337
#define rLinear(min_, max_) rMap(min, min_) rMap(max, max_) rMap(scale, linear)
338
#define rLog(min_, max_) rMap(min, min_) rMap(max, max_) rMap(scale, logarithmic)
339
340
//Special values
341
#define rSpecial(doc) ":special\0" STRINGIFY(doc) "\0"
342
#define rCentered ":centered\0"
343
344
//Default values
345
#define rDefault(default_value_) rMap(default, default_value_)
346
#define rDefaultId(default_value_) ":default\0=\"" STRINGIFY(default_value_) "\"S\0"
347
//#define rDefaultArr(default_value_, idx_) rMap(default[idx_], default_value_)
348
#define rPreset(no, default_value) \
349
":default " STRINGIFY(no) "\0=" STRINGIFY(default_value) "\0"
350
#define _rPreset(no, data, default_value) rPreset(no, default_value)
351
#define rPresetsAt(offs, ...) MAC_EACH_OFF(offs, _rPreset, offs, __VA_ARGS__)
352
#define _rPreset2(offs, data, preset_no) rPreset(preset_no, data)
353
#define rPresetAtMulti(val, ...) MAC_EACH_OFF(0, _rPreset2, val, __VA_ARGS__)
354
#define rPresets(...) rPresetsAt(0, __VA_ARGS__)
355
#define rDefaultDepends(dep_path_) rMap(default depends, dep_path_)
356
#define rDefaultMissing ""
// macro to denote yet missing default values
358
#define rNoDefaults ":no defaults\0"
359
360
//Misc properties
361
#define rDoc(doc) ":documentation\0=" doc "\0"
362
#define rOpt(numeric,symbolic) rMap(map numeric, symbolic)
363
#define rOptions(...) OPTIONS(__VA_ARGS__)
364
#define rOptionsBound(...) rOptions(__VA_ARGS__), rLinear(0,LAST_IMP(__VA_ARGS__))
365
366
//Zest Metadata
367
#define rShort(name) ":shortname\0=" name "\0"
368
369
370
//Callback Implementations
371
#define rBOIL_BEGIN [](const char *msg, rtosc::RtData &data) { \
372
(void) msg; (void) data; \
373
rObject *obj = (rObject*) data.obj;(void) obj; \
374
const char *args = rtosc_argument_string(msg); (void) args;\
375
const char *loc = data.loc; (void) loc;\
376
auto prop = data.port->meta(); (void) prop;
377
378
#define rBOIL_END }
379
380
#define rLIMIT(var, convert) \
381
if(prop["min"] && var < (decltype(var)) convert(prop["min"])) \
382
var = (decltype(var)) convert(prop["min"]);\
383
if(prop["max"] && var > (decltype(var)) convert(prop["max"])) \
384
var = (decltype(var)) convert(prop["max"]);
385
386
#define rTYPE(n) decltype(obj->n)
387
388
#define rCAPPLY(getcode, t, setcode) if((decltype(var))(getcode) != var) data.reply("/undo_change", "s" #t #t, data.loc, static_cast<int>(getcode), var); setcode;
389
#define rAPPLY(n,t) rCAPPLY(obj->n, t, obj->n = var)
390
391
#define rParamCb(name) rBOIL_BEGIN \
392
if(!strcmp("", args)) {\
393
data.reply(loc, "c", obj->name); \
394
} else { \
395
rTYPE(name) var = rtosc_argument(msg, 0).i; \
396
rLIMIT(var, atoi) \
397
rAPPLY(name, c) \
398
data.broadcast(loc, "c", obj->name);\
399
rChangeCb; \
400
} rBOIL_END
401
402
#define rParamFCb(name) rBOIL_BEGIN \
403
if(!strcmp("", args)) {\
404
data.reply(loc, "f", obj->name); \
405
} else { \
406
rTYPE(name) var = rtosc_argument(msg, 0).f; \
407
rLIMIT(var, atof) \
408
rAPPLY(name, f) \
409
data.broadcast(loc, "f", obj->name);\
410
rChangeCb; \
411
} rBOIL_END
412
413
#define rParamICb(name) rBOIL_BEGIN \
414
if(!strcmp("", args)) {\
415
data.reply(loc, "i", obj->name); \
416
} else { \
417
rTYPE(name) var = rtosc_argument(msg, 0).i; \
418
rLIMIT(var, atoi) \
419
rAPPLY(name, i) \
420
data.broadcast(loc, "i", obj->name);\
421
rChangeCb; \
422
} rBOIL_END
423
424
#define rCOptionCb_(getcode, setcode) { \
425
if(!strcmp("", args)) {\
426
data.reply(loc, "i", static_cast<int>(getcode)); \
427
} else if(!strcmp("s", args) || !strcmp("S", args)) { \
428
int var = \
429
enum_key(prop, rtosc_argument(msg, 0).s); \
430
/* make sure we have no out-of-bound options */
\
431
assert(!prop["min"] || \
432
var >= atoi(prop["min"])); \
433
assert(!prop["max"] || \
434
var <= atoi(prop["max"])); \
435
rCAPPLY(getcode, i, setcode) \
436
data.broadcast(loc, "i", getcode); \
437
rChangeCb; \
438
} else {\
439
int var = \
440
rtosc_argument(msg, 0).i; \
441
rLIMIT(var, atoi) \
442
rCAPPLY(getcode, i, setcode) \
443
data.broadcast(loc, rtosc_argument_string(msg), getcode);\
444
rChangeCb; \
445
} \
446
}
447
448
#define rOptionCb_(name) rCOptionCb_(obj->name, obj->name = static_cast<std::remove_reference<decltype(obj->name)>::type>(var))
449
450
#define rOptionCb(name) rBOIL_BEGIN \
451
rOptionCb_(name) \
452
rBOIL_END
453
454
#define rCOptionCb(getcode, setcode) rBOIL_BEGIN \
455
rCOptionCb_(getcode, setcode) \
456
rBOIL_END
457
458
459
#define rToggleCb(name) rBOIL_BEGIN \
460
if(!strcmp("", args)) {\
461
data.reply(loc, obj->name ? "T" : "F"); \
462
} else { \
463
if(obj->name != rtosc_argument(msg, 0).T) { \
464
data.broadcast(loc, args);\
465
obj->name = rtosc_argument(msg, 0).T; \
466
rChangeCb; \
467
} \
468
} rBOIL_END
469
470
#define SNIP \
471
while(*msg && *msg!='/') ++msg; \
472
msg = *msg ? msg+1 : msg;
473
474
#define rRecurCb(name) rBOIL_BEGIN \
475
data.obj = &obj->name; \
476
SNIP \
477
decltype(obj->name)::ports.dispatch(msg, data); \
478
rBOIL_END
479
480
#define rRecurPtrCb(name) rBOIL_BEGIN \
481
void *ptr = &obj->name; \
482
data.reply(loc, "b", sizeof(void*), &ptr); \
483
rBOIL_END
484
485
#define rRecurpCb(name) rBOIL_BEGIN \
486
data.obj = obj->name; \
487
if(obj->name == NULL) return; \
488
SNIP \
489
decltype(spice(rObject::name))::ports.dispatch(msg, data); \
490
rBOIL_END
491
492
#define rRecursCb(name, length) rBOILS_BEGIN \
493
data.obj = &obj->name[idx]; \
494
SNIP \
495
decltype(spice(rObject::name))::ports.dispatch(msg, data); \
496
rBOILS_END
497
498
#define rRecurspCb(name) rBOILS_BEGIN \
499
data.obj = obj->name[idx]; \
500
SNIP \
501
decltype(spice(rObject::name[0]))::ports.dispatch(msg, data); \
502
rBOILS_END
503
504
#define rActionCb(name) rBOIL_BEGIN obj->name(); rBOIL_END
505
#define rActioniCb(name) rBOIL_BEGIN \
506
obj->name(rtosc_argument(msg,0).i); rBOIL_END
507
508
//Array ops
509
510
#define rBOILS_BEGIN rBOIL_BEGIN \
511
const char *mm = msg; \
512
while(*mm && !isdigit(*mm)) ++mm; \
513
unsigned idx = atoi(mm);
514
515
#define rBOILS_END rBOIL_END
516
517
518
#define rArrayFCb(name) rBOILS_BEGIN \
519
if(!strcmp("", args)) {\
520
data.reply(loc, "f", obj->name[idx]); \
521
} else { \
522
float var = rtosc_argument(msg, 0).f; \
523
rLIMIT(var, atof) \
524
rAPPLY(name[idx], f) \
525
data.broadcast(loc, "f", obj->name[idx]);\
526
} rBOILS_END
527
528
#define rArrayTCb(name) rBOILS_BEGIN \
529
if(!strcmp("", args)) {\
530
data.reply(loc, obj->name[idx] ? "T" : "F"); \
531
} else { \
532
if(obj->name[idx] != rtosc_argument(msg, 0).T) { \
533
data.broadcast(loc, args);\
534
rChangeCb; \
535
} \
536
obj->name[idx] = rtosc_argument(msg, 0).T; \
537
} rBOILS_END
538
539
#define rArrayTCbMember(name, member) rBOILS_BEGIN \
540
if(!strcmp("", args)) {\
541
data.reply(loc, obj->name[idx].member ? "T" : "F"); \
542
} else { \
543
if(obj->name[idx].member != rtosc_argument(msg, 0).T) { \
544
data.broadcast(loc, args);\
545
rChangeCb; \
546
} \
547
obj->name[idx].member = rtosc_argument(msg, 0).T; \
548
} rBOILS_END
549
550
551
#define rArrayICb(name) rBOILS_BEGIN \
552
if(!strcmp("", args)) {\
553
data.reply(loc, "i", obj->name[idx]); \
554
} else { \
555
char var = rtosc_argument(msg, 0).i; \
556
rLIMIT(var, atoi) \
557
rAPPLY(name[idx], i) \
558
data.broadcast(loc, "i", obj->name[idx]);\
559
rChangeCb; \
560
} rBOILS_END
561
562
563
#define rArrayOptionCb(name) rBOILS_BEGIN \
564
rOptionCb_(name[idx]) \
565
rBOILS_END
566
567
#define rParamsCb(name, length) rBOIL_BEGIN \
568
data.reply(loc, "b", length, obj->name); rBOIL_END
569
570
#define rStringCb(name, length) rBOIL_BEGIN \
571
if(!strcmp("", args)) {\
572
data.reply(loc, "s", obj->name); \
573
} else { \
574
strncpy(obj->name, rtosc_argument(msg, 0).s, length-1); \
575
obj->name[length-1] = '\0'; \
576
data.broadcast(loc, "s", obj->name);\
577
rChangeCb; \
578
} rBOIL_END
579
580
581
#endif
Generated on Sat Aug 10 2024 19:15:11 for Real Time Open Sound Control librtosc by
1.11.0