// PlayStatic.cpp : implementation file
//

#include "stdafx.h"
#include "MsSDKTest.h"
#include "PlayStatic.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#pragma comment(lib, "vfw32")

/////////////////////////////////////////////////////////////////////////////
// CPlayStatic

CPlayStatic::CPlayStatic()
{
	m_bDestory = FALSE;
	m_bStartPlay = FALSE;
	m_nBuffLen = 0;
	m_nBmpWidth = 0;
	m_nBmpHeight = 0;
	m_pBmpInfo = NULL;
	m_pDspBuffer = NULL;
	m_bMaskMapShow = FALSE;
	m_bLButtonDown = FALSE;
	m_ptCurrent = m_ptStart = 0;
	m_rcMask.SetRectEmpty();
}

CPlayStatic::~CPlayStatic()
{
	m_bDestory = TRUE;
	Sleep(100);
	StopDisplay();
}

BEGIN_MESSAGE_MAP(CPlayStatic, CStatic)
	//{{AFX_MSG_MAP(CPlayStatic)
	ON_WM_PAINT()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPlayStatic message handlers
#define DRAW_MOTION_BORDER_PIXEL	1	//±ß¿òÏñËØµã
int DrawMaskRubber(unsigned char* data, int PicWidth, int PicHeight, int SkipWidth, int SkipHeight, int nBoardPixel)
{
	int i = 0;
	int j = 0;
	unsigned char* currData = data;
	for (i = 0; i < SkipHeight; i++) {
		for (j = 0; j < SkipWidth; j ++) {
			*currData++=255;//B
			*currData++;//G
			*currData++;//R
		}
		currData += (PicWidth - SkipWidth)*3;
	}
	return 0;	
}

void CALLBACK PlayCallBack(LONG nLiveHandle, DWORD dwDataType, void *pBuffer, DWORD dwBuffSize, int nWidth, int nHeight, void *pUser)
{
	CPlayStatic *pPlayStatic = (CPlayStatic*)pUser;
	if(dwDataType == IPC_DATA_TYPE_VIDEO){
		if(pPlayStatic->IsWndDestory())
			return;
		if(!pPlayStatic->IsPlayStart()){
			pPlayStatic->StartDisplay(pPlayStatic->GetShowWidth(), pPlayStatic->GetShowHeight(), nWidth, nHeight);
		}
		if(pPlayStatic->IsMaskShow()){
			CRect rcClient;pPlayStatic->GetClientRect(&rcClient);
			CPoint ptStart(pPlayStatic->m_ptStart);
			if(pPlayStatic->m_ptCurrent.x > rcClient.Width()) 
				pPlayStatic->m_ptCurrent.x = rcClient.Width();
			else if(pPlayStatic->m_ptCurrent.x < 0)
				pPlayStatic->m_ptCurrent.x  = 0;				
			if(pPlayStatic->m_ptCurrent.y >= rcClient.Height()) 
				pPlayStatic->m_ptCurrent.y = rcClient.Height()-1;
			else if(pPlayStatic->m_ptCurrent.y < 0)
				pPlayStatic->m_ptCurrent.y = 0;

			if(abs(pPlayStatic->m_ptCurrent.x - pPlayStatic->m_ptStart.x) >= rcClient.Width()/2){
				if((pPlayStatic->m_ptCurrent.x >= pPlayStatic->m_ptStart.x))
					pPlayStatic->m_ptCurrent.x = pPlayStatic->m_ptStart.x + rcClient.Width()/2;
				else
					pPlayStatic->m_ptCurrent.x = pPlayStatic->m_ptStart.x - rcClient.Width()/2;		
			}

			if(abs(pPlayStatic->m_ptCurrent.y - pPlayStatic->m_ptStart.y) >= rcClient.Height()/2){
				if(pPlayStatic->m_ptCurrent.y >= pPlayStatic->m_ptStart.y)
					pPlayStatic->m_ptCurrent.y = pPlayStatic->m_ptStart.y + rcClient.Height()/2;
				else
					pPlayStatic->m_ptCurrent.y = pPlayStatic->m_ptStart.y - rcClient.Height()/2;
			}

			if(pPlayStatic->m_ptCurrent.y > pPlayStatic->m_ptStart.y){
				ptStart.y = pPlayStatic->m_ptCurrent.y;
			}
			if(pPlayStatic->m_ptCurrent.x < pPlayStatic->m_ptStart.x)
				ptStart.x = pPlayStatic->m_ptCurrent.x;

			int nMargin = 3*((rcClient.Height()-ptStart.y-1)*nHeight/rcClient.Height()*nWidth + ptStart.x*nWidth/rcClient.Width());
			unsigned char* currData = (unsigned char*)pBuffer + nMargin;
			int nWidthValue = abs(pPlayStatic->m_ptCurrent.x - pPlayStatic->m_ptStart.x)*nWidth/rcClient.Width();
			int nHeightValue = abs(pPlayStatic->m_ptCurrent.y - pPlayStatic->m_ptStart.y)*nHeight/rcClient.Height();

			pPlayStatic->m_rcMask.left = pPlayStatic->m_ptStart.x*nWidth/rcClient.Width();
			pPlayStatic->m_rcMask.top = pPlayStatic->m_ptStart.y*nHeight/rcClient.Height();
			pPlayStatic->m_rcMask.right = pPlayStatic->m_ptCurrent.x*nWidth/rcClient.Width();
			pPlayStatic->m_rcMask.bottom = pPlayStatic->m_ptCurrent.y*nHeight/rcClient.Height();		
			
			DrawMaskRubber(currData, nWidth, nHeight, nWidthValue, nHeightValue, DRAW_MOTION_BORDER_PIXEL);
		}
		pPlayStatic->PutVideoBuffer((unsigned char*)pBuffer, nWidth, nHeight);
	}else if(dwDataType == IPC_DATA_TYPE_AUDIO){
	
	}
}

int CPlayStatic::PutVideoBuffer(unsigned char* data, int width, int height)
{
	if (m_pDspBuffer && m_bStartPlay) {
		if(m_pDspBuffer){
			if(m_nBuffLen < width*height*3){
				free(m_pDspBuffer);
				m_pDspBuffer = (unsigned char*)malloc(width*height*3);
				m_nBuffLen = width*height*3;
			}
			memcpy(m_pDspBuffer, data, width*height*3);
		}else{ 
			OutputDebugString("=========OutofMemory=========\n");
		}
		if(::IsWindow(m_hWnd))
			Invalidate(TRUE);
	}
	return 0;
}

int CPlayStatic::DisplayVideoBuffer(CDC* hDC, unsigned char* data, int ShowPosX, int ShowPosY, int showWidth, int showHeight, int BmpPosX, int BmpPosY, int BmpWidth, int BmpHeight)
{
	if (!m_bStartPlay || !m_pDspBuffer) {
		return -1;
	}
	if(m_nBuffLen < BmpWidth*BmpHeight*3){
		return -1;
	}
	::DrawDibDraw(m_hDib,
		hDC->m_hDC,
		ShowPosX,		// dest : left pos
		ShowPosY,		// dest : top pos
		showWidth,					 // don't zoom x
		showHeight,					 // don't zoom y
		&m_pBmpInfo->bmiHeader,			 // bmp header info
		m_pDspBuffer,					 // bmp data
		BmpPosX,					 // src :left
		BmpPosY,					 // src :top
		BmpWidth,				 // src : width
		BmpHeight,				 // src : height
		DDF_BACKGROUNDPAL			 // use prev params....
		);	
	return 0;
}

int CPlayStatic::StartDisplay(int nDisplayWidth, int nDisplayHeight, int nBmpWidth, int nBmpHeight)
{
	if (m_bStartPlay)
		StopDisplay();
	if (nDisplayWidth*nDisplayHeight == 0 || nBmpWidth*nBmpHeight == 0)
		return -1;

	m_nBmpWidth = nBmpWidth;
	m_nBmpHeight = nBmpHeight;

	m_nShowWidth = nDisplayWidth;
	m_nShowHeight = nDisplayHeight;
	m_pDspBuffer = (unsigned char*)malloc(nBmpWidth*nBmpHeight*3);
	m_nBuffLen = nBmpWidth*nBmpHeight*3;

	memset(m_pDspBuffer, 100, nBmpWidth*nBmpHeight*3);
	m_pBmpInfo=new BITMAPINFO;	m_pBmpInfo->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
	m_pBmpInfo->bmiHeader.biWidth=m_nBmpWidth;
	m_pBmpInfo->bmiHeader.biHeight=m_nBmpHeight;
	m_pBmpInfo->bmiHeader.biPlanes=1;
	m_pBmpInfo->bmiHeader.biBitCount=24;
	m_pBmpInfo->bmiHeader.biCompression=0;
	m_pBmpInfo->bmiHeader.biSizeImage=0;
	m_pBmpInfo->bmiHeader.biXPelsPerMeter=0;
	m_pBmpInfo->bmiHeader.biYPelsPerMeter=0;
	m_pBmpInfo->bmiHeader.biClrUsed=0;
	m_pBmpInfo->bmiHeader.biClrImportant=0;
	if((m_hDib=DrawDibOpen()) != NULL) {
		DrawDibBegin(m_hDib,
			NULL,
			-1,				// don't stretch
			-1,				// don't stretch
			&m_pBmpInfo->bmiHeader,
			m_nBmpWidth,         // width of image
			m_nBmpHeight,        // height of image
			0	
			);
	}
	m_bStartPlay = TRUE;
	return 0;
}

void CPlayStatic::StopDisplay()
{
	if(!m_bStartPlay)
		return;
	m_bStartPlay = FALSE;
	DrawDibEnd(m_hDib);
	DrawDibClose(m_hDib);
	m_hDib = NULL;
	delete m_pBmpInfo;
	m_pBmpInfo = NULL;
	free(m_pDspBuffer);
	m_pDspBuffer = NULL;
}

void CPlayStatic::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	CDC* pDC = &dc;

	CRect rcBounds;
	GetClientRect(&rcBounds);

	if (m_nShowWidth != rcBounds.Width() || m_nShowHeight != rcBounds.Height()) {
			m_nShowHeight = rcBounds.Height();
			m_nShowWidth = rcBounds.Width();
	}
	if (!m_bStartPlay) {
		CBrush   brush(RGB(27, 28, 32)); 
		CBrush*  pOldOne = pDC->SelectObject(&brush); 
		
		pDC->PatBlt(0, 0, rcBounds.Width(), rcBounds.Height(), PATCOPY); 
		pDC->SelectObject(pOldOne);
	}else {
		CRect rcDisplay;
		GetClientRect(&rcDisplay);

		int PosX = rcDisplay.left;
		int PosY = rcDisplay.top;
		int nShowWidth = rcDisplay.Width();
		int nShowHeight = rcDisplay.Height();

		DisplayVideoBuffer(pDC, m_pDspBuffer, PosX, PosY, nShowWidth, nShowHeight, 0, 0, m_nBmpWidth, m_nBmpHeight);
	}
}

void CPlayStatic::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CRect rcClient;GetClientRect(&rcClient);
	if(m_bMaskMapShow && m_bLButtonDown){
	//	CPoint ptStart(m_ptStart);
		if(m_ptCurrent.x > rcClient.Width()) 
			m_ptCurrent.x = rcClient.Width();
		if(m_ptCurrent.y >= rcClient.Height()) 
			m_ptCurrent.y = rcClient.Height()-1;
		else if(m_ptCurrent.y <= 0)
			m_ptCurrent.y = 0;
		
		ReleaseCapture();
		m_bLButtonDown = false;
	}	
	CStatic::OnLButtonUp(nFlags, point);
}

void CPlayStatic::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	CRect rcClient;GetClientRect(&rcClient);
	if(m_bMaskMapShow){
		m_bLButtonDown = true;
		m_ptCurrent = m_ptStart = point;
		if(m_ptStart.x > rcClient.Width()) 
			m_ptStart.x = rcClient.Width();
		else if(m_ptStart.x < 0)
			m_ptStart.x  = 0;				
		if(m_ptStart.y >= rcClient.Height()) 
			m_ptStart.y = rcClient.Height()-1;
		else if(m_ptStart.y < 0)
			m_ptStart.y = 0;
		SetCapture();
	}

	CStatic::OnLButtonDown(nFlags, point);
}

void CPlayStatic::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	SetFocus();
	if (!m_bStartPlay || m_nShowWidth*m_nShowHeight==0) {
		CStatic::OnMouseMove(nFlags, point);		
		return;
	}
	if(m_bMaskMapShow && m_bLButtonDown){
		m_ptCurrent = point;
	}
	
	CStatic::OnMouseMove(nFlags, point);
}

BOOL CPlayStatic::GetMaskRect(LPRECT rcMask)
{
	m_bLButtonDown = false;
	m_ptCurrent = m_ptStart = 0;

	m_rcMask.NormalizeRect();
	m_rcMask.top+=32;
	m_rcMask.bottom+=32;
	m_rcMask.left+=16;
	m_rcMask.right+=16;
	memcpy(rcMask, &m_rcMask, sizeof(CRect));
	m_rcMask.SetRectEmpty();
	return TRUE;
}