129 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			129 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								// File: Schedule.h
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Desc: DirectShow base classes.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Copyright (c) 1996-2001 Microsoft Corporation.  All rights reserved.
							 | 
						||
| 
								 | 
							
								//------------------------------------------------------------------------------
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef __CAMSchedule__
							 | 
						||
| 
								 | 
							
								#define __CAMSchedule__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class CAMSchedule : private CBaseObject
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								    virtual ~CAMSchedule();
							 | 
						||
| 
								 | 
							
								    // ev is the event we should fire if the advise time needs re-evaluating
							 | 
						||
| 
								 | 
							
								    CAMSchedule( HANDLE ev );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    DWORD GetAdviseCount();
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME GetNextAdviseTime();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // We need a method for derived classes to add advise packets, we return the cookie
							 | 
						||
| 
								 | 
							
								    DWORD_PTR AddAdvisePacket( const REFERENCE_TIME & time1, const REFERENCE_TIME & time2, HANDLE h, BOOL periodic );
							 | 
						||
| 
								 | 
							
								    // And a way to cancel
							 | 
						||
| 
								 | 
							
								    HRESULT Unadvise(DWORD_PTR dwAdviseCookie);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Tell us the time please, and we'll dispatch the expired events.  We return the time of the next event.
							 | 
						||
| 
								 | 
							
								    // NB: The time returned will be "useless" if you start adding extra Advises.  But that's the problem of
							 | 
						||
| 
								 | 
							
								    // whoever is using this helper class (typically a clock).
							 | 
						||
| 
								 | 
							
								    REFERENCE_TIME Advise( const REFERENCE_TIME & rtTime );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Get the event handle which will be set if advise time requires re-evaluation.
							 | 
						||
| 
								 | 
							
								    HANDLE GetEvent() const { return m_ev; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								    // We define the nodes that will be used in our singly linked list
							 | 
						||
| 
								 | 
							
								    // of advise packets.  The list is ordered by time, with the
							 | 
						||
| 
								 | 
							
								    // elements that will expire first at the front.
							 | 
						||
| 
								 | 
							
								    class CAdvisePacket
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    public:
							 | 
						||
| 
								 | 
							
								        CAdvisePacket()
							 | 
						||
| 
								 | 
							
								        {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        CAdvisePacket * m_next;
							 | 
						||
| 
								 | 
							
								        DWORD_PTR       m_dwAdviseCookie;
							 | 
						||
| 
								 | 
							
								        REFERENCE_TIME  m_rtEventTime;      // Time at which event should be set
							 | 
						||
| 
								 | 
							
								        REFERENCE_TIME  m_rtPeriod;         // Periodic time
							 | 
						||
| 
								 | 
							
								        HANDLE          m_hNotify;          // Handle to event or semephore
							 | 
						||
| 
								 | 
							
								        BOOL            m_bPeriodic;        // TRUE => Periodic event
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        CAdvisePacket( __inout_opt CAdvisePacket * next, LONGLONG time ) : m_next(next), m_rtEventTime(time)
							 | 
						||
| 
								 | 
							
								        {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        void InsertAfter( __inout CAdvisePacket * p )
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            p->m_next = m_next;
							 | 
						||
| 
								 | 
							
								            m_next    = p;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        int IsZ() const // That is, is it the node that represents the end of the list
							 | 
						||
| 
								 | 
							
								        { return m_next == 0; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        CAdvisePacket * RemoveNext()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            CAdvisePacket *const next = m_next;
							 | 
						||
| 
								 | 
							
								            CAdvisePacket *const new_next = next->m_next;
							 | 
						||
| 
								 | 
							
								            m_next = new_next;
							 | 
						||
| 
								 | 
							
								            return next;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        void DeleteNext()
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            delete RemoveNext();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        CAdvisePacket * Next() const
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            CAdvisePacket * result = m_next;
							 | 
						||
| 
								 | 
							
								            if (result->IsZ()) result = 0;
							 | 
						||
| 
								 | 
							
								            return result;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        DWORD_PTR Cookie() const
							 | 
						||
| 
								 | 
							
								        { return m_dwAdviseCookie; }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Structure is:
							 | 
						||
| 
								 | 
							
								    // head -> elmt1 -> elmt2 -> z -> null
							 | 
						||
| 
								 | 
							
								    // So an empty list is:       head -> z -> null
							 | 
						||
| 
								 | 
							
								    // Having head & z as links makes insertaion,
							 | 
						||
| 
								 | 
							
								    // deletion and shunting much easier.
							 | 
						||
| 
								 | 
							
								    CAdvisePacket   head, z;            // z is both a tail and a sentry
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    volatile DWORD_PTR  m_dwNextCookie;     // Strictly increasing
							 | 
						||
| 
								 | 
							
								    volatile DWORD  m_dwAdviseCount;    // Number of elements on list
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    CCritSec        m_Serialize;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // AddAdvisePacket: adds the packet, returns the cookie (0 if failed)
							 | 
						||
| 
								 | 
							
								    DWORD_PTR AddAdvisePacket( __inout CAdvisePacket * pPacket );
							 | 
						||
| 
								 | 
							
								    // Event that we should set if the packed added above will be the next to fire.
							 | 
						||
| 
								 | 
							
								    const HANDLE m_ev;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // A Shunt is where we have changed the first element in the
							 | 
						||
| 
								 | 
							
								    // list and want it re-evaluating (i.e. repositioned) in
							 | 
						||
| 
								 | 
							
								    // the list.
							 | 
						||
| 
								 | 
							
								    void ShuntHead();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Rather than delete advise packets, we cache them for future use
							 | 
						||
| 
								 | 
							
								    CAdvisePacket * m_pAdviseCache;
							 | 
						||
| 
								 | 
							
								    DWORD           m_dwCacheCount;
							 | 
						||
| 
								 | 
							
								    enum { dwCacheMax = 5 };             // Don't bother caching more than five
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    void Delete( __inout CAdvisePacket * pLink );// This "Delete" will cache the Link
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Attributes and methods for debugging
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								#ifdef DEBUG
							 | 
						||
| 
								 | 
							
								    void DumpLinkedList();
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    void DumpLinkedList() {}
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif // __CAMSchedule__
							 |