finished Mac NDOF device detection, moved core device ID to base NDOFManager, clarifi...
[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 static void NDOF_DeviceAdded(io_connect_t connection)
37         {
38         printf("ndof: device added\n"); // change these: printf --> informational reports
39
40 #if 0 // device preferences will be useful soon, but not for hardware model detection
41         ConnexionDevicePrefs p;
42         ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p);
43         printf("device type %d: %s\n", p.deviceID,
44                 p.deviceID == kDevID_SpaceNavigator ? "SpaceNavigator" :
45                 p.deviceID == kDevID_SpaceNavigatorNB ? "SpaceNavigator for Notebooks" :
46                 p.deviceID == kDevID_SpaceExplorer ? "SpaceExplorer" :
47                 "unknown");
48 #endif
49
50         // determine exactly which device is plugged in
51         int result = 0;
52         ConnexionControl(kConnexionCtlGetDeviceID, 0, &result);
53         unsigned short vendorID = result >> 16;
54         unsigned short productID = result & 0xffff;
55
56         ndof_manager->setDevice(vendorID, productID);
57         }
58
59 static void NDOF_DeviceRemoved(io_connect_t connection)
60         {
61         printf("ndof: device removed\n");
62         }
63
64 static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument)
65         {
66         switch (messageType)
67                 {
68                 case kConnexionMsgDeviceState:
69                         {
70                         ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument;
71
72                         GHOST_TUns64 now = ghost_system->getMilliSeconds();
73
74                         switch (s->command)
75                                 {
76                                 case kConnexionCmdHandleAxis:
77                                         ndof_manager->updateTranslation(s->axis, now);
78                                         ndof_manager->updateRotation(s->axis + 3, now);
79                                         ghost_system->notifyExternalEventProcessed();
80                                         break;
81
82                                 case kConnexionCmdHandleButtons:
83
84                                         // s->buttons field has only 16 bits, not enough for SpacePilotPro
85                                         // look at raw USB report for more button bits
86                                         printf("ndof: button bits = [");
87                                         for (int i = 0; i < 8; ++i)
88                                                 printf("%02x", s->report[i]);
89                                         printf("]\n");
90
91                                         ndof_manager->updateButtons(s->buttons, now);
92                                         ghost_system->notifyExternalEventProcessed();
93                                         break;
94
95                                 case kConnexionCmdAppSpecific:
96                                         printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value);
97                                         break;
98
99                                 default:
100                                         printf("ndof: mystery device command %d\n", s->command);
101                                 }
102                         break;
103                         }
104                 case kConnexionMsgPrefsChanged:
105                         printf("ndof: prefs changed\n"); // this includes app switches
106                         break;
107                 case kConnexionMsgDoAction:
108                         printf("ndof: do action\n"); // no idea what this means
109                         // 'calibrate device' in System Prefs sends this
110                         // 3Dx header file says to ignore these
111                         break;
112                 default:
113                         printf("ndof: mystery event %d\n", messageType);
114                 }
115         }
116
117 GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys)
118         : GHOST_NDOFManager(sys)
119         {
120         if (available())
121                 {
122                 // give static functions something to talk to:
123                 ghost_system = dynamic_cast<GHOST_SystemCocoa*>(&sys);
124                 ndof_manager = this;
125
126                 OSErr error = InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved);
127                 if (error)
128                         {
129                         printf("ndof: error %d while installing handlers\n", error);
130                         return;
131                         }
132
133                 // Pascal string *and* a four-letter constant. How old-skool.
134                 m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pblender",
135                         kConnexionClientModeTakeOver, kConnexionMaskAll);
136
137                 printf("ndof: client id = %d\n", m_clientID);
138                 }
139         else
140                 {
141                 printf("ndof: 3Dx driver not found\n");
142                 // This isn't a hard error, just means the user doesn't have a 3D mouse.
143                 }
144         }
145
146 GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa()
147         {
148         UnregisterConnexionClient(m_clientID);
149         CleanupConnexionHandlers();
150         ghost_system = NULL;
151         ndof_manager = NULL;
152         }
153
154 bool GHOST_NDOFManagerCocoa::available()
155         {
156 //      extern OSErr InstallConnexionHandlers() __attribute__((weak_import));
157 // ^-- not needed since the entire framework is weak-linked
158         return InstallConnexionHandlers != NULL;
159         }