// NetVideoPlayer.h

#define VOLUME_FULL		0
#define VOLUME_SILENCE	-10000


	

#pragma once

#using <System.Drawing.dll>

using namespace System;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
using namespace System::Runtime::InteropServices;

public enum class PLAYER_STATE
    {	PLAYER_STATE_Uninitialized	= 0,
	PLAYER_STATE_Graph_Stopped1	= ( PLAYER_STATE_Uninitialized + 1 ) ,
	PLAYER_STATE_Graph_Stopped2	= ( PLAYER_STATE_Graph_Stopped1 + 1 ) ,
	PLAYER_STATE_Nav_Stopped	= ( PLAYER_STATE_Graph_Stopped2 + 1 ) ,
	PLAYER_STATE_Playing	= ( PLAYER_STATE_Nav_Stopped + 1 ) ,
	PLAYER_STATE_Graph_Paused	= ( PLAYER_STATE_Playing + 1 ) ,
	PLAYER_STATE_Nav_Paused	= ( PLAYER_STATE_Graph_Paused + 1 ) ,
	PLAYER_STATE_Scanning	= ( PLAYER_STATE_Nav_Paused + 1 ) 
    } 	;


const GUID CLSID_FFDSHOW = { 0x04fe9017, 0xf873, 0x410e, 0x87, 0x1e, 0xab, 0x91, 0x66, 0x1a, 0x4e, 0xf7 };
bool sampleready;


class C
{
	int value_;

public:
		//	CComPtr<IMFVideoDisplayControl> m_pEVRAspectRatioControl2;
	C() 
	{

	}
	
		
		void SetValue(int *val) { value_ = *val;}
	const int& GetValue() { return value_; }

	//	CComPtr<IMFVideoDisplayControl> m_pEVRAspectRatioControl;
			CComPtr<IMediaControl> m_pMediaControl;

	CComPtr<IMediaSeeking> m_pMediaSeeking;
			CComPtr<ICaptureGraphBuilder2> m_pGraphBuilder2;
			CComPtr<IFilterGraph2> m_pFilterGraph;
				CComPtr<IMediaEventEx> m_pMediaEvent;
	CComPtr<IBasicAudio> m_pBasicAudio;
		CComPtr<IMediaPosition> m_pMediaPosition;
				CComPtr<IBaseFilter> pAudioRender;
						//CComPtr<IBaseFilter> pNullAudioRenderer;
						CComPtr<IBaseFilter> pColorConvertDMO;
						CComPtr<IDMOWrapperFilter> pDmoWrapper;
						CComPtr<IBaseFilter> nullRenderer;
						    CComPtr<IBaseFilter> grabberFilter;
							    CComPtr<IBaseFilter> sourceFilter;
						//CComPtr<IMediaFilter> pMediaFilter;



								



									//define vendor id and product id
#define VID 0x0314
#define PID 0xe457

//configure and interface number
//TODO figure out what these mean
#define MY_CONFIG 1
#define MY_INTF 0

//endpoints for communication
#define EP_IN 0x81
#define EP_OUT 0x01

//maximum packet size, 64 for full-speed, 512 for high-speed


void* asyncReadContext ;
void* asyncWriteContext ;




#define BUF_SIZE 2052//64
	
char writeBuffer[ BUF_SIZE ];
char readBuffer[1];

long cbBuffer;
CComPtr<ISampleGrabber> m_pSampleGrabber ;
 AM_MEDIA_TYPE globalmt;
};

	public ref class XDMDNative
	{
		
  //static System::String *_static_msg = 
  //  S"Static message called because static constructor invoked!";
  //static Int32 _instance_cnt = 0;
C* pC; 
	public:
~XDMDNative()
{



	InternalCleanup();

//if (pC->pColorConvertDMO != NULL)
//	{
//		pC->pColorConvertDMO.Release();
//		pC->pColorConvertDMO = NULL;
//	}

	if (pC->m_pFilterGraph != NULL)
	{
		pC->m_pFilterGraph.Release();
		pC->m_pFilterGraph = NULL;
	}



if (pC->pDmoWrapper != NULL)
	{
		//pC->pDmoWrapper->
		pC->pDmoWrapper.Release();
		pC->pDmoWrapper = NULL;
	}
if (pC->pColorConvertDMO != NULL)
	{
		pC->pColorConvertDMO.Release();
		pC->pColorConvertDMO = NULL;
	}



if (pC->nullRenderer != NULL)
	{
		pC->nullRenderer.Release();
		pC->nullRenderer = NULL;
	}
		if (pC->m_pSampleGrabber != NULL)
	{
		pC->m_pSampleGrabber->SetBufferSamples(FALSE);
		pC->m_pSampleGrabber.Release ();
		pC->m_pSampleGrabber = NULL;
	}

//
	if (pC->m_pFilterGraph != NULL)
	{
		pC->m_pFilterGraph.Release();
		pC->m_pFilterGraph = NULL;
	}

		if (pC->m_pGraphBuilder2 != NULL)
	{
		pC->m_pGraphBuilder2.Release();
		pC->m_pGraphBuilder2 = NULL;
	}



			if (pC->grabberFilter != NULL)
	{
		pC->grabberFilter.Release();
		pC->grabberFilter = NULL;
	}
delete pC;

}
		XDMDNative()


  {
	  //m_pSampleGrabber=NULL;
    //_instance_cnt++;
	W=0;
	pC = new C();
  }


		int FrameCount;
		
char *pBuffer;



//IVMRWindowlessControl9* windowlessCtrl = NULL;
//	ISampleGrabber* m_pSampleGrabber;
//		CComPtr<IVMRAspectRatioControl> m_pVMRAspectRatioControl;
//
////IMFVideoDisplayControl* m_pEVRAspectRatioControl=NULL;
//
//	CComPtr<IBaseFilter> pffdshow;
//	CComPtr<IBaseFilter> pVideoRender ;
//	CComPtr<IBaseFilter> pVideoRender2;
//	CComPtr<IPin> pPin;
//	CComPtr<IEnumPins> pEnum ;
//
//	CComPtr<IPin> pPin1;
//		CComPtr<IMFVideoDisplayControl> m_pEVRAspectRatioControl;
//CComPtr<IMFGetService> m_pEVRService;
//
//	CComPtr<IVMRAspectRatioControl9> m_pVMRAspectRatioControl9;
//			CComPtr<IMediaControl> m_pMediaControl;
//	CComPtr<IBasicVideo> m_pBasicVideo;
//	CComPtr<IMediaSeeking> m_pMediaSeeking;
//		CComPtr<IMediaEventEx> m_pMediaEventEx;
//	CComPtr<IVideoWindow> m_pVideoWindow;
//		CComPtr<IGraphBuilder> m_pGraphBuilder;
//		CComPtr<ICaptureGraphBuilder2> m_pGraphBuilder2;
//			CComPtr<IFilterGraph2> m_pFilterGraph;
//				CComPtr<IMediaEventEx> m_pMediaEvent;
//	CComPtr<IBasicAudio> m_pBasicAudio;
//		CComPtr<IMediaPosition> m_pMediaPosition;
//
//					//IBaseFilter* pSampleGrabber=NULL;
//		/*		IBaseFilter* pffdshow=NULL;
//	IBaseFilter* pVideoRender=NULL;
//		IBaseFilter* pVideoRender2=NULL;
//		IBaseFilter* pNullRenderer=NULL;*/
//
//				CComPtr<IBaseFilter> pAudioRender;
//						CComPtr<IBaseFilter> pNullAudioRenderer;
//							CComPtr<IOverlay> m_pOverlay;

	//enum class   PLAYER_STATE
 //   {	PLAYER_STATE_Uninitialized	= 0,
	//PLAYER_STATE_Graph_Stopped1	= ( PLAYER_STATE_Uninitialized + 1 ) ,
	//PLAYER_STATE_Graph_Stopped2	= ( PLAYER_STATE_Graph_Stopped1 + 1 ) ,
	//PLAYER_STATE_Nav_Stopped	= ( PLAYER_STATE_Graph_Stopped2 + 1 ) ,
	//PLAYER_STATE_Playing	= ( PLAYER_STATE_Nav_Stopped + 1 ) ,
	//PLAYER_STATE_Graph_Paused	= ( PLAYER_STATE_Playing + 1 ) ,
	//PLAYER_STATE_Nav_Paused	= ( PLAYER_STATE_Graph_Paused + 1 ) ,
	//PLAYER_STATE_Scanning	= ( PLAYER_STATE_Nav_Paused + 1 ) 
 //   } 	;
//int Instance();
  //void _FreeMediaType(AM_MEDIA_TYPE& mt);

usb_dev_handle *device ;

//gets device handle
usb_dev_handle* open_dev( void );

bool InitPinDMD2();
bool DisposePinDMD2();

//context handle for transfer and receive
//think of them bit like session id:s


void renderDMDFrame(int width, int height, array<Byte> ^currbuffer);

void RemoveAllFilters(IFilterGraph2 *pFilterGraph);
HRESULT DisconnectAllPins(IGraphBuilder* pGraph);
BOOL IsFFDShowInstalled();
	void ConfigureSampleGrabber();
	void ReleaseAllInterfacesFinal();
	void ConfigureSampleGrabber24bit();
	void ConfigureSampleGrabber16bit();

	void Converto8bitGray(int w, int h, int depth, array<Byte> ^argbvalues, array<Byte> ^arr);
	void Converto4bitGray(int w, int h, int depth, array<Byte> ^argbvalues, array<Byte> ^arr);
	void Converto4bitGrayFlipY(int w, int h, int depth, array<Byte> ^argbvalues, array<Byte> ^arr);

	void Clear(long Source, long Size,int color);
	void Clear(array<Byte> ^Source, long Size,int color);
	void Clear(System::Drawing::Bitmap ^Source, int color);
	void Render(System::Drawing::Bitmap ^Source, array<Byte> ^Buffer);
	void Render(long Source,int x, int y, array<Byte> ^Buffer);
	void Draw(array<Byte> ^SrcBuffer, array<Byte> ^DisplayBuf, int SrcWidth, int SrcHeight, System::Drawing::Rectangle ^SrcRect, System::Drawing::Rectangle ^DesRect, int Brightness, bool FlipX, bool FlipY,double SrcRectScale,double DesRectScale);
	void Draw(array<Byte> ^SrcBuffer, array<Byte> ^DisplayBuf, int SrcWidth, int SrcHeight,int DesWidth,int DesHeight, System::Drawing::Rectangle ^SrcRect, System::Drawing::Rectangle ^DesRect, int Brightness, bool FlipX, bool FlipY,double SrcRectScale,double DesRectScale);
	void DrawVideo(array<Byte> ^SrcBuffer, array<Byte> ^DisplayBuf, int SrcWidth, int SrcHeight,int DesWidth,int DesHeight, System::Drawing::Rectangle ^SrcRect, System::Drawing::Rectangle ^DesRect, int Brightness, bool FlipX, bool FlipY,double SrcRectScale,double DesRectScale);
void Converto8bitGrayFlipY(int w, int h, int depth, long Source, array<Byte> ^arr);
void Converto4bitGrayFlipY(int w, int h, int depth, long Source, array<Byte> ^arr);

	//void Converto8bitGray(int w, int h, int depth, Bitmap ^Source,, array<Byte> ^arr);
	void Converto4bitGray(int w, int h, int depth, System::Drawing::Bitmap ^Source, array<Byte> ^arr);
	void Converto4bitGrayFont(int w, int h, int depth, System::Drawing::Bitmap ^Source, array<Byte> ^arr);
	void Converto8bitGray(int w, int h, int depth, System::Drawing::Bitmap ^Source, array<Byte> ^arr);
	 System::Drawing::Rectangle^ ScaleRectangle(System::Drawing::Rectangle ^R, double Scale);
void Converto4bitGray(int w, int h, int depth, long Source, array<Byte> ^arr);
void Converto8bitGray(int w, int h, int depth, long Source, array<Byte> ^arr);
void _Sleep(int ms);
		bool GrabSampleToMemory(long buf,long l,bool wait);

		bool GrabSampleToBuffer(array<Byte> ^buf,long l);

	bool GrabSampleToMemory(long buf,long l);
	bool Open(System::String^ file, bool WMV, bool m_bAudioOn);
	bool Open24bit(System::String^ file, bool WMV, bool m_bAudioOn);
	bool Open16bit(System::String^ file, bool WMV, bool m_bAudioOn);
	int cntgrabs;
	bool Stop();
	bool StopWait();
	bool Play();
	bool PlayWait();
bool 	m_bFirstPlay;
	int VideoWidth();
	int VideoHeight();
	int VideoPitch();
	STDMETHODIMP Pause(void);
	STDMETHODIMP GrabSample();
	bool GrabSampleToDC(int HD);
	bool GrabSampleToDC(int HD,int width,int height);

	STDMETHODIMP Seek(LONGLONG position);
	STDMETHODIMP SetRate(double rate);
	LONGLONG GetCurrentPosition();
	LONGLONG GetDuration();
	void InternalCleanup();
	PLAYER_STATE State();
	PLAYER_STATE m_State;












String^ lastfile;
bool lastaudio;

	// CallbackFuncDelegate^ del;

private:

	
	LONGLONG LastMem;
	void SetState(PLAYER_STATE state);	
	void MyDeleteMediaType(AM_MEDIA_TYPE *pmt);
	void SetVolume(INT volume);
	HRESULT SaveGraphFile(CComPtr<ICaptureGraphBuilder2> pGraph, WCHAR *wszPath); 
	void ReleaseInterfaces();
	VIDEOINFOHEADER *pVih; 
		// TODO: Add your methods for this class here.
	int W;
	int H;
	int pitch;
	
		
	};

