updated Mac code to work with latest 3Dx beta driver -- all buttons work now
[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 #include "GHOST_NDOFManagerCocoa.h"
25 #include "GHOST_SystemCocoa.h"
26
27 extern "C" {
28         #include <3DconnexionClient/ConnexionClientAPI.h>
29         #include <stdio.h>
30         }
31
32 // static functions need to talk to these objects:
33 static GHOST_SystemCocoa* ghost_system = NULL;
34 static GHOST_NDOFManager* ndof_manager = NULL;
35
36 // 3Dconnexion drivers before 10.x are "old"
37 // not all buttons will work
38 static bool has_old_driver = true;
39
40 static void NDOF_DeviceAdded(io_connect_t connection)
41         {
42         printf("ndof: device added\n"); // change these: printf --> informational reports
43
44 #if 0 // device preferences will be useful soon
45         ConnexionDevicePrefs p;
46         ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p);
47 #endif
48
49         // determine exactly which device is plugged in
50         int result = 0;
51         ConnexionControl(kConnexionCtlGetDeviceID, 0, &result);
52         unsigned short vendorID = result >> 16;
53         unsigned short productID = result & 0xffff;
54
55         ndof_manager->setDevice(vendorID, productID);
56         }
57
58 static void NDOF_DeviceRemoved(io_connect_t connection)
59         {
60         printf("ndof: device removed\n");
61         }
62
63 static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument)
64         {
65         switch (messageType)
66                 {
67                 case kConnexionMsgDeviceState:
68                         {
69                         ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument;
70
71                         GHOST_TUns64 now = ghost_system->getMilliSeconds();
72
73                         switch (s->command)
74                                 {
75                                 case kConnexionCmdHandleAxis:
76                                         ndof_manager->updateTranslation(s->axis, now);
77                                         ndof_manager->updateRotation(s->axis + 3, now);
78                                         ghost_system->notifyExternalEventProcessed();
79                                         break;
80
81                                 case kConnexionCmdHandleButtons:
82                                         {
83                                         int button_bits = has_old_driver ? s->buttons8 : s->buttons;
84                                         ndof_manager->updateButtons(button_bits, now);
85                                         ghost_system->notifyExternalEventProcessed();
86                                         break;
87                                         }
88                                 case kConnexionCmdAppSpecific:
89                                         printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value);
90                                         break;
91
92                                 default:
93                                         printf("ndof: mystery device command %d\n", s->command);
94                                 }
95                         break;
96                         }
97                 case kConnexionMsgPrefsChanged:
98                         printf("ndof: prefs changed\n"); // this includes app switches
99                         break;
100                 case kConnexionMsgCalibrateDevice:
101                         printf("ndof: calibrate\n"); // but what should blender do?
102                         break;
103                 case kConnexionMsgDoMapping:
104                         printf("ndof: driver did something\n");
105                         // sent when the driver itself consumes an NDOF event
106                         // and performs whatever action is set in user prefs
107                         // 3Dx header file says to ignore these
108                         break;
109                 default:
110                         printf("ndof: mystery event %d\n", messageType);
111                 }
112         }
113
114 GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys)
115         : GHOST_NDOFManager(sys)
116         {
117         if (available())
118                 {
119                 // give static functions something to talk to:
120                 ghost_system = dynamic_cast<GHOST_SystemCocoa*>(&sys);
121                 ndof_manager = this;
122
123                 OSErr error = InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved);
124                 if (error)
125                         {
126                         printf("ndof: error %d while installing handlers\n", error);
127                         return;
128                         }
129
130                 // Pascal string *and* a four-letter constant. How old-skool.
131                 m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pblender",
132                         kConnexionClientModeTakeOver, kConnexionMaskAll);
133
134                 printf("ndof: client id = %d\n", m_clientID);
135
136                 if (SetConnexionClientButtonMask != NULL)
137                         {
138                         has_old_driver = false;
139                         SetConnexionClientButtonMask(m_clientID, kConnexionMaskAllButtons);
140                         }
141                 else
142                         printf("ndof: old 3Dx driver installed, some buttons may not work\n");
143                 }
144         else
145                 {
146                 printf("ndof: 3Dx driver not found\n");
147                 // This isn't a hard error, just means the user doesn't have a 3D mouse.
148                 }
149         }
150
151 GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa()
152         {
153         UnregisterConnexionClient(m_clientID);
154         CleanupConnexionHandlers();
155         ghost_system = NULL;
156         ndof_manager = NULL;
157         }
158
159 bool GHOST_NDOFManagerCocoa::available()
160         {
161 //      extern OSErr InstallConnexionHandlers() __attribute__((weak_import));
162 // ^-- not needed since the entire framework is weak-linked
163         return InstallConnexionHandlers != NULL;
164         }