To get started with eye tracking in your application you must first grab the StreamEngine library, there are two ways of integrating the library in your application, depending on your use case and preferred programming language. If you are using Visual Studio and coding in C++/C# then the NuGet Package Manager in Visual Studio is your friend. Or if you prefer a makefile based building system you can download the archive containing the library and all necessary header files. Here we will have a detailed look at the two ways of integrating StreamEngine in your app.

Makefile project

For those that are using a makefile based build systems, there is an easy way to integrate StreamEngine into your application:

  • Download the StreamEngine zip archive, here, and extract it into your prereqs subfolder of your project. The subfolder should include a lib directory which contains the tobii_stream_engine.dll for x86 and x64 architecture and an include directory featuring all necessary header files.
  • Then you need to setup the library and include paths for StreamEngine.
    • Add a library search directory (i.e ${PREREQS}/tobii/lib/${ARCH})
    • Add include directory of header files (i.e ${PREREQS}/tobii/include)
  • Link your application with tobii_stream_engine dynamic library.

Now you are all set to start using StreamEngine in your application. Check out the super simple sample bellow or move on to our more advanced best practices samples and Api documentation.

Super simple C# .NET application


using System;
using System.Collections.Generic;
using System.Diagnostics;
using Tobii.StreamEngine;

namespace Tobii.StreamEngine.Sample
{
    public static class StreamSample
    {
        private static void OnGazePoint(ref tobii_gaze_point_t gazePoint, IntPtr userData) 
        {
            // Check that the data is valid before using it
            if(gazePoint.validity == tobii_validity_t.TOBII_VALIDITY_VALID) 
            {
                Console.WriteLine($"Gaze point: {gazePoint.position.x}, {gazePoint.position.y}");
            }
        }

        public static void Main()
        {
            // Create API context
            IntPtr apiContext;
            tobii_error_t result = Interop.tobii_api_create(out apiContext, null);
            Debug.Assert(result == tobii_error_t.TOBII_ERROR_NO_ERROR);

            // Enumerate devices to find connected eye trackers
            List urls;
            result = Interop.tobii_enumerate_local_device_urls(apiContext, out urls);
            Debug.Assert(result == tobii_error_t.TOBII_ERROR_NO_ERROR);
            if(urls.Count == 0)
            {
                Console.WriteLine("Error: No device found");
                return;
            }

            // Connect to the first tracker found
            IntPtr deviceContext;
            result = Interop.tobii_device_create(apiContext, urls[0], Interop.tobii_field_of_use_t.TOBII_FIELD_OF_USE_INTERACTIVE, out deviceContext);
            Debug.Assert(result == tobii_error_t.TOBII_ERROR_NO_ERROR);

            // Subscribe to gaze data
            result = Interop.tobii_gaze_point_subscribe(deviceContext, OnGazePoint);
            Debug.Assert(result == tobii_error_t.TOBII_ERROR_NO_ERROR);

            // This sample will collect 1000 gaze points
            for ( int i=0; i<1000; i++ )
            {
                // Optionally block this thread until data is available. Especially useful if running in a separate thread.
                Interop.tobii_wait_for_callbacks(new [] { deviceContext });
                Debug.Assert(result == tobii_error_t.TOBII_ERROR_NO_ERROR || result == tobii_error_t.TOBII_ERROR_TIMED_OUT);
                
                // Process callbacks on this thread if data is available
                Interop.tobii_device_process_callbacks(deviceContext);
                Debug.Assert(result == tobii_error_t.TOBII_ERROR_NO_ERROR);
            }

            // Cleanup
            result = Interop.tobii_gaze_point_unsubscribe(deviceContext);
            Debug.Assert(result == tobii_error_t.TOBII_ERROR_NO_ERROR);
            result = Interop.tobii_device_destroy(deviceContext);
            Debug.Assert(result == tobii_error_t.TOBII_ERROR_NO_ERROR);
            result = Interop.tobii_api_destroy(apiContext);
            Debug.Assert(result == tobii_error_t.TOBII_ERROR_NO_ERROR);
        }
    }
}

Super simple C++ Application


#include <tobii/tobii.h>
#include <tobii/tobii_streams.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>

void gaze_point_callback( tobii_gaze_point_t const* gaze_point, void* /* user_data */)
{
    // Check that the data is valid before using it
    if( gaze_point->validity == TOBII_VALIDITY_VALID )
        printf( "Gaze point: %f, %f\n",
            gaze_point->position_xy[ 0 ],
            gaze_point->position_xy[ 1 ] );
}

void url_receiver( char const* url, void* user_data )
{
    char* buffer = (char*)user_data;
    if( *buffer != '\0' ) return; // only keep first value

    if( strlen( url ) < 256 )
        strcpy( buffer, url );
}

int main()
{
    // Create API
    tobii_api_t* api = NULL;
    tobii_error_t result = tobii_api_create( &api, NULL, NULL );
    assert( result == TOBII_ERROR_NO_ERROR );

    // Enumerate devices to find connected eye trackers, keep the first
    char url[ 256 ] = { 0 };
    result = tobii_enumerate_local_device_urls( api, url_receiver, url );
    assert( result == TOBII_ERROR_NO_ERROR );
    if(*url == '\0')
    {
        printf("Error: No device found\n");
        return 1;
    }

    // Connect to the first tracker found
    tobii_device_t* device = NULL;
    result = tobii_device_create( api, url, TOBII_FIELD_OF_USE_INTERACTIVE, &device );
    assert( result == TOBII_ERROR_NO_ERROR );

    // Subscribe to gaze data
    result = tobii_gaze_point_subscribe( device, gaze_point_callback, 0 );
    assert( result == TOBII_ERROR_NO_ERROR );

    // This sample will collect 1000 gaze points
    for( int i=0; i<1000; i++ )
    {
        // Optionally block this thread until data is available. Especially useful if running in a separate thread.
        result = tobii_wait_for_callbacks( 1, &device );
        assert( result == TOBII_ERROR_NO_ERROR || result == TOBII_ERROR_TIMED_OUT );

        // Process callbacks on this thread if data is available
        result = tobii_device_process_callbacks( device );
        assert( result == TOBII_ERROR_NO_ERROR );
    }

    // Cleanup
    result = tobii_gaze_point_unsubscribe( device );
    assert( result == TOBII_ERROR_NO_ERROR );
    result = tobii_device_destroy( device );
    assert( result == TOBII_ERROR_NO_ERROR );
    result = tobii_api_destroy( api );
    assert( result == TOBII_ERROR_NO_ERROR );
    return 0;
}

Analytical Use

Tobii’s consumer eye trackers are primarily intended for personal interaction use and not for analytical purposes. Any application that stores or transfers eye tracking data must have a special license from Tobii.

Downloads for Linux and MacOS

Contact Tobii