|
|
//+-------------------------------------------------------------------------
//
// 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; }
|