/*
-----------------------------------------------------------------------------
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.
-----------------------------------------------------------------------------
*/


/*
 Speech SCOL API based on SAPI library from microsoft : http://msdn.microsoft.com/en-us/library/ms723627(VS.85).aspx
 First version : may 2010
 Author : Hamza HAMDI
*/


/*! \mainpage speech Scol Plugin
 *
 * \section intro_sec Introduction
 * This plugin allow Scol Virtual Machine to use Microsoft SAPI Library 
 * 
 */


/*! @defgroup grpstt Text to Speech
 *  Scol functions definition
 *  @{
 */
/** @} */


//!Main include
#include "pluginSpeechPrerequisites.h"
#include "speech.h"
#include "reco.h"

//! global scol declaration
cbmachine ww;
HWND HScol = NULL;		


//! global object declaration
int OBJSPEECHSCOL;
int OBJRECOSCOL;


//! global Callback declaration for text to speech
int SCOL_SPEECH_START_CB = 0;
int SPEECH_START_CB;

int SCOL_SPEECH_END_CB = 1;
int SPEECH_END_CB;

int SCOL_SPEECH_WORD_CB = 2;
int SPEECH_WORD_CB;

int SCOL_SPEECH_TEXT_CB = 3;
int SPEECH_TEXT_CB;

int SCOL_SPEECH_PHONEME_CB = 4;
int SPEECH_PHONEME_CB;

int SCOL_SPEECH_VISEME_CB = 5;
int SPEECH_VISEME_CB;


//! global Callback declaration for recognition
int SCOL_RECO_END_CB = 0;
int RECOGNITION_END_CB;

int SCOL_RECO_TEXT_CB = 1;
int RECOGNITION_TEXT_CB;

int SCOL_RECO_START_CB = 2;
int RECOGNITION_START_CB;

int SCOL_RECO_TEXTS_ALT_CB = 3;
int RECOGNITION_TEXTS_ALT_CB;

int SCOL_RECO_WORDS_CB = 4;
int RECOGNITION_WORDS_CB;


//! Utils Conversions
wchar_t* convertCharToLPCWSTR(char * s_text)
{
  int char_count = MultiByteToWideChar(CP_ACP, 0, s_text, -1, NULL, 0);
	wchar_t* w_text = new wchar_t[char_count];
	MultiByteToWideChar(CP_ACP, 0, s_text, -1, w_text, char_count);

  return w_text;
}


char* convertWcharToChar(wchar_t * w_text)
{
  int wchar_count = WideCharToMultiByte(CP_ACP, 0, w_text, -1, NULL, 0,NULL,NULL);
	char* s_text = new char[wchar_count];
	WideCharToMultiByte(CP_ACP, 0, w_text, -1, s_text, wchar_count,NULL,NULL);

  return s_text;
}


/*!
* \brief function to destroy an OBJSPEECHSCOL in scol
* \param m : current machine
* \param handle : given handle
* \param obj : given OBJSPEECHSCOL
*
* \return 0 if success
*/
int destroySpeechObj(mmachine m, int handsys, int speechTab) 
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"destroySpeechObj\n");
#endif
	Speech* SpeechObj = (Speech*) MMfetch(m, MTOP(speechTab), 0);
	if (SpeechObj != 0)
	  SAFE_DELETE(SpeechObj);
  
	MMstore(m, MTOP(speechTab), 0, NULL);
	MMechostr(MSKDEBUG, "ObjSpeech destroyed.\n");
	return 0;
}


/*! @ingroup grpstt
*  \brief _CRSpeech : create speech instance
*  
*	 <b>Prototype:</b> fun [Chn] ObjSpeech
*
*  \param Chn : channel
*
*   \return ObjSpeech: speech object
*/
int _CRSpeech(mmachine m)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_CRSpeech\n");
#endif

	Speech* newSpeech = new Speech();
  if (newSpeech == 0)
	{
    MMset(m, 0, NIL);
		return 0;
	}

	int speechTab = MMmalloc(m, 1, TYPETAB);
	if (speechTab == NIL) 
	{
		SAFE_DELETE(newSpeech);
    MMset(m, 0, NIL);
		return 0;
	}

	MMstore(m, speechTab, 0, (int)newSpeech);
	MMpush(m, PTOM(speechTab));

	int k = 0;
	k = OBJcreate(m, OBJSPEECHSCOL, (int)newSpeech, NULL, NULL);

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif

	return k;
}


/*! @ingroup grpstt
*  \brief _DSSpeech : destroy speech instance
*  
*	 <b>Prototype:</b>  fun [ObjSpeech] I
*
*  \param ObjSpeech : speech object to destroy
*
*   \return I : 1 on success or NIL on fail
*/
int _DSSpeech (mmachine m) 
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_DSSpeech\n");
#endif

	int speechTab = MMget(m, 0);
	if (speechTab == NIL)
  {
		MMechostr(MSKDEBUG, "ObjSpeech NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

	OBJdelTM(m, OBJSPEECHSCOL, speechTab);
	MMset(m, 0, ITOM(1));

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief _SetSpeechText : Set speech Text
*  
*	 <b>Prototype:</b>  fun [ObjSpeech S] I
*
*  \param ObjSpeech : speech object to set
*  \param S : speech text
*
*   \return I : 1 on success or NIL on fail
*/
int _SetSpeechText (mmachine m) 
{	
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"__SetSpeechText\n");
#endif

  int text = MMpull(m);
  int speechTab = MMget(m, 0);
  if (speechTab == NIL)
  {
	  MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
	  MMset(m, 0, NIL);
	  return 0;
  }

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }

  std::string strText = MMstartstr(m, MTOP(text));
  objSpeech->SetSpeechText(strText);
  MMset(m, 0, ITOM(1));

#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief _SetSpeechVolume : Set speech volume
*  
*	 <b>Prototype:</b>  fun [ObjSpeech I] I
*
*  \param ObjSpeech : speech object to set
*  \param I : speech volume
*
*   \return I : 1 on success or NIL on fail
*/
int _SetSpeechVolume (mmachine m) 
{	
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_SetSpeechVolume\n");
#endif

  int vol = MMpull(m);
  int speechTab = MMget(m, 0);
  if ((speechTab == NIL) || (vol == NIL))
  {
	  MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
	  MMset(m, 0, NIL);
	  return 0;
  }

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }

  int nvolume = 0;
  if (MTOI(vol) > 0)
    nvolume = MTOI(vol);

  objSpeech->setVolumeSpeech(nvolume);

  MMset(m, 0, ITOM(1));

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief _GetSpeechVolume : Get speech volume
*  
*	 <b>Prototype:</b>  fun [ObjSpeech] I
*
*  \param ObjSpeech : speech object to set
*
*  \return I : speech volume
*/
int _GetSpeechVolume(mmachine m)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_GetSpeechVolume\n");
#endif

	int speechTab = MMget(m, 0);
	if (speechTab == NIL) 
	{
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }

	MMset(m, 0, ITOM(objSpeech->getVolumeSpeech()));

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif

  return 0;
}


/*! @ingroup grpstt
*  \brief _SetSpeechRate : set speech rate
*  
*	 <b>Prototype:</b>  fun [ObjSpeech I] I
*
*  \param ObjSpeech : speech object to set
*  \param I : speech rate
*
*   \return I : 1 on success or NIL on fail
*/
int _SetSpeechRate (mmachine m) 
{	
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_SetSpeechRate\n");
#endif
	
	int rate = MMpull(m);
	int speechTab = MMget(m, 0);
	if ((speechTab == NIL) || (rate == NIL))
  {
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }
	
	objSpeech->setRateSpeech(MTOI(rate));

	MMset(m, 0, ITOM(1));

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief _GetSpeechRate : get speech rate
*  
*	 <b>Prototype:</b>  fun [ObjSpeech] I
*
*  \param ObjSpeech : speech object to set
*
*   \return I : speech rate
*/
int _GetSpeechRate(mmachine m)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_GetSpeechRate\n");
#endif

	int speechTab = MMget(m, 0);
	if (speechTab == NIL) 
	{
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }

	MMset(m, 0, ITOM(objSpeech->getRateSpeech()));

#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif

	return 0;
}


/*! @ingroup grpstt
*  \brief _PlaySpeech : play speech
*  
*	 <b>Prototype:</b>  fun [ObjSpeech] I
*
*  \param ObjSpeech : speech object to set
*
*   \return I : 1 on success or NIL on fail
*/
int _PlaySpeech (mmachine m) 
{	
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_PlaySpeech\n");
#endif
	
	int speechTab = MMget(m, 0);
	if (speechTab == NIL) 
	{
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }
	
	objSpeech->play();

	MMset(m, 0, ITOM(1));

#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief _PauseSpeech : pause speech
*  
*	 <b>Prototype:</b>  fun [ObjSpeech] I
*
*  \param ObjSpeech : speech object to set
*
*   \return I : 1 on success or NIL on fail
*/
int _PauseSpeech (mmachine m) 
{	
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_PauseSpeech\n");
#endif
	
	int speechTab = MMget(m, 0);
	if (speechTab == NIL) 
	{
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }

	objSpeech->pauseResume();
	
  MMset(m, 0, ITOM(1));

#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief _ResumeSpeech : resume speech
*  
*	 <b>Prototype:</b>  fun [ObjSpeech] I
*
*  \param ObjSpeech : speech object to set
*
*   \return I : 1 on success or NIL on fail
*/
int _ResumeSpeech (mmachine m) 
{	
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_PauseSpeech\n");
#endif
	
	int speechTab = MMget(m, 0);
	if (speechTab == NIL) 
	{
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }

	objSpeech->pauseResume();

	MMset(m, 0, ITOM(1));

#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief _StopSpeech : Stop speech
*  
*	 <b>Prototype:</b>  fun [ObjSpeech] I
*
*  \param ObjSpeech : speech object to set
*
*   \return I : 1 on success or NIL on fail
*/
int _StopSpeech (mmachine m) 
{	
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_StopSpeech\n");
#endif
	
	int speechTab = MMget(m, 0);
	if (speechTab == NIL) 
	{
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }

	objSpeech->stop();

	MMset(m, 0, ITOM(1));

#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief n_CBSpeechStart : set callback 'start of speech'
*
*	 <b>Prototype:</b> fun [ObjSpeech fun [ObjSpeech u0] u1 u0] ObjSpeech
*
*  \param ObjSpeech : speech object
*  \param fun [ObjSpeech u0] : callback function
*  - ObjSpeech : speech object
*  - u0 : user parameter
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBSpeechStart(mmachine m)
{
	return OBJaddreflex(m, OBJSPEECHSCOL, SCOL_SPEECH_START_CB);
}


/*! @ingroup grpstt
*  \brief n_CBSpeechEnd : set callback end of speech
*  
*	 <b>Prototype:</b> fun [ObjSpeech fun [ObjSpeech u0] u1 u0] ObjSpeech
*
*  \param ObjSpeech : speech object
*  \param fun [ObjSpeech u0] : callback function
*  - ObjSpeech : speech object
*  - u0 : user parameter
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBSpeechEnd(mmachine m)
{
	return OBJaddreflex(m, OBJSPEECHSCOL, SCOL_SPEECH_END_CB);
}


/*!
* \brief C function that prepares the VM for the execution of the speech start event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getSpeechStartCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int* ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG, "getSpeechStartCb\n");
#endif

	int k = 0;
	Speech* SpeechObj =(Speech*) id;
	if (OBJbeginreflex(m, OBJSPEECHSCOL, (int)SpeechObj, SCOL_SPEECH_START_CB))
		return 0;

  k = OBJcallreflex(m, 0);
	return k;
}


/*!
* \brief C function that prepares the VM for the execution of the speech end event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getSpeechEndCb(mmachine m, HWND h, unsigned msg, UINT id, LONG param, int* ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"getSpeechEndCb\n");
#endif

	int k = 0;
	Speech* SpeechObj =(Speech*) id;
	if (OBJbeginreflex(m, OBJSPEECHSCOL, (int)SpeechObj, SCOL_SPEECH_END_CB))
		return 0;

  k = OBJcallreflex(m, 0);
	return k;
}


/*! @ingroup grpstt
*  \brief _GetSpeechVoices : get speech voices
*  
*	 <b>Prototype:</b> fun [ObjSpeech] [S r1]
*
*  \param ObjSpeech : speech object
*
*  \return [S r1] : list voices name
*/
int _GetSpeechVoices(mmachine m)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_GetSpeechVoices\n");
#endif

	std::list <char *>::iterator c1_Iter;
	unsigned int k ;
	
	int speechTab = MMpull(m);
	if (speechTab == NIL) 
	{
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
		MMpush(m, NIL);
		return 0;
	}

  Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);		
  if(!objSpeech)
  {
    MMpush(m, NIL);
    return 0;
  }

	std::list <char*> lParamSp = objSpeech->getVoiceAll();

	for (c1_Iter = lParamSp.begin(); c1_Iter != lParamSp.end(); c1_Iter++)
	{
		if (k=Mpushstrbloc(m, (char*)*c1_Iter))
      return k;
	}

	if (MMpush(m, NIL))
    return MERRMEM;

	for (c1_Iter = lParamSp.begin(); c1_Iter != lParamSp.end(); c1_Iter++)
	{
		if (MMpush(m, 2*2))
      return MERRMEM;

		if (k=MBdeftab(m))
      return k;
	}

#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief _SetSpeechVoice : set speech voice
*  
*	 <b>Prototype:</b>  fun [ObjSpeech S] I
*
*  \param ObjSpeech : speech object to set
*  \param S : speech voice
*
*   \return I : 1 on success or NIL on fail
*/
int _SetSpeechVoice(mmachine m)
{
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_SetSpeechVoice\n");
	#endif
	
	int voice = MMpull(m);
	int speechTab = MMget(m, 0);
	if (speechTab == NIL)
  {
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

	Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }

  std::string strVoice = MMstartstr(m, MTOP(voice));
  if (strVoice.empty())
  {
    MMset(m, 0, NIL);
    return 0;
  }

	objSpeech->SetSpeechVoice(strVoice);
	MMset(m, 0, ITOM(1));

	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif
	return 0;
}


/*! @ingroup grpstt
*  \brief _GetSpeechVoice : get speech voice
*  
*	 <b>Prototype:</b> fun [ObjSpeech] S
*
*  \param ObjSpeech : speech object
*
*  \return S : voice name
*/
int _GetSpeechVoice(mmachine m)
{
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_GetSpeechVoice\n");
	#endif

  int speechTab = MMget(m, 0);
	if (speechTab == NIL) 
	{
		MMechostr(MSKDEBUG,"ObjSpeech NIL\n");
    MMset(m, 0, NIL);
		return 0;
	}

	Speech* objSpeech = (Speech*) MMfetch(m, MTOP(speechTab), 0);
  if(!objSpeech)
  {
    MMset(m, 0, NIL);
    return 0;
  }

  std::string voice = objSpeech->getSpeechVoice();
  if(voice.empty())
  {
    MMset(m, 0, NIL);
    return 0;
  }

  //remove last param before push
  MMpull(m);
  Mpushstrbloc(m, (char*)voice.c_str());

#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG, "ok\n");
#endif

	return 0;
}


/*! @ingroup grpstt
*  \brief _CBSpeechWord : Set callback on speech word
*  
*	 <b>Prototype:</b> fun [ObjSpeech fun [ObjSpeech u0 S] u1 u0] ObjSpeech
*
*  \param ObjSpeech : speech object
*  \param fun [ObjSpeech u0 S] u1 : Callback function
*  - ObjSpeech : speech object
*  - u0 : user parameter
*  - S : word
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBSpeechWord(mmachine m)
{
	return OBJaddreflex(m, OBJSPEECHSCOL, SCOL_SPEECH_WORD_CB);
}


/*!
* \brief C function that prepares the VM for the execution of the speech word event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getSpeechWordCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"getSpeechWordCb\n");
#endif

	int k = 0;
	Speech* SpeechObj = (Speech*) id;
  std::string* word = (std::string*)param;
	
	if (OBJbeginreflex(m, OBJSPEECHSCOL, (int)SpeechObj, SCOL_SPEECH_WORD_CB))
  {
    SAFE_DELETE(word);
		return 0;
  }
	
	Mpushstrbloc(m, (char*)word->c_str());
  k=OBJcallreflex(m, 1);
  SAFE_DELETE(word);
	return k;
}


/*! @ingroup grpstt
*  \brief _CBSpeechText : Set callback on speech text
*  
*	 <b>Prototype:</b> fun [ObjSpeech fun [ObjSpeech u0 S] u1 u0] ObjSpeech
*
*  \param ObjSpeech : speech object
*  \param fun [ObjSpeech u0 S] u1 : Callback function
*  - ObjSpeech : speech object
*  - u0 : user parameter
*  - S : text
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBSpeechText(mmachine m)
{
	return OBJaddreflex(m, OBJSPEECHSCOL, SCOL_SPEECH_TEXT_CB);
}


/*!
* \brief C function that prepares the VM for the execution of the speech text event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getSpeechTextCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"getSpeechTextCb\n");
#endif

	int k = 0;
	Speech* SpeechObj = (Speech*) id;
  std::string* sentence = (std::string*)param;

	if (OBJbeginreflex(m, OBJSPEECHSCOL, (int)SpeechObj, SCOL_SPEECH_TEXT_CB))
  {
    SAFE_DELETE(sentence);
		return 0;
  }
	
	Mpushstrbloc(m, (char*)sentence->c_str());
	k=OBJcallreflex(m, 1);
	SAFE_DELETE(sentence);
	return k;
}


/*! @ingroup grpstt
*  \brief _CBSpeechPhoneme : set callback on speech phoneme
*  
*	 <b>Prototype:</b> fun [ObjSpeech fun [ObjSpeech u0 I] u1 u0] ObjSpeech
*
*  \param ObjSpeech : speech object
*  \param fun [ObjSpeech u0 I] u1 : Callback function
*  - ObjSpeech : speech object
*  - u0 : user parameter
*  - I : phoneme
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBSpeechPhoneme(mmachine m)
{
	return OBJaddreflex(m, OBJSPEECHSCOL, SCOL_SPEECH_PHONEME_CB);
}

/*!
* \brief C function that prepares the VM for the execution of the speech phoneme event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getSpeechPhonemeCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"getSpeechPhonemeCb\n");
#endif

	int k = 0;
	Speech* SpeechObj = (Speech*) id;

	if (OBJbeginreflex(m, OBJSPEECHSCOL, (int)SpeechObj, SCOL_SPEECH_PHONEME_CB))
		return 0;
	
	MMpush(m, ITOM(param));
	k = OBJcallreflex(m, 1);
	return k;
}


/*! @ingroup grpstt
*  \brief _CBSpeechPhoneme : set callback on speech viseme
*  
*	 <b>Prototype:</b> fun [ObjSpeech fun [ObjSpeech u0 I] u1 u0] ObjSpeech
*
*  \param ObjSpeech : speech object
*  \param fun [ObjSpeech u0 I] u1 : Callback function
*  - ObjSpeech : speech object
*  - u0 : user parameter
*  - I : viseme
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBSpeechViseme(mmachine m)
{
	return OBJaddreflex(m, OBJSPEECHSCOL, SCOL_SPEECH_VISEME_CB);
}

/*!
* \brief C function that prepares the VM for the execution of the speech viseme event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getSpeechVisemeCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"getSpeechVisemeCb\n");
#endif

	int k = 0;
	Speech* SpeechObj = (Speech*) id;

	if (OBJbeginreflex(m, OBJSPEECHSCOL, (int)SpeechObj, SCOL_SPEECH_VISEME_CB))
		return 0;
	
	MMpush(m, ITOM(param));
	k = OBJcallreflex(m, 1);
	return k;
}


/*! @defgroup grpreco Recognition
 *  Scol functions definition
 *  @{
 */
/** @} */


/*! @i
ngroup grpreco
*  \brief _CRRecognition : create recognition instance
*  
*	 <b>Prototype:</b> fun [Chn] ObjRecognition
*
*  \param Chn : channel
*
*   \return ObjRecognition: recognition object
*/
int _CRRecognition(mmachine m)
{
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG, "_CRRecognition\n");
	#endif

  Recognition* newRecognition = new Recognition();
  if(!newRecognition)
  {
    MMset(m, 0, NIL);
    return 0;
  }

  if(!newRecognition->initializeObjects())
  {
    SAFE_DELETE(newRecognition);
    MMset(m, 0, NIL);
    return 0;
  }

	int recognitionTab = MMmalloc(m, 1, TYPETAB);
	if (recognitionTab == NIL) 
	{
		SAFE_DELETE(newRecognition);
		MMset(m, 0, NIL);
		return MERRMEM;
	}

	MMstore(m, recognitionTab, 0, (int)newRecognition);
	MMpush(m, PTOM(recognitionTab));

	int k = 0;
	k = OBJcreate(m, OBJRECOSCOL, (int)newRecognition, 0, 0);

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif

	return k ;
}


/*!
* \brief function to destroy an OBJRECOSCOL in scol
* \param m : current machine
* \param handle : given handle
* \param obj : given OBJRECOSCOL
*
* \return 0 if success
*/
int destroyRecognitionObj(mmachine m, int handsys, int recognitionTab) 
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"destroyRecognitionObj\n");
#endif

	Recognition* RecognitionObj = (Recognition*) MMfetch(m, MTOP(recognitionTab), 0);
	if (RecognitionObj != 0)
	  SAFE_DELETE(RecognitionObj);

	MMstore(m, MTOP(recognitionTab), 0, 0);
	MMechostr(MSKDEBUG, "ObjRecognition destroyed.\n");
	return 0;
}


/*! @ingroup grpreco
*  \brief n_DSRecognition : destroy recognition instance
*  
*	 <b>Prototype:</b> fun [ObjRecognition] I
*
*  \param ObjRecognition : recognition object to destroy
*
*   \return : 1 on success or NIL on fail
*/
int _DSRecognition (mmachine m) 
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"_DSRecognition\n");
#endif

  int recognotionTab = MMget(m, 0);
  if (recognotionTab == NIL) 
  {
	  MMset(m, 0, NIL);
	  return 0;
  }

  OBJdelTM(m, OBJRECOSCOL, recognotionTab);
  MMset(m, 0, ITOM(1));

#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


/*! @ingroup grpreco
*  \brief _CBRecognitionEnd : set callback end of recognition
*  
*	 <b>Prototype:</b> fun [ObjRecognition fun [ObjRecognition u0] u1 u0] ObjRecognition
*
*  \param ObjRecognition : recognition object
*  \param fun [ObjRecognition u0] : callback function
*  - ObjSpeech : reconition object
*  - u0 : user parameter
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBRecognitionEnd(mmachine m)
{
	return OBJaddreflex(m, OBJRECOSCOL, SCOL_RECO_END_CB);
}


/*!
* \brief C function that prepares the VM for the execution of the recognition end event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getRecognitionEndCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"getRecognitionEndCb\n");
#endif

	int k = 0;
	Recognition * RecognitionObj =(Recognition *) id;

	if (OBJbeginreflex(m, OBJRECOSCOL, (int)RecognitionObj, SCOL_RECO_END_CB))
		return 0;

	k = OBJcallreflex(m, 0);
	return k;
}


/*! @ingroup grpreco
*  \brief _CBRecognitionStart : set callback start of recognition
*  
*	 <b>Prototype:</b> fun [ObjRecognition fun [ObjRecognition u0] u1 u0] ObjRecognition
*
*  \param ObjRecognition : recognition object
*  \param fun [ObjRecognition u0] : callback function
*  - ObjSpeech : reconition object
*  - u0 : user parameter
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBRecognitionStart(mmachine m)
{
	return OBJaddreflex(m, OBJRECOSCOL, SCOL_RECO_START_CB);
}


/*!
* \brief C function that prepares the VM for the execution of the recognition start event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getRecognitionStartCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG,"getRecognitionStartCb\n");
#endif

	int k = 0;
	Recognition * RecognitionObj =(Recognition *) id;

	if (OBJbeginreflex(m, OBJRECOSCOL, (int)RecognitionObj, SCOL_RECO_START_CB))
		return 0;

  k = OBJcallreflex(m, 0);
	return k;
}


/*! @ingroup grpreco
*  \brief _CBRecognitionText : Set callback on recognition text
*  
*	 <b>Prototype:</b> fun [ObjRecognition fun [ObjRecognition u0 S] u1 u0] ObjRecognition
*
*  \param ObjRecognition : recognition object
*  \param fun [ObjRecognition u0 S] u1 : Callback function
*  - ObjRecognition : recognition object
*  - u0 : user parameter
*  - S : text
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBRecognitionText(mmachine m)
{
	return OBJaddreflex(m, OBJRECOSCOL, SCOL_RECO_TEXT_CB);
}


/*!
* \brief C function that prepares the VM for the execution of the recognition text event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getRecognitionTextCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG, "getRecognitionTextCb\n");
#endif

	int k = 0;
	cbData* cbdata = (cbData*) param;
	Recognition* RecognitionObj = (Recognition*) id;
  std::string data = cbdata->getParamChar();

	if (OBJbeginreflex(m, OBJRECOSCOL, (int)RecognitionObj, SCOL_RECO_TEXT_CB))
  {
    SAFE_DELETE(cbdata);
		return 0;
  }
	
	Mpushstrbloc(m, (char*)data.c_str());
	k = OBJcallreflex(m, 1);
	SAFE_DELETE(cbdata);
	return k;
}


/*! @ingroup grpreco
*  \brief _CBRecognitionTextsAlt : Set callback on recognition texts alternates
*  
*	 <b>Prototype:</b> fun [ObjRecognition fun [ObjRecognition u0 [[S F]r1] u1 u0] ObjRecognition
*
*  \param ObjRecognition : recognition object
*  \param fun [ObjRecognition u0 [[S F]r1]] u1 : Callback function
*  - ObjRecognition : recognition object
*  - u0 : user parameter
*  - [[S F]r1] : list text alt
*  \param u0 : user parameter
*
*   \return : the same scol object
*/
int _CBRecognitionTextsAlt(mmachine m)
{
	return OBJaddreflex(m, OBJRECOSCOL, SCOL_RECO_TEXTS_ALT_CB);
}


/*!
* \brief C function that prepares the VM for the execution of the recognition alternates text event callback
* \param m : current machine
* \param h : main scol window
* \param msg : message
* \param id : pointer of the obj
* \param param : data pointer
* \param ret : user parameter
*
* \return res : 0 if success
*/
int getRecognitionTextsAltCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG, "getRecognitionTextsAltCb\n");
#endif

	int k = 0;
  int nb = 0;

	cbData* cbdata = (cbData*) param;
	Recognition* RecognitionObj = (Recognition *) id;
	if (OBJbeginreflex(m, OBJRECOSCOL, (int)RecognitionObj, SCOL_RECO_TEXTS_ALT_CB))
  {
    SAFE_DELETE(cbdata);
		return 0;
  }

  std::list <pTextRec> lParamText = cbdata->getlParamText();
  std::list <pTextRec>::iterator c1_Iter = lParamText.begin();
	while(c1_Iter != lParamText.end())
	{
    nb++;
    if (Mpushstrbloc(m,c1_Iter->altText.CopyToChar()))
    {
      SAFE_DELETE(cbdata);
      return MERRMEM;
    }
    if (MMpush(m,FTOM(c1_Iter->altConfidence)))
    {
      SAFE_DELETE(cbdata);
      return MERRMEM;
    }
    if (MMpush(m,4))
    {
      SAFE_DELETE(cbdata);
      return MERRMEM;
    }

    MBdeftab(m);
    c1_Iter++;
	}

	if (MMpush(m, NIL))
  {
    SAFE_DELETE(cbdata);
    return MERRMEM;
  }

  for(int i = 0; i < nb; i++)
  {
    if (MMpush(m,2*2))
    {
      SAFE_DELETE(cbdata);
      return MERRMEM;
    }
    
    if (k=MBdeftab(m))
    {
      SAFE_DELETE(cbdata);
      return k;
    }
  }

  k = OBJcallreflex(m, 1);
	SAFE_DELETE(cbdata);
	return k;
}


/*! @ingroup grpreco
*  \brief _CBRecognitionWords : Set callback on recognition words
*  
*	 <b>Prototype:</b> fun [ObjRecognition fun [ObjRecognition u0 [[S F] r1]] u1 u0] ObjRecognition
*
*  \param ObjRecognition : recognition object
*  \param fun [ObjRecognition u0 [S r1]] u1 : Callback function
*  - ObjRecognition : recognition object
*  - u0 : user parameter
*  - [[S F] r1] : list word 
*  \param u0 : user parameter
*
*   \return : 0 on success or -1 on fail
*/
/*
int _CBRecognitionWords(mmachine m)
{
	return OBJaddreflex(m, OBJRECOSCOL, SCOL_RECO_WORDS_CB);
}
*/

/*
int getRecognitionWordsCb(mmachine m,HWND h,unsigned msg,UINT id,LONG param,int *ret)
{
  std::list <char*>::iterator c1_Iter;
	int k = 0;
	cbData * cbdata = (cbData *) param;
	Recognition * RecognitionObj =(Recognition *) id;
	std::list <char*> lParamWords = cbdata->getlParamWords();

	// OBJbeginreflex(mmachine, objecttype, objectptr, cbtype)
	if (OBJbeginreflex(m, OBJRECOSCOL, (int)RecognitionObj, SCOL_RECO_WORDS_CB))
		return 0;


  //MMpull(m);
	for ( c1_Iter = lParamWords.begin( ); c1_Iter != lParamWords.end( ); c1_Iter++ )
	{
		if (k=Mpushstrbloc(m,(char*)*c1_Iter)) return k;
	}
	if (MMpush(m,NIL)) return MERRMEM;
	for ( c1_Iter = lParamWords.begin( ); c1_Iter != lParamWords.end( ); c1_Iter++ )
	{
		if (MMpush(m,2*2)) return MERRMEM;
		if (k=MBdeftab(m)) return k;
	}

	// OBJcallreflex(mmachine, nbparam)
	if ((k=OBJcallreflex(m, 1))) return k;
	
	SAFE_DELETE(cbdata);
	return k;
}
*/
/*! @ingroup grpreco
*  \brief _SetRecogntionVolume : Set recogntion volume
*  
*	 <b>Prototype:</b>  fun [ObjRecognition I] I
*
*  \param ObjRecognition : recogntion object to set
*  \param I : recogntion volume
*
*   \return I : 1 on success or NIL on fail
*/
int _SetRecogntionVolume (mmachine m) 
{	
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_SetRecogntionVolume\n");
	#endif
		
  int vol = MMpull(m);
	int recognitionTab = MMget(m, 0);
	if (recognitionTab == NIL)
  {
		MMechostr(MSKDEBUG,"ObjRecognition NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

	Recognition* ObjRecognition = (Recognition*) MMfetch(m, MTOP(recognitionTab), 0);
  if (!ObjRecognition)
  {
		MMset(m, 0, NIL);
		return 0;
	}
  
  int volume = 0;
  if ((vol != NIL) && (MTOI(vol) > 0))
    volume = MTOI(vol);

	ObjRecognition->setVolume(volume);
	MMset(m, 0, ITOM(1));

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif
		return 0;
}


/*! @ingroup grpreco
*  \brief _GetRecogntionVolume : Get recognition volume
*  
*	 <b>Prototype:</b>  fun [ObjRecognition] I
*
*  \param ObjRecognition : recognition object to set
*
*   \return I : recognition volume
*/
int _GetRecogntionVolume(mmachine m)
{
	#ifdef _SCOL_DEBUG_
		MMechostr(MSKDEBUG,"_GetRecogntionVolume\n");
	#endif

	int recognitionTab = MMget(m, 0);
	if (recognitionTab == NIL)
  {
		MMechostr(MSKDEBUG,"ObjRecognition NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

	Recognition* ObjRecognition = (Recognition*) MMfetch(m, MTOP(recognitionTab), 0);
  if (!ObjRecognition)
  {
		MMset(m, 0, NIL);
		return 0;
	}

	MMset(m, 0, ITOM(ObjRecognition->getVolume()));

	#ifdef	_SCOL_DEBUG_
		MMechostr(MSKDEBUG,"ok\n");
	#endif

	return 0;
}


/*! @ingroup grpreco
*  \brief _AddRecognitionWord : add recogntion word to dictionary
*  
*	 <b>Prototype:</b>  fun [ObjRecognition S] I
*
*  \param ObjRecognition : recogntion object to set
*  \param S : recogntion word
*
*   \return I : 1 on success or NIL on fail
*/
int _AddRecognitionWord(mmachine m) 
{	
#ifdef _SCOL_DEBUG_
	MMechostr(MSKDEBUG, "_AddRecognitionWord\n");
#endif
	
	int textWord = MMpull(m);
  int textRule = MMpull(m);

	if ((textWord == NIL) || (textRule == NIL))
  {
		MMset(m, 0, NIL);
		return 0;
	}

 	int recognitionTab = MMget(m, 0);
	if (recognitionTab == NIL)
  {
		MMechostr(MSKDEBUG,"ObjRecognition NIL\n");
		MMset(m, 0, NIL);
		return 0;
	}

	Recognition* ObjRecognition = (Recognition*) MMfetch(m, MTOP(recognitionTab), 0);
  if (!ObjRecognition)
  {
		MMset(m, 0, NIL);
		return 0;
	}

	char* strRule = (char*)MMstartstr(m,MTOP(textRule));					
  char* strWord = (char*)MMstartstr(m,MTOP(textWord));

  ObjRecognition->AddWord(strRule, strWord);
	MMset(m, 0, ITOM(1));

#ifdef	_SCOL_DEBUG_
	MMechostr(MSKDEBUG,"ok\n");
#endif
	return 0;
}


//! Nb of Scol functions or types
#define NbTplPKG	31


/*!
*	Scol function names
*/
char	*TplName[NbTplPKG] =
{
	"ObjSpeech",
	"ObjRecognition",
	"_CRSpeech",
	"_DSSpeech",
	"_SetSpeechText",
	"_SetSpeechVolume",
	"_GetSpeechVolume",
  "_SetSpeechRate",
	"_GetSpeechRate",
	"_PlaySpeech",
	"_PauseSpeech",
	"_ResumeSpeech",
	"_StopSpeech",
	"_CBSpeechStart",
	"_CBSpeechEnd",
	"_GetSpeechVoices",
  "_GetSpeechVoice",
	"_SetSpeechVoice",
	"_CBSpeechWord",
	"_CBSpeechText",
	"_CBSpeechPhoneme",
  "_CBSpeechViseme",
	
	"_CRRecognition",
	"_DSRecognition",
	"_CBRecognitionEnd",
	"_CBRecognitionText",
  "_CBRecognitionTextsAlt",
  //"_CBRecognitionWords",
	"_CBRecognitionStart",
	"_SetRecogntionVolume",
	"_GetRecogntionVolume",
  "_AddRecognitionWord" //10
	
};


/*!
*	Pointers to C functions that manipulate the VM for each scol function previously defined
*/
int (*TplFunc[NbTplPKG])(mmachine m)=
{
	NULL,			
	NULL,
	_CRSpeech,
	_DSSpeech,
	_SetSpeechText,
	_SetSpeechVolume,
	_GetSpeechVolume,
  _SetSpeechRate,
	_GetSpeechRate,
	_PlaySpeech,
	_PauseSpeech,
	_ResumeSpeech,
	_StopSpeech,
	_CBSpeechStart,
	_CBSpeechEnd,
	_GetSpeechVoices,
  _GetSpeechVoice,
	_SetSpeechVoice,
	_CBSpeechWord,
	_CBSpeechText,
	_CBSpeechPhoneme,
  _CBSpeechViseme,

	_CRRecognition,
	_DSRecognition,
	_CBRecognitionEnd,
	_CBRecognitionText,
  _CBRecognitionTextsAlt,
  //_CBRecognitionWords,
	_CBRecognitionStart,
	_SetRecogntionVolume,
	_GetRecogntionVolume,
  _AddRecognitionWord
};



/*!
*	Nb of arguments of each scol function
*/
int TplNArg[NbTplPKG]=
{
	TYPTYPE,	// ObjSpeech
	TYPTYPE,	// objRecognition
	1,				// _CRSpeech
	1,				// _DSSpeech		
	2,				// _SetSpeechText
	2,				// _SetSpeechVolume
	1,				// _GetSpeechVolume
  2,				// _SetSpeechRate
	1,				// _GetSpeechRate
	1,				// _PlaySpeech
	1,				// _PauseSpeech
	1,				// _ResumeSpeech
	1,				// _StopSpeech
	3,				// _CBSpeechStart,
	3,				// _CBSpeechEnd
	1,				// _GetSpeechVoices
  1,        // _GetSpeechVoice
	2,				// _SetSpeechVoice
	3,				// _CBSpeechWord
	3,				// _CBSpeechText
	3,				// _CBSpeechPhoneme
  3,        // _CBSpeechViseme
	
	1,				// _CRRecognition
	1,				// _DSRecognition
	3,				// _CBRecognitionEnd
	3,				// _CBRecognitionText
  3,        // _CBRecognitionTextsAlt
  //3,        // _CBRecognitionWords
	3,        // _CBRecognitionStart
	2,        // _SetRecogntionVolume
	1,				// _GetRecogntionVolume
  3         // _AddRecognitionWord
};


/*!
*	Prototypes of the scol functions
*/
char* TplType[NbTplPKG]=
{
	NULL,																																		// ObjSpeech
	NULL,																																		// ObjRecognition
	"fun [Chn] ObjSpeech",																									// _CRSpeech
	"fun [ObjSpeech] I",																										// _DSSpeech
	"fun [ObjSpeech S] I",																									// _SetSpeechText
	"fun [ObjSpeech I] I",																								  // _SetSpeechVolume
	"fun [ObjSpeech] I",																										// _GetSpeechVolume
  "fun [ObjSpeech I] I",																								  // _SetSpeechRate
	"fun [ObjSpeech] I",																										// _GetSpeechRate
	"fun [ObjSpeech] I",																										// _PlaySpeech
	"fun [ObjSpeech] I",																										// _PauseSpeech
	"fun [ObjSpeech] I",																										// _ResumeSpeech
	"fun [ObjSpeech] I",																										// _StopSpeech
  "fun [ObjSpeech fun [ObjSpeech u0] u1 u0] ObjSpeech",										// _CBSpeechStart
	"fun [ObjSpeech fun [ObjSpeech u0] u1 u0] ObjSpeech",										// _CBSpeechEnd
	"fun [ObjSpeech] [S r1]",																								// _GetSpeechVoices
  "fun [ObjSpeech] S",                                                    // _GetSpeechVoice
	"fun [ObjSpeech S] I",																									// _SetSpeechVoice
	"fun [ObjSpeech fun [ObjSpeech u0 S] u1 u0] ObjSpeech",									// _CBSpeechWord
	"fun [ObjSpeech fun [ObjSpeech u0 S] u1 u0] ObjSpeech",									// _CBSpeechText
	"fun [ObjSpeech fun [ObjSpeech u0 I] u1 u0] ObjSpeech",									// _CBSpeechPhoneme
	"fun [ObjSpeech fun [ObjSpeech u0 I] u1 u0] ObjSpeech",                 // _CBSpeechViseme

	"fun [Chn] ObjRecognition",																							// _CRRecognition
	"fun [ObjRecognition] I",																								// _DSRecognition
	"fun [ObjRecognition fun [ObjRecognition u0] u1 u0] ObjRecognition",		// _CBRecognitionEnd
	"fun [ObjRecognition fun [ObjRecognition u0 S] u1 u0] ObjRecognition",	// _CBRecognitionText
  "fun [ObjRecognition fun [ObjRecognition u0 [[S F] r1]] u1 u0] ObjRecognition",  //_CBRecognitionTextsAlt
  //"fun [ObjRecognition fun [ObjRecognition u0 [[S F] r1]] u1 u0] ObjRecognition",//_CBRecognitionWords
	"fun [ObjRecognition fun [ObjRecognition u0] u1 u0] ObjRecognition",		// _CBRecognitionStart
	"fun [ObjRecognition I] I",																							// _SetRecogntionVolume
	"fun [ObjRecognition] I",																								// _GetRecogntionVolume
  "fun [ObjRecognition S S] I"                                            // _AddRecognitionWord
	
};


/*!
* \brief Load the packages in Scol virtual machine
* \param mmachine : the scol machine
*/
int LoadSpeech(mmachine m)
{
	int k;

	//SPEECH
	OBJSPEECHSCOL = OBJregister(6, 1, destroySpeechObj, "OBJSPEECHSCOL");

	SPEECH_START_CB = OBJgetUserEvent();
	OBJdefEvent(SPEECH_START_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getSpeechStartCb);

	SPEECH_END_CB = OBJgetUserEvent();
	OBJdefEvent(SPEECH_END_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getSpeechEndCb);

  SPEECH_WORD_CB = OBJgetUserEvent();
	OBJdefEvent(SPEECH_WORD_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getSpeechWordCb);

	SPEECH_TEXT_CB = OBJgetUserEvent();
	OBJdefEvent(SPEECH_TEXT_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getSpeechTextCb);

	SPEECH_PHONEME_CB = OBJgetUserEvent();
	OBJdefEvent(SPEECH_PHONEME_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getSpeechPhonemeCb);

  SPEECH_VISEME_CB = OBJgetUserEvent();
	OBJdefEvent(SPEECH_VISEME_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getSpeechVisemeCb);

  //RECO
  OBJRECOSCOL = OBJregister(4, 1, destroyRecognitionObj, "OBJRECOSCOL");

	RECOGNITION_END_CB = OBJgetUserEvent();
	OBJdefEvent(RECOGNITION_END_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getRecognitionEndCb);

	RECOGNITION_TEXT_CB = OBJgetUserEvent() ;
	OBJdefEvent(RECOGNITION_TEXT_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getRecognitionTextCb);

  RECOGNITION_TEXTS_ALT_CB = OBJgetUserEvent() ;
	OBJdefEvent(RECOGNITION_TEXTS_ALT_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getRecognitionTextsAltCb);

  //RECOGNITION_WORDS_CB = OBJgetUserEvent() ;
	//OBJdefEvent( RECOGNITION_WORDS_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getRecognitionWordsCb);

	RECOGNITION_START_CB = OBJgetUserEvent();
	OBJdefEvent(RECOGNITION_START_CB, (int (__cdecl *)(struct Mmachine *,int,unsigned int,int,int,int *))getRecognitionStartCb);

	k = PKhardpak(m, "SpeechEngine", NbTplPKG, TplName, TplFunc, TplNArg, TplType);

	if (FAILED(::CoInitialize(NULL)))	
    return 0;

	return k;
}


/*! 
* \brief Starting point of the DLL
*/
extern "C" __declspec (dllexport) int ScolLoadPlugin(mmachine m, cbmachine w)
{
	int		k = 0;
	SCOLinitplugin(w);

	HScol=(HWND)SCgetExtra("hscol");	
	LoadSpeech(m);
	return k;
}


/*! 
* \brief Ending point of the DLL
*/
extern "C" __declspec (dllexport) int ScolUnloadPlugin()
{
	::CoUninitialize();
	return 0;
}

// Everything inside _cond and _endcond is ignored by doxygen
//! \cond
//! \endcond