API
 
Loading...
Searching...
No Matches
indiMacros.hpp
Go to the documentation of this file.
1/** \file indiMacros.hpp
2 * \brief Macros for INDI
3 * \author Jared R. Males (jaredmales@gmail.com)
4 *
5 * History:
6 * - 2018-05-27 created by JRM
7 *
8 * \ingroup app_files
9 */
10
11#ifndef app_indiMacros_hpp
12#define app_indiMacros_hpp
13
14/// Declare and define the static callback for a new property request.
15/** You should not normally use this macro, it is called by INDI_NEWCALLBACK_DECL.
16 *
17 * \param class the class name (with no \")
18 * \param prop the property member name (with no \")
19 *
20 * \ingroup indi
21 */
22#define SET_INDI_NEWCALLBACK(class, prop) static int st_ ## newCallBack ## _ ## prop( void * app, const pcf::IndiProperty &ipRecv)\
23 {\
24 return static_cast<class *>(app)->newCallBack ## _ ## prop(ipRecv);\
25 }
26
27/// Declare and define the static callback for a set property request.
28/** You should not normally use this macro, it is called by INDI_SETCALLBACK_DECL.
29 *
30 * \param class the class name (with no \")
31 * \param prop the property member name (with no \")
32 *
33 * \ingroup indi
34 */
35#define SET_INDI_SETCALLBACK(class, prop) static int st_ ## setCallBack ## _ ## prop( void * app, const pcf::IndiProperty &ipRecv)\
36 {\
37 return static_cast<class *>(app)->setCallBack ## _ ## prop(ipRecv);\
38 }
39
40/// Declare the callback for a new property request, and declare and define the static wrapper.
41/** After including this, you still need to actually define the callback.
42 *
43 * \param class the class name (with no \")
44 * \param prop the property member name (with no \")
45 *
46 * \ingroup indi
47 */
48#define INDI_NEWCALLBACK_DECL(class, prop) int newCallBack_ ## prop(const pcf::IndiProperty &ipRecv); \
49 SET_INDI_NEWCALLBACK(class, prop)
50
51/// Declare the callback for a set property request, and declare and define the static wrapper.
52/** After including this, you still need to actually define the callback.
53 *
54 * \param class the class name (with no \")
55 * \param prop the property member name (with no \")
56 *
57 * \ingroup indi
58 */
59#define INDI_SETCALLBACK_DECL(class, prop) int setCallBack_ ## prop(const pcf::IndiProperty &ipRecv); \
60 SET_INDI_SETCALLBACK(class, prop)
61
62/// Define the callback for a new property request.
63/** Creates a class::method definition, which must be appended with a const reference of type pcf::IndiProperty.
64 * Example usage for a class named xapp and an INDI property x:
65 * \code
66 INDI_NEWCALLBACK_DEFN(xapp, x)(const pcf::IndiProperty &ipRecv)
67 {
68 //do stuff with ipRecv
69
70 return 0; //Must return int.
71 }
72 \endcode
73 * After pre-processing the above code becomes
74 * \code
75 int xapp::newCallback_x(const pcf::IndiProperty &ipRecv)
76 {
77 //do stuff with ipRecv
78
79 return 0; //Must return int.
80 }
81 \endcode
82 *
83 *
84 * \param class the class name (with no \")
85 * \param prop the property member name (with no \")
86 *
87 * \ingroup indi
88 */
89#define INDI_NEWCALLBACK_DEFN(class, prop) int class::newCallBack_ ## prop
90
91/// Define the callback for a set property request.
92/** Creates a class::method definition, which must be appended with a const reference of type pcf::IndiProperty.
93 * Example usage for a class named xapp and an INDI property x:
94 * \code
95 INDI_SETCALLBACK_DEFN(xapp, x)(const pcf::IndiProperty &ipRecv)
96 {
97 //do stuff with ipRecv
98
99 return 0; //Must return int.
100 }
101 \endcode
102 * After pre-processing the above code becomes
103 * \code
104 int xapp::setCallback_x(const pcf::IndiProperty &ipRecv)
105 {
106 //do stuff with ipRecv
107
108 return 0; //Must return int.
109 }
110 \endcode
111 *
112 *
113 * \param class the class name (with no \")
114 * \param prop the property member name (with no \")
115 *
116 * \ingroup indi
117 */
118#define INDI_SETCALLBACK_DEFN(class, prop) int class::setCallBack_ ## prop
119
120#ifndef XWCTEST_INDI_CALLBACK_VALIDATION
121#define INDI_VALIDATE_LOG_ERROR(prop1, prop2) log<software_error>({__FILE__,__LINE__, "INDI properties do not match in callback: " \
122 + prop1.createUniqueKey() + " != " + prop2.createUniqueKey()});
123
124#define INDI_VALIDATE_LOG_ERROR_DERIVED(prop1, prop2) derivedT::template log<software_error>({__FILE__,__LINE__, "INDI properties do not match in callback: " \
125 + prop1.createUniqueKey() + " != " + prop2.createUniqueKey()});
126#else
127#define INDI_VALIDATE_LOG_ERROR(prop1, prop2)
128#define INDI_VALIDATE_LOG_ERROR_DERIVED(prop1,prop2)
129#endif
130
131/// Implementation of new callback INDI property validator for main class
132/** \param prop1 [in] the first property to compare
133 * \param prop2 [in] the second property to compare
134 */
135#define INDI_VALIDATE_CALLBACK_PROPS_IMPL(prop1, prop2) \
136 if(prop1.createUniqueKey() != prop2.createUniqueKey()) \
137 { \
138 INDI_VALIDATE_LOG_ERROR(prop1, prop2) \
139 return -1; \
140 }
141
142#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
143
144// When testing validation of callback checks, we add a return 0 to avoid executing the rest of the callback.
145#define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2) INDI_VALIDATE_CALLBACK_PROPS_IMPL(prop1, prop2) \
146 else {return 0;}
147
148#else
149
150/// Standard check for matching INDI properties in a callback
151/** Uses makeUniqueKey() to check.
152 *
153 * Causes a return -1 on a mismatch.
154 *
155 * Does nothing on a match.
156 *
157 * If the test macro XWCTEST_INDI_CALLBACK_VALIDATION is defined this will cause return 0 on a match.
158 *
159 * \param prop1 [in] the first property to compare
160 * \param prop2 [in] the second property to compare
161 */
162#define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2) INDI_VALIDATE_CALLBACK_PROPS_IMPL( prop1, prop2 )
163
164#endif
165
166
167/// Implementation of new callback INDI property validator for derived class
168/** \param prop1 [in] the first property to compare
169 * \param prop2 [in] the second property to compare
170 */
171#define INDI_VALIDATE_CALLBACK_PROPS_DERIVED_IMPL(prop1, prop2) \
172 if(prop1.createUniqueKey() != prop2.createUniqueKey()) \
173 { \
174 INDI_VALIDATE_LOG_ERROR_DERIVED(prop1, prop2) \
175 return -1; \
176 } \
177
178#ifdef XWCTEST_INDI_CALLBACK_VALIDATION
179
180// When testing validation of callback checks, we add a return 0 to avoid executing the rest of the callback.
181#define INDI_VALIDATE_CALLBACK_PROPS_DERIVED(prop1, prop2) INDI_VALIDATE_CALLBACK_PROPS_DERIVED_IMPL(prop1, prop2) else {return 0;}
182
183#else
184
185/// Standard check for matching INDI properties in a callback in a CRTP base class
186/** Uses makeUniqueKey() to check.
187 *
188 * Causes a return -1 on a mismatch.
189 *
190 * Does nothing on a match.
191 *
192 * If the test macro XWCTEST_INDI_CALLBACK_VALIDATION is defined this will cause return 0 on a match.
193 *
194 * \param prop1 [in] the first property to compare
195 * \param prop2 [in] the second property to compare
196 */
197#define INDI_VALIDATE_CALLBACK_PROPS_DERIVED(prop1, prop2) INDI_VALIDATE_CALLBACK_PROPS_DERIVED_IMPL( prop1, prop2)
198
199#endif
200
201/// Get the name of the static callback wrapper for a new property.
202/** Useful for passing the pointer to the callback.
203 *
204 * \param prop the property member name (with no \")
205 *
206 * \ingroup indi
207 */
208#define INDI_NEWCALLBACK(prop) st_newCallBack_ ## prop
209
210/// Get the name of the static callback wrapper for a set property.
211/** Useful for passing the pointer to the callback.
212 *
213 * \param prop the property member name (with no \")
214 *
215 * \ingroup indi
216 */
217#define INDI_SETCALLBACK(prop) st_setCallBack_ ## prop
218
219/// Register a NEW INDI property with the class, using the standard callback name.
220/** Is a wrapper for MagAOXApp::registerIndiPropertyNew.
221 *
222 * \param prop the property member name, with no quotes
223 * \param propName the property name, in quotes
224 * \param type the property type, pcf::IndiProperty::Type
225 * \param perm the property permissions, pcf::IndiProperty::PropertyPermType
226 * \param state the property state, pcf::IndiProperty::PropertyStateType
227 *
228 * \ingroup indi
229 */
230#define REG_INDI_NEWPROP(prop, propName, type) \
231if( registerIndiPropertyNew( prop, propName, type, pcf::IndiProperty::ReadWrite, pcf::IndiProperty::Idle, INDI_NEWCALLBACK(prop)) < 0) \
232{ \
233 return log<software_error,-1>({__FILE__,__LINE__, "failed to register new property"}); \
234}
235
236
237/// Register a NEW INDI property with the class, with no callback.
238/** Is a wrapper for MagAOXApp::registerIndiPropertyNew with NULL callback.
239 *
240 * \param prop the property member name, with no quotes
241 * \param propName the property name, in quotes
242 * \param type the property type, pcf::IndiProperty::Type
243 * \param perm the property permissions, pcf::IndiProperty::PropertyPermType
244 * \param state the property state, pcf::IndiProperty::PropertyStateType
245 *
246 * \ingroup indi
247 */
248#define REG_INDI_NEWPROP_NOCB(prop, propName, type) \
249if( registerIndiPropertyNew( prop, propName, type, pcf::IndiProperty::ReadOnly, pcf::IndiProperty::Idle, 0) < 0) \
250{ \
251 return log<software_error,-1>({__FILE__,__LINE__, "failed to register read only property"}); \
252}
253
254/// Register a NEW INDI property with the class, with no callback, using the derived class
255/** Is a wrapper for MagAOXApp::registerIndiPropertyNew with NULL callback.
256 *
257 * \param prop the property member name, with no quotes
258 * \param propName the property name, in quotes
259 * \param type the property type, pcf::IndiProperty::Type
260 * \param perm the property permissions, pcf::IndiProperty::PropertyPermType
261 * \param state the property state, pcf::IndiProperty::PropertyStateType
262 *
263 * \ingroup indi
264 */
265#define REG_INDI_NEWPROP_NOCB_DERIVED(prop, propName, type) \
266if( derived().registerIndiPropertyNew( prop, propName, type, pcf::IndiProperty::ReadOnly, pcf::IndiProperty::Idle, 0) < 0) \
267{ \
268 return derivedT::template log<software_error,-1>({__FILE__,__LINE__, "failed to register read only property"}); \
269}
270
271/// Register a SET INDI property with the class, using the standard callback name.
272/** Is a wrapper for MagAOXApp::registerIndiPropertySet.
273 *
274 * \param prop the property member name, with no quotes
275 * \param propName the property name, in quotes
276 * \param type the property type, pcf::IndiProperty::Type
277 * \param perm the property permissions, pcf::IndiProperty::PropertyPermType
278 * \param state the property state, pcf::IndiProperty::PropertyStateType
279 *
280 * \ingroup indi
281 */
282#define REG_INDI_SETPROP(prop, devName, propName) \
283if( registerIndiPropertySet( prop,devName, propName, INDI_SETCALLBACK(prop)) < 0) \
284{ \
285 return log<software_error,-1>({__FILE__,__LINE__, "failed to register set property"}); \
286}
287
288#define REG_INDI_SETPROP_DERIVED(prop, devName, propName) \
289if( derived().template registerIndiPropertySet( prop,devName, propName, INDI_SETCALLBACK(prop)) < 0) \
290{ \
291 return derivedT::template log<software_error,-1>({__FILE__,__LINE__, "failed to register set property"}); \
292}
293
294/// Create and register a NEW INDI property as a standard number as float, using the standard callback name.
295/** This wraps createStandardIndiNumber and registerIndiPropertyNew, with error checking.
296 * \p prop will have elements "current" and "target".
297 *
298 * \param prop [out] the property to create and setup
299 * \param name [in] the name of the property
300 * \param min [in] the minimum value for the elements, applied to both target and current
301 * \param max [in] the minimum value for the elements, applied to both target and current
302 * \param step [in] the step size for the elements, applied to both target and current
303 * \param format [in] the _ value for the elements, applied to both target and current. Set to "" to use the MagAO-X standard for type.
304 * \param label [in] [optional] the GUI label suggestion for this property
305 * \param group [in] [optional] the group for this property
306 *
307 * \ingroup indi
308 */
309#define CREATE_REG_INDI_NEW_NUMBERF( prop, name, min, max, step, format, label, group) \
310 if( createStandardIndiNumber<float>( prop, name, min, max, step, format, label, group) < 0) \
311 { \
312 log<software_error>({__FILE__,__LINE__, "error from createStandardIndiNumber"}); \
313 return -1; \
314 } \
315 if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
316 { \
317 log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
318 return -1; \
319 }
320
321/// Create and register a NEW INDI property as a standard number as int, using the standard callback name.
322/** This wraps createStandardIndiNumber and registerIndiPropertyNew, with error checking
323 * \p prop will have elements "current" and "target".
324 *
325 * \param prop [out] the property to create and setup
326 * \param name [in] the name of the property
327 * \param min [in] the minimum value for the elements, applied to both target and current
328 * \param max [in] the minimum value for the elements, applied to both target and current
329 * \param step [in] the step size for the elements, applied to both target and current
330 * \param format [in] the _ value for the elements, applied to both target and current. Set to "" to use the MagAO-X standard for type.
331 * \param label [in] [optional] the GUI label suggestion for this property
332 * \param group [in] [optional] the group for this property
333 *
334 * \ingroup indi
335 */
336#define CREATE_REG_INDI_NEW_NUMBERI( prop, name, min, max, step, format, label, group) \
337 if( createStandardIndiNumber<int>( prop, name, min, max, step, format, label, group) < 0) \
338 { \
339 log<software_error>({__FILE__,__LINE__, "error from createStandardIndiNumber"}); \
340 return -1; \
341 } \
342 if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
343 { \
344 log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
345 return -1; \
346 }
347
348/// Create and register a NEW INDI property as a standard number as unsigned int, using the standard callback name.
349/** This wraps createStandardIndiNumber and registerIndiPropertyNew, with error checking
350 * \p prop will have elements "current" and "target".
351 *
352 * \param prop [out] the property to create and setup
353 * \param name [in] the name of the property
354 * \param min [in] the minimum value for the elements, applied to both target and current
355 * \param max [in] the minimum value for the elements, applied to both target and current
356 * \param step [in] the step size for the elements, applied to both target and current
357 * \param format [in] the _ value for the elements, applied to both target and current. Set to "" to use the MagAO-X standard for type.
358 * \param label [in] [optional] the GUI label suggestion for this property
359 * \param group [in] [optional] the group for this property
360 *
361 * \ingroup indi
362 */
363#define CREATE_REG_INDI_NEW_NUMBERU( prop, name, min, max, step, format, label, group) \
364 if( createStandardIndiNumber<unsigned>( prop, name, min, max, step, format, label, group) < 0) \
365 { \
366 log<software_error>({__FILE__,__LINE__, "error from createStandardIndiNumber"}); \
367 return -1; \
368 } \
369 if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
370 { \
371 log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
372 return -1; \
373 }
374
375/// Create and register a RO INDI property as a number, using the standard callback name.
376/** This wraps createROIndiNumber and registerIndiPropertyReadOnly, with error checking.
377 *
378 * \param prop [out] the property to create and setup
379 * \param name [in] the name of the property
380 * \param label [in] [optional] the GUI label suggestion for this property
381 * \param group [in] [optional] the group for this property
382 *
383 * \ingroup indi
384 */
385#define CREATE_REG_INDI_RO_NUMBER( prop, name, label, group ) \
386 if( createROIndiNumber( prop, name, label, group ) < 0) \
387 { \
388 log<software_error>({__FILE__,__LINE__, "error from createROIndiNumber"}); \
389 return -1; \
390 } \
391 if( registerIndiPropertyReadOnly( prop ) < 0) \
392 { \
393 log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyReadOnly"}); \
394 return -1; \
395 }
396
397/// Create and register a NEW INDI property as a standard toggle switch, using the standard callback name.
398/** This wraps createStandardIndiToggleSw and registerIndiPropertyNew, with error checking
399 *
400 * \param prop the property member name, with no quotes
401 * \param name he property name, in quotes
402 *
403 * \ingroup indi
404 */
405#define CREATE_REG_INDI_NEW_TOGGLESWITCH( prop, name) \
406 if( createStandardIndiToggleSw( prop, name) < 0) \
407 { \
408 log<software_error>({__FILE__,__LINE__, "error from createStandardIndiToggleSw"}); \
409 return -1; \
410 } \
411 if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
412 { \
413 log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
414 return -1; \
415 }
416
417/// Create and register a read-only INDI property as a standard toggle switch, with no callback.
418/** This wraps createStandardIndiToggleSw and registerIndiPropertyNew with null callback, with error checking
419 *
420 * \param prop the property member name, with no quotes
421 * \param name he property name, in quotes
422 *
423 * \ingroup indi
424 */
425#define CREATE_REG_INDI_NEW_TOGGLESWITCH_NOCB( prop, name) \
426 if( createStandardIndiToggleSw( prop, name) < 0) \
427 { \
428 log<software_error>({__FILE__,__LINE__, "error from createStandardIndiToggleSw"}); \
429 return -1; \
430 } \
431 if( registerIndiPropertyNew( prop, nullptr) < 0) \
432 { \
433 log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
434 return -1; \
435 }
436
437/// Create and register a NEW INDI property as a standard request switch, using the standard callback name.
438/** This wraps createStandardIndiRequestSw and registerIndiPropertyNew, with error checking
439 *
440 * \param prop the property member name, with no quotes
441 * \param name he property name, in quotes
442 *
443 * \ingroup indi
444 */
445#define CREATE_REG_INDI_NEW_REQUESTSWITCH( prop, name) \
446 if( createStandardIndiRequestSw( prop, name) < 0) \
447 { \
448 log<software_error>({__FILE__,__LINE__, "error from createStandardIndiRequestSw"}); \
449 return -1; \
450 } \
451 if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
452 { \
453 log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
454 return -1; \
455 }
456
457/// Create and register a NEW INDI property as a standard number as float, using the standard callback name, using the derived class.
458/** This wraps createStandardIndiNumber and registerIndiPropertyNew, with error checking.
459 * \p prop will have elements "current" and "target".
460 *
461 * \param prop [out] the property to create and setup
462 * \param name [in] the name of the property
463 * \param min [in] the minimum value for the elements, applied to both target and current
464 * \param max [in] the minimum value for the elements, applied to both target and current
465 * \param step [in] the step size for the elements, applied to both target and current
466 * \param format [in] the _ value for the elements, applied to both target and current. Set to "" to use the MagAO-X standard for type.
467 * \param label [in] the GUI label suggestion for this property
468 * \param group [in] the group for this property
469 *
470 * \ingroup indi
471 */
472#define CREATE_REG_INDI_NEW_NUMBERF_DERIVED( prop, name, min, max, step, format, label, group) \
473 if( derived().template createStandardIndiNumber<float>( prop, name, min, max, step, format, label, group) < 0) \
474 { \
475 derivedT::template log<software_error>({__FILE__,__LINE__, "error from createStandardIndiNumber"}); \
476 return -1; \
477 } \
478 if( derived().template registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
479 { \
480 derivedT::template log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
481 return -1; \
482 }
483
484
485/// Create and register a NEW INDI property as a standard number as int, using the standard callback name, using the derived class
486/** This wraps createStandardIndiNumber and registerIndiPropertyNew, with error checking
487 * \p prop will have elements "current" and "target".
488 *
489 * \param prop [out] the property to create and setup
490 * \param name [in] the name of the property
491 * \param min [in] the minimum value for the elements, applied to both target and current
492 * \param max [in] the minimum value for the elements, applied to both target and current
493 * \param step [in] the step size for the elements, applied to both target and current
494 * \param format [in] the _ value for the elements, applied to both target and current. Set to "" to use the MagAO-X standard for type.
495 * \param label [in] the GUI label suggestion for this property
496 * \param group [in] the group for this property
497 *
498 * \ingroup indi
499 */
500#define CREATE_REG_INDI_NEW_NUMBERI_DERIVED( prop, name, min, max, step, format, label, group) \
501 if( derived().template createStandardIndiNumber<int>( prop, name, min, max, step, format, label, group) < 0) \
502 { \
503 derivedT::template log<software_error>({__FILE__,__LINE__, "error from createStandardIndiNumber"}); \
504 return -1; \
505 } \
506 if( derived().template registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
507 { \
508 derivedT::template log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
509 return -1; \
510 }
511
512/// Create and register a NEW INDI property as a standard toggle switch, using the standard callback name, using the derived class
513/** This wraps createStandardIndiToggleSw and registerIndiPropertyNew, with error checking
514 *
515 * \param prop the property member name, with no quotes
516 * \param name he property name, in quotes
517 *
518 * \ingroup indi
519 */
520#define CREATE_REG_INDI_NEW_TOGGLESWITCH_DERIVED( prop, name ) \
521 if( derived().template createStandardIndiToggleSw( prop, name) < 0) \
522 { \
523 derivedT::template log<software_error>({__FILE__,__LINE__, "error from createStandardIndiToggleSw"}); \
524 return -1; \
525 } \
526 if( derived().template registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
527 { \
528 derivedT::template log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
529 return -1; \
530 }
531
532/// Create and register a NEW INDI property as a standard request switch, using the standard callback name, using the derived class
533/** This wraps createStandardIndiRequestSw and registerIndiPropertyNew, with error checking
534 *
535 * \param prop the property member name, with no quotes
536 * \param name he property name, in quotes
537 *
538 * \ingroup indi
539 */
540#define CREATE_REG_INDI_NEW_REQUESTSWITCH_DERIVED( prop, name) \
541 if( derived().template createStandardIndiRequestSw( prop, name) < 0) \
542 { \
543 derivedT::template log<software_error>({__FILE__,__LINE__, "error from createStandardIndiRequestSw"}); \
544 return -1; \
545 } \
546 if( derived().template registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
547 { \
548 derivedT::template log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
549 return -1; \
550 }
551#endif //app_indiMacros_hpp