OSX: Compilefix for ndof symbols get magled when used extern C, now use discrete...
[blender.git] / intern / ghost / intern / GHOST_NDOFManagerCocoa.mm
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s):
19  *   Mike Erwin
20  *
21  * ***** END GPL LICENSE BLOCK *****
22  */
23
24 #ifdef WITH_INPUT_NDOF
25
26 #include "GHOST_NDOFManagerCocoa.h"
27 #include "GHOST_NDOFManager3Dconnexion.h"
28 #include "GHOST_SystemCocoa.h"
29
30 extern "C" {
31         #include <ConnexionClientAPI.h>
32         #include <stdio.h>
33         }
34
35
36 // static functions need to talk to these objects:
37 static GHOST_SystemCocoa* ghost_system = NULL;
38 static GHOST_NDOFManager* ndof_manager = NULL;
39
40 // 3Dconnexion drivers before 10.x are "old"
41 // not all buttons will work
42 static bool has_old_driver = true;
43
44 static void NDOF_DeviceAdded(io_connect_t connection)
45 {
46         printf("ndof: device added\n"); // change these: printf --> informational reports
47
48 #if 0 // device preferences will be useful some day
49         ConnexionDevicePrefs p;
50         ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p);
51 #endif
52
53         // determine exactly which device is plugged in
54         SInt32 result = 0;
55         GHOST_NDOFManager3Dconnexion_ConnexionControl(kConnexionCtlGetDeviceID, 0, &result);
56         unsigned short vendorID = result >> 16;
57         unsigned short productID = result & 0xffff;
58
59         ndof_manager->setDevice(vendorID, productID);
60 }
61
62 static void NDOF_DeviceRemoved(io_connect_t connection)
63 {
64         printf("ndof: device removed\n");
65 }
66
67 static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument)
68 {
69         switch (messageType)
70         {
71                 case kConnexionMsgDeviceState:
72                 {
73                         ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument;
74
75                         GHOST_TUns64 now = ghost_system->getMilliSeconds();
76
77                         switch (s->command)
78                         {
79                                 case kConnexionCmdHandleAxis:
80                                 {
81                                         // convert to blender view coordinates
82                                         short t[3] = {s->axis[0], -(s->axis[2]), s->axis[1]};
83                                         short r[3] = {-(s->axis[3]), s->axis[5], -(s->axis[4])};
84
85                                         ndof_manager->updateTranslation(t, now);
86                                         ndof_manager->updateRotation(r, now);
87
88                                         ghost_system->notifyExternalEventProcessed();
89                                         break;
90                                 }
91                                 case kConnexionCmdHandleButtons:
92                                 {
93                                         int button_bits = has_old_driver ? s->buttons8 : s->buttons;
94                                         ndof_manager->updateButtons(button_bits, now);
95                                         ghost_system->notifyExternalEventProcessed();
96                                         break;
97                                 }
98                                 case kConnexionCmdAppSpecific:
99                                         printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value);
100                                         break;
101
102                                 default:
103                                         printf("ndof: mystery device command %d\n", s->command);
104                         }
105                         break;
106                 }
107                 case kConnexionMsgPrefsChanged:
108                         // printf("ndof: prefs changed\n"); // this includes app switches
109                         // TODO: look through updated prefs for things blender cares about
110                         break;
111                 case kConnexionMsgCalibrateDevice:
112                         printf("ndof: calibrate\n"); // but what should blender do?
113                         break;
114                 case kConnexionMsgDoMapping:
115                         // printf("ndof: driver did something\n");
116                         // sent when the driver itself consumes an NDOF event
117                         // and performs whatever action is set in user prefs
118                         // 3Dx header file says to ignore these
119                         break;
120                 default:
121                         printf("ndof: mystery event %d\n", messageType);
122         }
123 }
124
125 GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys)
126     : GHOST_NDOFManager(sys)
127 {
128         if (GHOST_NDOFManager3Dconnexion_available())
129         {
130                 // give static functions something to talk to:
131                 ghost_system = dynamic_cast<GHOST_SystemCocoa*>(&sys);
132                 ndof_manager = this;
133
134                 OSErr error = GHOST_NDOFManager3Dconnexion_InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved);
135                 if (error) {
136                         printf("ndof: error %d while installing handlers\n", error);
137                         return;
138                 }
139
140                 // Pascal string *and* a four-letter constant. How old-skool.
141                 m_clientID = GHOST_NDOFManager3Dconnexion_RegisterConnexionClient('blnd', (UInt8*) "\007blender",
142                                                      kConnexionClientModeTakeOver, kConnexionMaskAll);
143
144                 // printf("ndof: client id = %d\n", m_clientID);
145
146                 if (GHOST_NDOFManager3Dconnexion_oldDRV()) {
147                         has_old_driver = false;
148                         GHOST_NDOFManager3Dconnexion_SetConnexionClientButtonMask(m_clientID, kConnexionMaskAllButtons);
149                 }
150                 else {
151                         printf("ndof: old 3Dx driver installed, some buttons may not work\n");
152                 }
153         }
154         else {
155                 printf("ndof: 3Dx driver not found\n");
156                 // This isn't a hard error, just means the user doesn't have a 3D mouse.
157         }
158 }
159
160 GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa()
161 {
162         if (GHOST_NDOFManager3Dconnexion_available())
163         {
164                 GHOST_NDOFManager3Dconnexion_UnregisterConnexionClient(m_clientID);
165         GHOST_NDOFManager3Dconnexion_UnregisterConnexionClient(m_clientID);
166
167                 GHOST_NDOFManager3Dconnexion_CleanupConnexionHandlers();
168                 ghost_system = NULL;
169                 ndof_manager = NULL;
170         }
171 }
172 #endif // WITH_INPUT_NDOF