/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */
#include "winpreview.h"

#include "stdio.h"

#ifndef _WIN32
#define snprintf _snprintf
#endif

UINT32 CWinPreview::zm_nWindowCount = 0;

///////////////////////////////////////////////////////////////////////
CWinPreview::CWinPreview()
: m_hWnd(NULL)
, m_nPreviewIndex(0)
{	
}   	

///////////////////////////////////////////////////////////////////////
CWinPreview::~CWinPreview(void)
{
    FreeWindow();
}

///////////////////////////////////////////////////////////////////////
LRESULT CALLBACK 
CWinPreview::WindowProc( HWND hwnd,      // handle to window
			UINT uMsg,      // message identifier
			WPARAM wParam,  // first message parameter
			LPARAM lParam   // second message parameter
			)
{
    CWinPreview *pThis = (CWinPreview *)::GetWindowLong(hwnd, GWL_USERDATA);
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}


///////////////////////////////////////////////////////////////////////
HX_RESULT CWinPreview::CreatePreviewWindow(UINT32 nPreviewIndex, short width, short height)
{
    HX_RESULT res = HXR_OK;
    
    if(m_nPreviewIndex == 0)
    {
	m_nPreviewIndex = nPreviewIndex;
    }
    
    memset(&m_bi, 0, sizeof(m_bi));
    
    m_bi.biSize = sizeof(m_bi);     
    m_bi.biWidth = width;
    m_bi.biHeight = height;
    
    m_bi.biPlanes = 1;
    m_bi.biBitCount = 24;//assume RGB32
    
    m_bi.biCompression = BI_RGB;//RGB
    m_bi.biSizeImage = m_bi.biWidth*m_bi.biHeight*m_bi.biBitCount/8;
    
    RECT rect;
    rect.top = 0; 
    rect.left = 0; 
    rect.bottom = m_bi.biHeight; 
    rect.right = m_bi.biWidth; 
    
    DWORD dwStyle = WS_CAPTION | WS_VISIBLE | WS_POPUPWINDOW;
    AdjustWindowRect(&rect, dwStyle, FALSE /* menu-present flag */);
    
    int nWndWidth = rect.right - rect.left;
    int nWndHeight = rect.bottom - rect.top;
    
    HINSTANCE hInstance = GetModuleHandle (NULL);     
    HWND hWndParent = GetFocus(); 
    
    WNDCLASSEX wndClassEx;
    // We need to set up a window class and a window for messages.
    wndClassEx.cbSize = sizeof(WNDCLASSEX);
    wndClassEx.style = 0;
    wndClassEx.lpfnWndProc = CWinPreview::WindowProc; 
    wndClassEx.cbClsExtra = 0;
    wndClassEx.cbWndExtra = 0;
    wndClassEx.hInstance = NULL; 
    wndClassEx.hIcon = NULL;
    wndClassEx.hCursor = NULL;
    wndClassEx.hbrBackground = NULL; 
    wndClassEx.lpszMenuName = NULL;
    wndClassEx.lpszClassName = "CRealPreviewWindowClass";
    wndClassEx.hIconSm = NULL; 
    ATOM Class = RegisterClassEx(&wndClassEx);
    
    char szWindowName[_MAX_PATH];
    _snprintf(szWindowName, _MAX_PATH, "PreviewWindow%d", m_nPreviewIndex);
    
    UINT32 nXPOS = (zm_nWindowCount % 3) * 200;
    UINT32 nYPOS = (zm_nWindowCount / 3) * 200;
    
    m_hWnd =  CreateWindow(
	"CRealPreviewWindowClass",    // pointer to registered class name
	szWindowName,			// pointer to window name
	dwStyle,			// window style
	nXPOS,			// horizontal position of window
	nYPOS,			// vertical position of window
	nWndWidth,			// window width
	nWndHeight,			// window height
	hWndParent,			// handle to parent or owner window
	NULL,				// handle to menu or child-window identifier
	hInstance,			// handle to application instance
	NULL				// pointer to window-creation data
	);
    
    if (::IsWindow(m_hWnd))
    {
	// store this on the window
	::SetWindowLong(m_hWnd, GWL_USERDATA, (LONG)this);
	
	m_hDrawDib = DrawDibOpen();
	m_hDC = ::GetDC(m_hWnd);
	::GetClientRect(m_hWnd, &m_rectClient);
	
	BOOL bRes = DrawDibBegin(m_hDrawDib, m_hDC, m_rectClient.right, m_rectClient.bottom,
	    &m_bi, m_bi.biWidth, m_bi.biHeight, 0);
	
	UINT32 nNumPalettes = DrawDibRealize(m_hDrawDib, m_hDC, FALSE);//not forcing background
    }
    
    zm_nWindowCount++;
    
    return res;
}

///////////////////////////////////////////////////////////////////////
void CWinPreview::FreeWindow(void)
{
    if (::IsWindow(m_hWnd))
    {
	int res = ReleaseDC(m_hWnd, m_hDC);
	BOOL bRes;
	bRes = DrawDibEnd(m_hDrawDib);
	bRes = DrawDibClose(m_hDrawDib);
	
	DestroyWindow(m_hWnd);   
	m_hWnd = NULL;
    }
    
}

///////////////////////////////////////////////////////////////////////
void CWinPreview::DrawVideo(const UCHAR* pBuffer, UINT32 size)
{
    if (::IsWindow(m_hWnd))
    {
	BOOL bResult = ::DrawDibDraw(m_hDrawDib, m_hDC, 
	    m_rectClient.left, m_rectClient.top, 
	    m_rectClient.right - m_rectClient.left, m_rectClient.bottom - m_rectClient.top, 
	    &m_bi, (void*) pBuffer, 
	    0, 0, m_bi.biWidth, m_bi.biHeight, 0);
	MSG msg;
	while (PeekMessage(&msg, NULL,  0, 0, PM_REMOVE)) 
	{ 
	    TranslateMessage(&msg);         
	    DispatchMessage(&msg);     
	}  
    }
}
