/*=============================================================================
	CAHALIOCycleTelemetryClient.h

	$Log: CAHALIOCycleTelemetryClient.h,v $
	Revision 1.11  2005/02/10 18:52:00  jcm10
	fix warnings
	
	Revision 1.10  2005/02/10 08:27:52  jcm10
	give the trace times some headroom
	
	Revision 1.9  2005/02/09 02:42:48  jcm10
	finish latency tracing support
	
	Revision 1.8  2005/02/03 07:40:06  jcm10
	add latency logging
	
	Revision 1.7  2004/02/24 02:27:06  jcm10
	make it compile without a prefix header
	
	Revision 1.6  2003/07/24 22:44:08  jcm10
	don't allow the telemetry port name to get too big
	
	Revision 1.5  2003/06/30 18:59:25  jcm10
	more telemetry clean up and fixes
	
	Revision 1.4  2003/06/26 21:46:39  jcm10
	add better detection of errors and signal present events
	
	Revision 1.3  2003/06/21 01:30:29  jcm10
	add support for getting the IO cycle summary in a for suitable for AppleWorks spreadsheets
	
	Revision 1.2  2003/06/20 19:04:06  jcm10
	clean up the telemetry
	
	Revision 1.1  2003/05/23 19:06:50  jcm10
	first checked in
	
	Revision 0.0  Thu May 22 2003 15:57:09 US/Pacific  moorf
	Created
		
	$NoKeywords: $
=============================================================================*/
#if !defined(__CAHALIOCycleTelemetryClient_h__)
#define __CAHALIOCycleTelemetryClient_h__

//=============================================================================
//	Includes
//=============================================================================

//	PublicUtility Includes
#include "CAHALTelemetry.h"

//	System Includes
#include <CoreAudio/CoreAudio.h>
#include <CoreFoundation/CoreFoundation.h>

//	Standard Library Includes
#include <deque>
#include <vector>

//=============================================================================
//	Types
//=============================================================================

class	CACFRemoteMessagePort;
class	CALatencyLog;

//=============================================================================
//	CAHALIOCycleTelemetry
//
//	This class encapsulates and unifies the raw telemetry data for a single IO cycle.
//	Host times are convertered to microseconds.
//=============================================================================

class CAHALIOCycleTelemetry
{

//	Construction/Destruction
public:
				CAHALIOCycleTelemetry();
				~CAHALIOCycleTelemetry();

//	Operations
public:
	UInt32		GetIOCycleNumber() const;
	UInt64		GetIntendedStartTime() const;
	UInt64		GetStartTime() const;
	UInt64		GetEndTime() const;
	Float64		GetDuration() const;
	Float64		GetRateScalar() const;
	void		GetIOProcTimes(AudioTimeStamp& outNow, AudioTimeStamp& outInputTime, AudioTimeStamp& outOutputTime) const;
	bool		HasError() const;
	bool		HasOverload() const;
	bool		HasInputError() const;
	bool		HasOutputError() const;
	bool		HasZeroTime() const;
	bool		HasSignal() const;
	bool		GetZeroTimeStamp(AudioTimeStamp& outZeroTime) const;
	bool		GetNextWakeUpTime(AudioTimeStamp& outWakeTime) const;
	
	Float64		GetTotalLoad() const;
	Float64		GetSchedulingLoad() const;
	Float64		GetReadLoad() const;
	Float64		GetIOProcLoad() const;
	Float64		GetWriteLoad() const;
	
	bool		AssimilateRawEvent(const CAHALIOCycleRawTelemetryEvent& inRawEvent);
	void		SetLastCycleEnd(const CAHALIOCycleRawTelemetryEvent& inRawEvent);
	
	bool		GetRawEventByKind(UInt32 inEventKind, CAHALIOCycleRawTelemetryEvent& outRawEvent) const;
	bool		GetBeginRawEvent(CAHALIOCycleRawTelemetryEvent& outRawEvent) const;
	bool		GetEndRawEvent(CAHALIOCycleRawTelemetryEvent& outRawEvent) const;
	
	UInt32		GetNumberRawEvents() const;
	bool		GetRawEventByIndex(UInt32 inEventIndex, CAHALIOCycleRawTelemetryEvent& outRawEvent) const;

//	Implementation
private:
	typedef std::vector<CAHALIOCycleRawTelemetryEvent>	RawEventList;
	
	CAHALIOCycleRawTelemetryEvent	mLastCycleEnd;
	RawEventList					mRawEvents;

};

//=============================================================================
//	CAHALIOCycleTelemetryClient
//=============================================================================

class CAHALIOCycleTelemetryClient
{

//	Construction/Destruction
public:
							CAHALIOCycleTelemetryClient(const char* inLatencyTraceFileName, const char* inLatencyTraceFileNameExtension);
	virtual					~CAHALIOCycleTelemetryClient();

	bool					Initialize(pid_t inProcess, AudioDeviceID inDevice);
	void					Teardown();

//	Operations
public:
	static CFStringRef		CreatePortName(pid_t inProcessID, CFStringRef inUID);
	
	bool					Update();
	void					Clear();
	
	UInt32					GetNumberIOCycles() const;
	UInt32					GetPreviousErrorIOCycleIndex(UInt32 inCurrentIndex) const;
	UInt32					GetNextErrorIOCycleIndex(UInt32 inCurrentIndex) const;
	UInt32					GetNumberEventsInIOCycle(UInt32 inIOCycleIndex) const;
	bool					IOCycleHasError(UInt32 inIOCycleIndex) const;
	bool					IOCycleHasSignal(UInt32 inIOCycleIndex) const;
	bool					EventInIOCycleHasError(UInt32 inIOCycleIndex, UInt32 inEventIndex) const;
	bool					EventInIOCycleHasSignal(UInt32 inIOCycleIndex, UInt32 inEventIndex) const;
	void					CreateSummaryHeaderForIOCycle(char* outSummary, bool inForSpreadSheet) const;
	void					CreateSummaryForIOCycle(UInt32 inIOCycleIndex, char* outSummary, bool inForSpreadSheet) const;
	void					CreateSummaryForEventInIOCycle(UInt32 inIOCycleIndex, UInt32 inEventIndex, char* outSummary) const;
	
	UInt32					GetNumberRawEvents() const;
	UInt32					GetPreviousErrorRawEventIndex(UInt32 inCurrentIndex) const;
	UInt32					GetNextErrorRawEventIndex(UInt32 inCurrentIndex) const;
	bool					IsRawEventError(UInt32 inEventIndex) const;
	bool					IsRawEventSignal(UInt32 inEventIndex) const;
	void					CreateSummaryHeaderForRawEvent(char* outSummary) const;
	void					CreateSummaryForRawEvent(UInt32 inEventIndex, char* outSummary) const;
	static void				CreateSummaryForRawEvent(const CAHALIOCycleRawTelemetryEvent& inEvent, const CAHALIOCycleRawTelemetryEvent& inPreviousEvent, UInt64 inAnchorTime, char* outSummary);
	static bool				IsRawEventError(const CAHALIOCycleRawTelemetryEvent& inEvent);
	static bool				IsRawEventSignal(const CAHALIOCycleRawTelemetryEvent& inEvent);

//	Server Operations
public:
	OSStatus				GetIsEnabledFromServer(bool& outIsEnabled);
	OSStatus				SetIsEnabledOnServer(bool inIsEnabled);
	OSStatus				GetServerIsFlippedFromServer(bool& outServerIsFlipped);
	OSStatus				ClearDataOnServer();

//	Latency Tracing
public:
	bool					CanDoLatencyTracing() const;
	bool					IsLatencyTracingEnabled() const;
	void					SetIsLatencyTracingEnabled(bool inIsEnabled);
	Float64					GetIOThreadSchedulingLatencyTrigger() const;
	void					SetIOThreadSchedulingLatencyTrigger(Float64 inTrigger);
	Float64					GetIOCycleDurationTrigger() const;
	void					SetIOCycleDurationTrigger(Float64 inTrigger);
	bool					GetOverloadTrigger() const;
	void					SetOverloadTrigger(bool inTrigger);

//	Implementation
private:
	typedef std::deque<CAHALIOCycleRawTelemetryEvent>	EventList;
	typedef std::deque<UInt32>							Index;
	typedef std::deque<CAHALIOCycleTelemetry>			IOCycleList;
	
	CACFRemoteMessagePort*	mMessagePort;
	bool					mServerIsFlipped;
	EventList				mRawTelemetry;
	IOCycleList				mIOCycleList;
	Index					mErrorCycleList;
	Index					mZerosCycleList;
	
	const char*				mLatencyTraceFileName;
	const char*				mLatencyTraceFileNameExtension;
	bool					mLatencyTracingEnabled;
	bool					mTraceTaken;
	CALatencyLog*			mLatencyLog;
	Float64					mIOThreadSchedulingLatencyTrigger;
	Float64					mIOCycleDurationTrigger;
	bool					mOverloadTrigger;

};

#endif
