/****************************************************************************
* 
*  $Id: main.cpp,v 1.1.1.1 1999/02/23 23:48:01 jordanb Exp $
*
*  Copyright (C) 1995,1996,1997 RealNetworks, Inc.
*  All rights reserved.
*
*  http://www.real.com/devzone
*
*  This program contains proprietary information of RealNetworks, Inc.,
*  and is licensed subject to restrictions on use and distribution.
*
*  main.cpp
*
*  Example client for RealMedia Architecture (RMA).
*
*/

//
// Modification History
//
//$LB (06/12/2003) : YUV->RGB conversion is now managed with 24 bits, instead of 16
//                   and buffer I/O is also processed with 24 bits
//
//$LB (07/12/2003) : call the REALcbState Callback in ExampleVideoSurface::OptimizedBlt (exvsurf.cpp) if the pixel format
//                   doesn't match with what scol is able to process
//
//$LB (10/12/2003) : call the REALstateCb callback in ExampleErrorSink::ErrorOccurred (exerror.cpp) when an error occured
//                   now the user is warned if the video codec is missing
//


/****************************************************************************
* Defines
*/
#define INITGUID     /* Interface ID's */


/****************************************************************************
* Includes
*/

#include "pntypes.h"
#include "pnwintyp.h"
#include "pncom.h"
#include "rmapckts.h"
#include "rmacomm.h"
#include "rmamon.h"
#include "rmafiles.h"
#include "rmaengin.h"
#include "rmacore.h"
#include "rmaclsnk.h"
#include "rmaerror.h"
#include "rmaauth.h"
#include "rmawin.h"
#include "rmaausvc.h"

#include "rmasite2.h"
#include "rmavsurf.h"

#include "../Main.h"
//#include "../x/scolplugin.h"
#include "Real.h"
#include "../colors.h"

#include "os.h"
#include "fivemmap.h"
#include "exadvsnk.h"
#include "exerror.h"
#include "exsitsup.h"


#include "exaumgr.h"
#include "excontxt.h"



struct MyReal
{
    struct MyRealBuf buf;
	ExampleClientContext* exContext;
    IRMAPlayer* pPlayer;
    IRMAErrorSink* pErrorSink;
    IRMAErrorSinkControl* pErrorSinkControl;
	IRMAAudioPlayer* pAudioPlayer;
};
typedef struct MyReal *myreal;



//$LB (10/12/2003)  : store the pointer to the last myreal struct created.
//                    used by (exerror.cpp)ExampleErrorSink::ErrorOccurred to
//                    warn the user the video codec is missing
myrealbuf lastreal;

//cbmachine ww;


/****************************************************************************
* Globals
*/
FPRMCREATEENGINE	m_fpCreateEngine;
FPRMCLOSEENGINE	 	m_fpCloseEngine;
BOOL			bShowMeTheStatistics = FALSE;
HINSTANCE		    hDll		= NULL;
IRMAClientEngine* pEngine;

int typeReal;
int RealId;


/****************************************************************************
*  main
*
*/

int loadReal()
{

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nloadReal");
#endif
/***************************************/

    // prepare/load the RMACore module
    char   szDllName[_MAX_PATH];
    DWORD bufSize;
    HKEY hKey; 
    PN_RESULT hRes;
	
    if (m_fpCreateEngine) return 0;
	
    szDllName[0] = '\0'; 
    bufSize = sizeof(szDllName) - 1;
	
    if(ERROR_SUCCESS == RegOpenKey(HKEY_CLASSES_ROOT,
		"Software\\RealNetworks\\Preferences\\DT_Common", &hKey)) 
    { 
		// get the path to pnen 
		hRes = RegQueryValue(hKey, "", szDllName, (long *)&bufSize); 
		RegCloseKey(hKey); 
    }
	
    strcat(szDllName, "pnen3260.dll");
	
    if (!(hDll = LoadLibrary(szDllName))) 
    {
		MMechostr(MSKDEBUG, "Failed to load the '%s' library.\n", szDllName);
		return -1;
    }
	
    MMechostr(MSKDEBUG, "Loaded rmacore\n");
    
    // retrieve the proc addresses from the module
    m_fpCreateEngine = (FPRMCREATEENGINE) GetProcAddress(hDll, "CreateEngine");
    m_fpCloseEngine  = (FPRMCLOSEENGINE)  GetProcAddress(hDll, "CloseEngine");
	
    if (m_fpCreateEngine == NULL ||	m_fpCloseEngine == NULL  )
    {
		m_fpCreateEngine	= NULL;
		m_fpCloseEngine	= NULL;
		return -1;
	}
    // create client engine 
    if (PNR_OK != m_fpCreateEngine((IRMAClientEngine**) &pEngine))
    {
		return -1;
    }

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nloadReal ok");
#endif
/***************************************/

	return 0;
}



int REALdestroybis(myreal s)
{
/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALdestroybis");
#endif
/***************************************/

	if (s->pPlayer)	s->pPlayer->Stop();

    if (s->pAudioPlayer)
    {
		s->pAudioPlayer->Release();
		s->pAudioPlayer = NULL;
    }

    if (s->pErrorSinkControl)
    {
		s->pErrorSinkControl->RemoveErrorSink(s->pErrorSink);
		s->pErrorSinkControl->Release();
		s->pErrorSinkControl = NULL;
    }
	
    if (s->exContext)
    {
		s->exContext->Release();
		s->exContext = NULL;
    }
    
    if (s->pPlayer)
    {
		pEngine->ClosePlayer(s->pPlayer);
		s->pPlayer->Release();
		s->pPlayer = NULL;
    }

	if (s->buf.buf)
	{
		free(s->buf.buf);
		s->buf.buf=NULL;
	}

	if (s->buf.login)
	{
		free(s->buf.login);
		s->buf.login=NULL;
	}

	if (s->buf.password)
	{
		free(s->buf.password);
		s->buf.password=NULL;
	}

	free((void*)s);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALdestroybis ok");
#endif
/***************************************/

	return 0;
}






int REALdestroy2(mmachine m, int handsys, int objm)
{
	myreal s;

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALdestroy2");
#endif
/***************************************/


	s=(myreal)MMfetch(m,objm>>1,0);
	if (s==NULL) return 0;
	MMstore(m,objm>>1,0,0); // blindage 010418
	return REALdestroybis(s);
}





int REALcreateEx(mmachine m)
{
    char* pszURL=NULL;
	myreal s;
	int p,k;

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALcreateEx");
#endif
/***************************************/

	
	if (loadReal())
	{
		MMechostr(MSKDEBUG,"cannot load real dll\n");
		MMpull(m);
		MMpull(m);
		MMpull(m);
		MMset(m,0,NIL);
		return 0;
	}
		

	s=(myreal)malloc(sizeof(struct MyReal));
	s->buf.id=RealId++;
	s->buf.buf=NULL;
	s->buf.m=m;
	s->buf.login=NULL;
	s->buf.password=NULL;
	s->exContext=NULL;
    s->pPlayer=NULL;
    s->pErrorSink=NULL;
    s->pErrorSinkControl=NULL;

	if ((p=MMpull(m))!=NIL)
	{
		s->buf.password=(char*)malloc(MMsizestr(m,p>>1)+1);
		if (s->buf.password) strcpy(s->buf.password,MMstartstr(m,p>>1));
	}
	if ((p=MMpull(m))!=NIL)
	{
		s->buf.login=(char*)malloc(MMsizestr(m,p>>1)+1);
		if (s->buf.login) strcpy(s->buf.login,MMstartstr(m,p>>1));
	}

	pszURL=MMstartstr(m,MMpull(m)>>1);

    if (!(s->exContext = new ExampleClientContext()))
    {
		REALdestroybis(s);
		MMechostr(MSKDEBUG,"error in creating client context\n");
		MMset(m,0,NIL);
		return 0;
    }
    s->exContext->AddRef();		
	
	
    // create player
    if (PNR_OK != pEngine->CreatePlayer(s->pPlayer))
    {
		REALdestroybis(s);
		MMechostr(MSKDEBUG,"error in creating real player\n");
		MMset(m,0,NIL);
		return 0;
    }
	
    // initialize the example context
    s->exContext->Init(s->pPlayer,&s->buf);


	
    s->pPlayer->SetClientContext(s->exContext);
	
    s->pPlayer->QueryInterface(IID_IRMAErrorSinkControl,(void**)&s->pErrorSinkControl);
    if ( s->pErrorSinkControl )
    {	
		s->exContext->QueryInterface(IID_IRMAErrorSink,(void**)&s->pErrorSink);
		if (s->pErrorSink)
		{
			s->pErrorSinkControl->AddErrorSink(s->pErrorSink, PNLOG_EMERG, PNLOG_INFO);
		}
    }	
	if ( PNR_OK != s->pPlayer->QueryInterface(IID_IRMAAudioPlayer, (void**) &s->pAudioPlayer ))
    {
		REALdestroybis(s);
		MMechostr(MSKDEBUG,"error in opening audio\n");
		MMset(m,0,NIL);
		return 0;
    }

    // There is only one URL for this presentation
    if (PNR_OK != s->pPlayer->OpenURL(pszURL))
    {
		REALdestroybis(s);
		MMechostr(MSKDEBUG,"error in opening url\n");
		MMset(m,0,NIL);
		return 0;
    }


	s->pPlayer->Begin();
	
    p=MMmalloc(m,16,TYPEBUF); if (p==NIL) return MERRMEM;
    MMstore(m,p,0,(int)s);
	s->buf.buf=NULL;
	s->buf.size=0;
	s->buf.width=s->buf.height=0;

	if (MMpush(m,p+p+1))return MERRMEM;
	MMechostr(MSKDEBUG,"real started %d\n",s->buf.id);

	k = OBJcreate(m,typeReal,s->buf.id,-1,0);

	//$LB (10/12/2003) : store the buffer pointer
	lastreal = (myrealbuf)&(s->buf);


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALcreateEx ok");
#endif
/***************************************/

	return k;
}




int REALcreate(mmachine m)
{
int k;

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALcreate");
#endif
/***************************************/

	if (MMpush(m,NIL)) return MERRMEM;
	if (MMpush(m,NIL)) return MERRMEM;

	k = REALcreateEx(m);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALcreate ok");
#endif
/***************************************/
	return k;
}




int REALcreateFromFile(mmachine m)
{
	int k;

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALcreateFromFile");
#endif
/***************************************/

	if (k=Mpushstrbloc(m,"file:///")) return k;
	if (MMpush(m,MMget(m,1))) return MERRMEM;
	if (k=MBstrcat(m)) return k;
	MMset(m,1,MMget(m,0));
	MMpull(m);
	if (MMpush(m,NIL)) return MERRMEM;
	if (MMpush(m,NIL)) return MERRMEM;

	k = REALcreateEx(m);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALcreateFromFile ok");
#endif
/***************************************/
	return k;
}





int REALgetImage(mmachine m)
{
	int p,k;
	myreal r;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALgetImage");
#endif
/***************************************/

	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if (r==NULL) return MMpush(m,NIL);
	if (MMpush(m,r->buf.width<<1)) return MERRMEM;
	if (MMpush(m,r->buf.height<<1)) return MERRMEM;
	if (r->buf.buf)
	{
		if (Mpushstrblocn(m,(char*)r->buf.buf,r->buf.size)) return MERRMEM;
	}
	else if (MMpush(m,NIL)) return MERRMEM;
	if (MMpush(m,3*2)) return MERRMEM;

	k = MBdeftab(m);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALgetImage ok");
#endif
/***************************************/

	return k;
}



int REALdestroy(mmachine m)
{
	int p;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALdestroy");
#endif
/***************************************/

    p=MMget(m,0);
    if (p==NIL) return 0;
	OBJdelTM(m,typeReal,p);
	MMset(m,0,0);



/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALdestroy ok");
#endif
/***************************************/
	return 0;
}






int fillRenderBuffer(mmachine m, renderbuffer rb, int s2)
{
    PtrObjVoid OB ;
    PtrObjBitmap B ;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nfillRenderBuffer");
#endif
/***************************************/

    if ( s2 == NIL ) return -1;
    OB = ( PtrObjVoid ) MMstart(m,s2>>1);
    B = ( PtrObjBitmap ) MMstart(m,OB->Buffer>>1);
	if (B->bits==NULL) return -1;
	//$LB
    rb->start    = (OBJBITMAP_BUFFER)B->bits;
    rb->nextline = B->BPL;
    rb->nbcolumn = B->TailleW;
    rb->nblines  = B->TailleH;



/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nfillRenderBuffer ok");
#endif
/***************************************/

    return 0;
}






int REALblit(mmachine m)
{
	struct RenderBuffer rb;
	int i, j, kx, x, ky, y, p, i0, offset, BPL;
	myreal mr;
	//$LB
	OBJBITMAP_BUFFER s;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALblit");
#endif
/***************************************/



	p = MMpull(m);
	if (p == NIL) return 0;
	mr = (myreal) MMfetch(m, p>>1, 0);
	if (mr == NULL) return 0;
	p = MMget(m,0);
	if (p == NIL) return 0;

	if (fillRenderBuffer(m, &rb, p)) return 0;

	//$LB
	s  = (OBJBITMAP_BUFFER)rb.start;
	kx = (mr->buf.width<<8) / rb.nbcolumn;
	ky = (mr->buf.height<<8) / rb.nblines;
    
	BPL = rb.nbcolumn *3;

	
	y=0;
	for(i=0;i<rb.nblines;i++)
	{
		i0 = (y>>8)*mr->buf.width;
		x  = 0;
		for (j=0; j < BPL; j+=3)
		{
			//$LB (06/12/2003) _COLOR_I16_TO_BGR (mr->buf.buf[i0+(x>>8)], &r, &g, &b); 
			offset = (i0+(x>>8)) * 3;
		
			s[j +0] = mr->buf.buf[offset + 0]; 
			s[j +1] = mr->buf.buf[offset + 1];
			s[j +2] = mr->buf.buf[offset + 2];
	
			x+=kx;
		}
		y+=ky;
		//$LB
		s+=rb.nextline;
	}
  


 
/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALblit ok");
#endif
/***************************************/

	return 0;
}











int REALisDone(mmachine m)
{
	int p,k;
	myreal r;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALisDone");
#endif
/***************************************/

	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	if (r->pPlayer->IsDone()) return MMpush(m,1<<1);

	k  =MMpush(m,0);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALisDone ok");
#endif
/***************************************/

	return k;
}




int REALpause(mmachine m)
{
	int p,k;
	myreal r;

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALpause");
#endif
/***************************************/

	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	r->pPlayer->Pause();

	k = MMpush(m,0);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALpause ok");
#endif
/***************************************/
	return k;
}






int REALplay(mmachine m)
{
	int p,k;
	myreal r;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALplay");
#endif
/***************************************/

	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	r->pPlayer->Begin();

	k = MMpush(m,0);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALplay ok");
#endif
/***************************************/

	return k;
}





int REALstop(mmachine m)
{
	int p,k;
	myreal r;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALstop");
#endif
/***************************************/

	
	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	r->pPlayer->Stop();

	k = MMpush(m,0);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALstop ok");
#endif
/***************************************/

	return k;
}




int REALseek(mmachine m)
{
	int p,i,k;
	myreal r;

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALseek");
#endif
/***************************************/


	i=MMpull(m)>>1;
	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	r->pPlayer->Seek(i); 

	k = MMpush(m,0);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALseek ok");
#endif
/***************************************/

	return k;
}




int REALisLive(mmachine m)
{
	int p,k;
	myreal r;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALisLive");
#endif
/***************************************/


	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	if (r->pPlayer->IsLive()) return MMpush(m,1<<1);

	k = MMpush(m,0);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALisLive ok");
#endif
/***************************************/

	return k;
}




int REALsetVolume(mmachine m)
{
	int p,i,k;
	myreal r;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALsetVolume");
#endif
/***************************************/

	i=MMpull(m)>>1;
	if (i<0) i=0;
	if (i>100) i=100;
	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	r->pAudioPlayer->GetAudioVolume()->SetVolume(i);

	k = MMpush(m,0);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALsetVolume ok");
#endif
/***************************************/

	return k;
}



int REALgetVolume(mmachine m)
{
	int p,i,k;
	myreal r;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALgetVolume");
#endif
/***************************************/

	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	i=r->pAudioPlayer->GetAudioVolume()->GetVolume();

	k = MMpush(m,i*2);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALgetVolume ok");
#endif
/***************************************/

	return k;
}




int REALsetMute(mmachine m)
{
	int p,i,k;
	myreal r;

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALsetMute");
#endif
/***************************************/

	i=MMpull(m)>>1;
	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	if (i) r->pAudioPlayer->GetAudioVolume()->SetMute(TRUE);
	else r->pAudioPlayer->GetAudioVolume()->SetMute(FALSE);

	k = MMpush(m,0);


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALsetMute ok");
#endif
/***************************************/

	return k;
}








int REALgetMute(mmachine m)
{
	int p,i,k;
	myreal r;


/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALgetMute");
#endif
/***************************************/

	p=MMpull(m);
	if (p==NIL) return MMpush(m,NIL);
	r=(myreal)MMfetch(m,p>>1,0);
	if ((r==NULL)||(r->pPlayer==NULL)) return MMpush(m,NIL);
	i=r->pAudioPlayer->GetAudioVolume()->GetMute();

	k = MMpush(m,i*2);

/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALgetMute ok");
#endif
/***************************************/

	return k;
}



int REALcbImage(mmachine m)
{
/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALcbImage");
#endif
/***************************************/

  return OBJaddreflex(m,typeReal,RFLREAL_IMAGE);
}




int REALcbState(mmachine m)
{
/***************************************/
#ifdef _DEBUG_MMEDIA_
	MMechostr(MSKDEBUG, "\nREALcbState");
#endif
/***************************************/

  return OBJaddreflex(m,typeReal,RFLREAL_STATE);
}




#define NREALPKG 29


char* REALname[NREALPKG]=
{
	"RealState","RealBuffering","RealContacting","RealOnBegin",
	"RealOnPause","RealOnStop","RealOnClosed","RealOnOpened",
	"RealPosition",

	//$LB (07/12/2003) : added REALerror state value to warn the user he doesn't have the codec
	"RealError",

	"RealStream","REALcreate","REALgetImage","REALdestroy",
	"REALblit","REALcbImage","REALisDone","REALcbState",
	"REALpause","REALplay","REALstop","REALseek",
	"REALisLive","REALcreateEx","REALsetVolume","REALsetMute",
	"REALgetVolume","REALgetMute","REALcreateFromFile"
};

#define bullshit int (__cdecl *)(struct Mmachine *)
int (*REALfun[NREALPKG])(mmachine m)=
{
	NULL,(bullshit)REALbuffering,(bullshit)REALcontacting,(bullshit)REALonBegin,
	(bullshit)REALonPause,(bullshit)REALonStop,(bullshit)REALonClosed,(bullshit)REALonOpened,
	(bullshit)REALposition,

	//$LB (07/12/2003) : i don't know who it comes from, but i love the "bullshit" thing... :)
	//                   added REALerror state value to warn the user he doesn't have the codec
	(bullshit)REALerror,

	NULL,REALcreate,REALgetImage,REALdestroy,
	REALblit,REALcbImage,REALisDone,REALcbState,
	REALpause,REALplay,REALstop,REALseek,
	REALisLive,REALcreateEx,REALsetVolume,REALsetMute,
	REALgetVolume,REALgetMute,REALcreateFromFile
};
int REALnarg[NREALPKG]=
{
	TYPTYPE,TYPCONS,TYPCONS,TYPCONS0,
	TYPCONS0,TYPCONS0,TYPCONS0,TYPCONS0,
	TYPCONS,
	//$LB (07/12/2003) 
	TYPCONS,

	TYPTYPE,2,1,1,
	2,3,1,3,
	1,1,1,2,
	1,4,2,2,
	1,1,2

};
char* REALtype[NREALPKG]=
{
	NULL,"fun [I] RealState","fun [S] RealState","fun [] RealState",
	"fun [] RealState","fun [] RealState","fun [] RealState","fun [] RealState",
	"fun [[I I]] RealState",

	//$LB (07/12/2003) 
	"fun [[I S]] RealState",

	NULL,"fun[Chn S] RealStream","fun[RealStream] [I I S]","fun[RealStream] I",
	"fun[ObjBitmap RealStream] ObjBitmap","fun [RealStream fun [RealStream u0] u1 u0] RealStream","fun[RealStream] I","fun [RealStream fun [RealStream u0 RealState] u1 u0] RealStream",
	"fun[RealStream] I","fun[RealStream] I","fun[RealStream] I","fun[RealStream I] I",
	"fun[RealStream] I","fun[Chn S S S] RealStream","fun[RealStream I] I","fun[RealStream I] I",
	"fun[RealStream] I","fun[RealStream] I","fun[Chn P] RealStream"
};

int SCOLloadREAL(mmachine m,cbmachine w)
//extern "C" __declspec (dllexport) int SCOLloadREAL(mmachine m,cbmachine w)
{
	int k;
	
	ww=w;
	m_fpCreateEngine	= NULL;
	m_fpCloseEngine	= NULL;
	RealId=123;
	k=PKhardpak(m,"REAL-1.0.pkg",NREALPKG,REALname,REALfun,REALnarg,REALtype);
	typeReal=OBJregister(RFLREAL_NB,0,REALdestroy2,"OBJTYPEREAL");
	return k;
}

	