This is example 17. This example demonstrates the following:
-
Processing online saccade events
This example is based on
example 10. This example adds an
onSaccadeEvent()
event handler function to print saccade start and end
events.
Source code
Source file: example17.c
Initialization
In the eyevec_create_thread()
function in the initialization part we provide
a saccade event callback function.
int main(void)
{
.
.
EyeVecResult err = eyevec_create_thread(eyevec,
onModeChange,
NULL, // onDisplayData,
NULL, // onEyeData,
NULL, // onBlinkEvent,
onSaccadeEvent, (1)
NULL, // onFixationEvent,
NULL, // onTestItemEvent,
&clientdata);
printError("eyevec_create_thread()", err);
if (err) return EXIT_FAILURE;
.
.
1 | Callback function for saccade start and end events. |
processInput()
See processInput() in example 16.
onSaccadeEvent()
In the onSaccadeEvent()
event handler function we call onSaccadeStart()
or onSaccadeEnd()
depending on the flag
parameter provided to the
onSaccadeEvent()
function.
static int onSaccadeEvent(const EyeVec* eyevec, int64_t eventtime,
const EyeVecSaccadeEventData* saccadedata, int flag, void* cldata)
{
const ClientData* clientdata = (const ClientData*)cldata;
if (clientdata == NULL) return 0;
if (flag == 0)
return onSaccadeStart(eyevec, eventtime, saccadedata, clientdata); (1)
return onSaccadeEnd(eyevec, eventtime, saccadedata, clientdata); (2)
}
1 | Call onSaccadeStart() with provided saccade data. |
2 | Call onSaccadeEnd() with provided saccade data. |
onSaccadeStart()
This function prints the relevant EyeVecSaccadeEventData attributes defined for the saccade start event.
static int onSaccadeStart(const EyeVec* eyevec, int64_t eventtime,
const EyeVecSaccadeEventData* saccadedata, const ClientData* clientdata)
{
(void)eyevec;
if (clientdata->showgazeevents) {
printf("onSaccadeStart:\n");
printf(" eventtime: %" PRId64 "\n",
eventtime);
printf(" side: %s\n",
side_string(saccadedata->side));
printf(" starttime: %" PRId64 "\n",
saccadedata->starttime);
printf(" gaze_start: %.3f, %.3f\n",
(double)saccadedata->gaze_start.x,
(double)saccadedata->gaze_start.y);
printf(" pupil_start: %.3f\n",
(double)saccadedata->pupil_start);
}
return 0;
}
onSaccadeEnd()
This function prints the relevant EyeVecSaccadeEventData attributes defined for the saccade end event.
static int onSaccadeEnd(const EyeVec* eyevec, int64_t eventtime,
const EyeVecSaccadeEventData* saccadedata, const ClientData* clientdata)
{
(void)eyevec;
if (clientdata->showgazeevents) {
printf("onSaccadeEnd:\n");
printf(" eventtime: %" PRId64 "\n",
eventtime);
printf(" side: %s\n",
side_string(saccadedata->side));
printf(" starttime: %" PRId64 "\n",
saccadedata->starttime);
if (saccadedata->endtime >= 0) {
printf(" duration: %d\n",
(int)(saccadedata->endtime - saccadedata->starttime));
}
printf(" gaze_end: %.3f, %.3f\n",
(double)saccadedata->gaze_end.x,
(double)saccadedata->gaze_end.y);
printf(" pupil_end: %.3f\n",
(double)saccadedata->pupil_end);
printf(" gaze_avg: %.3f, %.3f\n",
(double)saccadedata->gaze_avg.x,
(double)saccadedata->gaze_avg.y);
printf(" pupil_avg: %.3f\n",
(double)saccadedata->pupil_avg);
}
return 0;
}
Running
After a succesful build run the program:
-
Press
o
to calleyevec_open()
. Eye-tracker should go from off mode to idle mode. -
Press
z
to calleyevec_enter_data_mode()
. Eye-tracker should go from idle mode to data mode. Note, we’re skipping setup and calibration here; still make sure the eye-tracker can see your eyes. -
Press
g
to calleyevec_set_gaze_event_enabled(0, EYEVEC_ENABLE_SEND_WHILE_IN_RECORDING_MODE)
. -
Press
r
to calleyevec_start_recording()
. Eye-tracker should go from data mode to recording mode. Saccade events should be printed. -
Press
r
to calleyevec_stop_recording()
. Eye-tracker should go from recording mode to data mode. No more saccade events will be printed. -
Press
q
to quit.
Output might look like this (empty lines added for clarity):
eyevec_create_thread(): OK
eyevec_initialize(): OK
Type q to quit, ? for help.
[o]
onModeChange:
eventtime: 1750691913324342
oldmode: TRACKER_MODE_OFF
newmode: TRACKER_MODE_IDLE
eyevec_open(): OK
[z]
onModeChange:
eventtime: 1750691914693985
oldmode: TRACKER_MODE_IDLE
newmode: TRACKER_MODE_DATA
eyevec_enter_data_mode(): OK
[g]
eyevec_set_gaze_event_enabled(0, 0x1): OK
[r]
onModeChange:
eventtime: 1750691946585808
oldmode: TRACKER_MODE_DATA
newmode: TRACKER_MODE_RECORDING
eyevec_start_recording(): OK
onSaccadeStart:
eventtime: 1750691946818243
side: LEFT
starttime: 1750691946818243
gaze_start: 0.354, 0.472
pupil_start: 4.269
onSaccadeStart:
eventtime: 1750691946820244
side: RIGHT
starttime: 1750691946820244
gaze_start: 0.348, 0.465
pupil_start: 4.065
onSaccadeStart:
eventtime: 1750691946820244
side: MEAN
starttime: 1750691946820244
gaze_start: 0.348, 0.471
pupil_start: 4.176
onSaccadeEnd:
eventtime: 1750691946894257
side: LEFT
starttime: 1750691946818243
duration: 76014
gaze_end: 0.067, 0.904
pupil_end: 4.253
gaze_avg: 0.147, 0.754
pupil_avg: 4.281
onSaccadeEnd:
eventtime: 1750691946894257
side: MEAN
starttime: 1750691946820244
duration: 74013
gaze_end: 0.076, 0.917
pupil_end: 4.170
gaze_avg: 0.145, 0.769
pupil_avg: 4.193
onSaccadeEnd:
eventtime: 1750691946908260
side: RIGHT
starttime: 1750691946820244
duration: 88016
gaze_end: 0.079, 0.927
pupil_end: 4.057
gaze_avg: 0.138, 0.800
pupil_avg: 4.097
.
.
.
[q]
eyevec_cleanup(): OK
eyevec_destroy_thread(): OK