1 /*
2  * InputDeviceApp.cpp
3  *
4  * Copyright (C) 2003, 2019 J. "MUFTI" Scheurich
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program (see the file "COPYING" for details); if
18  * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19  * Cambridge, MA 02139, USA.
20  */
21 
22 #include <errno.h>
23 #include "stdafx.h"
24 
25 #include "DuneApp.h"
26 #include "InputDeviceApp.h"
27 #include "InputDevice.h"
28 
29 InputDevice*
getInputDevice(int i)30 InputDeviceApp::getInputDevice(int i)
31 {
32    if ((i<((int)m_inputDevices.size())) && (i>=0))
33       return m_inputDevices[i];
34    else
35       return NULL;
36 }
37 
38 int
setInputDevice(InputDevice * inputdevice)39 InputDeviceApp::setInputDevice(InputDevice* inputdevice)
40 {
41    return replaceOrAddInputDevice(inputdevice,
42          inputdevice->getDeviceOption(),
43          inputdevice->getDeviceName());
44 }
45 
46 void
accoutMaxNumberAxesInputDevices(void)47 InputDeviceApp::accoutMaxNumberAxesInputDevices(void)
48 {
49    int max=0;
50    for (long i=0;i<m_inputDevices.size();i++)
51       if (m_inputDevices[i]->get_number_axes()>max)
52          max=m_inputDevices[i]->get_number_axes();
53    m_maxNumberAxes=max;
54 }
55 
56 bool
hasInputDevices(void)57 InputDeviceApp::hasInputDevices(void)
58 {
59    if (m_inputDevices.size()>0)
60       {
61       for (long i=0; i < m_inputDevices.size(); i++)
62          if (m_inputDevices[i]->isValid())
63             return true;
64       return false;
65       }
66    else
67       return false;
68 }
69 
70 bool
has2AxesInputDevices(void)71 InputDeviceApp::has2AxesInputDevices(void)
72 {
73    for (long i=0;i<m_inputDevices.size();i++)
74       if (m_inputDevices[i]->get_number_axes()==2)
75          return true;
76    return false;
77 }
78 
79 bool
has3AxesInputDevices(void)80 InputDeviceApp::has3AxesInputDevices(void)
81 {
82    for (long i=0;i<m_inputDevices.size();i++)
83       if (m_inputDevices[i]->get_number_axes()==3)
84          return true;
85    return false;
86 }
87 
88 int
searchInputDevice(const char * option,const char * deviceName)89 InputDeviceApp::searchInputDevice(const char *option, const char *deviceName)
90 {
91    for (long i=0;i<m_inputDevices.size();i++)
92       if ((strcmp(m_inputDevices[i]->getDeviceOption(),
93                   option) == 0) &&
94           (strcmp(m_inputDevices[i]->getDeviceName(),
95                   deviceName) == 0))
96          return i;
97    return -1;
98 }
99 
100 int
replaceOrAddInputDevice(InputDevice * newDevice,const char * option,const char * deviceName)101 InputDeviceApp::replaceOrAddInputDevice(InputDevice* newDevice,
102                                         const char *option,
103                                         const char *deviceName)
104 {
105    int device = searchInputDevice(option, deviceName);
106    if (device > -1) {
107        if (m_inputDevices[device] != newDevice) {
108            delete m_inputDevices[device];
109            m_inputDevices[device] = newDevice;
110        }
111        return device;
112    } else if (newDevice != NULL) {
113        m_inputDevices.append(newDevice);
114        return m_inputDevices.size()-1;
115    }
116    return -1;
117 }
118 
119 void
deleteInputDevice(InputDevice * device)120 InputDeviceApp::deleteInputDevice(InputDevice* device)
121 {
122    for (long i=0;i<m_inputDevices.size();i++)
123       if (m_inputDevices[i] == device)
124            m_inputDevices.remove(i);
125 }
126 
127 
128 #ifdef HAVE_AFLOCK
129 AflockDevice*
getAflockDevice(int i)130 InputDeviceApp::getAflockDevice(int i)
131 {
132    if ((i<((int)m_aflockDevices.size())) && (i>=0))
133       return m_aflockDevices[i];
134    else
135       return NULL;
136 }
137 
138 int
setAflockDevice(AflockDevice * aflockDevice)139 InputDeviceApp::setAflockDevice(AflockDevice* aflockDevice)
140 {
141    return replaceOrAddAflockDevice(aflockDevice, aflockDevice->getDeviceName());
142 }
143 
144 int
searchAflockDevice(const char * deviceName)145 InputDeviceApp::searchAflockDevice(const char *deviceName)
146 {
147    for (long i=0;i<m_aflockDevices.size();i++)
148       if (strcmp(m_aflockDevices[i]->getDeviceName(),
149                  deviceName) == 0)
150          return i;
151    return -1;
152 }
153 
154 int
replaceOrAddAflockDevice(AflockDevice * newDevice,const char * deviceName)155 InputDeviceApp::replaceOrAddAflockDevice(AflockDevice* newDevice,
156                                          const char *deviceName)
157 {
158    int device = searchAflockDevice(deviceName);
159    if (device > -1) {
160        if (m_aflockDevices[device] != newDevice) {
161            delete m_aflockDevices[device];
162            m_aflockDevices[device] = newDevice;
163        }
164        return device;
165    } else
166        m_aflockDevices.append(newDevice);
167    return m_aflockDevices.size()-1;
168 }
169 
170 bool
returnTracker(void)171 InputDeviceApp::returnTracker(void)
172 {
173    if (m_aflockDevices.size()==0)
174       return(false);
175    else
176       for (long i=0;i<m_aflockDevices.size();i++)
177          delete m_aflockDevices[i];
178    return(true);
179 }
180 
181 void
stopTrackers(void)182 InputDeviceApp::stopTrackers(void)
183 {
184    for (long i=0;i<m_aflockDevices.size();i++)
185       m_aflockDevices[i]->stop();
186 }
187 
188 void
restartTrackers(void)189 InputDeviceApp::restartTrackers(void)
190 {
191    for (long i=0;i<m_aflockDevices.size();i++)
192       m_aflockDevices[i]->start();
193 }
194 
195 void
deleteAflockDevice(AflockDevice * device)196 InputDeviceApp::deleteAflockDevice(AflockDevice* device)
197 {
198    for (long i=0;i<m_aflockDevices.size();i++)
199       if (m_aflockDevices[i] == device)
200            m_aflockDevices.remove(i);
201 }
202 
203 #endif
204 
205 void
calibrateInputDevices(void)206 InputDeviceApp::calibrateInputDevices(void)
207 {
208    for (long i=0;i<m_inputDevices.size();i++)
209       m_inputDevices[i]->set_firstflag();
210 }
211 
212 void
increaseInputDevice(TransformMode * tm)213 InputDeviceApp::increaseInputDevice(TransformMode* tm)
214 {
215    for (long i=0;i<m_inputDevices.size();i++)
216       {
217       if (m_inputDevices[i]->isTracker() ||
218           m_inputDevices[i]->isWand()) continue;
219       if (tm->hasTranslation())
220          {
221          float factor=m_inputDevices[i]->getxyzfactor();
222          m_inputDevices[i]->setxyzfactor(2*factor);
223          }
224       if (tm->hasRotation())
225          {
226          float factor=m_inputDevices[i]->getrotfactor();
227          m_inputDevices[i]->setrotfactor(2*factor);
228          }
229       }
230 }
231 
232 void
decreaseInputDevice(TransformMode * tm)233 InputDeviceApp::decreaseInputDevice(TransformMode* tm)
234 {
235    for (long i=0;i<m_inputDevices.size();i++)
236       {
237       if (m_inputDevices[i]->isTracker() ||
238           m_inputDevices[i]->isWand()) continue;
239       if (tm->hasTranslation())
240          {
241          float factor=m_inputDevices[i]->getxyzfactor();
242          m_inputDevices[i]->setxyzfactor(0.5*factor);
243          }
244      if (tm->hasRotation())
245          {
246          float factor=m_inputDevices[i]->getrotfactor();
247          m_inputDevices[i]->setrotfactor(0.5*factor);
248          }
249       }
250 }
251 
252 
253 
254 // sort inputdevices
255 //
256 // make inputdevices without readdelay comes first in array
257 //
258 // so inputdevices with a readdelay can prepare the read,
259 // while other inputdevices can use the time to read data
260 
261 void
sortInputDevices(void)262 InputDeviceApp::sortInputDevices(void)
263 {
264     // only a few devices, it is ok to use bubblesort
265     bool changedflag=false;
266     do {
267        InputDevice* tmp;
268        changedflag=false;
269        for (long i=0;i<m_inputDevices.size()-1;i++)
270           if (!m_inputDevices[i]->hasReadDelay() &&
271                m_inputDevices[i+1]->hasReadDelay()) {
272              tmp=m_inputDevices[i];
273              m_inputDevices[i]=m_inputDevices[i+1];
274              m_inputDevices[i+1]=tmp;
275              changedflag=true;
276           }
277     } while (changedflag==true);
278 }
279 
280 void
setInputDeviceSetting(InputDevice * device,const char * setting)281 InputDeviceApp::setInputDeviceSetting(InputDevice *device, const char *setting)
282    {
283    if ((stringncmp(setting,"-x")==0) ||
284        (stringncmp(setting,"-y")==0) ||
285        (stringncmp(setting,"-z")==0) ||
286        (stringncmp(setting,"-all")==0) ||
287        (stringncmp(setting,"-none")==0))
288       device->setAxisInformation(setting);
289    else if (stringncmp(setting,"-axes")==0)
290       device->setNumberAxes(setting);
291    else if (strcmp(setting,"-sendalways")==0)
292       device->setSendAlways(true);
293    else if (strcmp(setting,"-dontcarefocus")==0)
294       setDontCareFocus();
295    }
296 
297 
298 void
InputDeviceLoadPreferences()299 InputDeviceApp::InputDeviceLoadPreferences()
300 {
301     assert(TheApp != NULL);
302 
303     MyString inputDeviceOption = "";
304     MyString inputDeviceName = "";
305     int i = 0;
306     bool hasAnotherDevice=false;
307     do {
308          inputDeviceOption = "";
309          inputDeviceOption += TheApp->GetArrayPreference("InputDeviceOption",
310                                                          i);
311          inputDeviceName = "";
312          inputDeviceName += TheApp->GetArrayPreference("InputDeviceName",
313                                                        i);
314          hasAnotherDevice=false;
315          if ((inputDeviceOption.length() > 0) && (inputDeviceName.length() > 0))
316              {
317              hasAnotherDevice=true;
318              InputDevice *device = InputDevice::createInputDevice(
319                                           inputDeviceOption, inputDeviceName);
320              replaceOrAddInputDevice(device,
321                                      inputDeviceOption, inputDeviceName);
322              if (device != NULL) {
323                  int j = 0;
324                  const char *setting = "";
325                  do {
326                      MyString settingsKey = "";
327                      settingsKey += "InputDeviceSettings";
328                      settingsKey.catInt(i);
329                      setting = TheApp->GetArrayPreference(settingsKey, j);
330                      if (strlen(setting) > 0)
331                          setInputDeviceSetting(device, setting);
332                      j++;
333                  } while (strlen(setting) > 0);
334              }
335          }
336          i++;
337     } while (hasAnotherDevice);
338 }
339 
340 void
InputDeviceSavePreferences()341 InputDeviceApp::InputDeviceSavePreferences()
342 {
343     assert(TheApp != NULL);
344 
345     for (int i = 0; i < getNumberInputDevices(); i++) {
346         InputDevice *device = getInputDevice(i);
347         TheApp->SetArrayPreference("InputDeviceOption", i,
348                                    device->getDeviceOption());
349         TheApp->SetArrayPreference("InputDeviceName", i,
350                                    device->getDeviceName());
351 /*
352         char *axes_name[6];
353         for (int j = 0; j < 6; j++)
354              axes_name[j] = device->getAxesInfo(j);
355 */
356 
357         for (int j = 0; j < 6; j++) {
358              int axis = device->getNumAxis(j);
359              MyString settings = "";
360              settings += "-";
361              if (device->get_ignore(axis))
362                  settings += "none=";
363              else {
364                  settings += device->getAxesInfo(j);
365                  settings += "=";
366                      if (device->get_sign(axis) < 0)
367                          settings += "-";
368              }
369              settings.catInt(device->getNumAxis(j));
370              if (!device->get_ignore(axis)) {
371                  settings += ",";
372                  settings.catInt(device->get_factor(axis));
373                  settings += ",";
374                  settings.catFloat(device->get_acceleration(axis));
375                  settings += ",";
376                  if (!device->get_zero_on_release(axis))
377                      settings += "wheel";
378                  settings += ",";
379                  settings.catFloat(device->get_zero_size_fraction(axis));
380              }
381              MyString settingsKey = "";
382              settingsKey += "InputDeviceSettings";
383              settingsKey.catInt(i);
384              TheApp->SetArrayPreference(settingsKey, j, settings);
385         }
386     }
387     TheApp->SetArrayPreference("InputDeviceOption", getNumberInputDevices(), ""
388                               );
389     TheApp->SetArrayPreference("InputDeviceName", getNumberInputDevices(), "");
390 }
391 
392 
393