API
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) else {return 0;}
146 
147 #else
148 
149 /// Standard check for matching INDI properties in a callback
150 /** Uses makeUniqueKey() to check.
151  *
152  * Causes a return -1 on a mismatch.
153  *
154  * Does nothing on a match.
155  *
156  * If the test macro XWCTEST_INDI_CALLBACK_VALIDATION is defined this will cause return 0 on a match.
157  *
158  * \param prop1 [in] the first property to compare
159  * \param prop2 [in] the second property to compare
160  */
161 #define INDI_VALIDATE_CALLBACK_PROPS(prop1, prop2) INDI_VALIDATE_CALLBACK_PROPS_IMPL( prop1, prop2 )
162 
163 #endif
164 
165 
166 /// Implementation of new callback INDI property validator for derived class
167 /** \param prop1 [in] the first property to compare
168  * \param prop2 [in] the second property to compare
169  */
170 #define INDI_VALIDATE_CALLBACK_PROPS_DERIVED_IMPL(prop1, prop2) \
171  if(prop1.createUniqueKey() != prop2.createUniqueKey()) \
172  { \
173  INDI_VALIDATE_LOG_ERROR_DERIVED(prop1, prop2) \
174  return -1; \
175  } \
176 
177 #ifdef XWCTEST_INDI_CALLBACK_VALIDATION
178 
179 // When testing validation of callback checks, we add a return 0 to avoid executing the rest of the callback.
180 #define INDI_VALIDATE_CALLBACK_PROPS_DERIVED(prop1, prop2) INDI_VALIDATE_CALLBACK_PROPS_DERIVED_IMPL(prop1, prop2) else {return 0;}
181 
182 #else
183 
184 /// Standard check for matching INDI properties in a callback in a CRTP base class
185 /** Uses makeUniqueKey() to check.
186  *
187  * Causes a return -1 on a mismatch.
188  *
189  * Does nothing on a match.
190  *
191  * If the test macro XWCTEST_INDI_CALLBACK_VALIDATION is defined this will cause return 0 on a match.
192  *
193  * \param prop1 [in] the first property to compare
194  * \param prop2 [in] the second property to compare
195  */
196 #define INDI_VALIDATE_CALLBACK_PROPS_DERIVED(prop1, prop2) INDI_VALIDATE_CALLBACK_PROPS_DERIVED_IMPL( prop1, prop2)
197 
198 #endif
199 
200 /// Get the name of the static callback wrapper for a new property.
201 /** Useful for passing the pointer to the callback.
202  *
203  * \param prop the property member name (with no \")
204  *
205  * \ingroup indi
206  */
207 #define INDI_NEWCALLBACK(prop) st_newCallBack_ ## prop
208 
209 /// Get the name of the static callback wrapper for a set property.
210 /** Useful for passing the pointer to the callback.
211  *
212  * \param prop the property member name (with no \")
213  *
214  * \ingroup indi
215  */
216 #define INDI_SETCALLBACK(prop) st_setCallBack_ ## prop
217 
218 /// Register a NEW INDI property with the class, using the standard callback name.
219 /** Is a wrapper for MagAOXApp::registerIndiPropertyNew.
220  *
221  * \param prop the property member name, with no quotes
222  * \param propName the property name, in quotes
223  * \param type the property type, pcf::IndiProperty::Type
224  * \param perm the property permissions, pcf::IndiProperty::PropertyPermType
225  * \param state the property state, pcf::IndiProperty::PropertyStateType
226  *
227  * \ingroup indi
228  */
229 #define REG_INDI_NEWPROP(prop, propName, type) \
230 if( registerIndiPropertyNew( prop, propName, type, pcf::IndiProperty::ReadWrite, pcf::IndiProperty::Idle, INDI_NEWCALLBACK(prop)) < 0) \
231 { \
232  return log<software_error,-1>({__FILE__,__LINE__, "failed to register new property"}); \
233 }
234 
235 
236 /// Register a NEW INDI property with the class, with no callback.
237 /** Is a wrapper for MagAOXApp::registerIndiPropertyNew with NULL callback.
238  *
239  * \param prop the property member name, with no quotes
240  * \param propName the property name, in quotes
241  * \param type the property type, pcf::IndiProperty::Type
242  * \param perm the property permissions, pcf::IndiProperty::PropertyPermType
243  * \param state the property state, pcf::IndiProperty::PropertyStateType
244  *
245  * \ingroup indi
246  */
247 #define REG_INDI_NEWPROP_NOCB(prop, propName, type) \
248 if( registerIndiPropertyNew( prop, propName, type, pcf::IndiProperty::ReadOnly, pcf::IndiProperty::Idle, 0) < 0) \
249 { \
250  return log<software_error,-1>({__FILE__,__LINE__, "failed to register read only property"}); \
251 }
252 
253 /// Register a SET INDI property with the class, using the standard callback name.
254 /** Is a wrapper for MagAOXApp::registerIndiPropertySet.
255  *
256  * \param prop the property member name, with no quotes
257  * \param propName the property name, in quotes
258  * \param type the property type, pcf::IndiProperty::Type
259  * \param perm the property permissions, pcf::IndiProperty::PropertyPermType
260  * \param state the property state, pcf::IndiProperty::PropertyStateType
261  *
262  * \ingroup indi
263  */
264 #define REG_INDI_SETPROP(prop, devName, propName) \
265 if( registerIndiPropertySet( prop,devName, propName, INDI_SETCALLBACK(prop)) < 0) \
266 { \
267  return log<software_error,-1>({__FILE__,__LINE__, "failed to register set property"}); \
268 }
269 
270 /// Create and register a NEW INDI property as a standard number as float, using the standard callback name.
271 /** This wraps createStandardIndiNumber and registerIndiPropertyNew, with error checking.
272  * \p prop will have elements "current" and "target".
273  *
274  * \param prop [out] the property to create and setup
275  * \param name [in] the name of the property
276  * \param min [in] the minimum value for the elements, applied to both target and current
277  * \param max [in] the minimum value for the elements, applied to both target and current
278  * \param step [in] the step size for the elements, applied to both target and current
279  * \param format [in] the _ value for the elements, applied to both target and current. Set to "" to use the MagAO-X standard for type.
280  * \param label [in] [optional] the GUI label suggestion for this property
281  * \param group [in] [optional] the group for this property
282  *
283  * \ingroup indi
284  */
285 #define CREATE_REG_INDI_NEW_NUMBERF( prop, name, min, max, step, format, label, group) \
286  if( createStandardIndiNumber<float>( prop, name, min, max, step, format, label, group) < 0) \
287  { \
288  log<software_error>({__FILE__,__LINE__, "error from createStandardIndiNumber"}); \
289  return -1; \
290  } \
291  if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
292  { \
293  log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
294  return -1; \
295  }
296 
297 /// Create and register a NEW INDI property as a standard number as int, using the standard callback name.
298 /** This wraps createStandardIndiNumber and registerIndiPropertyNew, with error checking
299  * \p prop will have elements "current" and "target".
300  *
301  * \param prop [out] the property to create and setup
302  * \param name [in] the name of the property
303  * \param min [in] the minimum value for the elements, applied to both target and current
304  * \param max [in] the minimum value for the elements, applied to both target and current
305  * \param step [in] the step size for the elements, applied to both target and current
306  * \param format [in] the _ value for the elements, applied to both target and current. Set to "" to use the MagAO-X standard for type.
307  * \param label [in] [optional] the GUI label suggestion for this property
308  * \param group [in] [optional] the group for this property
309  *
310  * \ingroup indi
311  */
312 #define CREATE_REG_INDI_NEW_NUMBERI( prop, name, min, max, step, format, label, group) \
313  if( createStandardIndiNumber<int>( prop, name, min, max, step, format, label, group) < 0) \
314  { \
315  log<software_error>({__FILE__,__LINE__, "error from createStandardIndiNumber"}); \
316  return -1; \
317  } \
318  if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
319  { \
320  log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
321  return -1; \
322  }
323 
324 /// Create and register a NEW INDI property as a standard number as unsigned int, using the standard callback name.
325 /** This wraps createStandardIndiNumber and registerIndiPropertyNew, with error checking
326  * \p prop will have elements "current" and "target".
327  *
328  * \param prop [out] the property to create and setup
329  * \param name [in] the name of the property
330  * \param min [in] the minimum value for the elements, applied to both target and current
331  * \param max [in] the minimum value for the elements, applied to both target and current
332  * \param step [in] the step size for the elements, applied to both target and current
333  * \param format [in] the _ value for the elements, applied to both target and current. Set to "" to use the MagAO-X standard for type.
334  * \param label [in] [optional] the GUI label suggestion for this property
335  * \param group [in] [optional] the group for this property
336  *
337  * \ingroup indi
338  */
339 #define CREATE_REG_INDI_NEW_NUMBERU( prop, name, min, max, step, format, label, group) \
340  if( createStandardIndiNumber<unsigned>( prop, name, min, max, step, format, label, group) < 0) \
341  { \
342  log<software_error>({__FILE__,__LINE__, "error from createStandardIndiNumber"}); \
343  return -1; \
344  } \
345  if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
346  { \
347  log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
348  return -1; \
349  }
350 
351 /// Create and register a NEW INDI property as a standard toggle switch, using the standard callback name.
352 /** This wraps createStandardIndiToggleSw and registerIndiPropertyNew, with error checking
353  *
354  * \param prop the property member name, with no quotes
355  * \param name he property name, in quotes
356  *
357  * \ingroup indi
358  */
359 #define CREATE_REG_INDI_NEW_TOGGLESWITCH( prop, name) \
360  if( createStandardIndiToggleSw( prop, name) < 0) \
361  { \
362  log<software_error>({__FILE__,__LINE__, "error from createStandardIndiToggleSw"}); \
363  return -1; \
364  } \
365  if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
366  { \
367  log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
368  return -1; \
369  }
370 
371 /// Create and register a read-only INDI property as a standard toggle switch, with no callback.
372 /** This wraps createStandardIndiToggleSw and registerIndiPropertyNew with null callback, with error checking
373  *
374  * \param prop the property member name, with no quotes
375  * \param name he property name, in quotes
376  *
377  * \ingroup indi
378  */
379 #define CREATE_REG_INDI_NEW_TOGGLESWITCH_NOCB( prop, name) \
380  if( createStandardIndiToggleSw( prop, name) < 0) \
381  { \
382  log<software_error>({__FILE__,__LINE__, "error from createStandardIndiToggleSw"}); \
383  return -1; \
384  } \
385  if( registerIndiPropertyNew( prop, nullptr) < 0) \
386  { \
387  log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
388  return -1; \
389  }
390 
391 /// Create and register a NEW INDI property as a standard request switch, using the standard callback name.
392 /** This wraps createStandardIndiRequestSw and registerIndiPropertyNew, with error checking
393  *
394  * \param prop the property member name, with no quotes
395  * \param name he property name, in quotes
396  *
397  * \ingroup indi
398  */
399 #define CREATE_REG_INDI_NEW_REQUESTSWITCH( prop, name) \
400  if( createStandardIndiRequestSw( prop, name) < 0) \
401  { \
402  log<software_error>({__FILE__,__LINE__, "error from createStandardIndiRequestSw"}); \
403  return -1; \
404  } \
405  if( registerIndiPropertyNew( prop, INDI_NEWCALLBACK(prop)) < 0) \
406  { \
407  log<software_error>({__FILE__,__LINE__, "error from registerIndiPropertyNew"}); \
408  return -1; \
409  }
410 
411 #endif //app_indiMacros_hpp