//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
// Oscilloscope filter
// { 35919F40-E904-11ce-8A03-00AA006ECB65 }
DEFINE_GUID(CLSID_Scope,
0x35919f40, 0xe904, 0x11ce, 0x8a, 0x3, 0x0, 0xaa, 0x0, 0x6e, 0xcb, 0x65);
class CScopeFilter;
class CScopeWindow;
// Class supporting the scope input pin
class CScopeInputPin : public CBaseInputPin
{
friend class CScopeFilter;
friend class CScopeWindow;
private:
CScopeFilter *m_pFilter; // The filter that owns us
public:
CScopeInputPin(CScopeFilter *pTextOutFilter,
HRESULT *phr,
LPCWSTR pPinName);
~CScopeInputPin();
// Lets us know where a connection ends
HRESULT BreakConnect();
// Check that we can support this input type
HRESULT CheckMediaType(const CMediaType *pmt);
// Actually set the current format
HRESULT SetMediaType(const CMediaType *pmt);
// IMemInputPin virtual methods
// Override so we can show and hide the window
HRESULT Active(void);
HRESULT Inactive(void);
// Here's the next block of data from the stream.
// AddRef it if you are going to hold onto it
STDMETHODIMP Receive(IMediaSample *pSample);
}; // CScopeInputPin
// This class looks after the management of a window. When the class gets
// instantiated the constructor spawns off a worker thread that does all
// the window work. The original thread waits until it is signaled to
// continue. The worker thread first registers the window class if it
// is not already done. Then it creates a window and sets it's size to
// a default iWidth by iHeight dimensions. The worker thread MUST be the
// one who creates the window as it is the one who calls GetMessage. When
// it has done all this it signals the original thread which lets it
// continue, this ensures a window is created and valid before the
// constructor returns. The thread start address is the WindowMessageLoop
// function. This takes as it's initialisation parameter a pointer to the
// CVideoWindow object that created it, the function also initialises it's
// window related member variables such as the handle and device contexts
// These are the video window styles
const DWORD dwTEXTSTYLES = (WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CLIPCHILDREN);
const DWORD dwCLASSSTYLES = (CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNCLIENT | CS_OWNDC);
const LPTSTR RENDERCLASS = TEXT("OscilloscopeWindowClass");
const LPTSTR TITLE = TEXT("Oscilloscope");
const int iWIDTH = 320; // Initial window width
const int iHEIGHT = 240; // Initial window height
const int WM_GOODBYE (WM_USER + 2); // Sent to close the window
class CScopeWindow : public CCritSec
{
friend class CScopeInputPin;
friend class CScopeFilter;
private:
HINSTANCE m_hInstance; // Global module instance handle
CScopeFilter *m_pRenderer; // The owning renderer object
HWND m_hwndDlg; // Handle for our dialog
HWND m_hwnd; // Handle for the graph window
HBRUSH m_hBrushBackground; // Used to paint background
HPEN m_hPen1; // We use two pens for drawing
HPEN m_hPen2; // the waveforms in the window
HPEN m_hPenTicks; // Used to draw ticks at bottom
HBITMAP m_hBitmap; // Draw all waveforms into here
HANDLE m_hThread; // Our worker thread
DWORD m_ThreadID; // Worker thread ID
CAMEvent m_SyncWorker; // Synchronise with worker thread
CAMEvent m_RenderEvent; // Signals sample to render
LONG m_Width; // Client window width
LONG m_Height; // Client window height
BOOL m_bActivated; // Has the window been activated
CRefTime m_StartSample; // Most recent sample start time
CRefTime m_EndSample; // And it's associated end time
BOOL m_bStreaming; // Are we currently streaming
POINT *m_pPoints1; // Array of points to graph Channel1
POINT *m_pPoints2; // Array of points to graph Channel2
int m_nPoints; // Size of m_pPoints[1|2]
int m_nIndex; // Index of last sample written
int m_LastMediaSampleSize; // Size of last MediaSample
int m_nChannels; // number of active channels
int m_nSamplesPerSec; // Samples per second
int m_nBitsPerSample; // Number bits per sample
int m_nBlockAlign; // Alignment on the samples
int m_MaxValue; // Max Value of the POINTS array
int m_LGain; // Left channel control settings
int m_LOffset; // And likewise its offset
int m_RGain; // Right channel control settings
int m_ROffset; // And likewise its offset
int m_nTimebase; // Timebase settings
BOOL m_fFreeze; // Flag toi signal we're UI frozen
int m_TBScroll; // Holds position in scroll range
// Hold window handles to controls
HWND m_hwndLGain;
HWND m_hwndLOffset;
HWND m_hwndLGainText;
HWND m_hwndLTitle;
HWND m_hwndRGain;
HWND m_hwndROffset;
HWND m_hwndRGainText;
HWND m_hwndRTitle;
HWND m_hwndTimebase;
HWND m_hwndFreeze;
HWND m_hwndTBScroll;
HWND m_hwndTBStart;
HWND m_hwndTBEnd;
HWND m_hwndTBDelta;
BOOL m_fTriggerPosZeroCrossing;
// These create and manage a video window on a separate thread
HRESULT UninitialiseWindow();
HRESULT InitialiseWindow(HWND hwnd);
HRESULT MessageLoop();
static DWORD __stdcall WindowMessageLoop(LPVOID lpvThreadParm);
// Maps windows message loop into C++ virtual methods
friend LRESULT CALLBACK WndProc(HWND hwnd, // Window handle
UINT uMsg, // Message ID
WPARAM wParam, // First parameter
LPARAM lParam); // Other parameter
// Called when we start and stop streaming
HRESULT ResetStreamingTimes();
// Window message handlers
BOOL OnClose();
BOOL OnPaint();
// Draw the waveform
void ClearWindow(HDC hdc);
BOOL AllocWaveBuffers(void);
void SearchForPosZeroCrossing(int StartPoint, int * IndexEdge);
void CopyWaveform(IMediaSample *pMediaSample);
void DrawPartialWaveform(HDC hdc,
int IndexStart,
int IndexEnd,
int ViewportStart,
int ViewportEnd);
void DrawWaveform(void);
void SetControlRanges(HWND hDlg);
void SetHorizScrollRange(HWND hDlg);
void ProcessVertScrollCommands(HWND hDlg, WPARAM wParam, LPARAM lParam);
void ProcessHorizScrollCommands(HWND hDlg, WPARAM wParam, LPARAM lParam);
friend BOOL CALLBACK ScopeDlgProc(HWND hwnd, // Window handle
UINT uMsg, // Message ID
WPARAM wParam, // First parameter
LPARAM lParam); // Other parameter
public:
// Constructors and destructors
CScopeWindow(TCHAR *pName, CScopeFilter *pRenderer, HRESULT *phr);
virtual ~CScopeWindow();
HRESULT StartStreaming();
HRESULT StopStreaming();
HRESULT InactivateWindow();
HRESULT ActivateWindow();
// Called when the input pin receives a sample
HRESULT Receive(IMediaSample * pIn);
}; // CScopeWindow
// This is the COM object that represents the oscilloscope filter
class CScopeFilter : public CBaseFilter, public CCritSec
{
public:
// Implements the IBaseFilter and IMediaFilter interfaces
DECLARE_IUNKNOWN
STDMETHODIMP Stop();
STDMETHODIMP Pause();
STDMETHODIMP Run(REFERENCE_TIME tStart);
public:
CScopeFilter(LPUNKNOWN pUnk,HRESULT *phr);
virtual ~CScopeFilter();
// Return the pins that we support
int GetPinCount();
CBasePin *GetPin(int n);
// This goes in the factory template table to create new instances
static CUnknown * WINAPI CreateInstance(LPUNKNOWN, HRESULT *);
STDMETHODIMP JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName);
private:
// The nested classes may access our private state
friend class CScopeInputPin;
friend class CScopeWindow;
CScopeInputPin *m_pInputPin; // Handles pin interfaces
CScopeWindow m_Window; // Looks after the window
}; // CScopeFilter