
/*	Copyright (C) G. Jespersen

	LAV Filters - Copyright (C) 2010-2013 Hendrik Leppkes http://www.1f0.de
	See LAV Licence.txt.*/

//
// Lav Filters XP support: 11//2020
//  See: https://github.com/Nevcairiel/LAVFilters/releases
//  Last for XP is 0.70.2 - 2017/07/06 
//  An XP Fork: https://github.com/3dyd/LAVFiltersXP
//


#if !defined PLAYER_H
#define PLAYER_H

#if _MSC_VER > 1000
#pragma once
#endif				// _MSC_VER > 1000
#include <dshow.h>	// first
#include <comdef.h> // IUnknownPtr

// See StdAfx.h for #pragma Strmbasd.lib, Strmiids.lib, Quartz.lib
// See StdAfx.h for #include <initguid.h> notes.

// Forward declaration for function ptr
// in PlayVideoLav.
class CMainFrame;


// From GCDL - http://www.gdcl.co.uk/2011/June/UnregisteredFilters.htm
// used by CreateObjectFromPath().
//
// Define the prototype of the class factory entry point in a COM dll
typedef HRESULT (STDAPICALLTYPE* FN_DLLGETCLASSOBJECT)(REFCLSID clsid, REFIID iid, void** ppv);
// Smart Pointer.
_COM_SMARTPTR_TYPEDEF(IBaseFilter, IID_IBaseFilter); // IBaseFilterPtr

// For CreateObjectFromPath() overload.
// Smart Pointers alternative.
typedef HRESULT (__stdcall * DllGetBaseFilterFunc)(REFCLSID, REFIID, void**);


////////////////////////////////////////////////////////////////
// class CPlayer

//
// Note Com is initialized in CDsLavApp::InitInstance()
//

class CPlayer
{
public:
	CPlayer();
	~CPlayer();

private:
	// Video playback.
	IGraphBuilder * m_pGraph;
	IMediaControl * m_pControl;
	IMediaEventEx * m_pEvent;
	IMediaSeeking * m_pSeeking;
	IVideoWindow  * m_pVidWin;
	IBasicVideo	  * m_pBaseVid;
	IBasicAudio	  * m_pBaseAudio;

	// DVD
	IBaseFilter	  *	m_pDvdNav;
	IMediaControl * m_pIDvdMedia;		// for DVD_HMSF_TimeCodeEvents todo
	IDvdControl2  *	m_pIDvdControl2;		// IDvdControl2 interface
	IDvdInfo2     *	m_pIDvdInfo2;       // IDvdInfo2 interface _IID_IDvdInfo2
	BOOL		m_redrawVid;
	BOOL		m_muted;
	int		m_curVolPercent;		// 0 - 100
	int		m_nPlays;			// debug
	HWND		m_hWndVideo;			// video window hwnd
	HWND		m_hWndEvents;		// event handler hwnd

	// CD Audio
	BOOL		m_cdPlaying;

	// DVD
	BOOL		m_dvdPlaying;
	UINT		m_dvdCurChapter;
	UINT		m_dvdCurTitle;
	DVD_DOMAIN	 m_dvdCurDomain; //= DVD_DOMAIN_FirstPlay
	// DVD seeking
	UINT		m_dvdCurTimeSec;
	UINT		m_dvdTotalTimeSec;
	UINT		m_dvdPrevChapter;
	UINT		m_dvdPrevTitle;
	UINT		m_dvdNumTitles;
	UINT		m_dvdNumChapters;		// this title
	UINT		m_nMenuButtons;
	UINT		m_nMenuButtonSel;
	DVD_DOMAIN	 m_dvdPrevDomain;

	// LAV Filters - managed by smart pointers.
	IBaseFilterPtr	m_pLavSrcFilter;
	IBaseFilterPtr	m_pLavVidFilter;
	IBaseFilterPtr	m_pLavAudFilter;

	// LAV Filters - app managed pointers.
	IBaseFilter	  *	m_pLavSrc;
	IBaseFilter	  *	m_pLavVid;
	IBaseFilter	  *	m_pLavAud;

	// Lav dll paths
	CString			m_pathLavSrc;
	CString			m_pathLavVid;
	CString			m_pathLavAud;

	// AsyncCd Filter - app managed pointer.
	IBaseFilter	  *	m_pAsyncCdSrc;

	// AsyncCd Filter path
	CString			m_pathAsyncCdSrc;

	// Misc
	CString			m_curDirectory;
	FILTER_STATE		m_fsCurrent;
	REFERENCE_TIME  m_rtTotalTime;
	BOOL				m_bIsStream;		// 11/22-4

// Operations
public:

	// From View - ControlsBar changes.
	BOOL		PlaybackTimeSliderMoved(BOOL moving, const UINT & newPos, UINT & seconds);
	BOOL		PlaybackTimeSliderMovedKeyboard(const UINT & newPos, UINT & seconds);	// 7/22
	BOOL		PlaybackVolSliderMoved(int newPos);
	BOOL		PlaybackGetCurTime(UINT & position, UINT & seconds);	

	// From View - start, stop, size, etc.
	BOOL		PlayDvdLav(CString path, CMainFrame * pMainFrame);
	BOOL		PlayCdLav(CString path, CMainFrame * pMainFrame, int volPercent = 50);	// 12/22
	BOOL		PlayVideoLav(const CString & path, CMainFrame * pMainFrame);

	BOOL		StepVolume(BOOL stepUp, LONG & newVol);
	BOOL		TogglePlaybackPause();
	BOOL		HandleVideoEvent(CMainFrame * pFrm);
	BOOL		SetVideoRect(CRect rect);
	void		ToggleVolumeMute();
	BOOL		StopPlayback();
	void		PausePlayback();
	void		PutVisible(BOOL hide);

	// DVD 
	void		DvdTitleChapterPlay(UINT title,  UINT chapter);
	UINT		DvdGetNumChaptersInTitle(UINT title);
	void		DvdMenuCall(DVD_MENU_ID id);
	void		DvdMouseSelect(POINT point, POINT pointScreen);
	void		DvdMouseActivate(POINT point);
	UINT		DvdGetCurTitle()	 { return m_dvdCurTitle; };
	UINT		DvdGetCurChapter()	 { return m_dvdCurChapter; };
	UINT		DvdGetNumTitles()    { return m_dvdNumTitles; };
	UINT		DvdGetNumChapters()  { return m_dvdNumChapters; };
	CString DvdGetTotalTimeStr();
	CString DvdGetCurDomainStr();
	DVD_DOMAIN DvdGetCurDomain() { return m_dvdCurDomain; }; // 8/22

	// Set.
	//
	void SetVolPercent(int iVolPercent) { m_curVolPercent = iVolPercent; }; // 11/23-1

	// Get
	//
	BOOL		IsPaused() { return m_fsCurrent == State_Paused; };
	BOOL		IsRunning() { return m_fsCurrent == State_Running; };
	BOOL		IsStopped() { return m_fsCurrent == State_Stopped; };
	BOOL		IsRunningOrPaused() { return !IsStopped(); };
	BOOL		IsRunningDvd() { return m_dvdPlaying; };
	BOOL		IsRunningCd() { return m_cdPlaying; };
	BOOL		IsMuted() { return m_muted; };
	BOOL		IsStream() { return m_bIsStream; };		// 11/22-4

	int		GetVolPercent() { return m_curVolPercent; };
	REFERENCE_TIME	GetTotalTime() { return m_rtTotalTime; };
	// DVD
	UINT		GetTimeSeconds(DVD_TIMECODE tc);
	DVD_TIMECODE GetTimeFromSeconds(UINT seconds);
	UINT		GetTimeSeconds2(DVD_HMSF_TIMECODE tc);
	DVD_HMSF_TIMECODE GetTimeFromSeconds2(UINT seconds);

	// Helpers
	HRESULT EnumFilters();
	void		UtilDeleteMediaType(AM_MEDIA_TYPE *pmt);

private:
	// Helpers
	BOOL		CleanPlayback();
	BOOL		CleanPlayback(const CString & errMsg);
	BOOL		CleanPlayback(const CString & errMsg, int hr);
	void		PrepareSeeking();
	void		PrepareSeekingDvd();
	int		DxVolToPercent(LONG dxVol);
	LONG		DxVolFromPercent(int percent);
	void		SetLavPerOsVersion();

	// GDCL - use smart pointers.
	// See PlayVideoLavTest().
	HRESULT CreateObjectFromPath(CString path, REFCLSID clsid, IUnknown** ppUnk);

	// Overload - use IBaseFilter pointers.
	// See PlayVideoLav().
	HRESULT CreateObjectFromPath(CString path, REFCLSID clsid, IBaseFilter ** pBaseFilter);

	// Pin fetch.
	HRESULT GetPin(IBaseFilter *pF, PIN_DIRECTION PinDir, 
				   const GUID& Category, IPin **ppPin);
	BOOL		PinMatchesCategory(IPin *pPin, const GUID & Category, PIN_DIRECTION PinDir);

	// Pin fetch2
	HRESULT GetPin2(IBaseFilter * pFilter, PIN_DIRECTION dirrequired, 
						 int iNum, IPin **ppPin);
};

#endif // _PLAYER_H
