/*
-----------------------------------------------------------------------------
This source file is part of OpenSpace3D
For the latest info, see http://www.openspace3d.com

Copyright (c) 2010 I-maginer

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt

You may alternatively use this source under the terms of a specific version of
the OpenSpace3D Unrestricted License provided you have obtained such a license from
I-maginer.
-----------------------------------------------------------------------------
*/

/*
 X10 CM11 domotic library
 First version : may 2011
 Author : Bastien Bourineau
 X10 API from http://nick.stefanisko.net/x10/
*/

/*! @defgroup grpx10 Scol functions definition
 *  Scol functions definition
 *  @{
 */
/** @} */

#include "plugin.h"
#include "x10device.h"

cbmachine ww;

HWND HScol; //Scol window Handle

//OBJECT
int OBJX10SCOL;
int OBJX10SCOL_NB_CB = 6;

//===== CB UNIT ON ===
int SCOL_UNIT_ON_CB = 0;
int UNIT_ON_CB;

//===== CB UNIT OFF ===
int SCOL_UNIT_OFF_CB = 1;
int UNIT_OFF_CB;

//===== CB UNIT DIM ===
int SCOL_UNIT_DIM_CB = 2;
int UNIT_DIM_CB;

//===== CB UNIT BRIGHT ===
int SCOL_UNIT_BRIGHT_CB = 3;
int UNIT_BRIGHT_CB;

//===== CB ALL OFF ===
int SCOL_ALL_OFF_CB = 4;
int ALL_OFF_CB;

//===== CB ALL LIGHTS ON ===
int SCOL_ALL_LIGHTS_ON_CB = 5;
int ALL_LIGHTS_ON_CB;


/*! \mainpage X10 CM11 Scol Plugin
 *
 * \section intro_sec Introduction
 * This plugin allow Scol Virtual Machine to use X10 CM11 device
 * 
*/


//!Scol CallBack for ObjX10 destruction
int destroyX10Obj(mmachine m, int handsys, int objtab) 
{
	X10Device* X10DeviceObj = (X10Device *) MMfetch(m, MTOP(objtab), 0);
	SAFE_DELETE(X10DeviceObj);
	MMstore(m, MTOP(objtab), 0, 0);

	return 0;
}


/*! @ingroup grpx10
* \brief _CRx10Device : This function create a new X10 connection Object
*
* <b>Prototype:</b> fun [Chn I] ObjX10
* \param Chn : the current channel
* \param I : device com port
*
* \return ObjX10 : The X10 Object, NIL on connection fail
*/
int _CRx10Device(mmachine m)
{
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_CRx10Device\n");
	#endif

	int port = MMpull(m);
  if ((port == NIL) || (MTOI(port) <= 0))
  { 
		MMset(m, 0, NIL);
		return 0;
	}

	//Create X10 connection
	X10Device* newX10Device = new X10Device(MTOI(port));
	if (newX10Device == 0)
	{
    MMechostr(MSKDEBUG, "_CRX10Device : Connection fail on %i\n", MTOI(port));
		MMset(m, 0, NIL);
    return 0;
	}

  if (newX10Device->IsConnected() == false)
	{
    MMechostr(MSKDEBUG, "_CRX10Device : Connection fail on %i\n", MTOI(port));
		MMset(m, 0, NIL);
    return 0;
	}

	int objtab = MMmalloc(m, 1, TYPETAB);
	if (objtab == NIL)
	{
		SAFE_DELETE(newX10Device); 
		MMset(m, 0, NIL);
	}

	MMstore(m, objtab, 0, (int)newX10Device);
	MMpush(m, PTOM(objtab));

	int k = OBJcreate(m, OBJX10SCOL, (int)newX10Device, NIL, NIL);

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif

	return k;
}


/*! @ingroup grpx10
* \brief _DSx10Device : This function destroy a X10 device Object
*
* <b>Prototype:</b> fun [ObjX10] I
* \param ObjX10 : the current X10 device
*
* \return I : 0 if success, NIL otherwise
*/
int _DSx10Device(mmachine m) 
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_DSx10Device\n");
#endif

	int objtab = MMget(m, 0);
	if (objtab == NIL)
  {
    MMechostr(MSKDEBUG, "_DSx10Device : ObjX10 NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

  OBJdelTM(m, OBJX10SCOL, objtab);
	MMset(m, 0, ITOM(0));

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpx10
* \brief _X10allUnitOff : This function send the AllUnitOff command
*
* <b>Prototype:</b> fun [ObjX10 S] I
* \param ObjX10 : the current X10 device
* \param S : House code
*
* \return I : 0 if success, NIL otherwise
*/
int _X10allUnitOff(mmachine m) 
{	
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_X10allUnitOff\n");
	#endif

	int houseCode = MMpull(m);
	int objtab = MMget(m, 0);
	if ((objtab == NIL) || (houseCode == NIL) || (MMsizestr(m, MTOP(houseCode)) > 1))
  {
		MMset(m, 0, NIL);
		return 0;
	}

  char* sHouseCode = MMstartstr(m, MTOP(houseCode));

	X10Device* X10DeviceObj = (X10Device*)MMfetch(m, MTOP(objtab), 0);
  if (X10DeviceObj == 0)
  {
    MMset(m, 0, NIL);
		return 0;
  }
  
  X10DeviceObj->AllOff(sHouseCode[0]);
  
  MMset(m, 0, ITOM(0));

#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif
		return 0;
}


/*! @ingroup grpx10
* \brief _X10allLightsOn : This function send the AllLightsOn command
*
* <b>Prototype:</b> fun [ObjX10 S] I
* \param ObjX10 : the current X10 device
* \param S : House code
*
* \return I : 0 if success, NIL otherwise
*/
int _X10allLightsOn(mmachine m) 
{	
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_X10allLightsOn\n");
	#endif

	int houseCode = MMpull(m);
	int objtab = MMget(m, 0);
	if ((objtab == NIL) || (houseCode == NIL) || (MMsizestr(m, MTOP(houseCode)) > 1))
  {
		MMset(m, 0, NIL);
		return 0;
	}

  char* sHouseCode = MMstartstr(m, MTOP(houseCode));

	X10Device* X10DeviceObj = (X10Device*)MMfetch(m, MTOP(objtab), 0);

  if (X10DeviceObj == 0)
  {
    MMset(m, 0, NIL);
		return 0;
  }
  
  X10DeviceObj->AllLightsOn(sHouseCode[0]);
  
  MMset(m, 0, ITOM(0));

#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif
		return 0;
}


/*! @ingroup grpx10
* \brief _X10unitOn : This function send the On command on an X10 unit
*
* <b>Prototype:</b> fun [ObjX10 S I] I
* \param ObjX10 : the current X10 device
* \param S : House code
* \param I : Unit code
*
* \return I : 0 if success, NIL otherwise
*/
int _X10unitOn(mmachine m) 
{
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_X10unitOn\n");
	#endif

	int unitCode = MMpull(m);
  int houseCode = MMpull(m);
	int objtab = MMget(m, 0);
	if ((objtab == NIL) || (houseCode == NIL) || (unitCode == NIL) || (MMsizestr(m, MTOP(houseCode)) > 1))
  {
		MMset(m, 0, NIL);
		return 0;
	}

  char* sHouseCode = MMstartstr(m, MTOP(houseCode));

	X10Device* X10DeviceObj = (X10Device*)MMfetch(m, MTOP(objtab), 0);

  if (X10DeviceObj == 0)
  {
    MMset(m, 0, NIL);
		return 0;
  }
  
  X10DeviceObj->On(sHouseCode[0], MTOI(unitCode));

  MMset(m, 0, ITOM(0));

#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif
		return 0;
}


/*! @ingroup grpx10
* \brief _X10unitOff : This function send the Off command on an X10 unit
*
* <b>Prototype:</b> fun [ObjX10 S I] I
* \param ObjX10 : the current X10 device
* \param S : House code
* \param I : Unit code
*
* \return I : 0 if success, NIL otherwise
*/
int _X10unitOff(mmachine m) 
{
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_X10unitOff\n");
	#endif

	int unitCode = MMpull(m);
  int houseCode = MMpull(m);
	int objtab = MMget(m, 0);
	if ((objtab == NIL) || (houseCode == NIL) || (unitCode == NIL) || (MMsizestr(m, MTOP(houseCode)) > 1))
  {
		MMset(m, 0, NIL);
		return 0;
	}

  char* sHouseCode = MMstartstr(m, MTOP(houseCode));

	X10Device* X10DeviceObj = (X10Device*)MMfetch(m, MTOP(objtab), 0);

  if (X10DeviceObj == 0)
  {
    MMset(m, 0, NIL);
		return 0;
  }
  
  X10DeviceObj->Off(sHouseCode[0], MTOI(unitCode));

  MMset(m, 0, ITOM(0));

#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif
		return 0;
}


/*! @ingroup grpx10
* \brief _X10unitDim : This function send the Dim command on an X10 unit
*
* <b>Prototype:</b> fun [ObjX10 S I] I
* \param ObjX10 : the current X10 device
* \param S : House code
* \param I : Unit code
* \param I : dim value 0 to 100
*
* \return I : 0 if success, NIL otherwise
*/
int _X10unitDim(mmachine m) 
{
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_X10unitDim\n");
	#endif

  int value = MMpull(m);
	int unitCode = MMpull(m);
  int houseCode = MMpull(m);
	int objtab = MMget(m, 0);
	if ((objtab == NIL) || (houseCode == NIL) || (unitCode == NIL) || (value == NIL) || (MMsizestr(m, MTOP(houseCode)) > 1))
  {
		MMset(m, 0, NIL);
		return 0;
	}

  char* sHouseCode = MMstartstr(m, MTOP(houseCode));

	X10Device* X10DeviceObj = (X10Device*)MMfetch(m, MTOP(objtab), 0);

  if (X10DeviceObj == 0)
  {
    MMset(m, 0, NIL);
		return 0;
  }
  
  X10DeviceObj->Dim(sHouseCode[0], MTOI(unitCode), MTOI(value)/100*22);

  MMset(m, 0, ITOM(0));

#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif
		return 0;
}


/*! @ingroup grpx10
* \brief _X10unitBright : This function send the Bright command on an X10 unit
*
* <b>Prototype:</b> fun [ObjX10 S I] I
* \param ObjX10 : the current X10 device
* \param S : House code
* \param I : Unit code
* \param I : dim value 0 to 100
*
* \return I : 0 if success, NIL otherwise
*/
int _X10unitBright(mmachine m) 
{
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_X10unitBright\n");
	#endif

  int value = MMpull(m);
	int unitCode = MMpull(m);
  int houseCode = MMpull(m);
	int objtab = MMget(m, 0);
	if ((objtab == NIL) || (houseCode == NIL) || (unitCode == NIL) || (value == NIL) || (MMsizestr(m, MTOP(houseCode)) > 1))
  {
		MMset(m, 0, NIL);
		return 0;
	}

  char* sHouseCode = MMstartstr(m, MTOP(houseCode));

	X10Device* X10DeviceObj = (X10Device*)MMfetch(m, MTOP(objtab), 0);

  if (X10DeviceObj == 0)
  {
    MMset(m, 0, NIL);
		return 0;
  }
  
  X10DeviceObj->Bright(sHouseCode[0], MTOI(unitCode), MTOI(value)/100*22);

  MMset(m, 0, ITOM(0));

#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif
		return 0;
}


/*! @ingroup grpx10
* \brief _CBx10UnitOn : This function set the Callback for Unit On event
*
* <b>Prototype:</b> fun [ObjX10 fun [ObjX10 u0 S I] u1 u0] ObjX10
* \param ObjX10 : the current ObjX10
* \param fun [ObjX10 u0 S I] u1 : SCOL CallBack function to call
* \param u0 : user parameter
* \param S : House code
* \param I : Unit code
* \param u1 : user callback return type
*
* \return ObjX10 : same X10 object if success, NIL otherwise
*/
int _CBx10UnitOn(mmachine m)
{
  return OBJaddreflex(m, OBJX10SCOL, SCOL_UNIT_ON_CB);
}

int getUnitOnCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
	int k = 0;
	X10Device* X10DeviceObj = (X10Device*)id;
  X10Command* command = (X10Command*)param;

  if (X10DeviceObj == 0)
  {
    delete(command);
    return 0;
  }

	// OBJbeginreflex(mmachine, objecttype, objectptr, cbtype)
	if (OBJbeginreflex(m, OBJX10SCOL, (int)X10DeviceObj, SCOL_UNIT_ON_CB))
  {
    delete(command);
    return 0;
  }

  char house[2];
  house[0] = command->HouseCode();
  house[1] = '\0';

  Mpushstrbloc(m, house);
  MMpush(m, ITOM(command->UnitCode()));

	k=OBJcallreflex(m, 2);
  delete(command);
	return k;
}


/*! @ingroup grpx10
* \brief _CBx10UnitOff : This function set the Callback for Unit Off event
*
* <b>Prototype:</b> fun [ObjX10 fun [ObjX10 u0 S I] u1 u0] ObjX10
* \param ObjX10 : the current ObjX10
* \param fun [ObjX10 u0 S I] u1 : SCOL CallBack function to call
* \param u0 : user parameter
* \param S : House code
* \param I : Unit code
* \param u1 : user callback return type
*
* \return ObjX10 : same X10 object if success, NIL otherwise
*/
int _CBx10UnitOff(mmachine m)
{
  return OBJaddreflex(m, OBJX10SCOL, SCOL_UNIT_OFF_CB);
}

int getUnitOffCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
	int k = 0;
	X10Device* X10DeviceObj = (X10Device*)id;
  X10Command* command = (X10Command*)param;

  if (X10DeviceObj == 0)
  {
    delete(command);
    return 0;
  }

	// OBJbeginreflex(mmachine, objecttype, objectptr, cbtype)
	if (OBJbeginreflex(m, OBJX10SCOL, (int)X10DeviceObj, SCOL_UNIT_OFF_CB))
  {
    delete(command);
    return 0;
  }

  char house[2];
  house[0] = command->HouseCode();
  house[1] = '\0';

  Mpushstrbloc(m, house);
  MMpush(m, ITOM(command->UnitCode()));

	k=OBJcallreflex(m, 2);
  delete(command);
	return k;
}


/*! @ingroup grpx10
* \brief _CBx10UnitDim : This function set the Callback for Unit Dim event
*
* <b>Prototype:</b> fun [ObjX10 fun [ObjX10 u0 S I] u1 u0] ObjX10
* \param ObjX10 : the current ObjX10
* \param fun [ObjX10 u0 S I I] u1 : SCOL CallBack function to call
* \param u0 : user parameter
* \param S : House code
* \param I : Unit code
* \param I : Dim value
* \param u1 : user callback return type
*
* \return ObjX10 : same X10 object if success, NIL otherwise
*/
int _CBx10UnitDim(mmachine m)
{
  return OBJaddreflex(m, OBJX10SCOL, SCOL_UNIT_DIM_CB);
}

int getUnitDimCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
	int k = 0;
	X10Device* X10DeviceObj = (X10Device*)id;
  X10Command* command = (X10Command*)param;

  if (X10DeviceObj == 0)
  {
    delete(command);
    return 0;
  }

	// OBJbeginreflex(mmachine, objecttype, objectptr, cbtype)
	if (OBJbeginreflex(m, OBJX10SCOL, (int)X10DeviceObj, SCOL_UNIT_DIM_CB))
  {
    delete(command);
    return 0;
  }

  char house[2];
  house[0] = command->HouseCode();
  house[1] = '\0';

  Mpushstrbloc(m, house);
  MMpush(m, ITOM(command->UnitCode()));
  MMpush(m, ITOM(command->Value()*(100/22)));

	k=OBJcallreflex(m, 3);
  delete(command);
	return k;
}


/*! @ingroup grpx10
* \brief _CBx10UnitBright : This function set the Callback for Unit Bright event
*
* <b>Prototype:</b> fun [ObjX10 fun [ObjX10 u0 S I] u1 u0] ObjX10
* \param ObjX10 : the current ObjX10
* \param fun [ObjX10 u0 S I I] u1 : SCOL CallBack function to call
* \param u0 : user parameter
* \param S : House code
* \param I : Unit code
* \param I : Bright value
* \param u1 : user callback return type
*
* \return ObjX10 : same X10 object if success, NIL otherwise
*/
int _CBx10UnitBright(mmachine m)
{
  return OBJaddreflex(m, OBJX10SCOL, SCOL_UNIT_BRIGHT_CB);
}

int getUnitBrightCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
	int k = 0;
	X10Device* X10DeviceObj = (X10Device*)id;
  X10Command* command = (X10Command*)param;

  if (X10DeviceObj == 0)
  {
    delete(command);
    return 0;
  }

	// OBJbeginreflex(mmachine, objecttype, objectptr, cbtype)
	if (OBJbeginreflex(m, OBJX10SCOL, (int)X10DeviceObj, SCOL_UNIT_BRIGHT_CB))
  {
    delete(command);
    return 0;
  }

  char house[2];
  house[0] = command->HouseCode();
  house[1] = '\0';

  Mpushstrbloc(m, house);
  MMpush(m, ITOM(command->UnitCode()));
  MMpush(m, ITOM(command->Value()*(100/22)));

	k=OBJcallreflex(m, 3);
  delete(command);
	return k;
}


/*! @ingroup grpx10
* \brief _CBx10AllUnitsOff : This function set the Callback for All Unit Off event
*
* <b>Prototype:</b> fun [ObjX10 fun [ObjX10 u0 S I] u1 u0] ObjX10
* \param ObjX10 : the current ObjX10
* \param fun [ObjX10 u0 S] u1 : SCOL CallBack function to call
* \param u0 : user parameter
* \param S : House code
* \param u1 : user callback return type
*
* \return ObjX10 : same X10 object if success, NIL otherwise
*/
int _CBx10AllUnitsOff(mmachine m)
{
  return OBJaddreflex(m, OBJX10SCOL, SCOL_ALL_OFF_CB);
}

int getAllOffCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
	int k = 0;
	X10Device* X10DeviceObj = (X10Device*)id;
  X10Command* command = (X10Command*)param;

  if (X10DeviceObj == 0)
  {
    delete(command);
    return 0;
  }

	// OBJbeginreflex(mmachine, objecttype, objectptr, cbtype)
	if (OBJbeginreflex(m, OBJX10SCOL, (int)X10DeviceObj, SCOL_ALL_OFF_CB))
  {
    delete(command);
    return 0;
  }

  char house[2];
  house[0] = command->HouseCode();
  house[1] = '\0';

  Mpushstrbloc(m, house);

	k=OBJcallreflex(m, 1);
  delete(command);
	return k;
}


/*! @ingroup grpx10
* \brief _CBx10AllLightsOn : This function set the Callback for All Lights On event
*
* <b>Prototype:</b> fun [ObjX10 fun [ObjX10 u0 S I] u1 u0] ObjX10
* \param ObjX10 : the current ObjX10
* \param fun [ObjX10 u0 S] u1 : SCOL CallBack function to call
* \param u0 : user parameter
* \param S : House code
* \param u1 : user callback return type
*
* \return ObjX10 : same X10 object if success, NIL otherwise
*/
int _CBx10AllLightsOn(mmachine m)
{
  return OBJaddreflex(m, OBJX10SCOL, SCOL_ALL_LIGHTS_ON_CB);
}

int getAllLightsOnCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
	int k = 0;
	X10Device* X10DeviceObj = (X10Device*)id;
  X10Command* command = (X10Command*)param;

  if (X10DeviceObj == 0)
  {
    delete(command);
    return 0;
  }

	// OBJbeginreflex(mmachine, objecttype, objectptr, cbtype)
	if (OBJbeginreflex(m, OBJX10SCOL, (int)X10DeviceObj, SCOL_ALL_LIGHTS_ON_CB))
  {
    delete(command);
    return 0;
  }

  char house[2];
  house[0] = command->HouseCode();
  house[1] = '\0';

  Mpushstrbloc(m, house);

	k=OBJcallreflex(m, 1);
  delete(command);
	return k;
}


//! Nb of Scol functions or types
#define NbTplPKG 15


/*!
*	Scol function names
*/
char	*TplName[NbTplPKG] =
{
	"ObjX10",
	"_CRx10Device",
	"_DSx10Device",
  "_X10allUnitOff",
  "_X10allLightsOn",
  "_X10unitOff",
  "_X10unitOn",
  "_X10unitDim",
  "_X10unitBright",
  "_CBx10AllUnitsOff",
  "_CBx10AllLightsOn",
  "_CBx10UnitOff",
  "_CBx10UnitOn",
  "_CBx10UnitDim",
  "_CBx10UnitBright"
};


/*!
*	Pointers to C functions that manipulate the VM for each scol function previously defined
*/
int (*TplFunc[NbTplPKG])(mmachine m)=
{
  NULL,
	_CRx10Device,
	_DSx10Device,
  _X10allUnitOff,
  _X10allLightsOn,
  _X10unitOff,
  _X10unitOn,
  _X10unitDim,
  _X10unitBright,
  _CBx10AllUnitsOff,
  _CBx10AllLightsOn,
  _CBx10UnitOff,
  _CBx10UnitOn,
  _CBx10UnitDim,
  _CBx10UnitBright
};


/*!
*	Nb of arguments of each scol function
*/
int TplNArg[NbTplPKG]=
{
  TYPTYPE,	            // ObjX10
	2,										// _CRx10Device
	1,									  // _DSx10Device
  2,                    // _X10allUnitOff
  2,                    // _X10allLightsOn
  3,                    // _X10unitOff
  3,                    // _X10unitOn
  4,                    // _X10unitDim
  4,                    // _X10unitBright
  3,                    // _CBx10AllUnitsOff
  3,                    // _CBx10AllLightsOn
  3,                    // _CBx10UnitOff
  3,                    // _CBx10UnitOn
  3,                    // _CBx10UnitDim
  3                     // _CBx10UnitBright
};


/*!
*	Prototypes of the scol functions
*/
char* TplType[NbTplPKG]=
{
	NULL,																											// ObjX10
	"fun [Chn I] ObjX10",																			// _CRx10Device
	"fun [ObjX10] I",																					// _DSx10Device
  "fun [ObjX10 S] I",                                       // _X10allUnitOff
  "fun [ObjX10 S] I",                                       // _X10allLightsOn
  "fun [ObjX10 S I] I",                                     // _X10unitOff
  "fun [ObjX10 S I] I",                                     // _X10unitOn
  "fun [ObjX10 S I I] I",                                   // _X10unitDim
  "fun [ObjX10 S I I] I",                                   // _X10unitBright
  "fun [ObjX10 fun [ObjX10 u0 S] u1 u0] ObjX10",            // _CBx10AllUnitsOff
  "fun [ObjX10 fun [ObjX10 u0 S] u1 u0] ObjX10",            // _CBx10AllLightsOn
  "fun [ObjX10 fun [ObjX10 u0 S I] u1 u0] ObjX10",          // _CBx10UnitOff
  "fun [ObjX10 fun [ObjX10 u0 S I] u1 u0] ObjX10",          // _CBx10UnitOn
  "fun [ObjX10 fun [ObjX10 u0 S I I] u1 u0] ObjX10",        // _CBx10UnitDim
  "fun [ObjX10 fun [ObjX10 u0 S I I] u1 u0] ObjX10"         // _CBx10UnitBright
};


// Everything inside _cond and _endcond is ignored by doxygen
//! \cond

/*!
* \brief Load the packages in Scol virtual machine
* \param mmachine : the scol machine
*/
int LoadX10Plugin(mmachine m)
{
	int			k;
  HScol = (HWND)SCgetExtra("hscol") ;

  // Scol type declaration
	OBJX10SCOL = OBJregister(OBJX10SCOL_NB_CB, 1, destroyX10Obj, "OBJX10SCOL");


	//******************************    Callbacks for X10 device    *******************************************************
    
  //===== CB UNIT ON ===
  UNIT_ON_CB = OBJgetUserEvent();
  OBJdefEvent(UNIT_ON_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getUnitOnCb);

  //===== CB UNIT OFF ===
  UNIT_OFF_CB = OBJgetUserEvent();
  OBJdefEvent(UNIT_OFF_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getUnitOffCb);

  //===== CB UNIT DIM ===
  UNIT_DIM_CB = OBJgetUserEvent();
  OBJdefEvent(UNIT_DIM_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getUnitDimCb);

  //===== CB UNIT BRIGHT ===
  UNIT_BRIGHT_CB = OBJgetUserEvent();
  OBJdefEvent(UNIT_BRIGHT_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getUnitBrightCb);

  //===== CB ALL OFF ===
  ALL_OFF_CB = OBJgetUserEvent();
  OBJdefEvent(ALL_OFF_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getAllOffCb);

  //===== CB ALL LIGHTS ON ===
  ALL_LIGHTS_ON_CB = OBJgetUserEvent();
  OBJdefEvent(ALL_LIGHTS_ON_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getAllLightsOnCb);

	k = PKhardpak(m, "X10DeviceEngine", NbTplPKG, TplName, TplFunc, TplNArg, TplType);

	return k;
}


//! \endcond


/*! 
* \brief Starting point of the DLL
*/
extern "C" __declspec (dllexport) int ScolLoadPlugin(mmachine m, cbmachine w)
{
	SCOLinitplugin(w);
	LoadX10Plugin(m);
	return 0;
}


/*! 
* \brief Ending point of the DLL
*/
extern "C" __declspec (dllexport) int ScolUnloadPlugin()
{
  return 0;
}