// FiCamera.h: interface for the CFiCamera class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_FICAMERA_H__45FEAFB2_DE30_465D_9D17_5D6C7084BED8__INCLUDED_)
#define AFX_FICAMERA_H__45FEAFB2_DE30_465D_9D17_5D6C7084BED8__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "FiCommon.h"
#include "FiUtil.h"
#include "FiDbg.h"

// Add camera class related declarations here:
#define VIDEO_PREVIEW_ENABLED_BIT 0x1
#define VIDEO_CAPTURE_ENABLED_BIT 0x2
#define TCP_STREAMING_ENABLED_BIT 0x4

#define BITS_IN_BYTE 8

typedef HRESULT (*FiCallback)(ULONG, double, BYTE *, BITMAPINFOHEADER *);
typedef HRESULT (*FiCallbackEx)(ULONG, double, BYTE *, BITMAPINFOHEADER *, void*);
typedef HRESULT (*YuvToRgbCallback)(BYTE *, BITMAPINFOHEADER *, void*);

class CFiCamera;
typedef void (*DeviceRemovalCallback)(CFiCamera*, void*);

class CFiSampleGrabberCB;

#ifdef CFICAMERA_DLL_BUILD
#define CFICAMERA_DLL_SPEC __declspec(dllexport)
#else
#define CFICAMERA_DLL_SPEC __declspec(dllimport)
#endif

#define CFICAMERA(type) CFICAMERA_DLL_SPEC type WINAPI

extern "C"
{
class CFICAMERA_DLL_SPEC CFiRemoteReceiver
{
public:
    CFiRemoteReceiver()
    {
        HRESULT hr;

        hr = FiCreateCaptureGraphBuilder(&m_GraphBuilder, &m_FilterGraph);

        hr = FiGetRegisteredFilterHandle(_T("Firei Net Receive"), &m_NetReceiveFilter, 
            CLSID_LegacyAmFilterCategory);

        hr = FiAddFilter(m_FilterGraph, m_NetReceiveFilter, _T("Firei Net Receive Filter"));

        ZeroMemory(&m_ImageSize, sizeof(SIZE));
    }

    ~CFiRemoteReceiver()
    {
        Stop();

        FiNukeDownstream(m_NetReceiveFilter, m_FilterGraph, NULL, 0);

        FiRemoveFilter(m_FilterGraph, m_NetReceiveFilter);

        m_NetReceiveFilter->Release();
        m_NetReceiveFilter = NULL;

        m_FilterGraph->Release();
        m_FilterGraph = NULL;

        m_GraphBuilder->Release();
        m_GraphBuilder = NULL;
    } 
    
    HRESULT Init(HWND a_PreviewWindow, LPRECT a_PreviewRect, WCHAR *a_RemoteURL)
    {
        FiNetRcv    *NetReceive;
        HRESULT      hr;

        Stop();
        FiNukeDownstream(m_NetReceiveFilter, m_FilterGraph, NULL, 0);

        hr = m_NetReceiveFilter->QueryInterface(IID_FiNetRcv, (void **)  &NetReceive);
        hr = NetReceive->SetURL(a_RemoteURL);
        hr = NetReceive->GetImageSize(&m_ImageSize);
        NetReceive->Release();

        hr = FiGraphRender(m_GraphBuilder, NULL, &MEDIATYPE_Video,
            m_NetReceiveFilter, NULL ,NULL);

        hr = FiEnableVideoWindow(m_FilterGraph, (OAHWND) a_PreviewWindow);

        hr = FiSetVideoWindowPosition(m_FilterGraph, a_PreviewRect->left, a_PreviewRect->top, 
            a_PreviewRect->right - a_PreviewRect->left, a_PreviewRect->bottom - a_PreviewRect->top);

        return hr;
    }

    HRESULT Start()
    {
        return FiRunGraph(m_FilterGraph);
    }
 
    HRESULT Stop()
    {
        return FiStopGraph(m_FilterGraph);
    }

    HRESULT Pause()
    {
        return FiPauseGraph(m_FilterGraph);
    }

    HRESULT SetPreviewRect(LPRECT a_PreviewRect)
    {
        return FiSetVideoWindowPosition(m_FilterGraph, a_PreviewRect->left, a_PreviewRect->top, 
            a_PreviewRect->right - a_PreviewRect->left, a_PreviewRect->bottom - a_PreviewRect->top);
    }

    SIZE m_ImageSize;

private:
    ICaptureGraphBuilder2  *m_GraphBuilder;
    IGraphBuilder          *m_FilterGraph;
    IBaseFilter            *m_NetReceiveFilter;
};

class CFICAMERA_DLL_SPEC CFiCamera  
{
// Construction
public:
    CFiCamera(HRESULT *phr);
    CFiCamera(ULONG uCameraIndex, HRESULT *phr);
    CFiCamera(ULONG uCameraIndex, LPCSTR *szMatchArray, LPCSTR *szNoMatchArray, HRESULT *phr);
    CFiCamera(ULONG uCameraIndex, LPCWSTR *szMatchArray, LPCWSTR *szNoMatchArray, HRESULT *phr);
    CFiCamera(CAMERA_GUID CameraGuid, HRESULT *phr);
protected:
	HRESULT InitA(ULONG uCameraIndex, LPCSTR *szMatchArray, LPCSTR *szNoMatchArray);
    HRESULT InitW(ULONG uCameraIndex, LPCWSTR *szMatchArray, LPCWSTR *szNoMatchArray);
	HRESULT Init(CAMERA_GUID CameraGuid);
    HRESULT SaveFeatureValuesToRegistry(ULONG a_uMemoryChannel);
    HRESULT GetFeatureValuesFromRegistry(ULONG a_uMemoryChannel);
    LONG    m_lMaxHWChannel;

// Attributes
public:
    BYTE                m_byCameraState;
    BYTE                m_byStreamState;
    BOOL                m_bCopyingCaptureFile;
    HWND                m_hViewerWnd;
    Fi_VENDOR_INFO      m_VendorInfo;
    ULONG               m_uMaxChannel;
    BOOL                m_bEnableOverlays;
    CHAR                m_szErrorMsg[256];
    CHAR                m_szLicenceString[256];
    FIREi_LICENCE_TYPE  m_LicenceType;
    IGraphBuilder*      m_pFilterGraph;

// Operations
public:
    HRESULT InitStream(FIREi_PIXEL_FORMAT a_outputFormat=RGB_24);
    HRESULT InitStream(HWND hPreviewWindow, LPRECT pPreviewWindowRect);
    HRESULT InitStream(CHAR *szVideoCaptureFile, FIREi_PIXEL_FORMAT a_captureFormat=pixel_format_none);
    HRESULT InitStream(WCHAR *szVideoCaptureFile, FIREi_PIXEL_FORMAT a_captureFormat=pixel_format_none);
    HRESULT InitStream(HWND hPreviewWindow,
        LPRECT pPreviewWindowRect, CHAR *szVideoCaptureFile, FIREi_PIXEL_FORMAT a_captureFormat=pixel_format_none);
    HRESULT InitStream(HWND hPreviewWindow,
        LPRECT pPreviewWindowRect, WCHAR *szVideoCaptureFile, FIREi_PIXEL_FORMAT a_captureFormat=pixel_format_none);
    HRESULT InitStream(CHAR *szVideoCaptureFile, CHAR *szVideoCompressorName);
    HRESULT InitStream(WCHAR *szVideoCaptureFile, WCHAR *szVideoCompressorName);
    HRESULT InitStream(HWND hPreviewWindow,
                       LPRECT pPreviewWindowRect,
                       CHAR *szVideoCaptureFile,
                       CHAR *szVideoCompressorName);
    HRESULT InitStream(HWND hPreviewWindow,
                       LPRECT pPreviewWindowRect,
                       WCHAR *szVideoCaptureFile,
                       WCHAR *szVideoCompressorName);
    HRESULT InitStream(CHAR *szVideoCaptureFile, CHAR *szVideoCompressorName, CHAR *szAudioCaptureDeviceName);
    HRESULT InitStream(WCHAR *szVideoCaptureFile, WCHAR *szVideoCompressorName, WCHAR *szAudioCaptureDeviceName);
    HRESULT InitStream(HWND hPreviewWindow,
                       LPRECT pPreviewWindowRect,
                       CHAR *szVideoCaptureFile,
                       CHAR *szVideoCompressorName,
                       CHAR *szAudioCaptureDeviceName);
    HRESULT InitStream(HWND hPreviewWindow,
                       LPRECT pPreviewWindowRect,
                       WCHAR *szVideoCaptureFile,
                       WCHAR *szVideoCompressorName,
                       WCHAR *szAudioCaptureDeviceName);
    HRESULT InitStream(HWND   hPreviewWindow,
                       LPRECT pPreviewWindowRect,
                       DWORD  XmitPort,
                       ULONG  ProfileIdx);
    HRESULT InitStream(DWORD XmitPort, ULONG ProfileIdx);

    HRESULT ShutdownStream();

    HRESULT GetNextFrameBuffer(long *a_pFrameSize, long *a_pFrameBuffer, FIREi_PIXEL_FORMAT a_Format);
    HRESULT SetCallback(FiCallback OnFrame, FIREi_PIXEL_FORMAT format);
    HRESULT SetCallback(FiCallbackEx OnFrame, FIREi_PIXEL_FORMAT format, void* Context);
    void SetDeviceRemovalCallback(DeviceRemovalCallback OnDeviceRemoved, void* Context);

    HRESULT Run();
    HRESULT Pause();
    HRESULT Stop();
    HRESULT Stop(HWND hProgress);

    HRESULT Get(FiExpoControlProperty property, float *plValue);
    HRESULT Get(FiColorControlProperty property, float *plValue);
    HRESULT Get(FiBasicControlProperty property, float *plValue);

    HRESULT Get(FiExpoControlProperty property, float *plValue , BOOL bAbsolute);
    HRESULT Get(FiColorControlProperty property, float *plValue, BOOL bAbsolute);
    HRESULT Get(FiBasicControlProperty property, float *plValue, BOOL bAbsolute);

    HRESULT Get(FiExpoControlProperty property, float *plValue, LONG *plFlags);
    HRESULT Get(FiColorControlProperty property, float *plValue, LONG *plFlags);
    HRESULT Get(FiBasicControlProperty property, float *plValue, LONG *plFlags);

    HRESULT GetRange(FiExpoControlProperty property, float *plMinValue, float *plMaxValue);
    HRESULT GetRange(FiColorControlProperty property, float *plMinValue, float *plMaxValue);
    HRESULT GetRange(FiBasicControlProperty property, float *plMinValue, float *plMaxValue);

    HRESULT GetRange(FiExpoControlProperty property, float *plMinValue, float *plMaxValue, BOOL bAbsolute);
    HRESULT GetRange(FiColorControlProperty property, float *plMinValue, float *plMaxValue, BOOL bAbsolute);
    HRESULT GetRange(FiBasicControlProperty property, float *plMinValue, float *plMaxValue, BOOL bAbsolute);

    HRESULT Set(FiExpoControlProperty property, float lValue);
    HRESULT Set(FiColorControlProperty property, float lValue);
    HRESULT Set(FiBasicControlProperty property, float lValue);

    HRESULT Set(FiExpoControlProperty property, float lValue , BOOL bAbsolute);
    HRESULT Set(FiColorControlProperty property, float lValue, BOOL bAbsolute);
    HRESULT Set(FiBasicControlProperty property, float lValue, BOOL bAbsolute);

    HRESULT Set(FiExpoControlProperty property, float lValue, LONG lFlags);
    HRESULT Set(FiColorControlProperty property, float lValue, LONG lFlags);
    HRESULT Set(FiBasicControlProperty property, float lValue, LONG lFlags);

    HRESULT AbsoluteToRelative(FiExpoControlProperty property, float AbsoluteValue, float *RelativeValue);
    HRESULT RelativeToAbsolute(FiExpoControlProperty property, float RelativeValue, float *AbsoluteValue);
    HRESULT AbsoluteToRelative(FiColorControlProperty property, float AbsoluteValue, float *RelativeValue);
    HRESULT RelativeToAbsolute(FiColorControlProperty property, float RelativeValue, float *AbsoluteValue);
    HRESULT AbsoluteToRelative(FiBasicControlProperty property, float AbsoluteValue, float *RelativeValue);
    HRESULT RelativeToAbsolute(FiBasicControlProperty property, float RelativeValue, float *AbsoluteValue);
    HRESULT AbsoluteToRelative(LONG property, float AbsoluteValue, float *RelativeValue);
    HRESULT RelativeToAbsolute(LONG property, float RelativeValue, float *AbsoluteValue);

    HRESULT AllocVideoCaptureFile(CHAR *szVideoCaptureFile, DWORDLONG dwlFileSize);
    HRESULT AllocVideoCaptureFile(WCHAR *szVideoCaptureFile, DWORDLONG dwlFileSize);
    HRESULT SetVideoCaptureFile(CHAR *szVideoCaptureFile);
    HRESULT SetVideoCaptureFile(WCHAR *szVideoCaptureFile);
    HRESULT SaveFrame(CHAR *a_szSavePath, GUID *a_encoderClsid);
    HRESULT SaveFrame(WCHAR *a_szSavePath, GUID *a_encoderClsid);

    BOOL IsPixelFormatSupported(FIREi_PIXEL_FORMAT format);
    BOOL IsResolutionSupported(FIREi_PIXEL_FORMAT format, FIREi_RES resolution);
    BOOL IsFrameRateSupported(FIREi_PIXEL_FORMAT format, FIREi_RES resolution, FIREi_FPS FrameRate);

    HRESULT GetCurrentPixelFormat(FIREi_PIXEL_FORMAT *format);
    HRESULT GetCurrentResolution(FIREi_RES *resolution);
    ULONG GetCurrentResolutionWidth();
    ULONG GetCurrentResolutionHeight();
    HRESULT GetCurrentFrameRate(FIREi_FPS *pFrameRate);
    LONG GetCurrentPacketSize(FIREi_PIXEL_FORMAT a_PixelFormat, FIREi_RES a_Res, LPRECT a_CustomRect);
    HRESULT SetStreamFormat(FIREi_PIXEL_FORMAT format, FIREi_RES resolution, FIREi_FPS FrameRate);
    HRESULT SetStreamFormat(FIREi_PIXEL_FORMAT format, FIREi_RES resolution, ULONG PacketSize);
	HRESULT SetStreamFormat(FIREi_PIXEL_FORMAT format, FIREi_RES resolution, LPRECT CustomRect, ULONG PacketSize);

    Fi_PACKET_INFO GetCustomPacketInfo(FIREi_PIXEL_FORMAT a_PixelFormat, FIREi_RES a_Res,  LPRECT a_CustomRect);
    POINT GetCustomUnitPos(FIREi_PIXEL_FORMAT a_PixelFormat, FIREi_RES a_Res);
    SIZE GetCustomUnitSize(FIREi_PIXEL_FORMAT a_PixelFormat, FIREi_RES a_Res);
    SIZE GetCustomMaxSize(FIREi_PIXEL_FORMAT a_PixelFormat, FIREi_RES a_Res);
    RECT GetCustomRect(FIREi_PIXEL_FORMAT a_PixelFormat, FIREi_RES a_Res);
    RECT SetCustomRect(FIREi_PIXEL_FORMAT a_PixelFormat, FIREi_RES a_Res, LPRECT a_NewRect);
    
    HRESULT LoadMemory(USHORT a_uMemoryChannel);
    HRESULT SaveMemory(USHORT a_uMemoryChannel);
    
    HRESULT SetWindow(HWND hPreviewWindow, LPRECT pPreviewWindowRect);
    HRESULT SetWindowPosition(LONG lLeft, LONG lTop, LONG lWidth, LONG lHeight);
    HRESULT SetFullScreenMode(BOOL bEnable);
    //HRESULT SetTriggerMode(BOOL bTriggerOn);

    HRESULT DisplayPropertyPages(BYTE byBlockMask = 0,
                                 UINT x = 0,
                                 UINT y = 0,
                                 HWND hParent = NULL,
                                 CHAR *szCaption = NULL);
    HRESULT DisplayPropertyPages(BYTE byBlockMask = 0,
                                UINT x = 0,
                                UINT y = 0,
                                HWND hParent = NULL,
                                WCHAR *szCaption = NULL);
    HRESULT DisplayPropertyPages(CHAR *szFilterName,
                                 BYTE byBlockMask = 0,
                                 UINT x = 0,
                                 UINT y = 0,
                                 HWND hParent = NULL,
                                 CHAR *szCaption = NULL);
    HRESULT DisplayPropertyPages(WCHAR *szFilterName,
                                 BYTE byBlockMask = 0,
                                 UINT x = 0,
                                 UINT y = 0,
                                 HWND hParent = NULL,
                                 WCHAR *szCaption = NULL);

    HRESULT DisplayStreamConfigPages(UINT x = 0, UINT y = 0, HWND hParent = NULL, CHAR *szCaption = NULL);
    HRESULT DisplayStreamConfigPages(UINT x = 0, UINT y = 0, HWND hParent = NULL, WCHAR *szCaption = NULL);

    BOOL HasColorBarSupport();
	HRESULT ShowColorBars(BOOL a_bShow);

    HRESULT GetEncodingProfileDesc(ULONG a_ProfileIndex, WCHAR* a_ProfileDescription, 
        ULONG *a_DescriptionLength);

    HRESULT GetEncodingProfileName(ULONG a_ProfileIndex, WCHAR* a_ProfileName, 
        ULONG *a_NameLength);

	void SetRawMode(FIREi_RAW_MODE a_RawMode);
    FIREi_RAW_MODE GetRawMode();
    void SetRawModeConversion(FIREi_RAW_MODE_CONVERSION a_RawModeConversion);
    FIREi_RAW_MODE_CONVERSION GetRawModeConversion();
    FIREi_LICENCE_TYPE GetLicenceType();
    HRESULT SetYMono16SignificantBits(int);
    HRESULT GetYMono16SignificantBits(int*);
    HRESULT Enable16BitSwap(BOOL);
    BOOL Is16BitSwapEnabled();
	HRESULT GetTriggerModeReg(TRIGGER_REG *);
	HRESULT SetTriggerModeReg(TRIGGER_REG &);
	BOOL IsTriggerModeSupported(FIREi_TRIGGER_MODE);
    BOOL IsTriggerSourceSupported(FIREi_TRIGGER_SOURCE);
    HRESULT SetSoftwareTrigger(BOOL);
    HRESULT ReadBlock(long, ULONG, void *);
    HRESULT WriteBlock(long, ULONG, void *);
    HRESULT ReadQuad(long, long*);
    HRESULT WriteQuad(long, long);
    long GetCommandRegBase();
    HRESULT GetAdapterInfo(FIREi_ADAPTER_INFO *);

    ULONG GetNumOfRegistryPresets();
    ULONG GetNumOfMemoryPresets();
    HRESULT LoadPresetsFromRegistry(USHORT a_uChannel);
    HRESULT SavePresetsToRegistry(USHORT a_uChannel);
    HRESULT LoadPresetsFromFile();
    HRESULT SavePresetsToFile();

// Implementation
public:
    ~CFiCamera();

protected:
	friend HRESULT OnFrameCallbackStub(BYTE *, BITMAPINFOHEADER *, CFiCamera *);
	HRESULT OnFrameCallback(BYTE *, BITMAPINFOHEADER *);

    friend HRESULT OnFrameCallbackStubEx(BYTE *, BITMAPINFOHEADER *, CFiCamera *);
	HRESULT OnFrameCallbackEx(BYTE *, BITMAPINFOHEADER *);

	HRESULT BuildGraph(const CHAR *);
    HRESULT BuildGraph(const WCHAR *);
    CLSID  ClassGuidFromName(const WCHAR *);

    void Set(FiExpoControlProperty, LPCTSTR, INT_PTR);
    void Set(FiColorControlProperty, LPCTSTR, INT_PTR);
    void Set(FiBasicControlProperty, LPCTSTR, INT_PTR);

    void Get(FiExpoControlProperty, LPCTSTR, INT_PTR);
    void Get(FiColorControlProperty, LPCTSTR, INT_PTR);
    void Get(FiBasicControlProperty, LPCTSTR, INT_PTR);

    friend LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
    virtual void OnDeviceRemoved();

    ULONG                  m_uCameraIndex;
    IBaseFilter            *m_pVideoCaptureDriver;
    IBaseFilter            *m_pAudioCaptureDriver;
    IBaseFilter            *m_pYuv2RgbFilter;
    IBaseFilter            *m_pInfoNetDumpFilter;
    FiNetDump              *m_pInfoNetDump;
    ICaptureGraphBuilder2  *m_pBuilder;
    PFi_VIDEO_FORMAT_INFO  m_pVideoFormatList;
    ULONG                  m_uStreamFormatsNumber;
    ULONG                  m_uStreamFormatIndex;
    WCHAR                  m_szVideoCaptureFile[_MAX_PATH];
    WORD                   m_wPreallocatedFileSize;
    BOOL                   m_hasColorBarSupport;
    FiCallback             m_onFrame;
    FiCallbackEx           m_onFrameEx;
    void                  *m_callbackExContext;
    DeviceRemovalCallback  m_onDeviceRemoved;
    void                  *m_deviceRemovedContext;
	TRIGGER_INQ_REG        m_triggerInq;
    LONG                   m_commandRegBase;
    HWND                   m_hDummyWnd;
    HDEVNOTIFY             m_hDevNotify;

#ifdef _DEBUG
    DWORD m_dwGraphNumber;
#endif

	void PreInitVideoCaptureDevice();
    HRESULT InitVideoCaptureDeviceA(ULONG uCameraIndex, LPCSTR *szMatchArray, LPCSTR *szNoMatchArray);
    HRESULT InitVideoCaptureDeviceW(ULONG uCameraIndex, LPCWSTR *szMatchArray, LPCWSTR *szNoMatchArray);
    HRESULT InitVideoCaptureDevice(CAMERA_GUID CameraGuid);
	HRESULT PostInitVideoCaptureDevice();
    LONG FormatIdxFromPixelFormatAndRes(FIREi_PIXEL_FORMAT a_PixelFromat, FIREi_RES a_Resolution);
    BOOL IsValidPath(LPCWSTR szVideoCaptureFile);
private:
    BOOL m_bInitialized;
};

CFICAMERA(HRESULT) GetEncodingProfileDesc(CFiCamera* pCamera, ULONG a_ProfileIndex, WCHAR* a_ProfileDescription, ULONG *a_DescriptionLength);
CFICAMERA(HRESULT) GetEncodingProfileName(CFiCamera* pCamera, ULONG a_ProfileIndex, WCHAR* a_ProfileName, ULONG *a_NameLength);

}

#endif
