windows-nt/Source/XPSP1/NT/multimedia/directx/dmusic/dmstyle/motiftrk.cpp
2020-09-26 16:20:57 +08:00

815 lines
21 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (c) 1998-1999 Microsoft Corporation
//
// File: motiftrk.cpp
//
//--------------------------------------------------------------------------
// READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// 4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX
//
// We disable this because we use exceptions and do *not* specify -GX (USE_NATIVE_EH in
// sources).
//
// The one place we use exceptions is around construction of objects that call
// InitializeCriticalSection. We guarantee that it is safe to use in this case with
// the restriction given by not using -GX (automatic objects in the call chain between
// throw and handler are not destructed). Turning on -GX buys us nothing but +10% to code
// size because of the unwind code.
//
// Any other use of exceptions must follow these restrictions or -GX must be turned on.
//
// READ THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
#pragma warning(disable:4530)
// MotifTrk.cpp : Implementation of CMotifTrack
//#include "stdafx.h"
//#include "Section.h"
#include "MotifTrk.h"
#include <stdlib.h> // for random number generator
#include <time.h> // to seed random number generator
#include "debug.h"
#include "dmusici.h"
#include "debug.h"
#include "..\shared\Validate.h"
/////////////////////////////////////////////////////////////////////////////
// MotifTrackState
MotifTrackState::MotifTrackState() :
m_mtMotifStart(0)
{
}
MotifTrackState::~MotifTrackState()
{
}
HRESULT MotifTrackState::Play(
MUSIC_TIME mtStart,
MUSIC_TIME mtEnd,
MUSIC_TIME mtOffset,
REFERENCE_TIME rtOffset,
IDirectMusicPerformance* pPerformance,
DWORD dwFlags,
BOOL fClockTime
)
{
m_mtPerformanceOffset = mtOffset;
BOOL fStart = (dwFlags & DMUS_TRACKF_START) ? TRUE : FALSE;
BOOL fSeek = (dwFlags & DMUS_TRACKF_SEEK) ? TRUE : FALSE;
BOOL fLoop = (dwFlags & DMUS_TRACKF_LOOP) ? TRUE : FALSE;
BOOL fControl = (dwFlags & DMUS_TRACKF_DIRTY) ? TRUE : FALSE;
if (fControl) // We need to make sure we get chords on beat boundaries
{
GetNextChord(mtStart, mtOffset, pPerformance, fStart);
}
MUSIC_TIME mtNotify = mtStart ? PatternTimeSig().CeilingBeat(mtStart) : 0;
if( m_fStateActive && m_pPatternTrack->m_fNotifyMeasureBeat && !fClockTime &&
( mtNotify < mtEnd ) )
{
mtNotify = NotifyMeasureBeat( mtNotify, mtEnd, mtOffset, pPerformance, dwFlags );
}
bool fReLoop = false;
DWORD dwPartFlags = PLAYPARTSF_FIRST_CALL;
if (fStart || fLoop || fSeek) dwPartFlags |= PLAYPARTSF_START;
if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
if ( fLoop || (mtStart > 0 && (fStart || fSeek || fControl)) ) dwPartFlags |= PLAYPARTSF_FLUSH;
PlayParts(mtStart, mtEnd, mtOffset, rtOffset, 0, pPerformance, dwPartFlags, dwFlags, fReLoop);
if (fReLoop)
{
dwPartFlags = PLAYPARTSF_RELOOP;
if (fClockTime) dwPartFlags |= PLAYPARTSF_CLOCKTIME;
PlayParts(mtStart, mtEnd, mtOffset, rtOffset, 0, pPerformance, dwPartFlags, dwFlags, fReLoop);
}
if( m_fStateActive && m_pPatternTrack->m_fNotifyMeasureBeat && !fClockTime &&
( mtNotify < mtEnd ) )
{
NotifyMeasureBeat( mtNotify, mtEnd, mtOffset, pPerformance, dwFlags );
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// MotifTrackInfo
MotifTrackInfo::MotifTrackInfo() :
m_pPattern(NULL)
{
m_dwPatternTag = DMUS_PATTERN_MOTIF;
}
MotifTrackInfo::~MotifTrackInfo()
{
if (m_pPattern) m_pPattern->Release();
}
HRESULT MotifTrackInfo::Init(
/*[in]*/ IDirectMusicSegment* pSegment
)
{
HRESULT hr = S_OK;
return hr;
}
HRESULT MotifTrackInfo::InitPlay(
/*[in]*/ IDirectMusicTrack* pParentrack,
/*[in]*/ IDirectMusicSegmentState* pSegmentState,
/*[in]*/ IDirectMusicPerformance* pPerformance,
/*[out]*/ void** ppStateData,
/*[in]*/ DWORD dwTrackID,
/*[in]*/ DWORD dwFlags
)
{
IDirectMusicSegment* pSegment = NULL;
MotifTrackState* pStateData = new MotifTrackState;
if( NULL == pStateData )
{
return E_OUTOFMEMORY;
}
*ppStateData = pStateData;
StatePair SP(pSegmentState, pStateData);
TListItem<StatePair>* pPair = new TListItem<StatePair>(SP);
if (!pPair) return E_OUTOFMEMORY;
m_StateList.AddHead(pPair);
TListItem<StylePair>* pHead = m_pISList.GetHead();
if (!pHead || !pHead->GetItemValue().m_pStyle) return E_FAIL;
pHead->GetItemValue().m_pStyle->GetStyleInfo((void **)&pStateData->m_pStyle);
pStateData->m_pTrack = pParentrack;
pStateData->m_pPatternTrack = this;
pStateData->m_dwVirtualTrackID = dwTrackID;
pStateData->m_pPattern = NULL;
pStateData->InitPattern(m_pPattern, 0);
pStateData->m_pSegState = pSegmentState; // weak reference, no addref.
pStateData->m_pPerformance = pPerformance; // weak reference, no addref.
pStateData->m_mtPerformanceOffset = 0;
pStateData->m_mtCurrentChordTime = 0;
pStateData->m_mtNextChordTime = 0;
pStateData->m_mtMotifStart = 0;
HRESULT hr = pStateData->ResetMappings();
if (FAILED(hr)) return hr;
if (m_fStateSetBySetParam)
{
pStateData->m_fStateActive = m_fActive;
}
else
{
pStateData->m_fStateActive = !(dwFlags & (DMUS_SEGF_CONTROL | DMUS_SEGF_SECONDARY));
}
if (m_lRandomNumberSeed)
{
pStateData->InitVariationSeeds(m_lRandomNumberSeed);
}
if( SUCCEEDED( pSegmentState->GetSegment(&pSegment)))
{
if (FAILED(pSegment->GetTrackGroup(pStateData->m_pTrack, &pStateData->m_dwGroupID)))
{
pStateData->m_dwGroupID = 0xffffffff;
}
pSegment->Release();
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// CMotifTrack
CMotifTrack::CMotifTrack() :
m_bRequiresSave(0), m_cRef(1), m_fCSInitialized(FALSE)
{
InterlockedIncrement(&g_cComponent);
::InitializeCriticalSection( &m_CriticalSection );
m_fCSInitialized = TRUE;
srand((unsigned int)time(NULL));
m_pTrackInfo = new MotifTrackInfo;
}
CMotifTrack::CMotifTrack(const CMotifTrack& rTrack, MUSIC_TIME mtStart, MUSIC_TIME mtEnd) :
m_bRequiresSave(0), m_cRef(1), m_fCSInitialized(FALSE)
{
InterlockedIncrement(&g_cComponent);
::InitializeCriticalSection( &m_CriticalSection );
m_fCSInitialized = TRUE;
srand((unsigned int)time(NULL));
m_pTrackInfo = new MotifTrackInfo((MotifTrackInfo*)rTrack.m_pTrackInfo, mtStart, mtEnd);
}
CMotifTrack::~CMotifTrack()
{
if (m_pTrackInfo)
{
delete m_pTrackInfo;
}
if (m_fCSInitialized)
{
::DeleteCriticalSection( &m_CriticalSection );
}
InterlockedDecrement(&g_cComponent);
}
STDMETHODIMP CMotifTrack::QueryInterface(
const IID &iid,
void **ppv)
{
V_INAME(CMotifTrack::QueryInterface);
V_REFGUID(iid);
V_PTRPTR_WRITE(ppv);
if (iid == IID_IUnknown || iid == IID_IDirectMusicTrack || iid == IID_IDirectMusicTrack8)
{
*ppv = static_cast<IDirectMusicTrack*>(this);
}
else if (iid == IID_IPersistStream)
{
*ppv = static_cast<IPersistStream*>(this);
}
else if (iid == IID_IMotifTrack)
{
*ppv = static_cast<IMotifTrack*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(this)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) CMotifTrack::AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) CMotifTrack::Release()
{
if (!InterlockedDecrement(&m_cRef))
{
delete this;
return 0;
}
return m_cRef;
}
//////////////////////////////////////////////////////////////////////
// IDirectMusicTrack::Init
HRESULT CMotifTrack::Init(
/* [in] */ IDirectMusicSegment __RPC_FAR *pSegment)
{
V_INAME(CMotifTrack::Init);
V_INTERFACE(pSegment);
HRESULT hr = S_OK;
if (!m_pTrackInfo)
return DMUS_E_NOT_INIT;
EnterCriticalSection( &m_CriticalSection );
hr = m_pTrackInfo->MergePChannels();
if (SUCCEEDED(hr))
{
pSegment->SetPChannelsUsed(m_pTrackInfo->m_dwPChannels, m_pTrackInfo->m_pdwPChannels);
hr = m_pTrackInfo->Init(pSegment);
}
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
HRESULT CMotifTrack::InitPlay(
/*[in]*/ IDirectMusicSegmentState* pSegmentState,
/*[in]*/ IDirectMusicPerformance* pPerformance,
/*[out]*/ void** ppStateData,
/*[in]*/ DWORD dwTrackID,
/*[in]*/ DWORD dwFlags
)
{
V_INAME(CMotifTrack::InitPlay);
V_PTRPTR_WRITE(ppStateData);
V_INTERFACE(pSegmentState);
V_INTERFACE(pPerformance);
EnterCriticalSection( &m_CriticalSection );
HRESULT hr = S_OK;
if (!m_pTrackInfo)
{
LeaveCriticalSection( &m_CriticalSection );
return DMUS_E_NOT_INIT;
}
hr = m_pTrackInfo->InitPlay(this, pSegmentState, pPerformance, ppStateData, dwTrackID, dwFlags);
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
HRESULT CMotifTrack::EndPlay(
/*[in]*/ void* pStateData
)
{
V_INAME(CMotifTrack::EndPlay);
V_BUFPTR_WRITE(pStateData, sizeof(MotifTrackState));
HRESULT hr = DMUS_E_NOT_INIT;
EnterCriticalSection( &m_CriticalSection );
if (m_pTrackInfo)
{
hr = m_pTrackInfo->EndPlay((MotifTrackState*)pStateData);
}
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
HRESULT CMotifTrack::Play(
/*[in]*/ void* pStateData,
/*[in]*/ MUSIC_TIME mtStart,
/*[in]*/ MUSIC_TIME mtEnd,
/*[in]*/ MUSIC_TIME mtOffset,
REFERENCE_TIME rtOffset,
DWORD dwFlags,
IDirectMusicPerformance* pPerf,
IDirectMusicSegmentState* pSegState,
DWORD dwVirtualID,
BOOL fClockTime
)
{
V_INAME(CMotifTrack::Play);
V_BUFPTR_WRITE( pStateData, sizeof(MotifTrackState));
V_INTERFACE(pPerf);
V_INTERFACE(pSegState);
HRESULT hr = DMUS_E_NOT_INIT;
EnterCriticalSection( &m_CriticalSection );
if (!m_pTrackInfo)
{
LeaveCriticalSection( &m_CriticalSection );
return DMUS_E_NOT_INIT;
}
MotifTrackState* pSD = (MotifTrackState *)pStateData;
if (pSD && pSD->m_pMappings)
{
BOOL fStart = (dwFlags & DMUS_TRACKF_START) ? TRUE : FALSE;
BOOL fSeek = (dwFlags & DMUS_TRACKF_SEEK) ? TRUE : FALSE;
BOOL fLoop = (dwFlags & DMUS_TRACKF_LOOP) ? TRUE : FALSE;
BOOL fControl = (dwFlags & DMUS_TRACKF_DIRTY) ? TRUE : FALSE;
if (fStart || fSeek || fLoop || fControl)
{
pSD->m_fNewPattern = TRUE;
pSD->m_mtCurrentChordTime = 0;
pSD->m_mtNextChordTime = 0;
pSD->m_mtLaterChordTime = 0;
// pSD->m_CurrentChord.bSubChordCount = 0;
for (DWORD dw = 0; dw < m_pTrackInfo->m_dwPChannels; dw++)
{
pSD->m_pMappings[dw].m_mtTime = 0;
pSD->m_pMappings[dw].m_dwPChannelMap = m_pTrackInfo->m_pdwPChannels[dw];
pSD->m_pMappings[dw].m_fMute = FALSE;
}
}
hr = pSD->Play(mtStart, mtEnd, mtOffset, rtOffset, pPerf, dwFlags, fClockTime);
}
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
HRESULT CMotifTrack::GetPriority(
/*[out]*/ DWORD* pPriority
)
{
return E_NOTIMPL;
}
HRESULT CMotifTrack::GetParam(
REFGUID rCommandGuid,
MUSIC_TIME mtTime,
MUSIC_TIME* pmtNext,
void *pData)
{
V_INAME(CMotifTrack::GetParam);
V_PTR_WRITE_OPT(pmtNext,MUSIC_TIME);
V_PTR_WRITE(pData,1);
V_REFGUID(rCommandGuid);
EnterCriticalSection( &m_CriticalSection );
if (!m_pTrackInfo)
{
LeaveCriticalSection( &m_CriticalSection );
return DMUS_E_NOT_INIT;
}
HRESULT hr = S_OK;
if( GUID_Valid_Start_Time == rCommandGuid )
{
if (m_pTrackInfo->m_dwPatternTag != DMUS_PATTERN_MOTIF) hr = E_FAIL;
else
{
MotifTrackInfo* pTrackInfo = (MotifTrackInfo*)m_pTrackInfo;
if (!pTrackInfo->m_pPattern) hr = E_POINTER;
else
{
DMUS_VALID_START_PARAM* pValidStartData = (DMUS_VALID_START_PARAM*)pData;
TListItem<MUSIC_TIME>* pScan = pTrackInfo->m_pPattern->m_StartTimeList.GetHead();
for (; pScan; pScan = pScan->GetNext())
{
if (pScan->GetItemValue() >= mtTime)
{
pValidStartData->mtTime = pScan->GetItemValue() - mtTime;
break;
}
}
if (!pScan) hr = DMUS_E_NOT_FOUND;
else
{
if (pmtNext)
{
if (pScan = pScan->GetNext())
{
*pmtNext = pScan->GetItemValue() - mtTime;
}
else
{
*pmtNext = 0;
}
}
hr = S_OK;
}
}
}
}
else
{
hr = DMUS_E_GET_UNSUPPORTED;
}
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
HRESULT CMotifTrack::SetParam(
REFGUID rguid,
MUSIC_TIME mtTime,
void __RPC_FAR *pData)
{
V_INAME(CMotifTrack::SetParam);
V_PTR_WRITE_OPT(pData,1);
V_REFGUID(rguid);
EnterCriticalSection( &m_CriticalSection );
if (!m_pTrackInfo)
{
LeaveCriticalSection( &m_CriticalSection );
return DMUS_E_NOT_INIT;
}
HRESULT hr = DMUS_E_SET_UNSUPPORTED;
if( rguid == GUID_EnableTimeSig )
{
if( m_pTrackInfo->m_fStateSetBySetParam && m_pTrackInfo->m_fActive )
{
hr = DMUS_E_TYPE_DISABLED;
}
else
{
m_pTrackInfo->m_fStateSetBySetParam = TRUE;
m_pTrackInfo->m_fActive = TRUE;
hr = S_OK;
}
}
else if( rguid == GUID_DisableTimeSig )
{
if( m_pTrackInfo->m_fStateSetBySetParam && !m_pTrackInfo->m_fActive )
{
hr = DMUS_E_TYPE_DISABLED;
}
else
{
m_pTrackInfo->m_fStateSetBySetParam = TRUE;
m_pTrackInfo->m_fActive = FALSE;
hr = S_OK;
}
}
else if ( rguid == GUID_SeedVariations )
{
if (pData)
{
m_pTrackInfo->m_lRandomNumberSeed = *((long*) pData);
hr = S_OK;
}
else hr = E_POINTER;
}
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
// IPersist methods
HRESULT CMotifTrack::GetClassID( LPCLSID pClassID )
{
V_INAME(CMotifTrack::GetClassID);
V_PTR_WRITE(pClassID, CLSID);
*pClassID = CLSID_DirectMusicMotifTrack;
return S_OK;
}
HRESULT CMotifTrack::IsParamSupported(
/*[in]*/ REFGUID rGuid
)
{
V_INAME(CMotifTrack::IsParamSupported);
V_REFGUID(rGuid);
if (!m_pTrackInfo)
{
return DMUS_E_NOT_INIT;
}
if ( rGuid == GUID_SeedVariations || rGuid == GUID_Valid_Start_Time )
{
return S_OK;
}
else if (m_pTrackInfo->m_fStateSetBySetParam)
{
if( m_pTrackInfo->m_fActive )
{
if( rGuid == GUID_DisableTimeSig ) return S_OK;
if( rGuid == GUID_EnableTimeSig ) return DMUS_E_TYPE_DISABLED;
}
else
{
if( rGuid == GUID_EnableTimeSig ) return S_OK;
if( rGuid == GUID_DisableTimeSig ) return DMUS_E_TYPE_DISABLED;
}
}
else
{
if(( rGuid == GUID_DisableTimeSig ) ||
( rGuid == GUID_EnableTimeSig ) )
{
return S_OK;
}
}
return DMUS_E_TYPE_UNSUPPORTED;
}
// IPersistStream methods
HRESULT CMotifTrack::IsDirty()
{
return m_bRequiresSave ? S_OK : S_FALSE;
}
HRESULT CMotifTrack::Save( LPSTREAM pStream, BOOL fClearDirty )
{
return E_NOTIMPL;
}
HRESULT CMotifTrack::GetSizeMax( ULARGE_INTEGER* /*pcbSize*/ )
{
return E_NOTIMPL;
}
HRESULT CMotifTrack::Load(LPSTREAM pStream )
{
return E_NOTIMPL;
}
HRESULT CMotifTrack::SetTrack(IUnknown* pStyle, void* pPattern)
{
if (!pStyle) return E_POINTER;
HRESULT hr = E_FAIL;
EnterCriticalSection( &m_CriticalSection );
if (!m_pTrackInfo)
{
LeaveCriticalSection( &m_CriticalSection );
return DMUS_E_NOT_INIT;
}
MotifTrackInfo* pTrackInfo = (MotifTrackInfo*)m_pTrackInfo;
if (m_pTrackInfo->m_dwPatternTag == DMUS_PATTERN_MOTIF)
{
IDMStyle* pIS = NULL;
hr = pStyle->QueryInterface(IID_IDMStyle, (void**)&pIS);
if (SUCCEEDED(hr))
{
if (pTrackInfo->m_pPattern) pTrackInfo->m_pPattern->Release();
pTrackInfo->m_pPattern = (CDirectMusicPattern*) pPattern;
if (pTrackInfo->m_pPattern) pTrackInfo->m_pPattern->AddRef();
pTrackInfo->InitTrackVariations(pTrackInfo->m_pPattern);
TListItem<StylePair>* pNew = new TListItem<StylePair>;
if (!pNew) hr = E_OUTOFMEMORY;
else
{
pNew->GetItemValue().m_mtTime = 0;
pNew->GetItemValue().m_pStyle = pIS;
pTrackInfo->m_pISList.AddTail(pNew);
hr = S_OK;
}
pIS->Release();
}
}
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
HRESULT STDMETHODCALLTYPE CMotifTrack::AddNotificationType(
/* [in] */ REFGUID rGuidNotify)
{
V_INAME(CMotifTrack::AddNotificationType);
V_REFGUID(rGuidNotify);
HRESULT hr = S_OK;
EnterCriticalSection( &m_CriticalSection );
if (m_pTrackInfo)
hr = m_pTrackInfo->AddNotificationType(rGuidNotify);
else
hr = DMUS_E_NOT_INIT;
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
HRESULT STDMETHODCALLTYPE CMotifTrack::RemoveNotificationType(
/* [in] */ REFGUID rGuidNotify)
{
V_INAME(CMotifTrack::RemoveNotificationType);
V_REFGUID(rGuidNotify);
HRESULT hr = S_OK;
EnterCriticalSection( &m_CriticalSection );
if (m_pTrackInfo)
hr = m_pTrackInfo->RemoveNotificationType(rGuidNotify);
else
hr = DMUS_E_NOT_INIT;
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
HRESULT STDMETHODCALLTYPE CMotifTrack::Clone(
MUSIC_TIME mtStart,
MUSIC_TIME mtEnd,
IDirectMusicTrack** ppTrack)
{
V_INAME(CMotifTrack::Clone);
V_PTRPTR_WRITE(ppTrack);
HRESULT hr = S_OK;
if(mtStart < 0 )
{
return E_INVALIDARG;
}
if(mtStart > mtEnd)
{
return E_INVALIDARG;
}
EnterCriticalSection( &m_CriticalSection );
CMotifTrack *pDM;
try
{
pDM = new CMotifTrack(*this, mtStart, mtEnd);
}
catch( ... )
{
pDM = NULL;
}
if (pDM == NULL) {
LeaveCriticalSection( &m_CriticalSection );
return E_OUTOFMEMORY;
}
hr = pDM->QueryInterface(IID_IDirectMusicTrack, (void**)ppTrack);
pDM->Release();
LeaveCriticalSection( &m_CriticalSection );
return hr;
}
STDMETHODIMP CMotifTrack::GetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
REFERENCE_TIME* prtNext,void* pParam,void * pStateData, DWORD dwFlags)
{
HRESULT hr;
MUSIC_TIME mtNext;
if (dwFlags & DMUS_TRACK_PARAMF_CLOCK)
{
hr = GetParam(rguidType,(MUSIC_TIME) (rtTime / REF_PER_MIL), &mtNext, pParam);
if (prtNext)
{
*prtNext = mtNext * REF_PER_MIL;
}
}
else
{
hr = GetParam(rguidType,(MUSIC_TIME) rtTime, &mtNext, pParam);
if (prtNext)
{
*prtNext = mtNext;
}
}
return hr;
}
STDMETHODIMP CMotifTrack::SetParamEx(REFGUID rguidType,REFERENCE_TIME rtTime,
void* pParam, void * pStateData, DWORD dwFlags)
{
if (dwFlags & DMUS_TRACK_PARAMF_CLOCK)
{
rtTime /= REF_PER_MIL;
}
return SetParam(rguidType, (MUSIC_TIME) rtTime , pParam);
}
STDMETHODIMP CMotifTrack::PlayEx(void* pStateData,REFERENCE_TIME rtStart,
REFERENCE_TIME rtEnd,REFERENCE_TIME rtOffset,
DWORD dwFlags,IDirectMusicPerformance* pPerf,
IDirectMusicSegmentState* pSegSt,DWORD dwVirtualID)
{
V_INAME(IDirectMusicTrack::PlayEx);
V_INTERFACE(pPerf);
V_INTERFACE(pSegSt);
HRESULT hr;
EnterCriticalSection(&m_CriticalSection);
if (dwFlags & DMUS_TRACKF_CLOCK)
{
// Convert all reference times to millisecond times. Then, just use same MUSIC_TIME
// variables.
hr = Play(pStateData,(MUSIC_TIME)(rtStart / REF_PER_MIL),(MUSIC_TIME)(rtEnd / REF_PER_MIL),
(MUSIC_TIME)(rtOffset / REF_PER_MIL),rtOffset,dwFlags,pPerf,pSegSt,dwVirtualID,TRUE);
}
else
{
hr = Play(pStateData,(MUSIC_TIME)rtStart,(MUSIC_TIME)rtEnd,
(MUSIC_TIME)rtOffset,0,dwFlags,pPerf,pSegSt,dwVirtualID,FALSE);
}
LeaveCriticalSection(&m_CriticalSection);
return hr;
}
STDMETHODIMP CMotifTrack::Play(
void *pStateData, // @parm State data pointer, from <om .InitPlay>.
MUSIC_TIME mtStart, // @parm The start time to play.
MUSIC_TIME mtEnd, // @parm The end time to play.
MUSIC_TIME mtOffset,// @parm The offset to add to all messages sent to
// <om IDirectMusicPerformance.SendPMsg>.
DWORD dwFlags, // @parm Flags that indicate the state of this call.
// See <t DMUS_TRACKF_FLAGS>. If dwFlags == 0, this is a
// normal Play call continuing playback from the previous
// Play call.
IDirectMusicPerformance* pPerf, // @parm The <i IDirectMusicPerformance>, used to
// call <om IDirectMusicPerformance.AllocPMsg>,
// <om IDirectMusicPerformance.SendPMsg>, etc.
IDirectMusicSegmentState* pSegSt, // @parm The <i IDirectMusicSegmentState> this
// track belongs to. QueryInterface() can be called on this to
// obtain the SegmentState's <i IDirectMusicGraph> in order to
// call <om IDirectMusicGraph.StampPMsg>, for instance.
DWORD dwVirtualID // @parm This track's virtual track id, which must be set
// on any <t DMUS_PMSG>'s m_dwVirtualTrackID member that
// will be queued to <om IDirectMusicPerformance.SendPMsg>.
)
{
V_INAME(IDirectMusicTrack::Play);
V_INTERFACE(pPerf);
V_INTERFACE(pSegSt);
EnterCriticalSection(&m_CriticalSection);
HRESULT hr = Play(pStateData,mtStart,mtEnd,mtOffset,0,dwFlags,pPerf,pSegSt,dwVirtualID,FALSE);
LeaveCriticalSection(&m_CriticalSection);
return hr;
}
STDMETHODIMP CMotifTrack::Compose(
IUnknown* pContext,
DWORD dwTrackGroup,
IDirectMusicTrack** ppResultTrack)
{
return E_NOTIMPL;
}
STDMETHODIMP CMotifTrack::Join(
IDirectMusicTrack* pNewTrack,
MUSIC_TIME mtJoin,
IUnknown* pContext,
DWORD dwTrackGroup,
IDirectMusicTrack** ppResultTrack)
{
return E_NOTIMPL;
}