/* -*- Mode: C++; tab-width: 4; c-indent-level: 4; -*- */
/* ----------------------------------------------------------------------

   Ultramarine COM like Interfaces

   &

   Ultramarine API の GUID風

---------------------------------------------------------------------- */
#ifndef __UMUTCOM_H__
#define __UMUTCOM_H__

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#pragma pack(push,8)


//
// UMID typedefs
//
typedef DWORD UMID;
typedef UMID* LPUMID;
typedef UMID*  PUMID;


// helper function
#define MAKEVER(iid,version)  ((((DWORD)(iid))&0xffff0000) | (((DWORD)(version))&0x0000ffff))


//
// COM風の定義のためのマクロ(comのそれと重なりそうだんねー)
//
#ifdef __cplusplus
// C++ {
#define _THIS_
#define _THIS  void
#define _PURE  =0
#define UMUTMETHOD(method) virtual UTRET __stdcall method
// }
#else 
// C {
#define _THIS_ void* This,
#define _THIS  void* This
#define _PURE
#define UMUTMETHOD(method) UTRET (__stdcall * method)
// }
#endif



//
// UMIDs
//
#define UMID_UNKNOWN   (0x00000000)
#define UMID_UMUTCTRL  (0x00010000)
#define UMID_UMSTATUS  (0x00020000)
#define UMID_UMCHANNELSTATUS (0x00030000)
#define UMID_UMMALLOC  (0x01100000)



//==========================================================================;
//
//                             Interfaces...
//
//==========================================================================;

//
// [ IUMUnknown ]
//
// AddRef,Releaseはダミー
//

#ifdef __cplusplus
struct IUMUnknown {
#else
struct ifaceIUMUnknown {
#endif
	/*** IUnknown methods ***/
	UMUTMETHOD(QueryInterface) ( _THIS_ UMID riid, LPVOID * ppvObj) _PURE;
	UMUTMETHOD(AddRef)         ( _THIS) _PURE;    // dummy
	UMUTMETHOD(Release)        ( _THIS) _PURE;    // dummy
};
#ifndef __cplusplus
typedef struct IUMUnknown {
	struct ifaceIUMUnknown *lpVtbl;
} IUMUnknown;
typedef struct ifaceIUMUnknown ifaceIUMUnknown;
#define IUMUnknown_QueryInterface(p,a,b)   (p)->lpVtbl->QueryInterface(p,a,b)
#define IUMUnknown_AddRef(p)               (p)->lpVtbl->AddRef(p)
#define IUMUnknown_Release(p)              (p)->lpVtbl->Release(p)
#endif



//
// [ IUMMalloc ]
//
// メモリ管理
//

#ifdef __cplusplus
struct IUMMalloc : public IUMUnknown {
#else
struct ifaceIUMMalloc {
#endif
	/*** IUnknown methods ***/
	UMUTMETHOD(QueryInterface) ( _THIS_ UMID riid, LPVOID * ppvObj) _PURE;
	UMUTMETHOD(AddRef)         ( _THIS) _PURE;
	UMUTMETHOD(Release)        ( _THIS) _PURE;

	/*** IUMMalloc methods ***/
	UMUTMETHOD(Malloc) ( _THIS_ int size, void** ppMem) _PURE;
	UMUTMETHOD(Free)   ( _THIS_ void* pMem) _PURE;
};

#ifndef __cplusplus
typedef struct IUMMalloc {
	struct ifaceIUMMalloc *lpVtbl;
} IUMMalloc;
typedef struct ifaceIUMMalloc ifaceIUMMalloc;
#define IUMMalloc_Malloc(p,a,b)            (p)->lpVtbl->Malloc(p,a,b)
#define IUMMalloc_Free(p,a)                (p)->lpVtbl->Free(p,a)
#endif






//
// [ IUMChannelStatus ]
//
// UMの各チャンネルの演奏状態に関する情報を得るためのインターフェース
//
#ifdef __cplusplus
struct IUMChannelStatus : public IUMUnknown {
#else
struct ifaceIUMChannelStatus {
#endif
	/*** IUnknown methods ***/
	UMUTMETHOD(QueryInterface) ( _THIS_ UMID riid, LPVOID * ppvObj) _PURE;
	UMUTMETHOD(AddRef)         ( _THIS) _PURE;
	UMUTMETHOD(Release)        ( _THIS) _PURE;

	/*** IUMChannelStatus methods ***/
	UMUTMETHOD( GetInfo )       ( _THIS_ UIPlayChannelInfo* pInfo) _PURE;
};

#ifndef __cplusplus
typedef struct IUMChannelStatus {
	struct ifaceIUMChannelStatus *lpVtbl;
} IUMChannelStatus;
typedef struct ifaceIUMChannelStatus ifaceIUMChannelStatus;
#define IUMChannelStatus_QueryInterface(p,a)            (p)->lpVtbl->QueryInterface(p,a)
#define IUMChannelStatus_AddRef(p)                      (p)->lpVtbl->AddRef(p)
#define IUMChannelStatus_Release(p)                     (p)->lpVtbl->Release(p)

#define IUMChannelStatus_GetInfo(p,a)                   (p)->lpVtbl->GetInfo(p,a)
#endif



//
// [ IUMStatus ]
//
// UMの演奏状態に関する情報を得るためのインターフェース
//

#ifdef __cplusplus
struct IUMStatus : public IUMUnknown {
#else
struct ifaceIUMStatus {
#endif
	/*** IUnknown methods ***/
	UMUTMETHOD(QueryInterface) ( _THIS_ UMID riid, LPVOID * ppvObj) _PURE;
	UMUTMETHOD(AddRef)         ( _THIS) _PURE;
	UMUTMETHOD(Release)        ( _THIS) _PURE;

	/*** IUMStatus methods ***/
	UMUTMETHOD( GetPlayLevel ) ( _THIS_ int* left, int* right) _PURE;
	UMUTMETHOD( GetPlayClock ) ( _THIS_ long* clocks) _PURE;
	UMUTMETHOD( GetChannelStatus ) ( _THIS_ UMID umid, int chno, IUMChannelStatus** ppObj ) _PURE;
	UMUTMETHOD( GetChannelInfo ) ( _THIS_ int chno, UIPlayChannelInfo* pInfo ) _PURE;
};

#ifndef __cplusplus
typedef struct IUMStatus {
	struct ifaceIUMStatus *lpVtbl;
} IUMStatus;
typedef struct ifaceIUMStatus ifaceIUMStatus;
#define IUMStatus_QueryInterface(p,a)            (p)->lpVtbl->QueryInterface(p,a)
#define IUMStatus_AddRef(p)                      (p)->lpVtbl->AddRef(p)
#define IUMStatus_Release(p)                     (p)->lpVtbl->Release(p)
#define IUMStatus_GetPlayLevel(p,a,b)            (p)->lpVtbl->GetPlayLevel(p,a,b)
#define IUMStatus_GetPlayClock(p,a)              (p)->lpVtbl->GetPlayClock(p,a)
#define IUMStatus_GetChannelStatus(p,a,b,c)      (p)->lpVtbl->GetChannelStatus(p,a,b,c)
#define IUMStatus_GetChannelInfo(p,a,b)          (p)->lpVtbl->GetChannelInfo(p,a,b)
#endif





//
// [ IUMUTCtrl ]
//
// UM APIそのもののインターフェース
//
// 順序に注意(引数が同じだと違いが分からない)。
//

#ifdef __cplusplus
struct IUMUTCtrl : public IUMUnknown {
#else
struct ifaceIUMUTCtrl {
#endif
	/*** IUnknown methods ***/
	UMUTMETHOD(QueryInterface) ( _THIS_ UMID riid, LPVOID * ppvObj) _PURE;
	UMUTMETHOD(AddRef)         ( _THIS) _PURE;
	UMUTMETHOD(Release)        ( _THIS) _PURE;

	/*** IUMUTCtrl methods ***/
	UMUTMETHOD( init ) ( _THIS_ UMUTDEVICE* pDevs ) _PURE;
	UMUTMETHOD( end  ) ( _THIS ) _PURE;
	UMUTMETHOD( getVersion ) ( _THIS_ UMUTVERSIONINFO* pVInfo ) _PURE;
	UMUTMETHOD( configDevice ) ( _THIS_ UMUTOUTCFG* pConfig ) _PURE;
	UMUTMETHOD( start )  ( _THIS_ HWND hwnd ) _PURE;
	UMUTMETHOD( stop )   ( _THIS ) _PURE;
	UMUTMETHOD( pause )  ( _THIS ) _PURE;
	UMUTMETHOD( resume ) ( _THIS ) _PURE;
	UMUTMETHOD( enableMMX )  ( _THIS ) _PURE;
	UMUTMETHOD( disableMMX ) ( _THIS ) _PURE;

	UMUTMETHOD( getSystemTime ) ( _THIS_ DWORD* dwTime) _PURE;
	UMUTMETHOD( registerMessage ) ( _THIS_ int notifycode, UINT windowmessage) _PURE;
	UMUTMETHOD( setMessageProperty ) ( _THIS_ int notifycode, DWORD param1, DWORD param2) _PURE;
	UMUTMETHOD( getLastError ) ( _THIS_ UMUTERROR* pError) _PURE;

	// エントリ分けたほうがいいような。
	UMUTMETHOD( mod_load ) ( _THIS_ const UMUTSRC* source, int nPcmDirs, const char* aszPcmdirs[]) _PURE;
	UMUTMETHOD( mod_release ) ( _THIS ) _PURE;
	UMUTMETHOD( mod_play ) ( _THIS ) _PURE;
	UMUTMETHOD( mod_stop ) ( _THIS ) _PURE;
	UMUTMETHOD( mod_pause ) ( _THIS ) _PURE;
	UMUTMETHOD( mod_resume ) ( _THIS ) _PURE;
	UMUTMETHOD( mod_volume ) ( _THIS_ int volume) _PURE;
	UMUTMETHOD( mod_stat ) ( _THIS_ UMUTMODSTAT* pModstat) _PURE;
	UMUTMETHOD( mod_fade ) ( _THIS_ int vol_start, int vol_stop, long time_sec) _PURE;
	UMUTMETHOD( mod_flushPcmCache ) ( _THIS_ BOOL fInvalidate) _PURE;
	UMUTMETHOD( mod_getModuleInfo ) ( _THIS_ const UMUTSRC* pSrc, UMUTMODINFO* pModInfo) _PURE;

	// こいつも。
	UMUTMETHOD( eff_load   ) ( _THIS_ int effno, const UMUTSRC* source, int type) _PURE;
	UMUTMETHOD( eff_loadEx ) ( _THIS_ int effno, const UMUTSRC* source, int type, const UMUTPREFILTER* pPrefilter) _PURE;
	UMUTMETHOD( eff_release ) ( _THIS_ int effno) _PURE;
	UMUTMETHOD( eff_play ) ( _THIS_ int chno, int effno) _PURE;
	UMUTMETHOD( eff_stop ) ( _THIS_ int chno) _PURE;
	UMUTMETHOD( eff_volume ) ( _THIS_ int chno, int volume) _PURE;
	UMUTMETHOD( eff_pan ) ( _THIS_ int chno, int pan) _PURE;
	UMUTMETHOD( eff_frequency ) ( _THIS_ int chno, int rate) _PURE;
	UMUTMETHOD( eff_stat ) ( _THIS_ int chno, UMUTEFFSTAT* pEffStat) _PURE;
};

#ifndef __cplusplus
typedef struct IUMUTCtrl {
	struct ifaceIUMUTCtrl *lpVtbl;
} IUMUTCtrl;
typedef struct ifaceIUMUTCtrl ifaceIUMUTCtrl;

#define IUMUTCtrl_init(p,a)              (p)->lpVtbl->init(p,a)
#define IUMUTCtrl_end(p)                 (p)->lpVtbl->end(p)
#define IUMUTCtrl_getVersion(p,a)        (p)->lpVtbl->getVersion(p,a)
#define IUMUTCtrl_configDevice(p,a)      (p)->lpVtbl->configDevice(p,a)

#define IUMUTCtrl_start(p,a)             (p)->lpVtbl->start(p,a)
#define IUMUTCtrl_stop(p)                (p)->lpVtbl->stop(p)
#define IUMUTCtrl_pause(p)               (p)->lpVtbl->pause(p)
#define IUMUTCtrl_resume(p)              (p)->lpVtbl->resume(p)
#define IUMUTCtrl_enableMMX(p)           (p)->lpVtbl->enableMMX(p)
#define IUMUTCtrl_disableMMX(p)          (p)->lpVtbl->disableMMX(p)

#define IUMUTCtrl_getSystemTime(p,a)      (p)->lpVtbl->getSystemTime(p,a)
#define IUMUTCtrl_registerMessage(p,a,b)  (p)->lpVtbl->registerMessage(p,a,b)
#define IUMUTCtrl_setMessageProperty(p,a,b,c)   (p)->lpVtbl->setMessageProperty(p,a,b,c)
#define IUMUTCtrl_getLastError(p,a)       (p)->lpVtbl->getLastError(p,a)

#define IUMUTCtrl_mod_load(p,a,b,c)      (p)->lpVtbl->mod_load(p,a,b,c)
#define IUMUTCtrl_mod_release(p)         (p)->lpVtbl->mod_release(p)
#define IUMUTCtrl_mod_play(p)            (p)->lpVtbl->mod_play(p)
#define IUMUTCtrl_mod_stop(p)            (p)->lpVtbl->mod_stop(p)
#define IUMUTCtrl_mod_pause(p)           (p)->lpVtbl->mod_pause(p)
#define IUMUTCtrl_mod_resume(p)          (p)->lpVtbl->mod_resume(p)
#define IUMUTCtrl_mod_volume(p,a)        (p)->lpVtbl->mod_volume(p,a)
#define IUMUTCtrl_mod_stat(p,a)          (p)->lpVtbl->mod_stat(p,a)
#define IUMUTCtrl_mod_fade(p,a,b,c)      (p)->lpVtbl->mod_fade(p,a,b,c)
#define IUMUTCtrl_mod_flushPcmCache(p,a)   (p)->lpVtbl->mod_flushPcmCache(p,a)
#define IUMUTCtrl_mod_getModuleInfo(p,a,b) (p)->lpVtbl->mod_getModuleInfo(p,a,b)

#define IUMUTCtrl_eff_load(p,a,b,c)       (p)->lpVtbl->eff_load(p,a,b,c)
#define IUMUTCtrl_eff_loadEx(p,a,b,c,d,e) (p)->lpVtbl->eff_loadEx(p,a,b,c,d,e)
#define IUMUTCtrl_eff_release(p,a)        (p)->lpVtbl->eff_release(p,a)
#define IUMUTCtrl_eff_play(p,a,b)         (p)->lpVtbl->eff_play(p,a,b)
#define IUMUTCtrl_eff_stop(p,a)           (p)->lpVtbl->eff_stop(p,a)
#define IUMUTCtrl_eff_volume(p,a,b)       (p)->lpVtbl->eff_volume(p,a,b)
#define IUMUTCtrl_eff_pan(p,a,b)          (p)->lpVtbl->eff_pan(p,a,b)
#define IUMUTCtrl_eff_frequency(p,a,b)    (p)->lpVtbl->eff_frequency(p,a,b)
#define IUMUTCtrl_eff_stat(p,a,b)         (p)->lpVtbl->eff_stat(p,a,b)

#endif


#pragma pack(pop)

#endif
