/* Wave.c  by S. Metrot 16/12/96
           gestion de la lecture des waves par une machine scol ... */

#include "x/version.h"
#include "x/scolplugin.h"

#include <mmsystem.h>
#include <VFW.h>

#include "objstr.h"

#include "sound/wave.h"

#include "objstr.h"

int OBJTYPMMEDIA;

/* reflexes type MMEDIA */
#define RFLMMEDIA_NB    1
#define RFLMMEDIA_MODE  0
//#define RFLMMEDIA_ERROR 1

// uncomment this line to attach every multimedia file to it's parent window
//#define __STICKtoWINDOW

/* canal parent x y w h file type */
int _CRmulti(mmachine m)
{
  int parent,x,y,w,h,file,type,flags;
  struct ObjWindow * Window;
  char * filename;
  PtrObjVoid OB;
  HWND hwn,hwnd;
  char MMERROR[255];
  int err;

  type=MMpull(m)>>1;
  file=MMpull(m)>>1;
  h=MMpull(m)>>1;
  w=MMpull(m)>>1;
  y=MMpull(m)>>1;
  x=MMpull(m)>>1;
  parent=MMpull(m)>>1;

  if (parent==NIL) 
  {
    MMset(m,0,NIL);
    return 0;
  }
  else
  {
    OB = ( PtrObjVoid ) MMstart(m,(parent) ) ;
    Window = (struct ObjWindow *) MMstart(m,(OB->Buffer>>1) ) ;
    hwn=Window->WHandler;
  }

//  if (flags==NIL) flags=0;
  if (file==NIL && type==NIL) 
  {
    MMset(m,0,NIL);
    return 0;
  }

  if (file==NIL)
    filename=MMstartstr(m,type);
  else
    filename=MMstartstr(m,file);

  flags=MCIWNDF_NOERRORDLG|MCIWNDF_NOMENU|MCIWNDF_NOOPEN|MCIWNDF_NOPLAYBAR|MCIWNDF_NOTIFYMODE;
  hwnd=MCIWndCreate(hwn,(HINSTANCE)SCgetExtra("this_inst"),flags, filename); 

  if (!hwnd)
  {
//    MMechostr(MSKDEBUG,"Cannot create this control!\n");
    MMset(m,0,NIL);
    return 0;
  }

  err=MCIWndGetError(hwnd,MMERROR,255);
//  MMechostr(MSKDEBUG,"ERROR ON MULTIMEDIA! : %d %s\n",err,MMERROR);

  if (err)
  {
    MMset(m,0,NIL);
    return 0;
  }

  SetWindowPos(hwnd,           // window to resize 
    NULL,                          // z-order: don't care 
    x, y,                          // position: don't care
    w,      // width 
    h,        //  new RECT
    /*SWP_NOMOVE |*/ SWP_NOZORDER | SWP_NOACTIVATE); 


  if (MMpush(m,(long)hwnd<<1)) 
  {
//    MMechostr(MSKDEBUG,"Memory Error.\n");
    return MERRMEM;
  }

//  MMechostr(MSKDEBUG,"MMEDIA OK!!!\n");
#ifdef __STICKtoWINDOW
  return OBJcreate(m,OBJTYPMMEDIA,(LONG)hwnd,OBJTYPWINDOW,parent);
//  return OBJcreate(m,OBJTYPMMEDIA,(LONG)h,OBJTYPWINDOW,parent);
#else
  return OBJcreate(m,OBJTYPMMEDIA,(LONG)hwnd,0,(int)NULL);
//  return OBJcreate(m,OBJTYPMMEDIA,(LONG)h,0,(int)NULL);
#endif
}

int _PLAYmulti (mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndPlay((HWND)h);

  return 0;
}

int _PAUSEmulti (mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndPause((HWND)h);

  return 0;
}

int _DSmulti (mmachine m)
{
  int h;

//  MMechostr(MSKDEBUG,"DESTROY MMEDIA \n");

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndStop((HWND)h);
  MCIWndClose((HWND)h);
  MCIWndDestroy((HWND)h);

  MMset(m,0,2);
  return 0;
}

int _SETmultiXYsource (mmachine m)
{
  int x,y,w,h;
  RECT rDest; 
  int hwnd;

  h=MMpull(m)>>1;
  w=MMpull(m)>>1;
  y=MMpull(m)>>1;
  x=MMpull(m)>>1;
  hwnd=MMget(m,0)>>1;
  if(hwnd==NIL) return 0;

  rDest.left = x; 
  rDest.right = x+w; 
  rDest.top = y; 
  rDest.bottom = y+h; 

  MCIWndPutSource((HWND)hwnd, &rDest);   // new source rectangle 
 
  return 0;
}

int _SETmultiXYdest (mmachine m)
{
  int x,y,w,h;
  RECT rDest; 
  int hwnd;

  h=MMpull(m)>>1;
  w=MMpull(m)>>1;
  y=MMpull(m)>>1;
  x=MMpull(m)>>1;
  hwnd=MMget(m,0)>>1;
  if(hwnd==NIL) return 0;

  rDest.left = x; 
  rDest.right = x+w; 
  rDest.top = y; 
  rDest.bottom = y+h; 

  MCIWndPutDest((HWND)hwnd, &rDest);   // new source rectangle 
 
  return 0;
}

int _SETmultiXYwin (mmachine m)
{
  int x,y,w,h;
  int hwnd;

  h=MMpull(m)>>1;
  w=MMpull(m)>>1;
  y=MMpull(m)>>1;
  x=MMpull(m)>>1;
  hwnd=MMget(m,0)>>1;
  if(hwnd==NIL) return 0;

  SetWindowPos((HWND)hwnd,           // window to resize 
    NULL,                          // z-order: don't care 
    x, y,                          // position: don't care
    w,      // width 
    h,        //  new RECT
    SWP_NOZORDER | SWP_NOACTIVATE); 
 
  return 0;
}

int _GETmultiXYwin (mmachine m)
{
  int hwnd;
  RECT rect;
  int t;

  hwnd=MMget(m,0)>>1;
  if (hwnd==NIL)
    return 0;

  GetWindowRect((HWND)hwnd,&rect);
//  SetWindowPos(hwnd,&rect);

  t=MMmalloc(m,4,TYPETAB);
  if (t==NIL) 
    return MERRMEM;

  MMstore(m,t,0,rect.left);
  MMstore(m,t,1,rect.top);
  MMstore(m,t,2,rect.right);
  MMstore(m,t,3,rect.bottom);

  MMset(m,0,t*2+1);

  return 0;
}

int _GETmultiXYdest (mmachine m)
{
  int hwnd;
  RECT rect;
  int t;

  hwnd=MMget(m,0)>>1;
  if (hwnd==NIL)
    return 0;

  MCIWndGetDest((HWND)hwnd,&rect);

  t=MMmalloc(m,4,TYPETAB);
  if (t==NIL) 
    return MERRMEM;

  MMstore(m,t,0,rect.left);
  MMstore(m,t,1,rect.top);
  MMstore(m,t,2,rect.right);
  MMstore(m,t,3,rect.bottom);

  MMset(m,0,t*2+1);

  return 0;
}

int _SETMultiReflexMode (mmachine m)
{
 	return OBJaddreflex(m,OBJTYPMMEDIA,RFLMMEDIA_MODE);
}

/*
int _SETMultiReflexError (mmachine m)
{
 	return OBJaddreflex(m,OBJTYPMMEDIA,RFLMMEDIA_ERROR);
}
*/
 // to handle multimedia events & notifies
int SCOLMmEventMode(mmachine m,HWND hwnd,unsigned msg,UINT wParam, LONG lParam,int *ret)
{
  int k;
  HWND h=(HWND)wParam;

/*  MMechostr(MSKDEBUG,"EVENT MMEDIA MODE\n");
	MMechostr(MSKDEBUG,"Mode mmedia %d window:%X\n",lParam,wParam);*/
  k=OBJbeginreflex(m,OBJTYPMMEDIA,(int)h,RFLMMEDIA_MODE);
  if (k==0)
	{
//		if (MMpush(m,wParam<<1)) return MERRMEM;
		if (MMpush(m,lParam<<1)) return MERRMEM;
		return OBJcallreflex(m,1);
	}
//  MMechostr(MSKDEBUG,"...NO REFLEX MMEDIA MODE\n");
  return 0;
}

/*
int SCOLMmEventError(mmachine m,UINT wParam,LONG lParam) // to handle multimedia events & notifies
{
  int k;
  HWND h=wParam;

  MMechostr(MSKDEBUG,"EVENT MMEDIA ERROR\n");
  k=OBJbeginreflex(m,OBJTYPMMEDIA,h,RFLMMEDIA_ERROR);
  if (k==0)
	{
 		MMechostr(MSKDEBUG,"Error mmedia %d window:%X\n",lParam,wParam);
//		if (MMpush(m,wParam<<1)) return MERRMEM;
		if (MMpush(m,lParam<<1)) return MERRMEM;
		return OBJcallreflex(m,2);
	}
  MMechostr(MSKDEBUG,"...NO REFLEX MMEDIA ERROR\n");
  return 0;
}
*/

int MMCloseDevice(mmachine m,HWND h)
{
//  MMechostr(MSKDEBUG,"AUTO DESTROY MMEDIA \n");

  MCIWndDestroy(h);

  return 0;
}

int _EJECTmulti (mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndEject((HWND)h);

  return 0;
}

int _GETmultiRepeat (mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  if (MCIWndGetRepeat((HWND)h))
    MMset(m,0,2);
  else
    MMset(m,0,0);

  return 0;
}

int _PLAYmultiFrom (mmachine m)
{
  int h;
  int loc;

  loc=MMpull(m)>>1;
  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndPlayFrom((HWND)h,loc);

  return 0;
}

int _PLAYmultiFromTo (mmachine m)
{
  int h,loc1,loc2;

  loc2=MMpull(m)>>1;
  loc1=MMpull(m)>>1;
  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndPlayFromTo((HWND)h,loc1,loc2);

  return 0;
}

int _PLAYmultiReverse (mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndPlayReverse((HWND)h);

  return 0;
}

int _PLAYmultiTo (mmachine m)
{
  int h,loc1;

  loc1=MMpull(m)>>1;
  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndPlayTo((HWND)h,loc1);

  return 0;
}

int _SETmultiRepeat (mmachine m)
{
  int h;
  BOOL repeat;

  repeat=(MMpull(m)>>1)?TRUE:FALSE;
  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndSetRepeat((HWND)h,repeat);

  return 0;
}

int _SETmultiEnd(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndEnd((HWND)h);

  return 0;
}

int _GETmultiEnd(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndGetEnd((HWND)h)<<1);

  return 0;
}

int _GETmultiLength(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndGetLength((HWND)h)<<1);

  return 0;
}

int _GETmultiPosition(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndGetPosition((HWND)h)<<1);

  return 0;
}

int _GETmultiStart(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndGetStart((HWND)h)<<1);

  return 0;
}

int _SETmultiHome(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndHome((HWND)h);

  return 0;
}

int _SEEKmulti(mmachine m)
{
  int h,loc;

  loc=MMpull(m)>>1;
  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndSeek((HWND)h,loc);

  return 0;
}

int _STEPmulti(mmachine m)
{
  int h,step;

  step=MMpull(m)>>1;
  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndStep((HWND)h,step);

  return 0;
}

int _GETmultiSpeed(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndGetSpeed((HWND)h)<<1);

  return 0;
}

int _GETmultiVolume(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndGetVolume((HWND)h)<<1);

  return 0;
}

int _GETmultiZoom(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndGetZoom((HWND)h)<<1);

  return 0;
}

int _SETmultiSpeed(mmachine m)
{
  int h,speed;

  speed=MMpull(m)>>1;
  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndSetSpeed((HWND)h,speed);

  return 0;
}

int _SETmultiVolume(mmachine m)
{
  int h,vol;

  vol=MMpull(m)>>1;
  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndSetVolume((HWND)h,vol);

  return 0;
}

int _SETmultiZoom(mmachine m)
{
  int h,zoom;

  zoom=MMpull(m)>>1;
  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndSetZoom((HWND)h,zoom);

  return 0;
}

int _GETmultiXYsource (mmachine m)
{
  int hwnd;
  RECT rect;
  int t;

  hwnd=MMget(m,0)>>1;
  if (hwnd==NIL)
    return 0;

  MCIWndGetSource((HWND)hwnd,&rect);

  t=MMmalloc(m,4,TYPETAB);
  if (t==NIL) 
    return MERRMEM;

  MMstore(m,t,0,rect.left);
  MMstore(m,t,1,rect.top);
  MMstore(m,t,2,rect.right);
  MMstore(m,t,3,rect.bottom);

  MMset(m,0,t*2+1);

  return 0;
}

int _GETmultiTimeFormat(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndGetTimeFormat((HWND)h,NULL,0)<<1);

  return 0;
}

int _SETmultiUseFrames(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndUseFrames((HWND)h);
  return 0;
}

int _SETmultiUseTime(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndUseTime((HWND)h);
  return 0;
}

int _SETmultiUseTracks(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndSetTimeFormat((HWND)h,"track");
  return 0;
}

int _SETmultiUseSamples(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndSetTimeFormat((HWND)h,"samples");
  return 0;
}

int _SETmultiUseBytes(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWndSetTimeFormat((HWND)h,"bytes");
  return 0;
}

int _GETmultiCanEject(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndCanEject((HWND)h)<<1);

  return 0;
}

int _GETmultiCanPlay(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndCanPlay((HWND)h)<<1);

  return 0;
}

int _GETmultiMode(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MMset(m,0,MCIWndGetMode((HWND)h,NULL,0)<<1);

  return 0;
}




/*
int _multi(mmachine m)
{
  int h;

  h=MMget(m,0)>>1;
  if(h==NIL) return 0;

  MCIWnd(h);

  return 0;
}
*/

int _CDAUDIO (mmachine m)
{
  return Mpushstrbloc (m,"CDAUDIO");
}

int _DIGITALVIDEO (mmachine m)
{
  return Mpushstrbloc (m,"DIGITALVIDEO");
}

int _VCR (mmachine m)
{
  return Mpushstrbloc (m,"VCR");
}

int _VIDEODISC (mmachine m)
{
  return Mpushstrbloc (m,"VIDEODISC");
}

int D2MMEDIA(mmachine m,int handsys,int objm)
{
    MMCloseDevice (m,(HWND)handsys);
	return 0;
}


#define NWAVEPKG 58

char* wavename[NWAVEPKG]=
{ "Multi",
  "Media",
  "_CRmulti",
  "_PLAYmulti",
  "_PAUSEmulti",
  "_DSmulti",
  "_SETmultiXYsource",
  "_GETmultiXYsource",
  "_SETmultiXYdest",
  "_GETmultiXYdest",
  "_SETmultiXYwin",
  "_GETmultiXYwin",
  "_EJECTmulti",
  "_PLAYmultiFrom",
  "_PLAYmultiFromTo",
  "_PLAYmultiReverse", //16
  "_PLAYmultiTo",
  "_SETmultiRepeat",
  "_GETmultiRepeat",
  "_SETmultiEnd",
  "_GETmultiEnd",
  "_GETmultiLength",
  "_GETmultiPosition",
  "_GETmultiStart",
  "_SETmultiHome",
  "_SEEKmulti",
  "_STEPmulti",
  "_GETmultiSpeed",
  "_GETmultiVolume",
  "_GETmultiZoom",
  "_SETmultiSpeed",
  "_SETmultiVolume", //32
  "_SETmultiZoom",
  "_GETmultiTimeFormat",
  "_SETmultiUseFrames",
  "_SETmultiUseTime",
  "_SETmultiUseTracks",
  "_SETmultiUseSamples",
  "_SETmultiUseBytes",
  "_GETmultiCanEject",
  "_GETmultiCanPlay",
  "_GETmultiMode",
  "_SETmultiReflexMode",
  "_CDAUDIO",
  "_DIGITALVIDEO",
  "_VCR",
  "_VIDEODISC",
  "MEDIA_MODE_NOTREADY", //48
  "MEDIA_MODE_STOP",
  "MEDIA_MODE_PLAY",
  "MEDIA_MODE_SEEK",
  "MEDIA_MODE_PAUSE",
  "MEDIA_MODE_OPEN",
  "FORMAT_BYTES",
  "FORMAT_FRAMES",
  "FORMAT_MILLISECONDS",
  "FORMAT_SAMPLES",
  "FORMAT_TRACKS"
};
int (*wavefun[NWAVEPKG])(mmachine m)=
{ NULL,
  NULL,
  _CRmulti,
  _PLAYmulti,
  _PAUSEmulti,
  _DSmulti,
  _SETmultiXYsource,
  _GETmultiXYsource,
  _SETmultiXYdest,
  _GETmultiXYdest,
  _SETmultiXYwin,
  _GETmultiXYwin,
  _EJECTmulti,
  _PLAYmultiFrom,
  _PLAYmultiFromTo,
  _PLAYmultiReverse,
  _PLAYmultiTo,
  _SETmultiRepeat,
  _GETmultiRepeat,
  _SETmultiEnd,
  _GETmultiEnd,
  _GETmultiLength,
  _GETmultiPosition,
  _GETmultiStart,
  _SETmultiHome,
  _SEEKmulti,
  _STEPmulti,
  _GETmultiSpeed,
  _GETmultiVolume,
  _GETmultiZoom,
  _SETmultiSpeed,
  _SETmultiVolume,
  _SETmultiZoom,
  _GETmultiTimeFormat,
  _SETmultiUseFrames,
  _SETmultiUseTime,
  _SETmultiUseTracks,
  _SETmultiUseSamples,
  _SETmultiUseBytes,
  _GETmultiCanEject,
  _GETmultiCanPlay,
  _GETmultiMode,
  _SETMultiReflexMode,
  _CDAUDIO,
  _DIGITALVIDEO,
  _VCR,
  _VIDEODISC,
  (void*)(int)(2*MCI_MODE_NOT_READY),(void*)(int)(2*MCI_MODE_STOP),(void*)(int)(2*MCI_MODE_PLAY),(void*)(int)(2*MCI_MODE_SEEK),
  (void*)(int)(2*MCI_MODE_PAUSE),(void*)(int)(2*MCI_MODE_OPEN),(void*)(int)(2*MCI_FORMAT_BYTES),(void*)(int)(2*MCI_FORMAT_FRAMES),
  (void*)(int)(2*MCI_FORMAT_MILLISECONDS),(void*)(int)(2*MCI_FORMAT_SAMPLES),(void*)(int)(2*MCI_FORMAT_TMSF)
};

int wavenarg[NWAVEPKG]=
{TYPTYPE,
 TYPTYPE,
 8 ,//_CRmulti,
 1, //_PLAYmulti,
 1, //_PAUSEmulti,
 1, //_DSmulti,
 5, //_SETmultiXYsource,
 1, //_GETmultiXYsource,
 5, //_SETmultiXYdest,
 1, //_GETmultiXYdest,
 5, //_SETmultiXYwin,
 1, //_GETmultiXYwin,
 1, //_EJECTmulti,
 2, //_PLAYmultiFrom,
 3, //_PLAYmultiFromTo,
 1, //_PLAYmultiReverse,
 2, //_PLAYmultiTo,
 2, //_SETmultiRepeat,
 1, //_GETmultiRepeat,
 1, //_SETmultiEnd,
 1, //_GETmultiEnd,
 1, //_GETmultiLength,
 1, //_GETmultiPosition,
 1, //_GETmultiStart,
 1, //_SETmultiHome,
 2, //_SEEKmulti,
 2, //_STEPmulti,
 1, //_GETmultiSpeed,
 1, //_GETmultiVolume,
 1, //_GETmultiZoom,
 2, //_SETmultiSpeed,
 2, //_SETmultiVolume,
 2, //_SETmultiZoom,
 1, //_GETmultiTimeFormat,
 1, //_SETmultiUseFrames,
 1, //_SETmultiUseTime,
 1, //_SETmultiUseTracks,
 1, //_SETmultiUseSamples,
 1, //_SETmultiUseBytes,
 1, //_GETmultiCanEject,
 1, //_GETmultiCanPlay,
 1, //_GETmultiMode,
 3,
 0,
 0,
 0,
 0,
 TYPVAR,TYPVAR,TYPVAR,TYPVAR,
 TYPVAR,TYPVAR,TYPVAR,TYPVAR,
 TYPVAR,TYPVAR,TYPVAR
};
 
char* wavetype[NWAVEPKG]=
{NULL,
 NULL,
 "fun [Chn ObjWin I I I I P Media] Multi" ,//_CRmulti,
 "fun [Multi] Multi", //_PLAYmulti,
 "fun [Multi] Multi", //_PAUSEmulti,
 "fun [Multi] I", //_DSmulti,
 "fun [Multi I I I I] Multi", //_SETmultiXYsource,
 "fun [Multi] [I I I I]", //_GETmultiXYsource,
 "fun [Multi I I I I] Multi", //_SETmultiXYdest,
 "fun [Multi] [I I I I]", //_GETmultiXYdest,
 "fun [Multi I I I I] Multi", //_SETmultiXYwin,
 "fun [Multi] [I I I I]", //_GETmultiXYwin,
 "fun [Multi] Multi", //_EJECTmulti,
 "fun [Multi I] Multi", //_PLAYmultiFrom,
 "fun [Multi I I] Multi", //_PLAYmultiFromTo,
 "fun [Multi] Multi", //_PLAYmultiReverse,
 "fun [Multi I] Multi", //_PLAYmultiTo,
 "fun [Multi I] Multi", //_SETmultiRepeat,
 "fun [Multi] I", //_GETmultiRepeat,
 "fun [Multi] Multi", //_SETmultiEnd,
 "fun [Multi] I", //_GETmultiEnd,
 "fun [Multi] I", //_GETmultiLength,
 "fun [Multi] I", //_GETmultiPosition,
 "fun [Multi] I", //_GETmultiStart,
 "fun [Multi] Multi", //_SETmultiHome,
 "fun [Multi I] Multi", //_SEEKmulti,
 "fun [Multi I] Multi", //_STEPmulti,
 "fun [Multi] I", //_GETmultiSpeed,
 "fun [Multi] I", //_GETmultiVolume,
 "fun [Multi] I", //_GETmultiZoom,
 "fun [Multi I] Multi", //_SETmultiSpeed,
 "fun [Multi I] Multi", //_SETmultiVolume,
 "fun [Multi I] Multi", //_SETmultiZoom,
 "fun [Multi] I", //_GETmultiTimeFormat,
 "fun [Multi] Multi", //_SETmultiUseFrames,
 "fun [Multi] Multi", //_SETmultiUseTime,
 "fun [Multi] Multi", //_SETmultiUseTracks,
 "fun [Multi] Multi", //_SETmultiUseSamples,
 "fun [Multi] Multi", //_SETmultiUseBytes,
 "fun [Multi] I", //_GETmultiCanEject,
 "fun [Multi] I", //_GETmultiCanPlay,
 "fun [Multi] I", //_GETmultiMode,
 "fun [Multi fun [Multi u0 I] u1 u0] Multi",
 "fun [] Media",
 "fun [] Media",
 "fun [] Media",
 "fun [] Media",
 "I","I","I","I",
 "I","I","I","I",
 "I","I","I"
};

int IniMMEDIA(mmachine m)
{
	int k;

	OBJTYPMMEDIA=OBJregister(RFLMMEDIA_NB,1,D2MMEDIA,"OBJTYPMMEDIA");
	OBJdefEvent(MCIWNDM_NOTIFYMODE,SCOLMmEventMode);

	if (k=PKhardpak(m,"wave.pkg",NWAVEPKG,wavename,wavefun
		,wavenarg,wavetype)) 
		return k;

	return 0;
}
