To connect to the Leap Motion device, create a LeapController object. The LeapController object automatically establishes a connection to the Leap Motion daemon or service which then passes tracking data, in the form of LeapFrame objects to your application.
LeapController *controller = [[LeapController alloc] init];
Use the LeapController object to get information about the state of the connection and connected hardware and to set connection options for your application.
Get LeapFrame objects containing tracking data by calling the LeapController.frame: function. You can call this function whenever your application is ready to process data to get the most recent set of data generated by the Leap Motion device. You can also implement a LeapListener object defining a callback function and the LeapController will invoke this function when a new frame of data is ready.
See Frames for more information.
Ordinarily, the Leap Motion service/daemon only sends tracking data to the application that has the operating system input focus. This prevents applications idling in the background from receiving input intended for another applications.
If your application runs in the foreground and you want to know whether the service/daemon considers your application to be the foreground application, you can check LeapController.hasFocus or listen to events dispatched by the controller. The service/daemon gets changes in application focus status directly from the operating system. Note that the Linux operating system does not provide this information, so applications running on Linux always receive tracking data.
Note that applications connecting to the Leap Motion service/daemon through the WebSocket server do not automatically start receiving data when they gain the operating system focus. Applications using the WebSocket server must explicitly request focus from the service when they move to the foreground. (The LeapJS JavaScript library does manage the foreground-background transition for you, however.)
You can tell the controller that your application wants data even when it is in the background using LeapController.setPolicy:. Set the BACKGROUND_POLICY_FLAG policy for applications such as mouse emulators or operating system controls that need data when they are not the focused application. The Allow Background Apps setting in the Leap Motion control panel must be checked or the attempt to set the policy is denied.
Note that your application does not receive frames if another Leap-enabled application is in the foreground, even when the background frames policy is in effect. The policy only matters when a non-Leap-enabled app has the operating system input focus.
LeapPolicyFlag *current = controller.policyFlags;
In order for your application to receive images from the Leap Motion cameras, you must set the Images policy. The Allow Images setting in the Leap Motion control panel must be checked or the attempt to set the policy is denied. See Camera Images.
To use the built-in gestures, you must enable them first using LeapController.enableGesture:enable::
[controller enableGesture:LEAP_GESTURE_TYPE_SWIPE enable:true];
Enable only those gestures that your application uses.
When you create a LeapController, the object attempts to establish a connection to the Leap Motion service/daemon. If it succeeds, the |Controller.isServiceConnected|_ property changes to true. Likewise, if the Leap Motion hardware is plugged in and detected by the service/daemon, the LeapController.isConnected property changes to true.
The isServiceConnected and isConnected properties can change while your application is running. You can monitor their values or listen for events dispatched by the controller when the connection status changes.
The LeapController object dispatches a number of events using NSNotifications. To handle these events, you can us the LeapListener protocol. Alternately, you can use the |LeapDelegate|_ protocol and designate a single object as the event handler.
The events include:
|Listener_onConnect|_ | The LeapController connects to the Leap Motion service/daemon and the Leap Motion hardware is attached. |
|Listener_onDeviceChange|_ | The status of a Leap Motion hardware device changes. |
|Listener_onDisconnect|_ | The LeapController disconnects from the Leap Motion service/daemon or the Leap Motion hardware is removed. |
|Listener_onExit|_ | The LeapController object is destroyed. |
|Listener_onFocusGained|_ | The application has gained operating system input focus and will start receiving tracking data. |
|Listener_onFocusLost|_ | The application has lost operating system input focus. The application will stop receiving tracking data unless it has set the BACKGROUND_FRAMES_POLICY. |
|Listener_onFrame|_ | A new LeapFrame of tracking data is available. |
|Listener_onInit|_ | The LeapController object is initialized. |
|Listener_onServiceConnect|_ | The LeapController has connected to the Leap Motion service/daemon. |
|Listener_onServiceDisconnect|_ | The LeapController has lost its connection to the Leap Motion service/daemon. |
The following example shows how to implement an object that adopts the LeapListener protocol:
#import "LeapObjectiveC.h"
@interface LeapEventListener : NSObject<LeapListener>
@end
@implementation LeapEventListener
- (void)onInit:(NSNotification *)notification
{
NSLog(@"Initialized");
}
- (void)onConnect:(NSNotification *)notification
{
NSLog(@"Connected");
LeapController *aController = (LeapController *)[notification object];
[aController enableGesture:LEAP_GESTURE_TYPE_CIRCLE enable:YES];
[aController enableGesture:LEAP_GESTURE_TYPE_KEY_TAP enable:YES];
[aController enableGesture:LEAP_GESTURE_TYPE_SCREEN_TAP enable:YES];
[aController enableGesture:LEAP_GESTURE_TYPE_SWIPE enable:YES];
}
- (void)onDisconnect:(NSNotification *)notification
{
//Note: not dispatched when running in a debugger.
NSLog(@"Disconnected");
}
- (void)onFrame:(NSNotification *)notification
{
LeapController *aController = (LeapController *)[notification object];
LeapFrame *frame = [aController frame:0];
NSLog(@"Frame id: %lld, timestamp: %lld, hands: %ld, fingers: %ld, tools: %ld, gestures: %ld",
[frame id], [frame timestamp], [[frame hands] count],
[[frame fingers] count], [[frame tools] count], [[frame gestures:nil] count]);
}
@end
LeapController *controller = [[LeapController alloc] init];
LeapEventListener *listener = [[LeapEventListener alloc] init];
[controller addListener:listener];
Each event callback function is invoked on an independent thread created by the Leap Motion library. The tracking data objects created by the library are thread safe, but you must make sure that other application data accessed from the callback function can be safely altered from seprate threads. You can avoid the complications associated with multithreaded applications by polling the LeapController for frames and state when convenient for your application instead of using listeners.
There are currently three types of Leap Motion hardware available: the standard controller as a separate computer peripheral, a controller embedded in a computer keyboard, and a controller embedded in a laptop computer The performance of all of these devices is equivalent. However, be aware that the devices are very different physically. For example, devices embedded in laptops cannot be unplugged, but rather are activated or deactivated with keyboard shortcuts.
You can get the device type from LeapDevice.type. Use LeapController.devices to get the list of attached devices (currently only one device is recognized at a time).