ThinkGear API Mac OS X example
/**
* This program serves as a simple example of how one can use ThinkGear.bundle inside their Core Foundation
* (e.g. Cocoa and Carbon-based) apps. For more details on OS X bundles, read:
* http://developer.apple.com/DOCUMENTATION/CoreFoundation/Conceptual/CFBundles/CFBundles.html
*
* Or check the "How to use the ThinkGear API in Xcode (Mac OS X)" document in the ThinkGear documentation.
*
* Note: When executing the program, make sure ThinkGear.bundle is in the same current directory.
*/
#include <CoreFoundation/CoreFoundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
/**
* Baud rate for use with TG_Connect() and TG_SetBaudrate().
*/
#define TG_BAUD_1200 1200
#define TG_BAUD_2400 2400
#define TG_BAUD_4800 4800
#define TG_BAUD_9600 9600
#define TG_BAUD_57600 57600
#define TG_BAUD_115200 115200
/**
* Data format for use with TG_Connect() and TG_SetDataFormat().
*/
#define TG_STREAM_PACKETS 0
#define TG_STREAM_5VRAW 1
#define TG_STREAM_FILE_PACKETS 2
/**
* Data type that can be requested from TG_GetValue().
*/
#define TG_DATA_BATTERY 0
#define TG_DATA_POOR_SIGNAL 1
#define TG_DATA_ATTENTION 2
#define TG_DATA_MEDITATION 3
#define TG_DATA_RAW 4
#define TG_DATA_DELTA 5
#define TG_DATA_THETA 6
#define TG_DATA_ALPHA1 7
#define TG_DATA_ALPHA2 8
#define TG_DATA_BETA1 9
#define TG_DATA_BETA2 10
#define TG_DATA_GAMMA1 11
#define TG_DATA_GAMMA2 12
CFURLRef bundleURL; // path reference to bundle
CFBundleRef thinkGearBundle; // bundle reference
int connectionID = -1; // ThinkGear connection handle
/*
* ThinkGear function pointers
*/
int (*TG_GetDriverVersion)() = NULL;
int (*TG_GetNewConnectionId)() = NULL;
int (*TG_Connect)(int, const char *, int, int) = NULL;
int (*TG_ReadPackets)(int, int) = NULL;
float (*TG_GetValue)(int, int) = NULL;
int (*TG_Disconnect)(int) = NULL;
void (*TG_FreeConnection)(int) = NULL;
/**
* This function handles signal interrupts.
*
* Basically perform cleanup on the objects and then exit the program.
*/
void siginthandler(int sig){
fprintf(stderr, "\nDisconnecting...\n");
// close the connection
if(connectionID != -1){
TG_Disconnect(connectionID);
TG_FreeConnection(connectionID);
}
// release the bundle references
if(bundleURL)
CFRelease(bundleURL);
if(thinkGearBundle)
CFRelease(thinkGearBundle);
exit(1);
}
/**
* The main driver for this program.
*
* Handle command-line arguments, initialize the ThinkGear connection,
* and handle output.
*/
int main (int argc, const char * argv[]) {
// register the signal interrupt handler
signal(SIGINT, siginthandler);
// cmd line argument checking
if(argc < 2){
fprintf(stderr, "Usage: %s portname\n", argv[0]);
exit(1);
}
const char * portname = argv[1]; // port name
int retVal = -1; // return values from TG functions
int numPackets = 0; // number of packets returned from ReadPackets
float signalQuality = 0.0; // poor signal status
float attention = 0.0; // eSense attention
float meditation = 0.0; // eSense meditation
// create the path reference to the bundle
bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
CFSTR("ThinkGear.bundle"),
kCFURLPOSIXPathStyle,
true);
// create the bundle reference
thinkGearBundle = CFBundleCreate(kCFAllocatorDefault, bundleURL);
// make sure the bundle actually exists
if(!thinkGearBundle){
fprintf(stderr, "Error: Could not find ThinkGear.bundle. Does it exist in the current directory?\n");
exit(1);
}
// now start setting the function pointers
TG_GetDriverVersion = (void *)CFBundleGetFunctionPointerForName(thinkGearBundle, CFSTR("TG_GetDriverVersion"));
TG_GetNewConnectionId = (void *)CFBundleGetFunctionPointerForName(thinkGearBundle, CFSTR("TG_GetNewConnectionId"));
TG_Connect = (void *)CFBundleGetFunctionPointerForName(thinkGearBundle, CFSTR("TG_Connect"));
TG_ReadPackets = (void *)CFBundleGetFunctionPointerForName(thinkGearBundle, CFSTR("TG_ReadPackets"));
TG_GetValue = (void *)CFBundleGetFunctionPointerForName(thinkGearBundle, CFSTR("TG_GetValue"));
TG_Disconnect = (void *)CFBundleGetFunctionPointerForName(thinkGearBundle, CFSTR("TG_Disconnect"));
TG_FreeConnection = (void *)CFBundleGetFunctionPointerForName(thinkGearBundle, CFSTR("TG_FreeConnection"));
// check for any invalid function pointers
if(!TG_GetDriverVersion || !TG_GetNewConnectionId || !TG_Connect || !TG_ReadPackets ||
!TG_GetValue || !TG_Disconnect || !TG_FreeConnection){
fprintf(stderr, "Error: Expected functions in ThinkGear.bundle were not found. Are you using the right version?\n");
exit(1);
}
// get the connection ID
connectionID = TG_GetNewConnectionId();
fprintf(stderr, "Connecting to %s ... ", portname);
// attempt to connect
retVal = TG_Connect(connectionID, portname, TG_BAUD_9600, TG_STREAM_PACKETS);
// check whether the connection attempt was successful
if(!retVal){
fprintf(stderr, "connected.\n");
// loop until we get the interrupt signal from the console. control
// then gets passed onto the signal handler function
while(1){
// sleep for half a second
usleep(500000);
// read the packets from the output stream
numPackets = TG_ReadPackets(connectionID, -1);
// check whether we've received any new packets
if(numPackets > 0){
// if so, parse them
signalQuality = TG_GetValue(connectionID, TG_DATA_POOR_SIGNAL);
attention = TG_GetValue(connectionID, TG_DATA_ATTENTION);
meditation = TG_GetValue(connectionID, TG_DATA_MEDITATION);
// then output everything
fprintf(stdout, "\rPoorSig: %3.0f, Att: %3.0f, Med: %3.0f", signalQuality, attention, meditation);
fflush(stdout);
}
}
}
else {
fprintf(stderr, "unable to connect. (%d)\n", retVal);
exit(1);
}
return 0;
}