/*		DirectMusic
 *
 * Copyright 2002 TransGaming Technologies Inc. 
 *
 */

typedef struct Voice {
    REFERENCE_TIME rtStart, rtEnd;
    IStream* pStream;
} Voice;

#define VOICES 16

/*****************************************************************************
 * IDirectMusicAudioPath implementation structure
 */
typedef struct IDirectMusicAudioPathImpl IDirectMusicAudioPathImpl;
struct IDirectMusicAudioPathImpl
{
    /* IUnknown fields */
    ICOM_VFIELD(IDirectMusicAudioPath);
    ICOM_VTABLE(IDirectMusicObject) *lpOVtbl;
    ICOM_VTABLE(IPersistStream) *lpPSVtbl;
    DWORD ref;
    /* IDirectMusicAudioPath fields */
    IDirectMusicPerformance8* pPerf;
    DWORD dsbuffers;
    IDirectSoundBuffer** dsbuffer;
    DWORD* dsplay;
    DWORD* dswrite;
    BOOL active;
    BOOL running;
    REFERENCE_TIME rtTime;
    DWORD rtRem;
    Voice voice[VOICES];
};


HMMIO DMIME_mmioOpen(IStream* pStream);
MMRESULT DMIME_mmioClose(HMMIO hmmio);
HRESULT DMIME_CloneStream(HMMIO hmmio, IStream** ppStream);
HRESULT DMIME_CommonChunk(HMMIO hmmio, LPMMCKINFO ck, LPDMUS_OBJECTDESC pDesc);
HRESULT DMIME_LoadReference(HMMIO hmmio, LPMMCKINFO pck, REFIID riid, void** ppObj);

typedef HRESULT (*DMIME_ClassCreator)(REFGUID lpGUID, IUnknown **ppObj, IUnknown *pUnkOuter);

HRESULT DirectMusicCreateStandardAudioPath(IDirectMusicPerformance8 *pPerf,
					   IDirectSound *pDS, DMUS_AUDIOPARAMS *pParams,
					   DWORD dwType, DWORD dwPChannelCount,
					   IDirectMusicAudioPath **ppObj);
HRESULT DirectMusicRunAudioPath(IDirectMusicAudioPath *iface, DWORD dwLatency);
HRESULT DirectMusicPlayInAudioPath(IDirectMusicAudioPath *iface, DMUS_PMSG *pMsg, DWORD dwLatency);
HRESULT DirectMusicStopAllInAudioPath(IDirectMusicAudioPath *iface);

HRESULT DirectMusicCreateSegmentState(IDirectMusicPerformance8 *pPerf,
				      IDirectMusicSegment8 *pSeg,
				      DWORD dwFlags,
				      DWORD dwVirtualID,
				      IDirectMusicSegmentState8 **ppObj);
HRESULT DirectMusicMarkSegmentStatePlaying(IDirectMusicSegmentState8* iface, BOOL playing,
					   REFERENCE_TIME rtTime, DWORD dwFlags);
HRESULT DirectMusicIsSegmentStatePlaying(IDirectMusicSegmentState8* iface);
HRESULT DirectMusicPlaySegmentState(IDirectMusicSegmentState8* iface, MUSIC_TIME mtEnd);

HRESULT DirectMusicPerformanceCreate(REFGUID lpGUID, IUnknown **ppObj, IUnknown *pUnkOuter);
HRESULT DirectMusicSegmentCreate(REFGUID lpGUID, IUnknown **ppObj, IUnknown *pUnkOuter);
HRESULT DirectMusicTempoTrackCreate(REFGUID lpGUID, IUnknown **ppObj, IUnknown *pUnkOuter);
HRESULT DirectMusicTimeSigTrackCreate(REFGUID lpGUID, IUnknown **ppObj, IUnknown *pUnkOuter);
HRESULT DirectMusicWaveTrackCreate(REFGUID lpGUID, IUnknown **ppObj, IUnknown *pUnkOuter);
HRESULT DirectMusicSeqTrackCreate(REFGUID lpGUID, IUnknown **ppObj, IUnknown *pUnkOuter);

#define FIELD_READ(buf, fld) do { \
    mmioRead(hmmio, (LPVOID)&(buf).fld, sizeof((buf).fld)); \
    /* add error checking here? */ \
  } while (0)

#define STRUCT_READ_START(buf) { unsigned _srcnt = 0; memset(&buf, 0, sizeof(buf));
#define STRUCT_READ(buf, fld) \
  if (ck.cksize >= (_srcnt + sizeof((buf).fld))) { \
    FIELD_READ(buf, fld); \
    _srcnt += sizeof((buf).fld); \
  }
#define STRUCT_READ_END(buf) }

#define STRING_READ(buf, fld) { unsigned _srsz = ck.cksize; \
    if (sizeof((buf).fld) < _srsz) _srsz = sizeof((buf).fld); \
    mmioRead(hmmio, (LPVOID)&(buf).fld, _srsz); \
  }
