|
SMI RED eye tracking plugin 1.0
|
00001 00002 /* 00003 ----------------------------------------------------------------------------- 00004 This source file is part of OpenSpace3D 00005 For the latest info, see http://www.openspace3d.com 00006 00007 Copyright (c) 2010 I-maginer 00008 00009 This program is free software; you can redistribute it and/or modify it under 00010 the terms of the GNU Lesser General Public License as published by the Free Software 00011 Foundation; either version 2 of the License, or (at your option) any later 00012 version. 00013 00014 This program is distributed in the hope that it will be useful, but WITHOUT 00015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00016 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00017 00018 You should have received a copy of the GNU Lesser General Public License along with 00019 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00020 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00021 http://www.gnu.org/copyleft/lesser.txt 00022 00023 You may alternatively use this source under the terms of a specific version of 00024 the OpenSpace3D Unrestricted License provided you have obtained such a license from 00025 I-maginer. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 00029 /* 00030 SMI RED eye tracking system library based on iView X SDK 00031 First version : june 2011 00032 Author : Aymeric Suteau 00033 */ 00034 00049 // Include Header File 00050 #include "Plugin.h" 00051 00053 cbmachine ww; 00054 HWND HScol = NULL; 00055 00057 int OBJSMISCOL; 00058 00060 //===== CB Connected === 00061 int SCOL_SMI_CONNECTED_CB = 0; 00062 int SMI_CONNECTED_CB; 00063 00064 //===== CB Disconnected === 00065 int SCOL_SMI_DISCONNECTED_CB = 1; 00066 int SMI_DISCONNECTED_CB; 00067 00068 //===== CB Calibration done === 00069 int SCOL_SMI_CALIBRATION_DONE_CB = 2; 00070 int SMI_CALIBRATION_DONE_CB; 00071 00072 //===== CB New fixation data === 00073 int SCOL_SMI_NEW_FIXATION_CB = 3; 00074 int SMI_NEW_FIXATION_CB; 00075 00076 //===== CB New sample data === 00077 int SCOL_SMI_NEW_SAMPLE_CB = 4; 00078 int SMI_NEW_SAMPLE_CB; 00079 00080 00094 00095 int destroySmiObj(mmachine m, int handsys, int eyeTrackingTab) 00096 { 00097 // Read the first element of a TAB element (table of objects) 00098 EyeTracking* EyeTrackingObj = (EyeTracking*) MMfetch(m, MTOP(eyeTrackingTab), 0); 00099 00100 // Safely dispose of "EyeTrackingObj" pointer 00101 SAFE_DELETE(EyeTrackingObj); 00102 00103 // Write the first element of a TAB element 00104 MMstore(m, MTOP(eyeTrackingTab), 0, 0); 00105 00106 // Display debug message 00107 MMechostr(0, "EyeTrackingObj destroyed.\n"); 00108 return 0; 00109 } 00110 00111 00124 int _OpenSmiDevice(mmachine m) 00125 { 00126 #ifdef _SCOL_DEBUG_ 00127 MMechostr(0,"_OpenSmiDevice\n"); 00128 #endif 00129 00130 // Declare local variables 00131 int k = 0; 00132 00133 // Retrieve stack parameters : [S I S I] 00134 // NOTE: The first parameter to pull from the stack is the last one to have been pushed 00135 int iReceiverPort = MMpull(m); 00136 int iReceiverIp = MMpull(m); 00137 int iSenderPort = MMpull(m); 00138 int iSenderIp = MMpull(m); 00139 00140 // Convert sender IP from magma to char* 00141 char* senderIp = (char*) MMstartstr(m, MTOP(iSenderIp)); 00142 00143 // Convert sender port from Magma to Integer 00144 int senderPort = 4444; 00145 if (iSenderPort != NIL) 00146 senderPort = MTOI(iSenderPort); 00147 00148 // Convert receiver IP from magma to char* 00149 char* receiverIp = (char*) MMstartstr(m, MTOP(iReceiverIp)); 00150 00151 // Convert receiver port from Magma to Integer 00152 int receiverPort = 5555; 00153 if (iReceiverPort != NIL) 00154 receiverPort = MTOI(iReceiverPort); 00155 00156 // Create EyeTracking instance 00157 EyeTracking* eyeTracking = new EyeTracking(); 00158 MMechostr(0, "_OpenSmiDevice ...new SMI RED EyeTracking instance created !\n"); 00159 00160 // TODO: Open remote EyeTracking system 00161 if (!eyeTracking->Connect(senderIp, senderPort, receiverIp, receiverPort)) 00162 { 00163 MMechostr(0, "_OpenSmiDevice ...initialization failed\n"); 00164 SAFE_DELETE(eyeTracking); 00165 MMset(m, 0, NIL); 00166 return 0; 00167 } 00168 00169 // Allocate a block in the stack for a table of EyeTracking objects 00170 int eyeTrackingTab = MMmalloc(m, 1, TYPETAB); 00171 if (eyeTrackingTab == NIL) 00172 { 00173 MMechostr(0, "_OpenSmiDevice ...MMmalloc failed\n"); 00174 SAFE_DELETE(eyeTracking); 00175 MMset(m, 0, NIL); 00176 return MERRMEM; 00177 } 00178 MMechostr(0, "_OpenSmiDevice ...MMmalloc successful\n"); 00179 00180 // Push the TAB EyeTracking object into the stack 00181 MMstore(m, eyeTrackingTab, 0, (int)eyeTracking); 00182 MMpush(m, PTOM(eyeTrackingTab)); 00183 00184 // Create a new SMI RED EyeTracking object 00185 k = OBJcreate(m, OBJSMISCOL, (int)eyeTracking, NULL, NULL); 00186 MMechostr(0, "_OpenSmiDevice ...object creation successful\n"); 00187 00188 #ifdef _SCOL_DEBUG_ 00189 MMechostr(0,"ok\n"); 00190 #endif 00191 00192 // Return EyeTracking object 00193 return k; 00194 } 00195 00196 00205 int _CloseSmiDevice(mmachine m) 00206 { 00207 #ifdef _SCOL_DEBUG_ 00208 MMechostr(0,"_CloseSmiDevice\n"); 00209 #endif 00210 00211 // Get the table of EyeTracking objects into the stack (without pulling it) 00212 int eyeTrackingTab = MMget(m, 0); 00213 MMechostr(0, "_CloseSmiDevice\n"); 00214 if (eyeTrackingTab == NIL) 00215 { 00216 MMechostr(0, "_CloseSmiDevice ...ObjSmi NIL\n"); 00217 MMset(m, 0, NIL); 00218 return 0; 00219 } 00220 00221 // Destroy EyeTracking object according to its type and magma object 00222 OBJdelTM(m, OBJSMISCOL, eyeTrackingTab); 00223 00224 // Reinitialize the stack 00225 MMset(m, 0, ITOM(0)); 00226 00227 #ifdef _SCOL_DEBUG_ 00228 MMechostr(0,"ok\n"); 00229 #endif 00230 00231 return 0; 00232 } 00233 00234 00246 int _CBSmiConnected(mmachine m) 00247 { 00248 MMechostr(0, "_CBSmiConnected ...adding reflex\n"); 00249 return OBJaddreflex(m, OBJSMISCOL, SCOL_SMI_CONNECTED_CB); 00250 } 00251 00252 int getSmiConnectedCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret) 00253 { 00254 int k = 0; 00255 EyeTracking* EyeTrackingObj = (EyeTracking*) id; 00256 00257 // OBJbeginreflex(mmachine, objecttype, objectptr, cbtype) 00258 if (OBJbeginreflex(m, OBJSMISCOL, (int)EyeTrackingObj, SCOL_SMI_CONNECTED_CB)) 00259 { 00260 MMechostr(0, "getSmiConnectedCb -> OBJbeginreflex failed.\n"); 00261 return 0; 00262 } 00263 return (OBJcallreflex(m, 0)); 00264 } 00265 00266 00278 int _CBSmiDisconnected(mmachine m) 00279 { 00280 MMechostr(0, "_CBSmiDisconnected ...adding reflex\n"); 00281 return OBJaddreflex(m, OBJSMISCOL, SCOL_SMI_DISCONNECTED_CB); 00282 } 00283 00284 int getSmiDisconnectedCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret) 00285 { 00286 int k = 0; 00287 EyeTracking* EyeTrackingObj = (EyeTracking*) id; 00288 00289 // OBJbeginreflex(mmachine, objecttype, objectptr, cbtype) 00290 if (OBJbeginreflex(m, OBJSMISCOL, (int)EyeTrackingObj, SCOL_SMI_DISCONNECTED_CB)) 00291 { 00292 MMechostr(0, "getSmiDisconnectedCb -> OBJbeginreflex failed.\n"); 00293 return 0; 00294 } 00295 return (OBJcallreflex(m, 0)); 00296 } 00297 00298 00310 int _CBSmiCalibrationDone(mmachine m) 00311 { 00312 MMechostr(0, "_CBSmiCalibrationDone ...adding reflex\n"); 00313 return OBJaddreflex(m, OBJSMISCOL, SCOL_SMI_CALIBRATION_DONE_CB); 00314 } 00315 00316 int getSmiCalibrationDoneCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret) 00317 { 00318 int k = 0; 00319 EyeTracking* EyeTrackingObj = (EyeTracking*) id; 00320 00321 // OBJbeginreflex(mmachine, objecttype, objectptr, cbtype) 00322 if (OBJbeginreflex(m, OBJSMISCOL, (int)EyeTrackingObj, SCOL_SMI_CALIBRATION_DONE_CB)) 00323 { 00324 MMechostr(0, "getSmiCalibrationDoneCb -> OBJbeginreflex failed.\n"); 00325 return 0; 00326 } 00327 return (OBJcallreflex(m, 0)); 00328 } 00329 00330 00342 int _CBSmiNewFixation(mmachine m) 00343 { 00344 MMechostr(0, "_CBSmiNewFixation ...adding reflex\n"); 00345 return OBJaddreflex(m, OBJSMISCOL, SCOL_SMI_NEW_FIXATION_CB); 00346 } 00347 00348 int getSmiNewFixationCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret) 00349 { 00350 int k = 0; 00351 FixationData* FixationDataObj = (FixationData*) param; 00352 EyeTracking* EyeTrackingObj = (EyeTracking*) id; 00353 float fDuration = FixationDataObj->duration; 00354 int iPosX = FixationDataObj->posX; 00355 int iPosY = FixationDataObj->posY; 00356 00357 // OBJbeginreflex(mmachine, objecttype, objectptr, cbtype) 00358 if (OBJbeginreflex(m, OBJSMISCOL, (int)EyeTrackingObj, SCOL_SMI_NEW_FIXATION_CB)) 00359 { 00360 MMechostr(0, "getSmiNewFixationCb -> OBJbeginreflex failed.\n"); 00361 return 0; 00362 } 00363 00364 // Push fixation data into the stack 00365 MMpush(m, FTOM(fDuration)); 00366 MMpush(m, ITOM(iPosX)); 00367 MMpush(m, ITOM(iPosY)); 00368 return (OBJcallreflex(m, 3)); 00369 } 00370 00371 00383 int _CBSmiNewSample(mmachine m) 00384 { 00385 MMechostr(0, "_CBSmiNewSample ...adding reflex\n"); 00386 return OBJaddreflex(m, OBJSMISCOL, SCOL_SMI_NEW_SAMPLE_CB); 00387 } 00388 00389 int getSmiNewSampleCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int *ret) 00390 { 00391 int k = 0; 00392 SampleData* SampleDataObj = (SampleData*) param; 00393 EyeTracking* EyeTrackingObj = (EyeTracking*) id; 00394 float fLeftDiam = SampleDataObj->leftPupilDiameter; 00395 float fRightDiam = SampleDataObj->rightPupilDiameter; 00396 int iLeftGazeX = SampleDataObj->leftGazeX; 00397 int iRightGazeX = SampleDataObj->rightGazeX; 00398 int iLeftGazeY = SampleDataObj->leftGazeY; 00399 int iRightGazeY = SampleDataObj->rightGazeY; 00400 00401 // OBJbeginreflex(mmachine, objecttype, objectptr, cbtype) 00402 if (OBJbeginreflex(m, OBJSMISCOL, (int)EyeTrackingObj, SCOL_SMI_NEW_FIXATION_CB)) 00403 { 00404 MMechostr(0, "getSmiNewFixationCb -> OBJbeginreflex failed.\n"); 00405 return 0; 00406 } 00407 00408 // Push sample data into the stack 00409 int tupleLeftEye = MMmalloc(m, 3, TYPETAB); 00410 if (tupleLeftEye == NIL) 00411 { 00412 MMset(m, 0, NIL); 00413 return MERRMEM; 00414 } 00415 MMstore(m, tupleLeftEye, 0, FTOM(fLeftDiam)); 00416 MMstore(m, tupleLeftEye, 1, ITOM(iLeftGazeX)); 00417 MMstore(m, tupleLeftEye, 2, ITOM(iLeftGazeY)); 00418 MMpush(m, PTOM(tupleLeftEye)); 00419 00420 int tupleRightEye = MMmalloc(m, 3, TYPETAB); 00421 if (tupleRightEye == NIL) 00422 { 00423 MMset(m, 0, NIL); 00424 return MERRMEM; 00425 } 00426 MMstore(m, tupleRightEye, 0, FTOM(fRightDiam)); 00427 MMstore(m, tupleRightEye, 1, ITOM(iRightGazeX)); 00428 MMstore(m, tupleRightEye, 2, ITOM(iRightGazeY)); 00429 MMpush(m, PTOM(tupleRightEye)); 00430 00431 return (OBJcallreflex(m, 2)); 00432 } 00433 00434 00452 int _StartCalibration(mmachine m) 00453 { 00454 #ifdef _SCOL_DEBUG_ 00455 MMechostr(0,"_StartCalibration\n"); 00456 #endif 00457 00458 // Retrieve stack parameters : [I I I I I I I I] 00459 // NOTE: The first parameter to pull from the stack is the last one to have been pushed 00460 int iTargetSize = MMpull(m); 00461 int iTargetShape = MMpull(m); 00462 int iBackgroundBrightness = MMpull(m); 00463 int iForegroundBrightness = MMpull(m); 00464 int iSpeed = MMpull(m); 00465 int iDisplayDevice = MMpull(m); 00466 int iValidation = MMpull(m); 00467 int iNbPoints = MMpull(m); 00468 00469 // Convert all stack parameters from Magma to Integer 00470 int nbPoints = 5; 00471 if (iNbPoints != NIL) 00472 nbPoints = MTOI(iNbPoints); 00473 00474 int validation = 1; 00475 if (iValidation != NIL) 00476 validation = MTOI(iValidation); 00477 00478 int displayDevice = 0; 00479 if (iDisplayDevice != NIL) 00480 displayDevice = MTOI(iDisplayDevice); 00481 00482 int speed = 0; 00483 if (iSpeed != NIL) 00484 speed = MTOI(iSpeed); 00485 00486 int foregroundBrightness = 20; 00487 if (iForegroundBrightness != NIL) 00488 foregroundBrightness = MTOI(iForegroundBrightness); 00489 00490 int backgroundBrightness = 239; 00491 if (iBackgroundBrightness != NIL) 00492 backgroundBrightness = MTOI(iBackgroundBrightness); 00493 00494 int targetShape = 1; 00495 if (iTargetShape != NIL) 00496 targetShape = MTOI(iTargetShape) + 1; 00497 00498 int targetSize = 10; 00499 if (iTargetSize != NIL) 00500 targetSize = MTOI(iTargetSize); 00501 00502 // Get the table of glove objects into the stack (without pulling it) 00503 int smiTab = MMget(m, 0); 00504 MMechostr(0, "_StartCalibration\n"); 00505 if (smiTab == NIL) 00506 { 00507 MMechostr(0, "_StartCalibration ...ObjSmi NIL\n"); 00508 MMset(m, 0, -1); 00509 return 0; 00510 } 00511 00512 // Read the first element of a TAB element (table of objects) 00513 EyeTracking* SmiObj = (EyeTracking*) MMfetch(m, MTOP(smiTab), 0); 00514 if (SmiObj == NULL) 00515 { 00516 // Write the first element in the stack, without pulling it 00517 MMset(m, 0, NIL); 00518 return 0; 00519 } 00520 00521 // Set up the calibration for SMI RED system 00522 SmiObj->SetCalibration(nbPoints, // 5-point calibration method 00523 1, // Visualization by SDK 00524 displayDevice, // Primary device for display 00525 speed, // Low validation speed 00526 1, // Point auto-acceptance 00527 foregroundBrightness, // Target brightness 00528 backgroundBrightness, // Background brightness 00529 targetShape, // Calibration target shape = CIRCLE1 00530 targetSize, // Default target size is 10 pixels 00531 "../resource/cursor1.bmp"); // Target shape filename 00532 00533 // Start the calibration process 00534 SmiObj->Calibrate(validation); 00535 00536 MMset(m, 0, ITOM(0)); 00537 00538 #ifdef _SCOL_DEBUG_ 00539 MMechostr(0,"ok\n"); 00540 #endif 00541 00542 return 0; 00543 } 00544 00545 00555 int _ShowEyes(mmachine m) 00556 { 00557 #ifdef _SCOL_DEBUG_ 00558 MMechostr(0,"_ShowEyes\n"); 00559 #endif 00560 00561 // Retrieve stack parameter 00562 int iShowEyes = MMpull(m); 00563 00564 // Convert stack parameter from Magma to Integer 00565 int showEyes = 1; 00566 if (iShowEyes != NIL) 00567 showEyes = MTOI(iShowEyes); 00568 00569 // Get the table of glove objects into the stack (without pulling it) 00570 int smiTab = MMget(m, 0); 00571 MMechostr(0, "_ShowEyes\n"); 00572 if (smiTab == NIL) 00573 { 00574 MMechostr(0, "_ShowEyes ...ObjSmi NIL\n"); 00575 MMset(m, 0, -1); 00576 return 0; 00577 } 00578 00579 EyeTracking* SmiObj = (EyeTracking*) MMfetch(m, MTOP(smiTab), 0); 00580 if (SmiObj == NULL) 00581 { 00582 // Write the first element in the stack, without pulling it 00583 MMset(m, 0, NIL); 00584 return 0; 00585 } 00586 00587 // Check if eye tracking window must be displayed 00588 if (showEyes == 1) 00589 SmiObj->ShowTrackingWindow(); 00590 00591 MMset(m, 0, ITOM(0)); 00592 00593 #ifdef _SCOL_DEBUG_ 00594 MMechostr(0,"ok\n"); 00595 #endif 00596 00597 return 0; 00598 } 00599 00600 00608 00609 00611 #define NbTplPKG 10 00612 00613 00617 char *TplName[NbTplPKG] = 00618 { 00619 "ObjSmi", 00620 "_OpenSmiDevice", 00621 "_CloseSmiDevice", 00622 "_CBSmiConnected", 00623 "_CBSmiDisconnected", 00624 "_CBSmiCalibrationDone", 00625 "_CBSmiNewFixation", 00626 "_CBSmiNewSample", 00627 "_StartCalibration", 00628 "_ShowEyes" 00629 }; 00630 00631 00635 int (*TplFunc[NbTplPKG])(mmachine m)= 00636 { 00637 NULL, // ObjSmi 00638 _OpenSmiDevice, // _OpenSmiDevice 00639 _CloseSmiDevice, // _CloseSmiDevice 00640 _CBSmiConnected, // _CBSmiConnected 00641 _CBSmiDisconnected, // _CBSmiDisconnected 00642 _CBSmiCalibrationDone, // _CBSmiCalibrationDone 00643 _CBSmiNewFixation, // _CBSmiNewFixation 00644 _CBSmiNewSample, // _CBSmiNewSample 00645 _StartCalibration, // _StartCalibration 00646 _ShowEyes // _ShowEyes 00647 }; 00648 00649 00653 int TplNArg[NbTplPKG]= 00654 { 00655 TYPTYPE, // ObjSmi 00656 5, // _OpenSmiDevice 00657 1, // _CloseSmiDevice 00658 3, // _CBSmiConnected 00659 3, // _CBSmiDisconnected 00660 3, // _CBSmiCalibrationDone 00661 3, // _CBSmiNewFixation 00662 3, // _CBSmiNewSample 00663 9, // _StartCalibration 00664 2 // _ShowEyes 00665 }; 00666 00667 00671 char* TplType[NbTplPKG]= 00672 { 00673 NULL, // ObjSmi 00674 "fun [Chn S I S I] ObjSmi", // _OpenSmiDevice 00675 "fun [ObjSmi] I", // _CloseSmiDevice 00676 "fun [ObjSmi fun [ObjSmi u0] u1 u0] ObjSmi", // _CBSmiConnected 00677 "fun [ObjSmi fun [ObjSmi u0] u1 u0] ObjSmi", // _CBSmiDisconnected 00678 "fun [ObjSmi fun [ObjSmi u0] u1 u0] ObjSmi", // _CBSmiCalibrationDone 00679 "fun [ObjSmi fun [ObjSmi u0 F I I] u1 u0] ObjSmi", // _CBSmiNewFixation 00680 "fun [ObjSmi fun [ObjSmi u0 [F I I] [F I I]] u1 u0] ObjSmi", // _CBSmiNewSample 00681 "fun [ObjSmi I I I I I I I I] I", // _StartCalibration 00682 "fun [ObjSmi I] I" // _ShowEyes 00683 }; 00684 00685 00693 // Everything inside _cond and _endcond is ignored by doxygen 00695 00700 int LoadSmi(mmachine m) 00701 { 00702 // Return variable for PKhardpak function 00703 int k; 00704 00705 // Declare a new type of object ("OBJSMISCOL") 00706 OBJSMISCOL = OBJregister(5, 1, destroySmiObj, "OBJSMISCOL"); 00707 00708 // Get new user events and associate these events with a callback 00709 SMI_CONNECTED_CB = OBJgetUserEvent(); 00710 OBJdefEvent(SMI_CONNECTED_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getSmiConnectedCb); 00711 00712 SMI_CALIBRATION_DONE_CB = OBJgetUserEvent(); 00713 OBJdefEvent(SMI_CALIBRATION_DONE_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getSmiCalibrationDoneCb); 00714 00715 SMI_DISCONNECTED_CB = OBJgetUserEvent(); 00716 OBJdefEvent(SMI_DISCONNECTED_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getSmiDisconnectedCb); 00717 00718 SMI_NEW_FIXATION_CB = OBJgetUserEvent(); 00719 OBJdefEvent(SMI_NEW_FIXATION_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getSmiNewFixationCb); 00720 00721 SMI_NEW_SAMPLE_CB = OBJgetUserEvent(); 00722 OBJdefEvent(SMI_NEW_SAMPLE_CB, (int (__cdecl *)(struct Mmachine *, int, unsigned int, int, int, int *))getSmiNewSampleCb); 00723 00724 // Load package 00725 k = PKhardpak(m, "FusionEngine", NbTplPKG, TplName, TplFunc, TplNArg, TplType); 00726 return k; 00727 } 00729 00730 00734 extern "C" __declspec (dllexport) int ScolLoadPlugin(mmachine m, cbmachine w) 00735 { 00736 SCOLinitplugin(w); 00737 00738 // Get Scol window handle (for message callback) 00739 HScol = (HWND)SCgetExtra("hscol"); 00740 LoadSmi(m); 00741 return 0; 00742 } 00743 00744 00748 extern "C" __declspec (dllexport) int ScolUnloadPlugin() 00749 { 00750 return 0; 00751 }
1.7.3