// Copyright (c) 1999 Microsoft Corporation. All rights reserved. // // Declaration of CSegTriggerTrack. // // This track type holds events that cause other segments to be cued at // specific points during playback of a segment. #pragma once #include "trackhelp.h" #include "tlist.h" #include "smartref.h" ////////////////////////////////////////////////////////////////////// // Types // Items in list of events struct TriggerInfo { TriggerInfo() : lTriggerTime(0), lTimePhysical(0), dwPlayFlags(0), dwFlags(0), pIDMSegment(NULL) {} ~TriggerInfo() { RELEASE(pIDMSegment); } HRESULT Clone(const TriggerInfo &o, MUSIC_TIME mtStart) { lTriggerTime = o.lTriggerTime - mtStart; lTimePhysical = o.lTimePhysical - mtStart; dwPlayFlags = o.dwPlayFlags; dwFlags = o.dwFlags; pIDMSegment = o.pIDMSegment; pIDMSegment->AddRef(); return S_OK; } // from event header chunk MUSIC_TIME lTriggerTime; // Logical time MUSIC_TIME lTimePhysical; DWORD dwPlayFlags; DWORD dwFlags; // from reference IDirectMusicSegment *pIDMSegment; }; // State data. This track needs to get the audio path that's currently playing so that it // can use it when playing triggered segments. struct CSegTriggerTrackState : public CStandardStateData { CSegTriggerTrackState() : pAudioPath(NULL) {}; ~CSegTriggerTrackState() { if (pAudioPath) pAudioPath->Release(); } IDirectMusicAudioPath *pAudioPath; }; ////////////////////////////////////////////////////////////////////// // CSegTriggerTrack class CSegTriggerTrack; typedef CPlayingTrack CSegTriggerTrackBase; class CSegTriggerTrack : public CSegTriggerTrackBase { public: // When the segment trigger track plays one of its items, it plays a segment. If an invalidation occurs, that Play operation // can't be retracted. Then the track is played again (with the FLUSH bit set). This was causing it to trigger the segment // a second time. To fix this, the last parameter to the CSegTriggerTrackBase is false, which instructs it not to call play // a second time when the FLUSH bit is set. CSegTriggerTrack(HRESULT *pHr) : CSegTriggerTrackBase(&g_cComponent, CLSID_DirectMusicSegmentTriggerTrack, true, false), m_dwFlags(NULL), m_dwRecursionCount(0) {} // Implement SetParam by calling SetParam in turn on all the child segments. This is needed, for example so that downloading a segment with a segment trigger track will download all the triggered segments as well. STDMETHOD(IsParamSupported)(REFGUID rguid) { return S_OK; } // Once or more of our child segments could potentially support any type of parameter. STDMETHOD(SetParam)(REFGUID rguid, MUSIC_TIME mtTime, void *pData); STDMETHOD(InitPlay)( IDirectMusicSegmentState *pSegmentState, IDirectMusicPerformance *pPerformance, void **ppStateData, DWORD dwTrackID, DWORD dwFlags); protected: HRESULT PlayItem( const TriggerInfo &item, statedata &state, IDirectMusicPerformance *pPerf, IDirectMusicSegmentState* pSegSt, DWORD dwVirtualID, MUSIC_TIME mtOffset, REFERENCE_TIME rtOffset, bool fClockTime); HRESULT LoadRiff(SmartRef::RiffIter &ri, IDirectMusicLoader *pIDMLoader); private: HRESULT LoadTrigger(SmartRef::RiffIter ri, IDirectMusicLoader *pIDMLoader); // Data DWORD m_dwFlags; // from track header (sgth chunk) BOOL m_dwRecursionCount; // Used to keep track of recursive calls to self. };