SMI RED eye tracking plugin 1.0

src/Plugin.cpp

Go to the documentation of this file.
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 }