2009-02-09 21:15:56 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// File: Schedule.h
|
|
|
|
//
|
|
|
|
// Desc: DirectShow base classes.
|
|
|
|
//
|
2018-04-28 16:52:15 +00:00
|
|
|
// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved.
|
2009-02-09 21:15:56 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
2018-04-28 16:52:15 +00:00
|
|
|
CAdvisePacket( __inout_opt CAdvisePacket * next, LONGLONG time ) : m_next(next), m_rtEventTime(time)
|
2009-02-09 21:15:56 +00:00
|
|
|
{}
|
|
|
|
|
2018-04-28 16:52:15 +00:00
|
|
|
void InsertAfter( __inout CAdvisePacket * p )
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
|
|
|
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)
|
2018-04-28 16:52:15 +00:00
|
|
|
DWORD_PTR AddAdvisePacket( __inout CAdvisePacket * pPacket );
|
2009-02-09 21:15:56 +00:00
|
|
|
// 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
|
|
|
|
|
2018-04-28 16:52:15 +00:00
|
|
|
void Delete( __inout CAdvisePacket * pLink );// This "Delete" will cache the Link
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
// Attributes and methods for debugging
|
|
|
|
public:
|
|
|
|
#ifdef DEBUG
|
|
|
|
void DumpLinkedList();
|
|
|
|
#else
|
|
|
|
void DumpLinkedList() {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // __CAMSchedule__
|