Developing using the OS X driver

Questions and answers about the SpaceNavigator 3D Mouse on Mac OS X

Moderator: Moderators

Developing using the OS X driver

Postby stew » Wed Jan 10, 2007 7:31 am

I noticed that the OS X driver beta comes with a few headers in /System/Library/3DconnexionClient.framework that look very inviting. Is there any documentation or a OS X beta SDK available?

One thing I tried out with the beta drivers is a C program like this:
Code: Select all
void AddedDevice(io_connect_t connection)
{
   printf("added device\n");
}
void RemovedDevice(io_connect_t connection)
{
   printf("removed device\n");
}
void HandleMessage(io_connect_t connection, natural_t messageType, void *messageArgument)
{
   printf("received message\n");
   return;
}

int main(int argc, char *argv[])
{
   OSErr err = InstallConnexionHandlers (HandleMessage, AddedDevice, RemovedDevice);
   UInt32 signature = kConnexionClientWildcard;
   UInt8 *name = "";
   UInt16 mode = kConnexionClientModePlugin;
   UInt32 mask = kConnexionMaskAll;
   UInt16 myID = RegisterConnexionClient(signature, name, mode, mask);
   CFRunLoopRun();
   UnregisterConnexionClient(myID);
   CleanupConnexionHandlers();
   return 0;
}


This code gives me correct messages when I plug or unplug my SpaceNavigator, but I was unable to read any axis information from it. The only time HandleMessage gets called is when I press a button that has been assigned in the prefs panel.

Any hints on how I can get access to the axis data?
stew
 
Posts: 10
Joined: Wed Dec 20, 2006 9:34 am

Postby flomotan » Wed Jan 10, 2007 10:41 am

It's good to see the developer community taking an interest in this :).

The SDK is not officially released and is subject to change without notice. It may not even exist when the final driver is released. In other words, you're on your own here. Having given the mandatory disclaimer, here's how you can get axis data:

Call RegisterConnexionClient with mode = kConnexionClientModeTakeOver and mask = kConnexionMaskAxis.

In your message handler, process the incoming message using code similar to this.

Code: Select all
static void
messageHandlerProc(io_connect_t connection, natural_t messageType, void *messageArgument)
{
   ConnexionDeviceStatePtr msg;

   msg = (ConnexionDeviceStatePtr)messageArgument;
   
   switch(messageType)
   {
      case kConnexionMsgDeviceState:
         /* Device state messages are broadcast to all clients.  It is up to
          * the client to figure out if the message is meant for them. This
          * is done by comparing the "client" id sent in the message to our
          * assigned id when the connection to the driver was established.
          *
          */
         switch (msg->command)
         {
            case kConnexionCmdHandleAxis:
               // msg->axis[0] .. [5] contain X, Y, Z, Rx, Ry, Rz data                           
               break;
                   
                       
            case kConnexionCmdHandleButtons:
               // msg->value is the button state
               // msg->buttons is the button ID
               break;                  
         }
         break;

      default:
         // other messageTypes can happen and should be ignored
         break;
   }
}
flomotan
Moderator
Moderator
 
Posts: 287
Joined: Mon Jan 08, 2007 3:37 pm

Postby stew » Wed Jan 10, 2007 5:04 pm

Thanks a lot!
stew
 
Posts: 10
Joined: Wed Dec 20, 2006 9:34 am

trying to develop with Cocoa

Postby wave » Tue Jan 16, 2007 10:30 am

Thanks for the info about talking to the device. One nit - on my system, the framework got installed in /Library/Frameworks/, not /System/Library/Frameworks - I assume that's correct?

Also, like the other poster, my add and remove device procs get called, but I don't get anything sent to the handle message one - I twist the Navigator, press buttons, etc - nothing.

Any ideas?

In my case, I'm developing with Objective-C/Cocoa, and have a simple app with a class that looks like this:

#import <Cocoa>
#import <3DconnexionClient>


@interface MyController : NSObject
{
UInt16 _myID;
}
@end


#import "MyController.h"

@implementation MyController

static void
HandleMessage(io_connect_t connection, natural_t messageType, void *messageArgument) {

ConnexionDeviceStatePtr msg = (ConnexionDeviceStatePtr)messageArgument;

switch(messageType) {
case kConnexionMsgDeviceState:
/* Device state messages are broadcast to all clients. It is up to
* the client to figure out if the message is meant for them. This
* is done by comparing the "client" id sent in the message to our
* assigned id when the connection to the driver was established.
*
*/
switch (msg->command)
{
case kConnexionCmdHandleAxis:
// msg->axis[0] .. [5] contain X, Y, Z, Rx, Ry, Rz data
{
SInt16 x = msg->axis[0];
SInt16 y = msg->axis[1];
SInt16 z = msg->axis[2];
SInt16 Rx = msg->axis[3];
SInt16 Ry = msg->axis[4];
SInt16 Rz = msg->axis[5];

NSLog(@"x, y, z == (%hi, %hi, %hi) Rx, Ry, Rz == (%hi, %hi, %hi)", x, y, z, Rx, Ry, Rz);
}
break;


case kConnexionCmdHandleButtons:
// msg->value is the button state
// msg->buttons is the button ID
{
SInt32 buttonState = msg->value;
UInt16 buttonID = msg->buttons;
NSLog(@"button %hu pressed - value is %d", buttonID, buttonState);
}
break;
}
break;

default:
// other messageTypes can happen and should be ignored
break;
}
}

static void
AddedDevice(io_connect_t connection) {
NSLog(@"added device %p", connection);
}

static void
RemovedDevice(io_connect_t connection) {
NSLog(@"removed device %p", connection);
}


- (void)awakeFromNib {
OSErr err = InstallConnexionHandlers(HandleMessage, AddedDevice, RemovedDevice);
if (err == noErr) {
UInt32 signature = kConnexionClientWildcard;
UInt16 mode = kConnexionClientModePlugin;
UInt32 mask = kConnexionMaskAll;
_myID = RegisterConnexionClient(signature, NULL, mode, mask);
NSLog(@"installed handlers for 3Dconnexion Space Navigator and registed client : %hi", _myID);

} else {
NSLog(@"problem installing handlers for 3Dconnexion Space Navigator : %d", err);
}
}

- (void)dealloc {
if (_myID) {
UnregisterConnexionClient(_myID);
CleanupConnexionHandlers();
}
[super dealloc];
}

@end
wave
 
Posts: 2
Joined: Tue Jan 16, 2007 10:25 am

Postby flomotan » Tue Jan 16, 2007 3:08 pm

/Library/Frameworks is the recommended place for 3rd party frameworks.

Call RegisterConnexionClient with mode = kConnexionClientModeTakeOver and mask = kConnexionMaskAxis. This should resolve your issue.

Also, as much as possible, do not use kConnexionClientWildcard as the signature. Instead, provide the 32bit signature you have assigned for your application. This will allow you create specific settings for your application in our preference pane. Just use "Add Application..." to add your app.
flomotan
Moderator
Moderator
 
Posts: 287
Joined: Mon Jan 08, 2007 3:37 pm

Postby wave » Fri Jan 19, 2007 10:18 am

Thanks.

We had figured out the kConnexionClientModeTakeOver but the other info is very useful.

Especially the Wildcard one - I was wondering why my app was getting called when I rotated the device in SketchUp :-)

We're doing great now. My one nit is that when I install the freshly downloaded driver on a machine, it asks to check for a newer one, and says that 0.1.0 is available, which is newer than 0.1 (or vice versa). If I let it get it, it takes to the same download page.

I appreciate the check, but the logic currently seems broken.
wave
 
Posts: 2
Joined: Tue Jan 16, 2007 10:25 am

Postby flomotan » Tue Jan 23, 2007 12:25 pm

Glad to hear you're up and running.

Thanks for pointing out the issue with version check. It's now fixed and will be part of our next release.
flomotan
Moderator
Moderator
 
Posts: 287
Joined: Mon Jan 08, 2007 3:37 pm

Postby GregVDS » Thu Feb 22, 2007 8:20 am

Where do I find the Mac Beta SDK please?

All the best,

GregVDS
All the best,

GregVDS
GregVDS
 
Posts: 18
Joined: Wed Feb 21, 2007 3:11 am
Location: Bruxelles

Simple code example

Postby JiriHnidek » Thu Mar 15, 2007 5:21 am

Hi,
this is my first post here. This is very simple c code (it only prints some debuging informations to stdout, but it can be very good begining and tutorial for any mac os x coder):

Code: Select all
#include <stdio.h>
#include <MacTypes.h>
#include <ConnexionClient.h>
#include <ConnexionClientAPI.h>

static void AddedDevice(io_connect_t connection)
{
   printf("added device\n");
}
static void RemovedDevice(io_connect_t connection)
{
   printf("removed device\n");
}
static void HandleMessage(io_connect_t connection, natural_t messageType, void *messageArgument)
{
   ConnexionDeviceStatePtr msg;

   msg = (ConnexionDeviceStatePtr)messageArgument;

   switch(messageType) {
      case kConnexionMsgDeviceState:
         switch (msg->command) {
            case kConnexionCmdHandleAxis:
               printf("%d, %d, %d, %d, %d, %d\n",
                     msg->axis[0], msg->axis[2], msg->axis[2],
                     msg->axis[3], msg->axis[4], msg->axis[5]);
               break;
            case kConnexionCmdHandleButtons:
               printf("msg->value: %d\n", msg->value);
               printf("msg->buttons: %d\n", msg->buttons);
               break;
         }
         break;
   }
}

int main(int argc, char *argv[])
{
   OSErr err = InstallConnexionHandlers (HandleMessage, AddedDevice, RemovedDevice);
   UInt32 signature = kConnexionClientWildcard;
   UInt8 *name = "";
   UInt16 mode = kConnexionClientModeTakeOver; /*kConnexionClientModePlugin;*/
   UInt32 mask = kConnexionMaskAxis; /*kConnexionMaskAll;*/
   UInt16 myID = RegisterConnexionClient(signature, name, mode, mask);
   CFRunLoopRun();
   UnregisterConnexionClient(myID);
   CleanupConnexionHandlers();
   return 0;
}


You will probably need Makefile too:

Code: Select all
CC=gcc
CFLAGS=-I /Library/Frameworks/3DconnexionClient.framework/Versions/Current/Headers/ -I /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers
LFLAGS=-framework 3DconnexionClient -framework Carbon

all: 3dconn

3dconn: 3dconn.o
        ${CC} -o 3dconn ${LFLAGS} 3dconn.o

3dconn.o: 3dconn.c
        ${CC} -c ${CFLAGS} -o 3dconn.o 3dconn.c

clean:
        rm -f *.o *~ 3dconn


I guess, that uou will need to remove white spaces with tabs in makefile.
JiriHnidek
 
Posts: 1
Joined: Thu Mar 15, 2007 5:06 am

Postby Snow123 » Fri Mar 28, 2008 1:24 am

This code gives me correct messages when I plug or unplug my SpaceNavigator, but I was unable to read any axis information from it. The only time HandleMessage gets called is when I press a button that has been assigned in the prefs panel.
Snow123
 
Posts: 3
Joined: Fri Mar 28, 2008 1:16 am

Postby flomotan » Fri Mar 28, 2008 8:44 am

An official SDK with documentation for OS X is available at http://www.3dconnexion.com/support/sdk.php
flomotan
Moderator
Moderator
 
Posts: 287
Joined: Mon Jan 08, 2007 3:37 pm


Return to Mac OS X Discussion Forum

Who is online

Users browsing this forum: No registered users and 1 guest