/*
 * (C) 2003-2006 Gabest
 * (C) 2006-2016 see Authors.txt
 *
 * This file is part of MPC-BE.
 *
 * MPC-BE is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * MPC-BE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

struct PresentFollowing {
	CString	cPresent;
	CString SummaryDesc;
	CString	StartTime;
	CString	Duration;
	CMapStringToString ExtendedDescriptorsItems;
	CStringList ExtendedDescriptorsTexts;
	CString	cFollowing;
};

interface __declspec(uuid("165BE9D6-0929-4363-9BA3-580D735AA0F6"))
IGraphBuilder2 :
public IFilterGraph2 {
	STDMETHOD(IsPinDirection) (IPin* pPin, PIN_DIRECTION dir) PURE;
	STDMETHOD(IsPinConnected) (IPin* pPin) PURE;
	STDMETHOD(ConnectFilter) (IBaseFilter* pBF, IPin* pPinIn) PURE;
	STDMETHOD(ConnectFilter) (IPin* pPinOut, IBaseFilter* pBF) PURE;
	STDMETHOD(ConnectFilterDirect) (IPin* pPinOut, IBaseFilter* pBF, const AM_MEDIA_TYPE* pmt) PURE;
	STDMETHOD(NukeDownstream) (IUnknown* pUnk) PURE;
	STDMETHOD(FindInterface) (REFIID iid, void** ppv, BOOL bRemove) PURE;
	STDMETHOD(AddToROT) () PURE;
	STDMETHOD(RemoveFromROT) () PURE;
};

// private use only
interface __declspec(uuid("43CDA93D-6A4E-4A07-BD3E-49D161073EE7"))
IGraphBuilderDeadEnd :
public IUnknown {
	STDMETHOD_(size_t, GetCount)() PURE;
	STDMETHOD(GetDeadEnd) (int iIndex, CAtlList<CStringW>& path, CAtlList<CMediaType>& mts) PURE;
};

// private use only
interface __declspec(uuid("F3698B5C-2561-46DB-813E-52D3853A2B5F"))
IGraphBuilderSub :
public IUnknown {
	STDMETHOD(RenderSubFile) (LPCWSTR lpcwstrFileName) PURE;
};

// private use only
interface __declspec(uuid("4EBE052F-3BF0-450D-90F8-33DDC9551FD0"))
IGraphBuilderAudio :
public IUnknown {
	STDMETHOD(RenderAudioFile) (LPCWSTR lpcwstrFileName) PURE;
};

// private use only
interface __declspec(uuid("43CDA93D-6A4E-4A07-BD3E-49D161073EE7"))
IBDATuner :
public IUnknown {
	STDMETHOD(SetChannel)	(int nChannelPrefNumber) PURE;
	STDMETHOD(SetAudio)		(int nAudioIndex) PURE;
	STDMETHOD(SetFrequency)	(ULONG ulFrequency) PURE;
	STDMETHOD(Scan)			(ULONG ulFrequency, HWND hWnd) PURE;
	STDMETHOD(GetStats)		(BOOLEAN& bPresent, BOOLEAN& bLocked, LONG& lStrength, LONG& lQuality) PURE;
	STDMETHOD(UpdatePSI)	(PresentFollowing &NowNext) PURE;
};

class CPlayerWindow : public CWnd
{
public:
	CPlayerWindow() {}

protected:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	DECLARE_MESSAGE_MAP()
};

enum {
	EC_BG_AUDIO_CHANGED = EC_USER+1,
	EC_BG_ERROR
};

class CBaseGraph
	: public CUnknown
	, public IGraphBuilder2
	, public IMediaControl
	, public IMediaEventEx
	, public IMediaSeeking
	, public IVideoWindow
	, public IBasicVideo
	, public IBasicAudio
	, public IAMOpenProgress
{
	OAHWND m_hNotifyWnd;
	long m_lNotifyMsg;
	LONG_PTR m_lNotifyInstData;

	struct GMSG {
		long m_lEventCode;
		LONG_PTR m_lParam1, m_lParam2;
	};
	CList<GMSG> m_msgqueue;

protected:
	void ClearMessageQueue();

public:
	CBaseGraph();
	virtual ~CBaseGraph();

	DECLARE_IUNKNOWN;
	STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);

	void NotifyEvent(long lEventCode, LONG_PTR lParam1 = 0, LONG_PTR lParam2 = 0);

protected:
	// IDispatch
	STDMETHODIMP GetTypeInfoCount(UINT* pctinfo);
	STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo);
	STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId);
	STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr);

	// IFilterGraph
	STDMETHODIMP AddFilter(IBaseFilter* pFilter, LPCWSTR pName);
	STDMETHODIMP RemoveFilter(IBaseFilter* pFilter);
	STDMETHODIMP EnumFilters(IEnumFilters** ppEnum);
	STDMETHODIMP FindFilterByName(LPCWSTR pName, IBaseFilter** ppFilter);
	STDMETHODIMP ConnectDirect(IPin* ppinOut, IPin* ppinIn, const AM_MEDIA_TYPE* pmt);
	STDMETHODIMP Reconnect(IPin* ppin);
	STDMETHODIMP Disconnect(IPin* ppin);
	STDMETHODIMP SetDefaultSyncSource();

	// IGraphBuilder
	STDMETHODIMP Connect(IPin* ppinOut, IPin* ppinIn);
	STDMETHODIMP Render(IPin* ppinOut);
	STDMETHODIMP RenderFile(LPCWSTR lpcwstrFile, LPCWSTR lpcwstrPlayList);
	STDMETHODIMP AddSourceFilter(LPCWSTR lpcwstrFileName, LPCWSTR lpcwstrFilterName, IBaseFilter** ppFilter);
	STDMETHODIMP SetLogFile(DWORD_PTR hFile);
	STDMETHODIMP Abort();
	STDMETHODIMP ShouldOperationContinue();

	// IFilterGraph2
	STDMETHODIMP AddSourceFilterForMoniker(IMoniker* pMoniker, IBindCtx* pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter** ppFilter);
	STDMETHODIMP ReconnectEx(IPin* ppin, const AM_MEDIA_TYPE* pmt);
	STDMETHODIMP RenderEx(IPin* pPinOut, DWORD dwFlags, DWORD* pvContext);

	// IGraphBuilder2
	STDMETHODIMP IsPinDirection(IPin* pPin, PIN_DIRECTION dir);
	STDMETHODIMP IsPinConnected(IPin* pPin);
	STDMETHODIMP ConnectFilter(IBaseFilter* pBF, IPin* pPinIn);
	STDMETHODIMP ConnectFilter(IPin* pPinOut, IBaseFilter* pBF);
	STDMETHODIMP ConnectFilterDirect(IPin* pPinOut, IBaseFilter* pBF, const AM_MEDIA_TYPE* pmt);
	STDMETHODIMP NukeDownstream(IUnknown* pUnk);
	STDMETHODIMP FindInterface(REFIID iid, void** ppv, BOOL bRemove);
	STDMETHODIMP AddToROT();
	STDMETHODIMP RemoveFromROT();

	// IMediaControl
	STDMETHODIMP Run();
	STDMETHODIMP Pause();
	STDMETHODIMP Stop();
	STDMETHODIMP GetState(LONG msTimeout, OAFilterState* pfs);
	STDMETHODIMP RenderFile(BSTR strFilename);
	STDMETHODIMP AddSourceFilter(BSTR strFilename, IDispatch** ppUnk);
	STDMETHODIMP get_FilterCollection(IDispatch** ppUnk);
	STDMETHODIMP get_RegFilterCollection(IDispatch** ppUnk);
	STDMETHODIMP StopWhenReady();

	// IMediaEvent
	STDMETHODIMP GetEventHandle(OAEVENT* hEvent);
	STDMETHODIMP GetEvent(long* lEventCode, LONG_PTR* lParam1, LONG_PTR* lParam2, long msTimeout);
	STDMETHODIMP WaitForCompletion(long msTimeout, long* pEvCode);
	STDMETHODIMP CancelDefaultHandling(long lEvCode);
	STDMETHODIMP RestoreDefaultHandling(long lEvCode);
	STDMETHODIMP FreeEventParams(long lEvCode, LONG_PTR lParam1, LONG_PTR lParam2);

	// IMediaEventEx
	STDMETHODIMP SetNotifyWindow(OAHWND hwnd, long lMsg, LONG_PTR lInstanceData);
	STDMETHODIMP SetNotifyFlags(long lNoNotifyFlags);
	STDMETHODIMP GetNotifyFlags(long* lplNoNotifyFlags);

	// IMediaSeeking
	STDMETHODIMP GetCapabilities(DWORD* pCapabilities);
	STDMETHODIMP CheckCapabilities(DWORD* pCapabilities);
	STDMETHODIMP IsFormatSupported(const GUID* pFormat);
	STDMETHODIMP QueryPreferredFormat(GUID* pFormat);
	STDMETHODIMP GetTimeFormat(GUID* pFormat);
	STDMETHODIMP IsUsingTimeFormat(const GUID* pFormat);
	STDMETHODIMP SetTimeFormat(const GUID* pFormat);
	STDMETHODIMP GetDuration(LONGLONG* pDuration);
	STDMETHODIMP GetStopPosition(LONGLONG* pStop);
	STDMETHODIMP GetCurrentPosition(LONGLONG* pCurrent);
	STDMETHODIMP ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat);
	STDMETHODIMP SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags);
	STDMETHODIMP GetPositions(LONGLONG* pCurrent, LONGLONG* pStop);
	STDMETHODIMP GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest);
	STDMETHODIMP SetRate(double dRate);
	STDMETHODIMP GetRate(double* pdRate);
	STDMETHODIMP GetPreroll(LONGLONG* pllPreroll);

	// IVideoWindow
	STDMETHODIMP put_Caption(BSTR strCaption);
	STDMETHODIMP get_Caption(BSTR* strCaption);
	STDMETHODIMP put_WindowStyle(long WindowStyle);
	STDMETHODIMP get_WindowStyle(long* WindowStyle);
	STDMETHODIMP put_WindowStyleEx(long WindowStyleEx);
	STDMETHODIMP get_WindowStyleEx(long* WindowStyleEx);
	STDMETHODIMP put_AutoShow(long AutoShow);
	STDMETHODIMP get_AutoShow(long* AutoShow);
	STDMETHODIMP put_WindowState(long WindowState);
	STDMETHODIMP get_WindowState(long* WindowState);
	STDMETHODIMP put_BackgroundPalette(long BackgroundPalette);
	STDMETHODIMP get_BackgroundPalette(long* pBackgroundPalette);
	STDMETHODIMP put_Visible(long Visible);
	STDMETHODIMP get_Visible(long* pVisible);
	STDMETHODIMP put_Left(long Left);
	STDMETHODIMP get_Left(long* pLeft);
	STDMETHODIMP put_Width(long Width);
	STDMETHODIMP get_Width(long* pWidth);
	STDMETHODIMP put_Top(long Top);
	STDMETHODIMP get_Top(long* pTop);
	STDMETHODIMP put_Height(long Height);
	STDMETHODIMP get_Height(long* pHeight);
	STDMETHODIMP put_Owner(OAHWND Owner);
	STDMETHODIMP get_Owner(OAHWND* Owner);
	STDMETHODIMP put_MessageDrain(OAHWND Drain);
	STDMETHODIMP get_MessageDrain(OAHWND* Drain);
	STDMETHODIMP get_BorderColor(long* Color);
	STDMETHODIMP put_BorderColor(long Color);
	STDMETHODIMP get_FullScreenMode(long* FullScreenMode);
	STDMETHODIMP put_FullScreenMode(long FullScreenMode);
	STDMETHODIMP SetWindowForeground(long Focus);
	STDMETHODIMP NotifyOwnerMessage(OAHWND hwnd, long uMsg, LONG_PTR wParam, LONG_PTR lParam);
	STDMETHODIMP SetWindowPosition(long Left, long Top, long Width, long Height);
	STDMETHODIMP GetWindowPosition(long* pLeft, long* pTop, long* pWidth, long* pHeight);
	STDMETHODIMP GetMinIdealImageSize(long* pWidth, long* pHeight);
	STDMETHODIMP GetMaxIdealImageSize(long* pWidth, long* pHeight);
	STDMETHODIMP GetRestorePosition(long* pLeft, long* pTop, long* pWidth, long* pHeight);
	STDMETHODIMP HideCursor(long HideCursor);
	STDMETHODIMP IsCursorHidden(long* CursorHidden);

	// IBasicVideo
	STDMETHODIMP get_AvgTimePerFrame(REFTIME* pAvgTimePerFrame);
	STDMETHODIMP get_BitRate(long* pBitRate);
	STDMETHODIMP get_BitErrorRate(long* pBitErrorRate);
	STDMETHODIMP get_VideoWidth(long* pVideoWidth);
	STDMETHODIMP get_VideoHeight(long* pVideoHeight);
	STDMETHODIMP put_SourceLeft(long SourceLeft);
	STDMETHODIMP get_SourceLeft(long* pSourceLeft);
	STDMETHODIMP put_SourceWidth(long SourceWidth);
	STDMETHODIMP get_SourceWidth(long* pSourceWidth);
	STDMETHODIMP put_SourceTop(long SourceTop);
	STDMETHODIMP get_SourceTop(long* pSourceTop);
	STDMETHODIMP put_SourceHeight(long SourceHeight);
	STDMETHODIMP get_SourceHeight(long* pSourceHeight);
	STDMETHODIMP put_DestinationLeft(long DestinationLeft);
	STDMETHODIMP get_DestinationLeft(long* pDestinationLeft);
	STDMETHODIMP put_DestinationWidth(long DestinationWidth);
	STDMETHODIMP get_DestinationWidth(long* pDestinationWidth);
	STDMETHODIMP put_DestinationTop(long DestinationTop);
	STDMETHODIMP get_DestinationTop(long* pDestinationTop);
	STDMETHODIMP put_DestinationHeight(long DestinationHeight);
	STDMETHODIMP get_DestinationHeight(long* pDestinationHeight);
	STDMETHODIMP SetSourcePosition(long Left, long Top, long Width, long Height);
	STDMETHODIMP GetSourcePosition(long* pLeft, long* pTop, long* pWidth, long* pHeight);
	STDMETHODIMP SetDefaultSourcePosition();
	STDMETHODIMP SetDestinationPosition(long Left, long Top, long Width, long Height);
	STDMETHODIMP GetDestinationPosition(long* pLeft, long* pTop, long* pWidth, long* pHeight);
	STDMETHODIMP SetDefaultDestinationPosition();
	STDMETHODIMP GetVideoSize(long* pWidth, long* pHeight);
	STDMETHODIMP GetVideoPaletteEntries(long StartIndex, long Entries, long* pRetrieved, long* pPalette);
	STDMETHODIMP GetCurrentImage(long* pBufferSize, long* pDIBImage);
	STDMETHODIMP IsUsingDefaultSource();
	STDMETHODIMP IsUsingDefaultDestination();

	// IBasicAudio
	STDMETHODIMP put_Volume(long lVolume);
	STDMETHODIMP get_Volume(long* plVolume);
	STDMETHODIMP put_Balance(long lBalance);
	STDMETHODIMP get_Balance(long* plBalance);

	// IAMOpenProgress
	STDMETHODIMP QueryProgress(LONGLONG* pllTotal, LONGLONG* pllCurrent);
	STDMETHODIMP AbortOperation();
};
