ndof: rework Mac driver glue
authorMike Erwin <significant.bit@gmail.com>
Sat, 24 Oct 2015 17:58:06 +0000 (19:58 +0200)
committerMike Erwin <significant.bit@gmail.com>
Sun, 25 Oct 2015 20:19:26 +0000 (21:19 +0100)
Load driver dynamically at runtime instead of weak-linking the
3Dconnexion framework. Driver no longer needed at build time!

Works with really old drivers (as in PowerMac old), more recent
versions, and the latest which allows us to process events on a
separate thread.

intern/ghost/CMakeLists.txt
intern/ghost/SConscript
intern/ghost/intern/GHOST_NDOFManager.h
intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c [deleted file]
intern/ghost/intern/GHOST_NDOFManager3Dconnexion.h [deleted file]
intern/ghost/intern/GHOST_NDOFManagerCocoa.h
intern/ghost/intern/GHOST_NDOFManagerCocoa.mm
intern/ghost/intern/GHOST_SystemCocoa.mm

index 761bcb4..948b4bf 100644 (file)
@@ -166,11 +166,6 @@ elseif(APPLE AND NOT WITH_X11)
 
                        intern/GHOST_NDOFManagerCocoa.h
                )
-
-               list(APPEND SRC_NDOF3DCONNEXION
-                       intern/GHOST_NDOFManager3Dconnexion.c
-                       intern/GHOST_NDOFManager3Dconnexion.h
-               )
        endif()
 
        if(WITH_CODEC_QUICKTIME)
@@ -338,8 +333,3 @@ endif()
 add_definitions(${GL_DEFINITIONS})
 
 blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}")
-
-# workaround for apple clang mangling extern "C" symbols
-if(WITH_INPUT_NDOF AND APPLE)
-       blender_add_lib(bf_intern_ghostndof3dconnexion "${SRC_NDOF3DCONNEXION}" "${INC}" "${INC_SYS}")
-endif()
index 7856621..0abd2c2 100644 (file)
@@ -33,7 +33,6 @@ Import ('env')
 window_system = env['OURPLATFORM']
 
 sources = env.Glob('intern/*.cpp')
-sources2 = env.Glob('intern/GHOST_NDOFManager3Dconnexion.c')
 if window_system == 'darwin':
     sources += env.Glob('intern/*.mm')
     #remove, will be readded below if needed.
@@ -193,7 +192,3 @@ elif window_system == 'darwin' and env['C_COMPILER_ID'] == 'gcc' and  env['CCVER
 
 else:
     env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] )
-    
-if window_system == 'darwin' and env['WITH_BF_3DMOUSE']: # build seperate to circumvent extern "C" linkage issues
-    env.BlenderLib ('bf_intern_ghostndof3dconnexion', sources2, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15] )
-
index 48a4881..ba82f37 100644 (file)
@@ -107,10 +107,13 @@ typedef enum {
 class GHOST_NDOFManager
 {
 public:
-       GHOST_NDOFManager(GHOST_System &);
-
+       GHOST_NDOFManager(GHOST_System&);
        virtual ~GHOST_NDOFManager() {}
 
+       // whether multi-axis functionality is available (via the OS or driver)
+       // does not imply that a device is plugged in or being used
+       virtual bool available() = 0;
+
        // each platform's device detection should call this
        // use standard USB/HID identifiers
        bool setDevice(unsigned short vendor_id, unsigned short product_id);
diff --git a/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c b/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.c
deleted file mode 100644 (file)
index 01e301f..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s):
- *   Jake Kauth on 9/12/13.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifdef WITH_INPUT_NDOF
-
-#include <ConnexionClientAPI.h>
-#include <stdio.h>
-
-#include "GHOST_NDOFManager3Dconnexion.h"
-
-/* It is to be noted that these implementations are linked in as
- * 'extern "C"' calls from GHOST_NDOFManagerCocoa.
- *
- * This is done in order to
- * preserve weak linking capability (which as of clang-3.3 and xcode5
- * breaks weak linking when there is name mangling of c++ libraries.)
- *
- * We need to have the weak linked file as pure C.  Therefore we build a 
- * compiled bridge from the real weak linked calls and the calls within C++
- *
- */
-
-OSErr GHOST_NDOFManager3Dconnexion_available(void)
-{
-       // extern unsigned int InstallConnexionHandlers() __attribute__((weak_import));
-       // Make the linker happy for the framework check (see link below for more info)
-       // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html
-       return InstallConnexionHandlers != 0;
-       // this means that the driver is installed and dynamically linked to blender
-}
-
-OSErr GHOST_NDOFManager3Dconnexion_oldDRV()
-{
-       //extern unsigned int SetConnexionClientButtonMask() __attribute__((weak_import));
-       // Make the linker happy for the framework check (see link below for more info)
-       // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html
-       return SetConnexionClientButtonMask != 0;
-       // this means that the driver has this symbol
-}
-
-UInt16 GHOST_NDOFManager3Dconnexion_RegisterConnexionClient(UInt32 signature, UInt8 *name, UInt16 mode, UInt32 mask)
-{
-       return RegisterConnexionClient(signature,  name,  mode,  mask);
-}
-
-void GHOST_NDOFManager3Dconnexion_SetConnexionClientButtonMask(UInt16 clientID, UInt32 buttonMask)
-{
-       return SetConnexionClientButtonMask( clientID,  buttonMask);
-}
-
-void GHOST_NDOFManager3Dconnexion_UnregisterConnexionClient(UInt16 clientID)
-{
-       return UnregisterConnexionClient( clientID);
-}
-
-OSErr GHOST_NDOFManager3Dconnexion_InstallConnexionHandlers(
-        ConnexionMessageHandlerProc messageHandler,
-        ConnexionAddedHandlerProc addedHandler,
-        ConnexionRemovedHandlerProc removedHandler)
-{
-       return InstallConnexionHandlers( messageHandler,  addedHandler,  removedHandler);
-}
-
-void GHOST_NDOFManager3Dconnexion_CleanupConnexionHandlers(void)
-{
-       return CleanupConnexionHandlers();
-}
-
-OSErr GHOST_NDOFManager3Dconnexion_ConnexionControl(UInt32 message, SInt32 param, SInt32 *result)
-{
-       return ConnexionControl( message,  param, result);
-}
-
-#endif // WITH_INPUT_NDOF
diff --git a/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.h b/intern/ghost/intern/GHOST_NDOFManager3Dconnexion.h
deleted file mode 100644 (file)
index 9a84c14..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s):
- *   Jake Kauth on 9/12/13.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __GHOST_NDOFMANAGER3DCONNEXION_H__
-#define __GHOST_NDOFMANAGER3DCONNEXION_H__
-
-#ifdef WITH_INPUT_NDOF
-#include <ConnexionClientAPI.h>
-
-
-OSErr GHOST_NDOFManager3Dconnexion_available(void);
-OSErr GHOST_NDOFManager3Dconnexion_oldDRV(void);
-OSErr                  GHOST_NDOFManager3Dconnexion_InstallConnexionHandlers(ConnexionMessageHandlerProc messageHandler, ConnexionAddedHandlerProc addedHandler, ConnexionRemovedHandlerProc removedHandler);
-void                   GHOST_NDOFManager3Dconnexion_CleanupConnexionHandlers(void);
-UInt16                 GHOST_NDOFManager3Dconnexion_RegisterConnexionClient(UInt32 signature, UInt8 *name, UInt16 mode, UInt32 mask);
-void                   GHOST_NDOFManager3Dconnexion_SetConnexionClientButtonMask(UInt16 clientID, UInt32 buttonMask);
-void                   GHOST_NDOFManager3Dconnexion_UnregisterConnexionClient(UInt16 clientID);
-OSErr  GHOST_NDOFManager3Dconnexion_ConnexionControl(UInt32 message, SInt32 param, SInt32 *result);
-
-extern OSErr InstallConnexionHandlers(ConnexionMessageHandlerProc messageHandler, ConnexionAddedHandlerProc addedHandler, ConnexionRemovedHandlerProc removedHandler) __attribute__((weak_import));
-extern void            CleanupConnexionHandlers(void) __attribute__((weak_import));
-extern UInt16 RegisterConnexionClient(UInt32 signature, UInt8 *name, UInt16 mode, UInt32 mask) __attribute__((weak_import));
-extern void SetConnexionClientButtonMask(UInt16 clientID, UInt32 buttonMask) __attribute__((weak_import));
-extern void UnregisterConnexionClient(UInt16 clientID) __attribute__((weak_import));
-extern OSErr   ConnexionControl(UInt32 message, SInt32 param, SInt32 *result) __attribute__((weak_import));
-
-
-#endif // WITH_INPUT_NDOF
-
-#endif // #include guard
index 2a1b492..464ba48 100644 (file)
 
 #ifdef WITH_INPUT_NDOF
 
-
-extern "C" {
-#include <ConnexionClientAPI.h>
-#include <stdio.h>
-}
-
-
 #include "GHOST_NDOFManager.h"
-extern "C"  OSErr   GHOST_NDOFManager3Dconnexion_available(void);
-extern "C"  OSErr   GHOST_NDOFManager3Dconnexion_oldDRV(void);
-extern "C"  OSErr   GHOST_NDOFManager3Dconnexion_InstallConnexionHandlers(ConnexionMessageHandlerProc messageHandler, ConnexionAddedHandlerProc addedHandler, ConnexionRemovedHandlerProc removedHandler);
-extern "C"  void GHOST_NDOFManager3Dconnexion_CleanupConnexionHandlers(void);
-extern "C"  UInt16  GHOST_NDOFManager3Dconnexion_RegisterConnexionClient(UInt32 signature, UInt8 *name, UInt16 mode, UInt32 mask);
-extern "C"  void    GHOST_NDOFManager3Dconnexion_SetConnexionClientButtonMask(UInt16 clientID, UInt32 buttonMask);
-extern "C"  void       GHOST_NDOFManager3Dconnexion_UnregisterConnexionClient(UInt16 clientID);
-extern "C"  OSErr      GHOST_NDOFManager3Dconnexion_ConnexionControl(UInt32 message, SInt32 param, SInt32 *result);
 
 // Event capture is handled within the NDOF manager on Macintosh,
 // so there's no need for SystemCocoa to look for them.
@@ -50,14 +35,9 @@ class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager
 {
 public:
        GHOST_NDOFManagerCocoa(GHOST_System&);
-
        ~GHOST_NDOFManagerCocoa();
 
-       // whether multi-axis functionality is available (via the OS or driver)
-       // does not imply that a device is plugged in or being used
-    
-private:
-       unsigned short m_clientID;
+       bool available();
 };
 
 
index 6eedaaf..6fee39d 100644 (file)
 
 #ifdef WITH_INPUT_NDOF
 
+#define DEBUG_NDOF_DRIVER false
+
 #include "GHOST_NDOFManagerCocoa.h"
-#include "GHOST_NDOFManager3Dconnexion.h"
 #include "GHOST_SystemCocoa.h"
 
-extern "C" {
-       #include <ConnexionClientAPI.h>
-       #include <stdio.h>
-}
+#include <stdint.h>
+#include <dlfcn.h>
 
+#if DEBUG_NDOF_DRIVER
+  #include <cstdio>
+#endif
 
-// static functions need to talk to these objects:
+// static callback functions need to talk to these objects:
 static GHOST_SystemCocoa* ghost_system = NULL;
 static GHOST_NDOFManager* ndof_manager = NULL;
 
-// 3Dconnexion drivers before 10.x are "old"
-// not all buttons will work
-static bool has_old_driver = true;
+static uint16_t clientID = 0;
+
+static bool driver_loaded = false;
+static bool has_old_driver = false; // 3Dconnexion drivers before 10 beta 4 are "old", not all buttons will work
+static bool has_new_driver = false; // drivers >= 10.2.2 are "new", and can process events on a separate thread
+
+// replicate just enough of the 3Dx API for our uses, not everything the driver provides
+
+#define kConnexionClientModeTakeOver 1
+#define kConnexionMaskAll 0x3fff
+#define kConnexionMaskAllButtons 0xffffffff
+#define kConnexionCmdHandleButtons 2
+#define kConnexionCmdHandleAxis 3
+#define kConnexionCmdAppSpecific 10
+#define kConnexionMsgDeviceState '3dSR'
+#define kConnexionCtlGetDeviceID '3did'
+
+#pragma pack(push,2) // just this struct
+struct ConnexionDeviceState {
+       uint16_t version;
+       uint16_t client;
+       uint16_t command;
+       int16_t param;
+       int32_t value;
+       uint64_t time;
+       uint8_t report[8];
+       uint16_t buttons8; // obsolete! (pre-10.x drivers)
+       int16_t axis[6]; // tx, ty, tz, rx, ry, rz
+       uint16_t address;
+       uint32_t buttons;
+};
+#pragma pack(pop)
+
+// callback functions:
+typedef void (*AddedHandler)(uint32_t);
+typedef void (*RemovedHandler)(uint32_t);
+typedef void (*MessageHandler)(uint32_t, uint32_t msg_type, void* msg_arg);
 
-static void NDOF_DeviceAdded(io_connect_t connection)
+// driver functions:
+typedef int16_t (*SetConnexionHandlers_ptr)(MessageHandler, AddedHandler, RemovedHandler, bool);
+typedef int16_t (*InstallConnexionHandlers_ptr)(MessageHandler, AddedHandler, RemovedHandler);
+typedef void (*CleanupConnexionHandlers_ptr)();
+typedef uint16_t (*RegisterConnexionClient_ptr)(uint32_t signature, const char* name, uint16_t mode, uint32_t mask);
+typedef void (*SetConnexionClientButtonMask_ptr)(uint16_t clientID, uint32_t buttonMask);
+typedef void (*UnregisterConnexionClient_ptr)(uint16_t clientID);
+typedef int16_t (*ConnexionClientControl_ptr)(uint16_t clientID, uint32_t message, int32_t param, int32_t* result);
+
+#define DECLARE_FUNC(name) name##_ptr name = NULL
+
+DECLARE_FUNC(SetConnexionHandlers);
+DECLARE_FUNC(InstallConnexionHandlers);
+DECLARE_FUNC(CleanupConnexionHandlers);
+DECLARE_FUNC(RegisterConnexionClient);
+DECLARE_FUNC(SetConnexionClientButtonMask);
+DECLARE_FUNC(UnregisterConnexionClient);
+DECLARE_FUNC(ConnexionClientControl);
+
+
+static void* load_func(void* module, const char* func_name)
 {
-       printf("ndof: device added\n"); // change these: printf --> informational reports
+       void* func = dlsym(module, func_name);
 
-#if 0 // device preferences will be useful some day
-       ConnexionDevicePrefs p;
-       ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p);
+#if DEBUG_NDOF_DRIVER
+       if (func) {
+               printf("'%s' loaded :D\n", func_name);
+       }
+       else {
+               printf("<!> %s\n", dlerror());
+       }
+#endif
+
+       return func;
+}
+
+#define LOAD_FUNC(name) name = (name##_ptr) load_func(module, #name)
+
+static bool load_driver_functions()
+{
+       if (driver_loaded) {
+               return true;
+       }
+
+       void* module = dlopen("3DconnexionClient.framework/3DconnexionClient", RTLD_LAZY | RTLD_LOCAL);
+
+       if (module) {
+               LOAD_FUNC(SetConnexionHandlers);
+
+               if (SetConnexionHandlers != NULL) {
+                       driver_loaded = true;
+                       has_new_driver = true;
+               }
+               else {
+                       LOAD_FUNC(InstallConnexionHandlers);
+
+                       driver_loaded = (InstallConnexionHandlers != NULL);
+               }
+
+               if (driver_loaded) {
+                       LOAD_FUNC(CleanupConnexionHandlers);
+                       LOAD_FUNC(RegisterConnexionClient);
+                       LOAD_FUNC(SetConnexionClientButtonMask);
+                       LOAD_FUNC(UnregisterConnexionClient);
+                       LOAD_FUNC(ConnexionClientControl);
+
+                       has_old_driver = (SetConnexionClientButtonMask == NULL);
+               }
+
+               dlclose(module); // functions will remain loaded
+       }
+#if DEBUG_NDOF_DRIVER
+       else {
+               printf("<!> %s\n", dlerror());
+       }
+
+       printf("loaded: %s\n", driver_loaded ? "YES" : "NO");
+       printf("old: %s\n", has_old_driver ? "YES" : "NO");
+       printf("new: %s\n", has_new_driver ? "YES" : "NO");
+#endif
+
+       return driver_loaded;
+       }
+
+
+static void DeviceAdded(uint32_t unused)
+{
+#if DEBUG_NDOF_DRIVER
+       printf("ndof: device added\n");
 #endif
 
        // determine exactly which device is plugged in
-       SInt32 result = 0;
-       GHOST_NDOFManager3Dconnexion_ConnexionControl(kConnexionCtlGetDeviceID, 0, &result);
-       unsigned short vendorID = result >> 16;
-       unsigned short productID = result & 0xffff;
+       int32_t result;
+       ConnexionClientControl(clientID, kConnexionCtlGetDeviceID, 0, &result);
+       int16_t vendorID = result >> 16;
+       int16_t productID = result & 0xffff;
 
        ndof_manager->setDevice(vendorID, productID);
 }
 
-static void NDOF_DeviceRemoved(io_connect_t connection)
+static void DeviceRemoved(uint32_t unused)
 {
+#if DEBUG_NDOF_DRIVER
        printf("ndof: device removed\n");
+#endif
 }
 
-static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument)
+static void DeviceEvent(uint32_t unused, uint32_t msg_type, void* msg_arg)
 {
-       switch (messageType)
-       {
-               case kConnexionMsgDeviceState:
-               {
-                       ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument;
+       if (msg_type == kConnexionMsgDeviceState) {
+               ConnexionDeviceState* s = (ConnexionDeviceState*)msg_arg;
 
+               // device state is broadcast to all clients; only react if sent to us
+               if (s->client == clientID) {
+                       // TODO: is s->time compatible with GHOST timestamps? if so use that instead.
                        GHOST_TUns64 now = ghost_system->getMilliSeconds();
 
-                       switch (s->command)
-                       {
+                       switch (s->command) {
                                case kConnexionCmdHandleAxis:
                                {
                                        // convert to blender view coordinates
@@ -91,82 +210,71 @@ static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, voi
                                case kConnexionCmdHandleButtons:
                                {
                                        int button_bits = has_old_driver ? s->buttons8 : s->buttons;
+                                       printf("button bits: 0x%08x\n", button_bits);
                                        ndof_manager->updateButtons(button_bits, now);
                                        ghost_system->notifyExternalEventProcessed();
                                        break;
                                }
+#if DEBUG_NDOF_DRIVER
                                case kConnexionCmdAppSpecific:
                                        printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value);
                                        break;
 
                                default:
                                        printf("ndof: mystery device command %d\n", s->command);
+#endif
                        }
-                       break;
                }
-               case kConnexionMsgPrefsChanged:
-                       // printf("ndof: prefs changed\n"); // this includes app switches
-                       // TODO: look through updated prefs for things blender cares about
-                       break;
-               case kConnexionMsgCalibrateDevice:
-                       printf("ndof: calibrate\n"); // but what should blender do?
-                       break;
-               case kConnexionMsgDoMapping:
-                       // printf("ndof: driver did something\n");
-                       // sent when the driver itself consumes an NDOF event
-                       // and performs whatever action is set in user prefs
-                       // 3Dx header file says to ignore these
-                       break;
-               default:
-                       printf("ndof: mystery event %d\n", messageType);
        }
 }
 
 GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys)
     : GHOST_NDOFManager(sys)
 {
-       if (GHOST_NDOFManager3Dconnexion_available())
-       {
+       if (load_driver_functions()) {
                // give static functions something to talk to:
                ghost_system = dynamic_cast<GHOST_SystemCocoa*>(&sys);
                ndof_manager = this;
 
-               OSErr error = GHOST_NDOFManager3Dconnexion_InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved);
+               uint16_t error;
+               if (has_new_driver) {
+                       const bool separate_thread = false; // TODO: rework Mac event handler to allow this
+                       error = SetConnexionHandlers(DeviceEvent, DeviceAdded, DeviceRemoved, separate_thread);
+               }
+               else {
+                       error = InstallConnexionHandlers(DeviceEvent, DeviceAdded, DeviceRemoved);
+               }
+
                if (error) {
-                       printf("ndof: error %d while installing handlers\n", error);
+#if DEBUG_NDOF_DRIVER
+                       printf("ndof: error %d while setting up handlers\n", error);
+#endif
                        return;
                }
 
                // Pascal string *and* a four-letter constant. How old-skool.
-               m_clientID = GHOST_NDOFManager3Dconnexion_RegisterConnexionClient('blnd', (UInt8*) "\007blender",
-                                                    kConnexionClientModeTakeOver, kConnexionMaskAll);
-
-               // printf("ndof: client id = %d\n", m_clientID);
+               clientID = RegisterConnexionClient('blnd', "\007blender", kConnexionClientModeTakeOver, kConnexionMaskAll);
 
-               if (GHOST_NDOFManager3Dconnexion_oldDRV()) {
-                       has_old_driver = false;
-                       GHOST_NDOFManager3Dconnexion_SetConnexionClientButtonMask(m_clientID, kConnexionMaskAllButtons);
-               }
-               else {
-                       printf("ndof: old 3Dx driver installed, some buttons may not work\n");
+               if (!has_old_driver) {
+                       SetConnexionClientButtonMask(clientID, kConnexionMaskAllButtons);
                }
        }
-       else {
-               printf("ndof: 3Dx driver not found\n");
-               // This isn't a hard error, just means the user doesn't have a 3D mouse.
-       }
 }
 
 GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa()
 {
-       if (GHOST_NDOFManager3Dconnexion_available())
-       {
-               GHOST_NDOFManager3Dconnexion_UnregisterConnexionClient(m_clientID);
-               GHOST_NDOFManager3Dconnexion_UnregisterConnexionClient(m_clientID);
+       if (driver_loaded) {
+               UnregisterConnexionClient(clientID);
+               CleanupConnexionHandlers();
 
-               GHOST_NDOFManager3Dconnexion_CleanupConnexionHandlers();
                ghost_system = NULL;
                ndof_manager = NULL;
        }
 }
+
+bool GHOST_NDOFManagerCocoa::available()
+{
+       return driver_loaded;
+}
+
 #endif // WITH_INPUT_NDOF
index a3c48ff..cd61e37 100644 (file)
@@ -50,9 +50,9 @@
 #include "GHOST_TimerTask.h"
 #include "GHOST_WindowManager.h"
 #include "GHOST_WindowCocoa.h"
+
 #ifdef WITH_INPUT_NDOF
-#include "GHOST_NDOFManagerCocoa.h"
-#include "GHOST_NDOFManager3Dconnexion.h"
+  #include "GHOST_NDOFManagerCocoa.h"
 #endif
 
 #include "AssertMacros.h"