Instrument Neutral Distributed Interface INDI 2.2.5
indicontroller.cpp
Go to the documentation of this file.
1/*******************************************************************************
2 Copyright (C) 2013 Jasem Mutlaq <[email protected]>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17*******************************************************************************/
18
19#include "indicontroller.h"
20
21#include <cstring>
22
23namespace INDI
24{
26{
27 device = cdevice;
28
29 JoystickSettingT = nullptr;
30 JoystickSettingTP.ntp = 0;
31
35}
36
38{
39 for (int i = 0; i < JoystickSettingTP.ntp; i++)
40 free(JoystickSettingT[i].aux0);
41
42 free(JoystickSettingT);
43}
44
45void Controller::mapController(const char *propertyName, const char *propertyLabel, ControllerType type,
46 const char *initialValue)
47{
48 if (JoystickSettingT == nullptr)
49 JoystickSettingT = static_cast<IText *>(malloc(sizeof(IText)));
50
51 // Ignore duplicates
52 for (int i = 0; i < JoystickSettingTP.ntp; i++)
53 {
54 if (!strcmp(propertyName, JoystickSettingT[i].name))
55 return;
56 }
57
58 IText *buf = static_cast<IText *>(realloc(JoystickSettingT, (JoystickSettingTP.ntp + 1) * sizeof(IText)));
59 if (buf == nullptr)
60 {
61 free (JoystickSettingT);
62 perror("Failed to allocate memory for joystick controls.");
63 return;
64 }
65 else
66 JoystickSettingT = buf;
67
68 ControllerType *ctype = static_cast<ControllerType *>(malloc(sizeof(ControllerType)));
69 *ctype = type;
70
71 memset(JoystickSettingT + JoystickSettingTP.ntp, 0, sizeof(IText));
72 IUFillText(&JoystickSettingT[JoystickSettingTP.ntp], propertyName, propertyLabel, initialValue);
73
74 JoystickSettingT[JoystickSettingTP.ntp++].aux0 = ctype;
75
76 IUFillTextVector(&JoystickSettingTP, JoystickSettingT, JoystickSettingTP.ntp, device->getDeviceName(),
77 "JOYSTICKSETTINGS", "Settings", "Joystick", IP_RW, 0, IPS_IDLE);
78}
79
81{
82 for (int i = 0; i < JoystickSettingTP.ntp; i++)
83 {
84 free(JoystickSettingT[i].aux0);
85 free(JoystickSettingT[i].text);
86 }
87
88 JoystickSettingTP.ntp = 0;
89 free(JoystickSettingT);
90 JoystickSettingT = nullptr;
91}
92
94{
95 IUFillSwitch(&UseJoystickS[0], "ENABLE", "Enable", ISS_OFF);
96 IUFillSwitch(&UseJoystickS[1], "DISABLE", "Disable", ISS_ON);
97 IUFillSwitchVector(&UseJoystickSP, UseJoystickS, 2, device->getDeviceName(), "USEJOYSTICK", "Joystick", OPTIONS_TAB,
99
100 IUFillText(&JoystickDeviceT[0], "SNOOP_JOYSTICK_DEVICE", "Device", "Joystick");
101 IUFillTextVector(&JoystickDeviceTP, JoystickDeviceT, 1, device->getDeviceName(), "SNOOP_JOYSTICK", "Snoop Joystick",
103
104 return true;
105}
106
107void Controller::ISGetProperties(const char *dev)
108{
109 if (dev != nullptr && strcmp(dev, device->getDeviceName()))
110 return;
111
112 if (device->isConnected())
113 {
114 device->defineProperty(&UseJoystickSP);
115 device->defineProperty(&JoystickDeviceTP);
116
117 if (JoystickSettingT && UseJoystickS[0].s == ISS_ON)
118 device->defineProperty(&JoystickSettingTP);
119 }
120}
121
123{
124 if (device->isConnected())
125 {
126 device->defineProperty(&UseJoystickSP);
127 device->defineProperty(&JoystickDeviceTP);
128
129 if (JoystickSettingT && UseJoystickS[0].s == ISS_ON)
130 device->defineProperty(&JoystickSettingTP);
131 }
132 else
133 {
134 device->deleteProperty(UseJoystickSP.name);
135 device->deleteProperty(JoystickDeviceTP.name);
136 device->deleteProperty(JoystickSettingTP.name);
137 }
138
139 return true;
140}
141
142bool Controller::ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
143{
144 if (strcmp(dev, device->getDeviceName()) == 0)
145 {
146 // Enable joystick support
147 if (!strcmp(name, UseJoystickSP.name))
148 {
149 IUUpdateSwitch(&UseJoystickSP, states, names, n);
150
151 UseJoystickSP.s = IPS_OK;
152
153 if (UseJoystickSP.sp[0].s == ISS_ON)
155 else
157
158 IDSetSwitch(&UseJoystickSP, nullptr);
159
160 return true;
161 }
162 }
163
164 return false;
165}
166
167bool Controller::ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
168{
169 if (strcmp(dev, device->getDeviceName()) == 0)
170 {
171 if (!strcmp(name, "SNOOP_JOYSTICK"))
172 {
173 IUUpdateText(&JoystickDeviceTP, texts, names, n);
174 JoystickDeviceTP.s = IPS_IDLE;
175
176 IDSetText(&JoystickDeviceTP, nullptr);
177
178 if (UseJoystickSP.sp[0].s == ISS_ON)
179 {
180 // Let's switch over to the new joystick.
182 }
183
184 return true;
185 }
186
187 if (!strcmp(name, "JOYSTICKSETTINGS") && n <= JoystickSettingTP.ntp)
188 {
189 for (int i = 0; i < JoystickSettingTP.ntp; i++)
190 {
191 IText *tp = IUFindText(&JoystickSettingTP, names[i]);
192 if (tp)
193 {
194 ControllerType cType = getControllerType(texts[i]);
195 ControllerType myType = *(static_cast<ControllerType *>(JoystickSettingT[i].aux0));
196 if (cType != myType)
197 {
198 JoystickSettingTP.s = IPS_ALERT;
199 IDSetText(&JoystickSettingTP, nullptr);
200 DEBUGFDEVICE(dev, INDI::Logger::DBG_ERROR, "Cannot change controller type to %s.", texts[i]);
201 return false;
202 }
203 }
204 }
205
206 IUUpdateText(&JoystickSettingTP, texts, names, n);
207
208 for (int i = 0; i < n; i++)
209 {
210 if (strstr(JoystickSettingT[i].text, "JOYSTICK_"))
211 IDSnoopDevice(JoystickDeviceT[0].text, JoystickSettingT[i].text);
212 }
213
214 JoystickSettingTP.s = IPS_OK;
215 IDSetText(&JoystickSettingTP, nullptr);
216 return true;
217 }
218 }
219
220 return false;
221}
222
224{
225 XMLEle *ep = nullptr;
226 double mag = 0, angle = 0;
227
228 // If joystick is disabled, do not process anything.
229 if (UseJoystickSP.sp[0].s == ISS_OFF)
230 return false;
231
232 const char *propName = findXMLAttValu(root, "name");
233
234 // Check axis
235 if (!strcmp("JOYSTICK_AXES", propName))
236 {
237 for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
238 {
239 const char *elemName = findXMLAttValu(ep, "name");
240 const char *setting = getControllerSetting(elemName);
241 if (setting == nullptr)
242 continue;
243
244 mag = atof(pcdataXMLEle(ep));
245
246 axisCallbackFunc(setting, mag, device);
247 }
248 }
249 // Check buttons
250 else if (!strcmp("JOYSTICK_BUTTONS", propName))
251 {
252 for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
253 {
254 const char *elemName = findXMLAttValu(ep, "name");
255 const char *setting = getControllerSetting(elemName);
256
257 if (setting == nullptr)
258 continue;
259
260 buttonCallbackFunc(setting, strcmp(pcdataXMLEle(ep), "Off") ? ISS_ON : ISS_OFF, device);
261 }
262 }
263 // Check joysticks
264 else if (strstr(propName, "JOYSTICK_"))
265 {
266 const char *setting = getControllerSetting(propName);
267
268 // We don't have this here, so let's not process it
269 if (setting == nullptr)
270 return false;
271
272 for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
273 {
274 if (!strcmp("JOYSTICK_MAGNITUDE", findXMLAttValu(ep, "name")))
275 mag = atof(pcdataXMLEle(ep));
276 else if (!strcmp("JOYSTICK_ANGLE", findXMLAttValu(ep, "name")))
277 angle = atof(pcdataXMLEle(ep));
278 }
279
280 joystickCallbackFunc(setting, mag, angle, device);
281 }
282
283 return false;
284}
285
287{
288 IUSaveConfigSwitch(fp, &UseJoystickSP);
289 IUSaveConfigText(fp, &JoystickSettingTP);
290 IUSaveConfigText(fp, &JoystickDeviceTP);
291
292 return true;
293}
294
296{
297 device->defineProperty(&JoystickSettingTP);
298
299 for (int i = 0; i < JoystickSettingTP.ntp; i++)
300 {
301 if (strstr(JoystickSettingTP.tp[i].text, "JOYSTICK_"))
302 IDSnoopDevice(JoystickDeviceT[0].text, JoystickSettingTP.tp[i].text);
303 }
304
305 IDSnoopDevice(JoystickDeviceT[0].text, "JOYSTICK_AXES");
306 IDSnoopDevice(JoystickDeviceT[0].text, "JOYSTICK_BUTTONS");
307}
308
310{
311 device->deleteProperty(JoystickSettingTP.name);
312}
313
315{
316 joystickCallbackFunc = JoystickCallback;
317}
318
320{
321 axisCallbackFunc = AxisCallback;
322}
323
325{
326 buttonCallbackFunc = buttonCallback;
327}
328
329void Controller::joystickEvent(const char *joystick_n, double mag, double angle, void *context)
330{
331 INDI_UNUSED(joystick_n);
332 INDI_UNUSED(mag);
333 INDI_UNUSED(angle);
334 INDI_UNUSED(context);
335}
336
337void Controller::axisEvent(const char *axis_n, int value, void *context)
338{
339 INDI_UNUSED(axis_n);
340 INDI_UNUSED(value);
341 INDI_UNUSED(context);
342}
343
344void Controller::buttonEvent(const char *button_n, int button_value, void *context)
345{
346 INDI_UNUSED(button_n);
347 INDI_UNUSED(button_value);
348 INDI_UNUSED(context);
349}
350
352{
354
355 if (strstr(name, "JOYSTICK_"))
356 targetType = CONTROLLER_JOYSTICK;
357 else if (strstr(name, "AXIS_"))
358 targetType = CONTROLLER_AXIS;
359 else if (strstr(name, "BUTTON_"))
360 targetType = CONTROLLER_BUTTON;
361
362 return targetType;
363}
364
365const char *Controller::getControllerSetting(const char *name)
366{
367 for (int i = 0; i < JoystickSettingTP.ntp; i++)
368 if (!strcmp(JoystickSettingT[i].text, name))
369 return JoystickSettingT[i].name;
370
371 return nullptr;
372}
373}
bool isConnected() const
const char * getDeviceName() const
void setButtonCallback(buttonFunc buttonCallback)
setButtonCallback Sets the callback function when a new button input is detected.
static void joystickEvent(const char *joystick_n, double mag, double angle, void *context)
virtual bool ISSnoopDevice(XMLEle *root)
const char * getControllerSetting(const char *name)
virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n)
void clearMap()
clearMap clears all properties added previously by mapController()
void mapController(const char *propertyName, const char *propertyLabel, ControllerType type, const char *initialValue)
mapController adds a new property to the joystick's settings.
virtual bool initProperties()
void setAxisCallback(axisFunc axisCallback)
setAxisCallback Sets the callback function when a new axis input is detected.
INDI::DefaultDevice * device
virtual bool saveConfigItems(FILE *fp)
virtual void ISGetProperties(const char *dev)
std::function< void(const char *button_n, ISState state, void *context)> buttonFunc
buttonFunc Button callback function signature.
axisFunc axisCallbackFunc
virtual bool updateProperties()
void setJoystickCallback(joystickFunc joystickCallback)
setJoystickCallback Sets the callback function when a new joystick input is detected.
joystickFunc joystickCallbackFunc
virtual bool ISNewText(const char *dev, const char *name, char *texts[], char *names[], int n)
static void buttonEvent(const char *button_n, int value, void *context)
std::function< void(const char *axis_n, double value, void *context)> axisFunc
axisFunc Axis callback function signature.
Controller(INDI::DefaultDevice *cdevice)
Controller Default ctor.
ControllerType getControllerType(const char *name)
std::function< void(const char *joystick_n, double mag, double angle, void *context)> joystickFunc
joystickFunc Joystick callback function signature.
buttonFunc buttonCallbackFunc
static void axisEvent(const char *axis_n, int value, void *context)
Class to provide extended functionality for devices in addition to the functionality provided by INDI...
virtual bool deleteProperty(const char *propertyName)
Delete a property and unregister it. It will also be deleted from all clients.
void defineProperty(INumberVectorProperty *property)
const char * OPTIONS_TAB
OPTIONS_TAB Where all the driver's options are located. Those may include auxiliary controls,...
ISState
Switch state.
Definition indiapi.h:148
@ ISS_OFF
Definition indiapi.h:149
@ ISS_ON
Definition indiapi.h:150
@ IP_RW
Definition indiapi.h:184
@ IPS_ALERT
Definition indiapi.h:162
@ IPS_IDLE
Definition indiapi.h:159
@ IPS_OK
Definition indiapi.h:160
@ ISR_1OFMANY
Definition indiapi.h:171
void IUSaveConfigSwitch(FILE *fp, const ISwitchVectorProperty *svp)
Add a switch vector property value to the configuration file.
Definition indidevapi.c:33
IText * IUFindText(const ITextVectorProperty *tvp, const char *name)
Find an IText member in a vector text property.
Definition indidevapi.c:265
void IUFillTextVector(ITextVectorProperty *tvp, IText *tp, int ntp, const char *dev, const char *name, const char *label, const char *group, IPerm p, double timeout, IPState s)
Assign attributes for a text vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:509
void IUFillSwitch(ISwitch *sp, const char *name, const char *label, ISState s)
Assign attributes for a switch property. The switch's auxiliary elements will be set to NULL.
Definition indidevapi.c:376
void IUFillText(IText *tp, const char *name, const char *label, const char *initialText)
Assign attributes for a text property. The text's auxiliary elements will be set to NULL.
Definition indidevapi.c:416
void IUSaveConfigText(FILE *fp, const ITextVectorProperty *tvp)
Add a text vector property value to the configuration file.
Definition indidevapi.c:28
void IUFillSwitchVector(ISwitchVectorProperty *svp, ISwitch *sp, int nsp, const char *dev, const char *name, const char *label, const char *group, IPerm p, ISRule r, double timeout, IPState s)
Assign attributes for a switch vector property. The vector's auxiliary elements will be set to NULL.
Definition indidevapi.c:453
#define INDI_UNUSED(x)
Definition indidevapi.h:132
int IUUpdateSwitch(ISwitchVectorProperty *svp, ISState *states, char *names[], int n)
Update all switches in a switch vector property.
void IDSetSwitch(const ISwitchVectorProperty *svp, const char *fmt,...)
int IUUpdateText(ITextVectorProperty *tvp, char *texts[], char *names[], int n)
Update all text members in a text vector property.
void IDSnoopDevice(const char *snooped_device, const char *snooped_property)
Function a Driver calls to snoop on another Device. Snooped messages will then arrive via ISSnoopDevi...
Definition indidriver.c:143
void IDSetText(const ITextVectorProperty *tvp, const char *fmt,...)
#define DEBUGFDEVICE(device, priority, msg,...)
Definition indilogger.h:61
const char * findXMLAttValu(XMLEle *ep, const char *name)
Find an XML element's attribute value.
Definition lilxml.cpp:644
XMLEle * nextXMLEle(XMLEle *ep, int init)
Iterate an XML element for a list of nesetd XML elements.
Definition lilxml.cpp:555
char * pcdataXMLEle(XMLEle *ep)
Return the pcdata of an XML element.
Definition lilxml.cpp:606
Namespace to encapsulate INDI client, drivers, and mediator classes.
uint16_t type
Definition pwc-ioctl.h:0
One text descriptor.
char name[MAXINDINAME]
Definition indiapi.h:369
ISState s
Definition indiapi.h:353
char name[MAXINDINAME]
Definition indiapi.h:248
char * text
Definition indiapi.h:230