/* windisp.c
 *
 * MPEG2AVI
 * --------
 * v0.16B3
 *  some minor cosmetic update
 * v0.15
 *  renamed CropRect to lpCropRect
 *  added keyboard control to for playback. <PAUSE>, filter-toggle
 *  also added facility for adjusting IVTC's state on-the-fly, to
 *  help user determine the correct "start frame offset"
 *
 * v0.14
 *  some modifications to support 1/2 resolution output and cropping.
 *  Both functions are done *before* display_dib() are called.
 *  
 *
 * v0.10 initial release
 *
 * Elementary routines for drawing to screen.
   This file was added to the original MSSG (MPEG Software Simulation
   Group) MPEG2V12 codec.  It enables the MPEG2V12 decoder to
   display frames through the Windows GDI interface.
   This file is *NOT* part of the original MSSG MPEG2V12 distribution!

   For the best results, the user should set his Windows desktop color depth
   to 24bpp (or alternatively 32bpp.)  Currently, this code does not create
   a new window for the DIB-surface's attachment.  The DIB is drawn directly
   on top of the desktop.
*/


#include<windows.h>
#include<vfw.h>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>

#include"config.h"
#include"global.h"


/*
 *
 * Draw to a Win32 display device.
 *
 * display_dib()      = draws RGB24 to Windows GDI (DIB)
 * 
 */

/* v0.14
 *    The source_frame now comes as packed YUV444 (24bpp)
 * Color-conversion is skipped until the last step, for a
 * very minor savings in computation.
 *
 * Draw the decoded RGB24 frames/fields to GDI (Win32 screen)
 * right now it only supports 720x480 images
 * requires mpeg2dec.exe to be called with "-f" option
 */


/* private definitions */
#define VIEW_GDI_PLAY 0
#define VIEW_GDI_PAUSE 1
#define KEY_GDI_PAUSE ' ' /* ASCII <spacebar> */

#define WNDCLASS_MYVID 0

//
// MainFrameProc
//
// Handles the message sent to the main window
//
long FAR PASCAL myVidWndProc( HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
    switch( message ){
        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;
		//case WM_PAINT:
		case WM_PAINT:
			break;



        default:
            return DefWindowProc( hwnd, message, wParam, lParam );
    }
    return (LRESULT) 0;

} // MainFrameProc


void
/* display_dib( LPBITMAPINFOHEADER lpbmih ) */
display_dib( unsigned char *source_frame, LPRECT lpCropRect, long FrameNum )
{
	/* The DrawDibBegin() function changes parameters of a DrawDib DC or 
	   initializes a new DrawDib DC.
	*/

	int key;
	static HDRAWDIB hdd = NULL; 
		/* our handle to the DisplayContext */
	static HDC hdc = NULL;
	static WNDCLASS myVidWnd; /* preview window's WindowClass */
	static unsigned char *ivtc_frame; /* output frame from IVTC algorithm */
	static int first_iteration = 1; 
	char myClassName[] = "myVidWnd";

	static BITMAPINFOHEADER bmih;
	static LPBITMAPINFOHEADER lpbmih;
	static int view_mode = VIEW_GDI_PLAY; /* PLAY or PAUSE */
	static HWND hWnd = NULL; /* handle to our preview window */

	/*

typedef struct tagBITMAPINFOHEADER{ 
    DWORD  biSize; 
    LONG   biWidth; 
    LONG   biHeight; 
    WORD   biPlanes; 
    WORD   biBitCount 
    DWORD  biCompression; 
    DWORD  biSizeImage; 
    LONG   biXPelsPerMeter; 
    LONG   biYPelsPerMeter; 
    DWORD  biClrUsed; 
    DWORD  biClrImportant; 
} BITMAPINFOHEADER; 
 */

	if ( first_iteration )
	{
		first_iteration = 0;	/* disable this flag */
		lpbmih = &bmih;
		view_mode = VIEW_GDI_PLAY;
		hdd = DrawDibOpen();
		if ( hdd == NULL )
		{
			fprintf( stderr, "\nCouldn't open DrawDib() library!");
			exit( ERROR );
		}


		/* Initialize the bitmap structure. */
		bmih.biSize = sizeof(BITMAPINFOHEADER); 

		/* v0.14 Stored_Picture_xxx determines output resolution */
		bmih.biWidth = lpCropRect->right - lpCropRect->left ;
		bmih.biHeight = lpCropRect->bottom - lpCropRect->top;

		bmih.biPlanes = 1;				/* must be 1 */
		bmih.biCompression = BI_RGB;      /* standard RGB bitmap  */
		bmih.biBitCount = 24;              /* 8 bits-per-pixel R,G,B format */
		bmih.biSizeImage = 0;			/* okay to be 0 for BI_RGB */
		bmih.biXPelsPerMeter = bmih.biYPelsPerMeter = 0;
		bmih.biClrUsed = bmih.biClrImportant = 0;

		/* The following code initialize WNDCLASS myVidWnd, our preview-window */
		/* all these variables must be loaded, otherwise RegisterClass() fails!*/
		myVidWnd.style = CS_NOCLOSE | CS_HREDRAW | CS_VREDRAW;
		myVidWnd.lpfnWndProc = myVidWndProc; /* myVidWnd's message handler */
		myVidWnd.cbClsExtra =0;
		myVidWnd.cbWndExtra =0;
		myVidWnd.hInstance = 0; /* must be 0? */
		myVidWnd.hIcon = LoadIcon( 0, IDI_APPLICATION ); /* icon */
		myVidWnd.hCursor =  LoadCursor( 0, IDC_ARROW ); /* cursor */
		myVidWnd.hbrBackground = GetStockObject( GRAY_BRUSH );
			/* generic background, doesn't matter we won't use it anyway */
		myVidWnd.lpszClassName = myClassName;
		myVidWnd.lpszMenuName = NULL; /* no default menu */

		if ( !RegisterClass( &myVidWnd ) )
			fprintf( stderr,"\ndisplay_dib() : RegisterClass() failed (%lX)!",
				GetLastError() );
		else
		{
			printf( "\ndisplay_dib() : RegisterClass() succeeded! " );
			hWnd = CreateWindow(
				myClassName,
				"MPEG2AVI Preview window",
				WS_CAPTION | WS_VISIBLE | WS_POPUPWINDOW,
				0, 0, // position of window on screen (X,Y )
				bmih.biWidth + 6, bmih.biHeight + 25 , // X/Y size
				0,
				0,
				0, //hInstance
				0
				);
			UpdateWindow( hWnd );
			//ShowWindow( hWnd, 0 );
		}

	/*	BOOL DrawDibBegin(
	HDRAWDIB hdd,             
	HDC hdc,                  
	int dxDest,               
	int dyDest,               
	LPBITMAPINFOHEADER lpbi,  
	int dxSrc,                
	int dySrc,                
	UINT wFlags               
	);	*/

		hdc = GetDC( hWnd ); /* GetDC( HWND hWnd ) */
		//printf( "  hDC = %lu\n", hdc) ;

		if ( !DrawDibBegin( hdd, hdc, lpbmih->biWidth, lpbmih->biHeight, 
			lpbmih, lpbmih->biWidth, lpbmih->biHeight, 0 ) )
			printf("\nDrawDibBegin() unsuccessful!");
		else
		{
		//	printf("\nDrawDibBegin() successful!");
			printf("  DIB dimensions : <%ld * %ld>\n", lpbmih->biWidth, 
				lpbmih->biHeight);
		}
		printf("\n<SPACEBAR> toggles PAUSE MODE.  '%c' toggles filter mode\n",
			KEY_FILTER_TOGGLE );

		printf("%c/%c changes IVTC frame-offset. '%c'=(IVTC ON/OFF)\n",
				KEY_IVTC_UP, KEY_IVTC_DOWN, KEY_IVTC_DISABLE );
		printf("'%c' toggles (ON/OFF) IVTC auto-disable mode\n",
			KEY_IVTC_TG_AUTODISABLE );

		printf("<ARROW KEYS> adjust aspect-ratio '-3X', '-3Y'\n");
		printf("'%c' resets aspect-ratio to 1:1\n", KEY_RESIZE_RESET );


	} /* endif - if ( first_iteration )

/*
	BOOL DrawDibDraw(
  HDRAWDIB hdd,             
  HDC hdc,                  
  int xDst,                 
  int yDst,                 
  int dxDst,                
  int dyDst,                
  LPBITMAPINFOHEADER lpbi,  
  LPVOID lpBits,            
  int xSrc,                 
  int ySrc,                 
  int dxSrc,                
  int dySrc,                
  UINT wFlags               
);
*/

	/* in v0.13 and earlier, display_dib() called the inverse_telecine()
	   function directly.  Now, this has been moved back to 
	   display_avi_gdi() [ store.c ]
	   display_dib() calls the color-space convertor
	 */


	ivtc_frame = source_frame; /* already IVTC'd by store.c */
	
	/* DRAW THE BITMAP TO SCREEN */
	if ( ivtc_frame != NULL )	/* have something to display? */
	{
		//printf("\rMPEG Frame %ld :                       ", FrameNum );
		/* convert color space & crop the output bitmap */
		// 0.16B1 moved earlier yuv2rgb24( ivtc_frame, lpCropRect );
		DrawDibDraw( hdd, hdc, 0,0, lpbmih->biWidth, lpbmih->biHeight,
			lpbmih, (LPVOID) ivtc_frame , 0, 0, lpbmih->biWidth, 
			lpbmih->biHeight, DDF_SAME_DRAW  );
	}
	else
		printf("\rFrame %lu : NOT DISPLAYED (IVTC)", FrameNum );
		
	/* Detect keypresses...recent keypress?  If not, don't _getch() */
	if ( _kbhit() || view_mode == VIEW_GDI_PAUSE )		
	{
		key = _getch();	/* yes, read keypress */
		if( toupper( key ) == toupper( KEY_GDI_PAUSE ) ) /* 32 = <spacebar> */
		{
			view_mode = ( view_mode == VIEW_GDI_PAUSE ) ?
				VIEW_GDI_PLAY : VIEW_GDI_PAUSE;;
		}
		if ( view_mode == VIEW_GDI_PAUSE )
			printf(" <PAUSED> ");

		switch ( toupper( key ) )
		{
			case KEY_IVTC_UP : g_cmd_ivtc = KEY_IVTC_UP ;
				break;
			case KEY_IVTC_DOWN : g_cmd_ivtc = KEY_IVTC_DOWN;
				break;
			case KEY_IVTC_DISABLE :	g_cmd_ivtc = KEY_IVTC_DISABLE;
				break;
			case KEY_IVTC_TG_AUTODISABLE :
				g_cmd_ivtc = KEY_IVTC_TG_AUTODISABLE ;
				break;
			case KEY_FILTER_TOGGLE :g_cmd_filter = KEY_FILTER_TOGGLE;
				break;
			case KEY_QUIT :	printf("\n<QUIT>");
				exit(ERROR);
				break;
			case KEY_RESIZE_RESET : g_cmd_resize = KEY_RESIZE_RESET;
				break;
			default:
				;
		}

		if ( key == KEYEX ) /* extended keypress info? */
		{
			key = _getch();
			switch ( key )
			{
			  case KEYEX_RESIZE_XINC : g_cmd_resize = KEYEX_RESIZE_XINC;
				break;
			  case KEYEX_RESIZE_XDEC : g_cmd_resize = KEYEX_RESIZE_XDEC;
				break;
			  case KEYEX_RESIZE_YINC : g_cmd_resize = KEYEX_RESIZE_YINC;
				break;
			  case KEYEX_RESIZE_YDEC : g_cmd_resize = KEYEX_RESIZE_YDEC;
				break;

			  default:
				  ;
			}
		} /* endif (key == KEYEX ) */
	}

	if ( g_cmd_buttonStop )
	{
		printf("\n<FRangeEnd>");
		exit(0);
	}

	/* clear text msgs from previously displayed frames */
	printf("                ");
}
