/*
 *  vo_p96_pip.c
 *  VO module for MPlayer AmigaOS4
 *  using p96 PIP
 *  Writen by Jörg strohmayer
*/

#undef __USE_INLINE__

#define USE_VMEM64	1

#define ALL_REACTION_CLASSES
#define ALL_REACTION_MACROS

#include <reaction/reaction.h>
#include <reaction/reaction_macros.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "config.h"

#include <proto/cybergraphics.h>
#include <proto/graphics.h>


#include "../sub/osd.h"
#include "../sub/sub.h"

#include "mp_msg.h"
#include "video_out.h"
#include "video_out_internal.h"

#include "../mplayer.h"
#include "../libmpcodecs/vf_scale.h"
#include "../input/input.h"

//#include <inttypes.h>     // Fix <postproc/rgb2rgb.h> bug
//#include <postproc/rgb2rgb.h>
#include <version.h>

/* ARexx */
#include <proto/intuition.h>

//#include "MPlayer-arexx.h"
/* ARexx */

// OS specific
#include <libraries/keymap.h>
#include <osdep/keycodes.h>

#include <proto/intuition.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/asl.h>
#include <proto/wb.h>
#include <proto/icon.h>
#include <proto/requester.h>
#include <proto/layout.h>
#include <proto/utility.h>
#include <gadgets/layout.h>
#define __NOLIBBASE__
#define __NOGLOBALIFACE__
#include <proto/application.h>
#include <proto/gadtools.h>
#include <proto/layers.h>
#include <proto/Picasso96API.h>
#include <exec/types.h>
#include <intuition/icclass.h>
#include <graphics/text.h>
#include <graphics/rpattr.h>
#include <graphics/layers.h>
#include <dos/dostags.h>
#include <dos/dos.h>
#include <classes/requester.h>
#include <intuition/gadgetclass.h>

#ifdef __amigaos4__
#include <proto/Picasso96API.h>
#include <libraries/Picasso96.h>
#endif

#include "aspect.h"
#include "input/input.h"
#ifdef __amigaos4__
#include "mp_msg.h"
#endif
#include "../libmpdemux/demuxer.h"

#include "vo_p96pip.h"

#include <assert.h>
#undef CONFIG_GUI

#ifdef CONFIG_GUI
#include "vo_p96pip_gui.c"
#endif


#include "gui/interface.h"
#include "gui/morphos/gui.h"


UWORD ZoomDatapip [] =
{
	(UWORD) ~0,
	(UWORD) ~0,
	0,
	0
};


#define MIN_WIDTH 290
#define MIN_HEIGHT 217


#define MUIA_Application_PubScreenName	0x80427690

extern int player_idle_mode;

extern struct Window *PlayerWindow;

/***************************/
static BOOL p96pip_GiveArg(const char *arg)
{
    // Default settings
    p96pip_BorderMode  = ALWAYSBORDER;

    if ( (arg) )
    {
        if (!(memcmp(arg, "NOBORDER", strlen("NOBORDER") ) ) ) p96pip_BorderMode = NOBORDER;
        else if (!(memcmp(arg, "TINYBORDER", strlen("TINYBORDER") ) ) ) p96pip_BorderMode = TINYBORDER;
    }

    return TRUE;
}

/***************************/
static BOOL p96pip_OpenOSLibs(void)
{
    if (!(P96Base = IExec->OpenLibrary(P96NAME, 2)))
    {
        p96pip_CloseOSLibs();
        return FALSE;
    }

    if (!(IP96 = (struct P96IFace*) IExec->GetInterface(P96Base, "main", 1, NULL)))
    {
        p96pip_CloseOSLibs();
        return FALSE;
    }

	
    if ( ! (GfxBase = IExec->OpenLibrary("graphics.library", 0L) ) )
    {
        p96pip_CloseOSLibs();
        return FALSE;
    }

    IGraphics = (struct GraphicsIFace*) IExec->GetInterface( (struct Library*)GfxBase, "main", 1, NULL );
    if (!IGraphics)
    {
        p96pip_CloseOSLibs();
        return FALSE;
    }	
	
    if ( ! (LayersBase = IExec->OpenLibrary("layers.library", 0L) ) )
    {
        p96pip_CloseOSLibs();
        return FALSE;
    }

    ILayers = (struct LayersIFace*) IExec->GetInterface( (struct Library*)LayersBase, "main", 1, NULL );
    if (!ILayers)
    {
        p96pip_CloseOSLibs();
        return FALSE;
    }

    if ( ! (GadToolsBase = (struct Library *) IExec->OpenLibrary("gadtools.library",0UL)) )
    {
        p96pip_CloseOSLibs();
        return FALSE;
    }

    IGadTools = (struct GadToolsIFace *) IExec->GetInterface(GadToolsBase,"main",1,0UL);
    if (!IGadTools)
    {
        p96pip_CloseOSLibs();
        return FALSE;
    }

	if ( ! (ApplicationBase = (struct Library *) IExec->OpenLibrary("application.library", 51L)) )
	{
        p96pip_CloseOSLibs();
		return FALSE;
	}
	else
	{
	    if (ApplicationBase->lib_Version > 53 || (ApplicationBase->lib_Version >= 53 && ApplicationBase->lib_Revision >= 4))
    	    hasNotificationSystem = TRUE;
	    else
    	    hasNotificationSystem = FALSE;
	}
	IApplication = (struct ApplicationIFace *) IExec->GetInterface(ApplicationBase,"application",1,NULL);
	if (!IApplication)
	{
        p96pip_CloseOSLibs();
		return FALSE;
	}

    return TRUE;
}

/**********************/
static void p96pip_CloseOSLibs(void)
{
    if (IP96)
    {
        IExec->DropInterface((struct Interface *)IP96);
        IP96 = NULL;
    }

    if (P96Base)
    {
        IExec->CloseLibrary (P96Base);
        P96Base = NULL;
    }

    if (IGraphics)
    {
        IExec->DropInterface((struct Interface*) IGraphics);
    }

    if (GfxBase)
    {
        IExec->CloseLibrary(GfxBase);
        GfxBase = NULL;
    }
				
    if (ILayers)
    {
        IExec->DropInterface((struct Interface*) ILayers);
    }

    if (LayersBase)
    {
        IExec->CloseLibrary(LayersBase);
        LayersBase = NULL;
    }

    if (IGadTools)
    {
        IExec->DropInterface((struct Interface*) IGadTools);
    }

    if (GadToolsBase)
    {
        IExec->CloseLibrary(GadToolsBase);
        GadToolsBase = NULL;
    }

	if (ApplicationBase)
	{
		IExec->CloseLibrary(ApplicationBase);
		ApplicationBase = NULL;
	}
	if (IApplication)
	{
		IExec->DropInterface((struct Interface*)IApplication);
		IApplication = NULL;
    }

}
static char *p96pip_GetWindowTitle(void)
{
    if (filename)
    {
    	current_filename = strdup(filename);
        window_title = (char *) IExec->AllocVec(strlen(filename) + 11,MEMF_SHARED|MEMF_CLEAR);
        //strcpy(window_title,"MPlayer - ");
        strcat(window_title,filename);
    }
    else
    {
        window_title = (char *) IExec->AllocVec(strlen("MPlayer for AmigaOS4")+1, MEMF_SHARED|MEMF_CLEAR);
        strcpy(window_title,"MPlayer for AmigaOS4");
    }
    return(window_title);
}

/******************************** DRAW ALPHA ******************************************/

/**
 * draw_alpha is used for osd and subtitle display.
 *
 **/
static void draw_alpha_yv12(int x0, int y0, int w, int h, unsigned char* src, unsigned char *srca, int stride)
{
	register int x;
	register UWORD *dstbase;
	register UWORD *dst;
	struct BitMap *bm;
    struct RenderInfo ri;
    int lock_h;
    int numbuffers=0;

	if (!w || !h)
		return;

    IP96->p96PIP_GetTags(My_Window, P96PIP_SourceBitMap   , (ULONG)&bm   ,
    								P96PIP_NumberOfBuffers, &numbuffers  ,
    								TAG_END, TAG_DONE );

    if (! (lock_h = IP96->p96LockBitMap(bm, (uint8 *)&ri, sizeof(struct RenderInfo))))
    {
        // Unable to lock the BitMap -> do nothing
        return;
    }

    dstbase = (UWORD *)(ri.Memory + ( ( (y0 * image_width) + x0) * 2));

    do
    {
        x = 0;
        do
        {
            dst = dstbase;
            if (srca[x])
            {
                __asm__ __volatile__(
                    "li %%r4,0x0080;"
                    "rlwimi %%r4,%1,8,16,23;"
                    "sth %%r4,0(%0);"
                    :
                    : "b" ( dst + x), "r" (src[x])
                    : "r4"
                );
            }
        } while (++x < w);

        src     +=   stride;
        srca    +=   stride;
        dstbase +=   image_width;

    } while (--h);

	if (numbuffers>1)
	{
		uint32 WorkBuf, DispBuf, NextWorkBuf;

		IP96->p96PIP_GetTags(My_Window,	P96PIP_WorkBuffer,      &WorkBuf,
								 		P96PIP_DisplayedBuffer, &DispBuf,
								 		TAG_END, TAG_DONE );

		NextWorkBuf = (WorkBuf+1) % numbuffers;

		if (NextWorkBuf == DispBuf) IGraphics->WaitTOF();

		IP96->p96PIP_SetTags(My_Window,	P96PIP_VisibleBuffer, WorkBuf, //P96PIP_WorkBuffer, WorkBuf,
								 		P96PIP_WorkBuffer,    NextWorkBuf, //P96PIP_DisplayedBuffer, NextWorkBuf,
								 		TAG_END, TAG_DONE);
	}

    IP96->p96UnlockBitMap(bm, lock_h);
}

/******************************** PREINIT ******************************************/
static int preinit(const char *arg)
{
    mp_msg(MSGT_VO, MSGL_INFO, "VO: [p96_pip]\n");
    if( !p96pip_OpenOSLibs() )
    {
        return -1;
    }
	
	// do actual check on overlay and return -1 to make proper fallback to cgx_wpa:
	struct Window *pipWindow;  
	LONG error = 0;  

	pipWindow = IP96->p96PIP_OpenTags (P96PIP_SourceFormat, RGBFB_YUV422CGX,   /* Pixel format of overlay */  
								P96PIP_SourceWidth,  256,           /* Width of overlay surface */  
								P96PIP_SourceHeight, 256,           /* Height of overlay surface */  
								P96PIP_ErrorCode,    (LONG) &error,  

								WA_Title,         "Overlay Window",  
								WA_Activate,      FALSE,  
								WA_Hidden,        TRUE,             							
			
								WA_Width,         400,  
								WA_Height,        400,  
                                
								WA_PubScreenName, "Workbench", 
                                
								TAG_DONE);  

	if (pipWindow)  
	{      
		// we have overlay, good !
		IP96->p96PIP_Close(pipWindow);
	}  
	else  
	{ 
		// no overlay possible
		return -1;    
	} 	
	
	
    if (!p96pip_GiveArg(arg))
    {
        p96pip_CloseOSLibs();
        return -1;
    }

#ifdef CONFIG_GUI
	mygui = malloc(sizeof(*mygui));
	initguimembers();
#endif
    return 0;
}

static ULONG GoFullScreen(void)
{
	uint32_t left = 0, top = 0;
    ULONG ModeID = INVALID_ID;

	int i = 0;
	if (WinLayout)
		IIntuition->DisposeObject(WinLayout);

	for (i=0;i<6;i++)
		if (NULL != image[i]) IIntuition->DisposeObject((Object *) image[i]);

    if (My_Window)
    {
		IP96->p96PIP_Close(My_Window);
		if (IconifyGadget)
		{
			IIntuition->DisposeObject(IconifyGadget);
			IconifyGadget = NULL;
		}
		if (IconifyImage)
		{
			IIntuition->DisposeObject(IconifyImage);
			IconifyImage = NULL;
		}
		My_Window = NULL;
	}

	My_Screen = IIntuition->OpenScreenTags ( 		NULL,								
								SA_LikeWorkbench,	TRUE,
								SA_Type,			PUBLICSCREEN,
								SA_PubName, 		"MPlayer Screen",
								SA_Title, 			"MPlayer Screen",
					            SA_ShowTitle, 		FALSE,
								SA_Quiet, 			TRUE,
								SA_Compositing,		FALSE, // no white strips anymore, yeah !
								TAG_DONE);

	if ( ! My_Screen )
	{
		return INVALID_ID;
	}

	#ifdef __amigaos4__
	//new from cgx_overlay
	ICyberGfx->FillPixelArray( &(My_Screen->RastPort), 0,0, My_Screen->Width, My_Screen->Height, 0x00000000); 
	#endif
	
	/* Entering Game Mode so Notification System doesn't send messages to us.. */
	//IApplication->SetApplicationAttrs(AppID, APPATTR_NeedsGameMode, TRUE, TAG_DONE);

	/* Fill the screen with black color */
	IP96->p96RectFill(&(My_Screen->RastPort), 0,0, My_Screen->Width, My_Screen->Height, 0x00000000);

	/* calculate new video size/aspect */
	aspect_save_screenres(My_Screen->Width,My_Screen->Height);

   	aspect(&out_width,&out_height,A_ZOOM);

    left=(My_Screen->Width-out_width)/2;
    top=(My_Screen->Height-out_height)/2;

    My_Window = IP96->p96PIP_OpenTags(
                      	P96PIP_SourceFormat, RGBFB_YUV422CGX,
                      	P96PIP_SourceWidth,  image_width,
                      	P96PIP_SourceHeight, image_height,
						P96PIP_NumberOfBuffers, NUMBUFFERS,

                      	//WA_CustomScreen,    (ULONG) My_Screen,
						WA_PubScreen,    (ULONG) My_Screen,
						
                      	WA_ScreenTitle,     (ULONG) "MPlayer 1.0 (11.11.2010) (SVN: r32620)", //"MPlayer ",
                      	WA_Left,            left,
                      	WA_Top,             top,
                      	WA_SmartRefresh,    TRUE,
                      	WA_CloseGadget,     FALSE,
                      	WA_DepthGadget,     FALSE,
                      	WA_DragBar,         FALSE,
                      	WA_Borderless,      TRUE,
                      	WA_SizeGadget,      FALSE,
                      	WA_Activate,        TRUE,
                      	WA_StayTop,		  	TRUE,
						WA_DropShadows,		FALSE,
                      	WA_Flags,			WFLG_RMBTRAP,
                      	//WA_IDCMP,           IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_VANILLAKEY | IDCMP_MOUSEMOVE,						
						WA_IDCMP,	IDCMP_IDCMPUPDATE | IDCMP_GADGETDOWN |IDCMP_MOUSEBUTTONS | IDCMP_ACTIVEWINDOW  | IDCMP_MOUSEMOVE |  IDCMP_REFRESHWINDOW | IDCMP_RAWKEY, 
					
                      	TAG_DONE);

	hasGUI = FALSE;

	if ( !My_Window )
	{
		return INVALID_ID;
	}
	IP96->p96RectFill(My_Window->RPort, 0,0, My_Screen->Width, My_Screen->Height, 0x00000000);

	mouse_hidden = TRUE;
	IIntuition->SetPointer(My_Window, EmptyPointer, 1, 16, 0, 0);

    if ( (ModeID = IGraphics->GetVPModeID(&My_Window->WScreen->ViewPort) ) == INVALID_ID)
   	{
        return INVALID_ID;
   	}

    IIntuition->SetWindowAttrs(My_Window,
                               WA_Left,left,
                               WA_Top,top,
                               WA_Width,out_width,
                               WA_Height,out_height,
                               TAG_DONE);

	vo_screenwidth = My_Screen->Width;
	vo_screenheight = My_Screen->Height;
	vo_dwidth = window_width;
	vo_dheight = window_height;
	vo_fs = 1;

    IIntuition->ScreenToFront(My_Screen);

	Cgx_ControlBlanker(My_Screen, FALSE);
	
    return ModeID;
}
/**********************/
static ULONG Open_PIPWindow(void)
{

	// some for os4
	extern APTR app;
	struct Screen *scrn = NULL;
	struct Screen *ready_screen = NULL;
	char *pubScreenNamea;

	
    // Window
    ULONG ModeID = INVALID_ID;
    APTR vi;
	DIcon = NULL;

    My_Window = NULL;

	if(use_gui) {		
		pubScreenNamea=xget(app, MUIA_Application_PubScreenName);
	}
	
	
    if ( ( My_Screen = IIntuition->LockPubScreen ( NULL ) ) )
    {
        struct DrawInfo *dri;

        vi = IGadTools->GetVisualInfoA(My_Screen,NULL);
        if (vi)
        {
            if (isStarted == FALSE)
            {
                isStarted = TRUE;
            }
            else
            {
            	int i = 0;
            	
                if (is_ontop==1)
                    nm[13].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
                else
                    nm[13].nm_Flags = MENUTOGGLE|CHECKIT;

                if (loop_on==1)
                    nm[11].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
                else
                    nm[11].nm_Flags = MENUTOGGLE|CHECKIT;

				for (i=24;i<35;i++)
                    nm[i].nm_Flags = MENUTOGGLE|CHECKIT;

				switch(AspectRatio)
				{
					case AR_ORIGINAL:
	                    nm[24].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_16_10:
	                    nm[25].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_16_9:
	                    nm[26].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_185_1:
	                    nm[27].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_221_1:
	                    nm[28].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_235_1:
	                    nm[29].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_239_1:
	                    nm[30].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_5_3:
	                    nm[31].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_4_3:
	                    nm[32].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_5_4:
	                    nm[33].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
					case AR_1_1:
	                    nm[34].nm_Flags = MENUTOGGLE|CHECKIT|CHECKED;
					break;
				}
            }

            menu = IGadTools->CreateMenusA(nm,NULL);
            if (menu)
            {
                if (IGadTools->LayoutMenus(menu,vi,GTMN_NewLookMenus,TRUE,TAG_END))
                {
                    ModeID = IGraphics->GetVPModeID(&My_Screen->ViewPort);

                    if ( (dri = IIntuition->GetScreenDrawInfo(My_Screen) ) )
                    {
                        ULONG bw, bh;
					    static TEXT ProgramName[512];
						BOOL HasName = FALSE;
						
						IconifyImage = IIntuition->NewObject(NULL, "sysiclass", SYSIA_DrawInfo, (ULONG) dri, SYSIA_Which, ICONIFYIMAGE, TAG_DONE);

						IconifyGadget = IIntuition->NewObject(NULL, "buttongclass",
							GA_ID, 			GID_Iconify,
							GA_RelVerify, 	TRUE,
							GA_Image, 		IconifyImage,
							GA_TopBorder, 	TRUE,
							GA_RelRight, 	0,
							GA_Titlebar, 	TRUE,
							TAG_END);

						if (IDOS->Cli())
						{
							TEXT tempFileName[1024];

							if (IDOS->GetProgramName(tempFileName, sizeof(tempFileName)))
							{
								strcpy(ProgramName, "PROGDIR:");
								strlcat(ProgramName, IDOS->FilePart(tempFileName), sizeof(ProgramName));
								HasName = TRUE;
							}
						}
						else
						{
							strlcpy(ProgramName, IExec->FindTask(NULL)->tc_Node.ln_Name, sizeof(ProgramName));
							HasName = TRUE;
						}

						DIcon = HasName ? IIcon->GetDiskObject(ProgramName) : NULL;

                        switch(p96pip_BorderMode)
                        {
                            case NOBORDER:
								bw = 0;
								bh = 0;
							break;

                            default:
								bw = My_Screen->WBorLeft + My_Screen->WBorRight;
								bh = My_Screen->WBorTop + My_Screen->Font->ta_YSize + 1 + My_Screen->WBorBottom;
							break;
                        }

                        if (FirstTime)
                        {
							/* Set dimension and position */

                            win_left = (My_Screen->Width - (window_width + bw)) / 2;
                            win_top  = (My_Screen->Height - (window_height + bh)) / 2;
                            old_d_posx = win_left;
                            old_d_posy = win_top;
                            FirstTime = FALSE;
                        }

						ZoomDatapip[0] = 0;
						ZoomDatapip[1] = 0;
						ZoomDatapip[2] = My_Screen->Width;
						ZoomDatapip[3] = My_Screen->Height;
						
                        switch(p96pip_BorderMode)
                        {
                            case NOBORDER:
                                My_Window = IP96->p96PIP_OpenTags(
                                    P96PIP_SourceFormat, 	RGBFB_YUV422CGX,
                                    P96PIP_SourceWidth,  	image_width,
                                    P96PIP_SourceHeight, 	image_height,
                                    P96PIP_AllowCropping, 	TRUE,
									P96PIP_NumberOfBuffers, NUMBUFFERS,

                                    //WA_CustomScreen,    (ULONG) My_Screen,
									WA_PubScreen,    (ULONG) My_Screen,
									
                                    //WA_ScreenTitle,     (ULONG) "MPlayer ",
									WA_ScreenTitle,     (ULONG) "MPlayer 1.0 (11.11.2010) (SVN: r32620)", //"MPlayer ",
                                    WA_Left,            old_d_posx,
                                    WA_Top,             old_d_posy,
									WA_InnerWidth,		window_width,
									WA_InnerHeight,		window_height,
                                    WA_NewLookMenus,    TRUE,
                                    WA_SmartRefresh,    TRUE,
                                    WA_CloseGadget,     FALSE,
                                    WA_DepthGadget,     FALSE,
                                    WA_DragBar,         FALSE,
                                    WA_Borderless,      TRUE,
                                    WA_SizeGadget,      FALSE,
									WA_Activate,		TRUE,
									WA_Hidden,			TRUE,
                                    WA_StayTop,         (is_ontop==1) ? TRUE : FALSE,
                                    WA_IDCMP,           IDCMP_IDCMPUPDATE | IDCMP_GADGETDOWN |IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_VANILLAKEY | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_MOUSEMOVE | IDCMP_CHANGEWINDOW,									
                                    WA_Gadgets,         &MyDragGadget,
                                    WA_MaxWidth, 		My_Screen->Width,
                                    WA_MaxHeight, 		My_Screen->Height,
                                TAG_DONE);
                                hasGUI = FALSE;
                            break;

                            case TINYBORDER:
                                My_Window = IP96->p96PIP_OpenTags(
                                    P96PIP_SourceFormat, 	RGBFB_YUV422CGX,
                                    P96PIP_SourceWidth,  	image_width,
                                    P96PIP_SourceHeight, 	image_height,
                                    P96PIP_AllowCropping, 	TRUE,
									P96PIP_NumberOfBuffers, NUMBUFFERS,

                                    //WA_CustomScreen,    (ULONG) My_Screen,
									WA_PubScreen,    (ULONG) My_Screen,
									
                                    //WA_ScreenTitle,     (ULONG) "MPlayer ",
									WA_ScreenTitle,     (ULONG) "MPlayer 1.0 (11.11.2010) (SVN: r32620)", //"MPlayer ",
                                    WA_Left,            old_d_posx,
                                    WA_Top,             old_d_posy,
									WA_InnerWidth,		window_width,
									WA_InnerHeight,		window_height,
                                    WA_NewLookMenus,    TRUE,
                                    WA_SmartRefresh,    TRUE,
                                    WA_CloseGadget,     FALSE,
                                    WA_DepthGadget,     FALSE,
                                    WA_DragBar,         FALSE,
                                    WA_Borderless,      FALSE,
                                    WA_SizeGadget,      FALSE,
									WA_Activate,		TRUE,
									WA_Hidden,			TRUE,
                                    WA_StayTop,         (is_ontop==1) ? TRUE : FALSE,
                                    WA_IDCMP,           IDCMP_IDCMPUPDATE | IDCMP_GADGETDOWN |IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_VANILLAKEY | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_MOUSEMOVE | IDCMP_CHANGEWINDOW,
                                    WA_Gadgets,         &MyDragGadget,
                                    WA_MaxWidth, 		My_Screen->Width,
                                    WA_MaxHeight, 		My_Screen->Height,
                                TAG_DONE);
                                hasGUI = FALSE;
                            break;

                            default:
								if (use_gui) {										
									scrn = IIntuition->LockPubScreen (pubScreenNamea);
									ready_screen = scrn;
								} else {
									ready_screen = My_Screen;
								}	
								
								My_Window = IP96->p96PIP_OpenTags(
									P96PIP_SourceFormat, 	RGBFB_YUV422CGX,
									P96PIP_SourceWidth,		image_width,
									P96PIP_SourceHeight,	image_height,
									P96PIP_AllowCropping,	TRUE,
									P96PIP_NumberOfBuffers, NUMBUFFERS,
									P96PIP_Relativity, PIPRel_Width | PIPRel_Height,
//									P96PIP_Left, 1,
//									P96PIP_Top, 1,
#ifdef CONFIG_GUI
									P96PIP_Width, (ULONG) -1,
									P96PIP_Height, (ULONG)-34,
#endif
									P96PIP_ColorKeyPen, 	0,

									//WA_CustomScreen,	(ULONG) ready_screen,
									WA_PubScreen,	(ULONG) ready_screen,
									
									//WA_ScreenTitle,		(ULONG) "MPlayer",
									WA_ScreenTitle,     (ULONG) "MPlayer 1.0 (11.11.2010) (SVN: r32620)", //"MPlayer ",
									WA_Title,			p96pip_GetWindowTitle(),
									WA_Left,			old_d_posx,
									WA_Top,				old_d_posy,
									WA_InnerWidth,		window_width,
									WA_InnerHeight,		window_height,
									WA_MaxWidth,		~0,
									WA_MaxHeight,		~0,
									WA_MinWidth, 		MIN_WIDTH,
									WA_MinHeight, 		MIN_HEIGHT,
									WA_NewLookMenus,	TRUE,
									WA_SmartRefresh,	TRUE,
									WA_NoCareRefresh,	TRUE,
									WA_CloseGadget,		TRUE,
									WA_DepthGadget,		TRUE,
									WA_DragBar,			TRUE,
									WA_Borderless,		FALSE,
									WA_SizeGadget,		TRUE,
									WA_SizeBBottom,		TRUE,
									WA_Activate,		TRUE,
									WA_Hidden,			FALSE, //this avoid a bug into WA_StayTop when used with WA_Hidden									
                                    WA_StayTop,         (is_ontop==1) ? TRUE : FALSE,
									
									WA_Zoom,          ZoomDatapip, 
									
									#if 0
									WA_IDCMP,			IDCMP_MOUSEBUTTONS |
														IDCMP_CHANGEWINDOW |
														IDCMP_MOUSEMOVE |
														IDCMP_GADGETDOWN,
														IDCMP_VANILLAKEY |
														IDCMP_MENUPICK |
														IDCMP_IDCMPUPDATE |
														IDCMP_GADGETUP |
														IDCMP_RAWKEY |
														IDCMP_CLOSEWINDOW |
														IDCMP_NEWSIZE,
									#endif
									
									#ifdef __amigaos4__
									
									WA_IDCMP,       IDCMP_MOUSEBUTTONS | 
													IDCMP_CHANGEWINDOW | 
													IDCMP_MOUSEMOVE |
													IDCMP_GADGETUP |
													IDCMP_GADGETDOWN |		
													IDCMP_INACTIVEWINDOW | 
													IDCMP_ACTIVEWINDOW  | 
													IDCMP_IDCMPUPDATE | 	
													IDCMP_REFRESHWINDOW | 
													IDCMP_RAWKEY |
													IDCMP_CLOSEWINDOW | 
													IDCMP_NEWSIZE,
													
									WA_Flags,        WFLG_REPORTMOUSE, 								
									
									#endif

								TAG_DONE);
								
								if(use_gui) {
									IIntuition->UnlockPubScreen(NULL, scrn);
								}	
// = TRUE for GUI
                                hasGUI = FALSE;
                        }

                        IIntuition->FreeScreenDrawInfo(My_Screen, dri);
                    }

					// add iconify gadget
					/*
                    if (My_Window)
                    {
						if (DIcon)
							IIntuition->AddGadget(My_Window, (struct Gadget *)IconifyGadget, -1);
					}
					*/

					vo_screenwidth = My_Screen->Width;
					vo_screenheight = My_Screen->Height;
                }
            }
        }

		IIntuition->UnlockPubScreen(NULL, My_Screen);
    }

    if ( !My_Window )
    {
        mp_msg(MSGT_VO, MSGL_ERR, "Unable to open a window\n");
        return INVALID_ID;
    }

    if ( (ModeID = IGraphics->GetVPModeID(&My_Window->WScreen->ViewPort) ) == INVALID_ID)
    {
        return INVALID_ID;
    }

	mouse_hidden = FALSE;
	IIntuition->ClearPointer(My_Window);

	vo_dwidth = My_Window->Width - (My_Window->BorderLeft + My_Window->BorderRight);
	vo_dheight = My_Window->Height - (My_Window->BorderBottom + My_Window->BorderTop);
	vo_fs = 0;

    IIntuition->ScreenToFront(My_Window->WScreen);

	Cgx_ControlBlanker(My_Screen, FALSE);
	
	// hide/show
	PlayerWindow = My_Window;
	
    return ModeID;
}

static ULONG Open_FullScreen(void)
{
    ULONG ModeID = INVALID_ID;

    ModeID = GoFullScreen();
    return ModeID;
}
/**************************/
static int PrepareVideo(uint32_t in_format, uint32_t out_format)
{
    g_in_format = in_format;
    g_out_format= out_format;

    return 0;
}


/******************************** CONFIG ******************************************/
static int config(uint32_t width, uint32_t height, uint32_t d_width,
             uint32_t d_height, uint32_t flags, char *title,
             uint32_t format)
{
    uint32_t out_format;
    ULONG ModeID = INVALID_ID;

	if (Stopped==TRUE || My_Window)
		FreeGfx();
		
	ratio = (float)d_width/(float)d_height;

	if (d_width<MIN_WIDTH || d_height<MIN_HEIGHT)
	{
		d_width = MIN_WIDTH * ratio;
		d_height = MIN_HEIGHT * ratio;
	}
	//else
	//	d_height = d_width / ratio;

    if (old_d_width==0 || old_d_height==0)
    {
        old_d_width     = d_width;
        old_d_height    = d_height;
    }

    if (keep_width==0 || keep_height==0)
    {
		keep_width     = d_width;
		keep_height    = d_height;
    }

	image_width = width;
	image_height = height;
    image_format = format;

    vo_fs = flags & VOFLAG_FULLSCREEN;

	window_width  = d_width;
	window_height = d_height;

    //printf("\nconfig: image_width:%d, image_height:%d\nwidth: %d, height: %d\nd_width: %d, d_height:%d",image_width, image_height, width, height, d_width, d_height);
    //printf("\nconfig: old_d_width:%d, old_d_height:%d\nkeep_width: %d, keep_height: %d",old_d_width, old_d_height, keep_width, keep_height);
    //printf("\nconfig: window_width:%d, window_height:%d\n",window_width, window_height);

	EmptyPointer = IExec->AllocVec(12, MEMF_PUBLIC | MEMF_CLEAR);

	if ( vo_fs )
	{
		ModeID = Open_FullScreen();
	}
	else
		ModeID = Open_PIPWindow();

    if (INVALID_ID == ModeID)
    {
       return 1;
    }

    rp = My_Window->RPort;
    UserMsg = My_Window->UserPort;

    vo_draw_alpha_func = draw_alpha_yv12;
    out_format = IMGFMT_YV12;

    if (PrepareVideo(format, out_format) < 0)
    {
        return 1;
    }

	if (hasGUI == TRUE)
	{
		//p96pip_TimerInit();
		//p96pip_TimerReset(RESET_TIME);
	}
	Stopped = FALSE;
    return 0; // -> Ok
}

#define PLANAR_2_CHUNKY(Py, Py2, Pu, Pv, dst, dst2)	\
	{											\
	register ULONG Y = *++Py;				\
	register ULONG Y2= *++Py;				\
	register ULONG U = *++Pu;				\
	register ULONG V = *++Pv;				\
												\
	__asm__ __volatile__ (					\
		"rlwinm %%r3,%1,0,0,7;"			\
		"rlwinm %%r4,%1,16,0,7;"   		\
		"rlwimi %%r3,%2,24,8,15;"		\
		"rlwimi %%r4,%2,0,8,15;"		\
		"rlwimi %%r3,%1,24,16,23;"		\
		"rlwimi %%r4,%1,8,16,23;"		\
		"rlwimi %%r3,%3,8,24,31;"		\
		"rlwimi %%r4,%3,16,24,31;"		\
												\
		"stw %%r3,4(%0);"			\
		"stwu %%r4,8(%0);"				\
												\
	    : "+b" (dst)						\
	    : "r" (Y), "r" (U), "r" (V) 		\
	    : "r3", "r4");				\
												\
	Y = *++Py2;							\
	__asm__ __volatile__ (				\
		"rlwinm %%r3,%1,0,0,7;"			\
		"rlwinm %%r4,%1,16,0,7;"			\
		"rlwimi %%r3,%2,8,8,15;"			\
		"rlwimi %%r4,%2,16,8,15;"		\
		"rlwimi %%r3,%1,24,16,23;"		\
		"rlwimi %%r4,%1,8,16,23;"		\
		"rlwimi %%r3,%3,24,24,31;"		\
		"rlwimi %%r4,%3,0,24,31;"		\
												\
		"stw %%r3,4(%0);"		\
		"stwu %%r4,8(%0);"				\
											\
	    : "+b" (dst)						\
	    : "r" (Y2), "r" (U), "r" (V) 		\
	    : "r3", "r4");				\
												\
	Y2= *++Py2;							\
	__asm__ __volatile__ (				\
		"rlwinm %%r3,%1,0,0,7;" 		\
		"rlwinm %%r4,%1,16,0,7;"   		\
		"rlwimi %%r3,%2,24,8,15;"		\
		"rlwimi %%r4,%2,0,8,15;"		\
		"rlwimi %%r3,%1,24,16,23;"		\
		"rlwimi %%r4,%1,8,16,23;"		\
		"rlwimi %%r3,%3,8,24,31;"		\
		"rlwimi %%r4,%3,16,24,31;"		\
												\
		"stw %%r3,4(%0);"			\
		"stwu %%r4,8(%0);"				\
												\
	    : "+b" (dst2)						\
	    : "r" (Y), "r" (U), "r" (V) 		\
	    : "r3", "r4");				\
									\
	__asm__ __volatile__ (				\
		"rlwinm %%r3,%1,0,0,7;"		\
		"rlwinm %%r4,%1,16,0,7;"		\
		"rlwimi %%r3,%2,8,8,15;"		\
		"rlwimi %%r4,%2,16,8,15;"		\
		"rlwimi %%r3,%1,24,16,23;"		\
		"rlwimi %%r4,%1,8,16,23;"		\
		"rlwimi %%r3,%3,24,24,31;"		\
		"rlwimi %%r4,%3,0,24,31;"		\
												\
		"stw %%r3,4(%0);"				\
		"stwu %%r4,8(%0);"				\
												\
	    : "+b" (dst2)						\
	    : "r" (Y2), "r" (U), "r" (V) 		\
	    : "r3", "r4");					\
	}

#if USE_VMEM64
#define PLANAR_2_CHUNKY_64(Py, Py2, Pu, Pv, dst, dst2, tmp)	\
	{											\
	register ULONG Y = *++Py;				\
	register ULONG Y2= *++Py;				\
	register ULONG U = *++Pu;				\
	register ULONG V = *++Pv;				\
												\
	__asm__ __volatile__ (					\
		"rlwinm %%r3,%1,0,0,7;"			\
		"rlwinm %%r4,%1,16,0,7;"   		\
		"rlwimi %%r3,%2,24,8,15;"		\
		"rlwimi %%r4,%2,0,8,15;"		\
		"rlwimi %%r3,%1,24,16,23;"		\
		"rlwimi %%r4,%1,8,16,23;"		\
		"rlwimi %%r3,%3,8,24,31;"		\
		"rlwimi %%r4,%3,16,24,31;"		\
												\
		"stw %%r3,0(%4);"			\
		"stw %%r4,4(%4);"			\
		"lfd %%f1,0(%4);"			\
		"stfdu %%f1,8(%0);"			\
												\
	    : "+b" (dst)						\
	    : "r" (Y), "r" (U), "r" (V), "r" (tmp) 		\
	    : "r3", "r4", "fr1");				\
												\
	Y = *++Py2;							\
	__asm__ __volatile__ (				\
		"rlwinm %%r3,%1,0,0,7;"			\
		"rlwinm %%r4,%1,16,0,7;"			\
		"rlwimi %%r3,%2,8,8,15;"			\
		"rlwimi %%r4,%2,16,8,15;"		\
		"rlwimi %%r3,%1,24,16,23;"		\
		"rlwimi %%r4,%1,8,16,23;"		\
		"rlwimi %%r3,%3,24,24,31;"		\
		"rlwimi %%r4,%3,0,24,31;"		\
												\
		"stw %%r3,0(%4);"			\
		"stw %%r4,4(%4);"			\
		"lfd %%f1,0(%4);"			\
		"stfdu %%f1,8(%0);"			\
											\
	    : "+b" (dst)						\
	    : "r" (Y2), "r" (U), "r" (V), "r" (tmp)		\
	    : "r3", "r4", "fr1");				\
												\
	Y2= *++Py2;							\
	__asm__ __volatile__ (				\
		"rlwinm %%r3,%1,0,0,7;" 		\
		"rlwinm %%r4,%1,16,0,7;"   		\
		"rlwimi %%r3,%2,24,8,15;"		\
		"rlwimi %%r4,%2,0,8,15;"		\
		"rlwimi %%r3,%1,24,16,23;"		\
		"rlwimi %%r4,%1,8,16,23;"		\
		"rlwimi %%r3,%3,8,24,31;"		\
		"rlwimi %%r4,%3,16,24,31;"		\
												\
		"stw %%r3,0(%4);"			\
		"stw %%r4,4(%4);"			\
		"lfd %%f1,0(%4);"			\
		"stfdu %%f1,8(%0);"			\
												\
	    : "+b" (dst2)						\
	    : "r" (Y), "r" (U), "r" (V), "r" (tmp) 		\
	    : "r3", "r4", "fr1");				\
									\
	__asm__ __volatile__ (				\
		"rlwinm %%r3,%1,0,0,7;"		\
		"rlwinm %%r4,%1,16,0,7;"		\
		"rlwimi %%r3,%2,8,8,15;"		\
		"rlwimi %%r4,%2,16,8,15;"		\
		"rlwimi %%r3,%1,24,16,23;"		\
		"rlwimi %%r4,%1,8,16,23;"		\
		"rlwimi %%r3,%3,24,24,31;"		\
		"rlwimi %%r4,%3,0,24,31;"		\
												\
		"stw %%r3,0(%4);"			\
		"stw %%r4,4(%4);"			\
		"lfd %%f1,0(%4);"			\
		"stfdu %%f1,8(%0);"			\
												\
	    : "+b" (dst2)						\
	    : "r" (Y2), "r" (U), "r" (V), "r" (tmp) 		\
	    : "r3", "r4", "fr1");					\
	}
#endif

//
int numbuffers=0;  

/******************************** DRAW_SLICE ******************************************/
static int draw_slice(uint8_t *image[], int stride[], int w,int h,int x,int y)
{
    struct RenderInfo ri;
    struct BitMap *bm = NULL;
    int lock_h;
    unsigned int w3, _w2;
  

/*
    w -= (w%8);
*/
    IP96->p96PIP_GetTags(My_Window, P96PIP_SourceBitMap   , (ULONG)&bm   ,
    								P96PIP_NumberOfBuffers, &numbuffers  ,
    								TAG_END, TAG_DONE );

    if (! (lock_h = IP96->p96LockBitMap(bm, (uint8 *)&ri, sizeof(struct RenderInfo))))
    {
        // Unable to lock the BitMap -> do nothing
        return -1;
    }

    w3 = w & -8;
    _w2 = w3 / 8; // Because we write 8 pixels (aka 16 bit word) at each loop
    h &= -2;

    if (h > 0 && _w2)
    {
        ULONG *srcdata, *srcdata2;

        ULONG *py, *py2, *pu, *pv;
        ULONG *_py, *_py2, *_pu, *_pv;

        _py = py = (ULONG *) image[0];
        _pu = pu = (ULONG *) image[1];
        _pv = pv = (ULONG *) image[2];

        srcdata = (ULONG *) ((uint32)ri.Memory + ( ( (y * image_width) + x) * 2));

        // The data must be stored like this:
        // YYYYYYYY UUUUUUUU : pixel 0
        // YYYYYYYY VVVVVVVV : pixel 1

        // We will read one word of Y (4 byte)
        // then read one word of U and V
        // After another Y word because we need 2 Y for 1 (U & V)

        _py--;
        _pu--;
        _pv--;

        stride[0] &= -8;
        stride[1] &= -8;
        stride[2] &= -8;

#if USE_VMEM64
        /* If aligned buffer, use 64bit writes. It might be worth
           the effort to manually align in other cases, but that'd
           need to handle all conditions such like:
           a) UWORD, UQUAD ... [end aligment]
           b) ULONG, UQUAD ... [end aligment]
           c) ULONG, UWORD, UQUAD ... [end aligment]
           - Piru
        */
        if (!(((uint32) srcdata) & 7))
        {
            ULONG _tmp[3];
            // this alignment crap is needed in case we don't have aligned stack
            register ULONG *tmp = (APTR)((((ULONG) _tmp) + 4) & -8);

            srcdata -= 2;

            do
            {
                int w2 = _w2;
                h -= 2;

                _py2 = (ULONG *)(((ULONG)_py) + (stride[0] ) );

                py = _py;
                py2 = _py2;
                pu = _pu;
                pv = _pv;

                srcdata2 = (ULONG *) ( (ULONG) srcdata + w3 * 2 );

                do
                {
                    // Y is like that : Y1 Y2 Y3 Y4
                    // U is like that : U1 U2 U3 U4
                    // V is like that : V1 V2 V3 V4

                    PLANAR_2_CHUNKY_64(py, py2, pu, pv, srcdata, srcdata2, tmp);

                } while (--w2);

                srcdata = (ULONG *) ( (ULONG) srcdata + (w3 << 1) );
                _py = (ULONG *)(((ULONG)_py) + (stride[0] << 1) );
                _pu = (ULONG *)(((ULONG)_pu) + stride[1]);
                _pv = (ULONG *)(((ULONG)_pv) + stride[2]);

            } while (h);
        }
        else
#endif
        {
            srcdata--;

            do
            {
                int w2 = _w2;

                h -= 2;

                _py2 = (ULONG *)(((ULONG)_py) + (stride[0] ) );

                py = _py;
                py2 = _py2;
                pu = _pu;
                pv = _pv;

                srcdata2 = (ULONG *) ( (ULONG) srcdata + w3 * 2 );

                do
                {
                    // Y is like that : Y1 Y2 Y3 Y4
                    // U is like that : U1 U2 U3 U4
                    // V is like that : V1 V2 V3 V4

                    PLANAR_2_CHUNKY(py, py2, pu, pv, srcdata, srcdata2);

                } while (--w2);

                srcdata = (ULONG *) ( (ULONG) srcdata + (w3 << 1) );
                _py = (ULONG *)(((ULONG)_py) + (stride[0] << 1) );
                _pu = (ULONG *)(((ULONG)_pu) + stride[1]);
                _pv = (ULONG *)(((ULONG)_pv) + stride[2]);

            } while (h);
        }
    }
	
/* we move it to flippage instead */
/*
	if (numbuffers>1)
	{
		uint32 WorkBuf, DispBuf, NextWorkBuf;

		IP96->p96PIP_GetTags(My_Window,	P96PIP_WorkBuffer, &WorkBuf,
								 		P96PIP_DisplayedBuffer, &DispBuf,
								 		TAG_END, TAG_DONE );

		NextWorkBuf = (WorkBuf+1) % numbuffers;

		if (NextWorkBuf == DispBuf) IGraphics->WaitTOF();

		IP96->p96PIP_SetTags(My_Window,	P96PIP_VisibleBuffer, WorkBuf,
								 		P96PIP_WorkBuffer,    NextWorkBuf,
								 		TAG_END, TAG_DONE );
	}
*/

    IP96->p96UnlockBitMap(bm, lock_h);

    return 0;
}
/******************************** DRAW_OSD ******************************************/

static void draw_osd(void)
{
    vo_draw_text(image_width, image_height, vo_draw_alpha_func);
}
/******************************** FLIP_PAGE ******************************************/
static void flip_page(void)
{	   
	if (numbuffers>1)
	{		
		uint32 WorkBuf, DispBuf, NextWorkBuf;

		IP96->p96PIP_GetTags(My_Window,	P96PIP_WorkBuffer, &WorkBuf,
								 		P96PIP_DisplayedBuffer, &DispBuf,
								 		TAG_END, TAG_DONE );

		NextWorkBuf = (WorkBuf+1) % numbuffers;

		if (NextWorkBuf == DispBuf) IGraphics->WaitTOF();

		IP96->p96PIP_SetTags(My_Window,	P96PIP_VisibleBuffer, WorkBuf,
								 		P96PIP_WorkBuffer,    NextWorkBuf,
								 		TAG_END, TAG_DONE );
	}
      
}
/******************************** DRAW_FRAME ******************************************/
static int draw_frame(uint8_t *src[])
{
    // Nothing
    return -1;
}

/************************************************************************************/
/* Just a litle func to help uninit and control										*/
/* it close screen (if fullscreen), the windows, and free all gfx related stuff		*/
/* but do not close any libs														*/
/************************************************************************************/

static void FreeGfx(void)
{
	int i = 0;

	//p96pip_TimerExit();

	Cgx_ControlBlanker(My_Screen, TRUE);
	
	if (window_title)
	{
		IExec->FreeVec(window_title);
		window_title = NULL;
	}
	
    if (AppWin)
   	{
		IWorkbench->RemoveAppWindow(AppWin);
		AppWin = NULL;
   	}

	if (EmptyPointer)
	{
		if (My_Window) IIntuition->ClearPointer(My_Window);
		IExec->FreeVec(EmptyPointer);
		EmptyPointer = NULL;
	}
	
	if (My_Window)
    {
   	    IIntuition->ClearMenuStrip(My_Window);

		if (WinLayout)
		{
			IIntuition->DisposeObject(WinLayout);
			WinLayout = NULL;
		}

		for (i=0;i<7;i++)
		{
			if (NULL != image[i])
			{
				IIntuition->DisposeObject((Object *) image[i]);
				image[i] = NULL;
			}
		}

   	    IP96->p96PIP_Close(My_Window);
		if (IconifyGadget) 
		{
			IIntuition->DisposeObject(IconifyGadget);
			IconifyGadget = NULL;
		}

		if (IconifyImage) 
		{
			IIntuition->DisposeObject(IconifyImage);
			IconifyImage = NULL;
		}
       	My_Window = NULL;

	}
    if (My_Screen)
   	{
		IIntuition->CloseScreen(My_Screen);
		My_Screen = NULL;
   	}
}
/******************************** UNINIT    ******************************************/
static void uninit(void)
{
	if (player_idle_mode==0)
	{
	    FreeGfx();

	    p96pip_CloseOSLibs();
	}
	else
	{
    	keep_width = 0;
	    keep_height = 0;
    	old_d_width = 0;
	    old_d_height = 0;

		isPaused = TRUE;
		//p96pip_ChangePauseButton();        
		isPaused = FALSE;
		Stopped = TRUE;
	}
}

/******************************** CONTROL ******************************************/
static int control(uint32_t request, void *data, ...)
{
    switch (request)
    {
        case VOCTRL_GUISUPPORT:
		 #warning that one to make video drivers be in preference window !
            return VO_TRUE; // was VO_FALSE;
		break;
		
		
        case VOCTRL_FULLSCREEN:
			vo_fs = !vo_fs;

			FreeGfx(); // Free/Close all gfx stuff (screen windows, buffer...);
			if ( config(image_width, image_height, window_width, window_height, vo_fs, NULL, image_format) < 0) return VO_FALSE;

            return VO_TRUE;
		break;
        case VOCTRL_ONTOP:
        	vo_ontop = !vo_ontop;
        	is_ontop = !is_ontop;
        	
			FreeGfx(); // Free/Close all gfx stuff (screen windows, buffer...);
			if ( config(image_width, image_height, window_width, window_height, FALSE, NULL, image_format) < 0) return VO_FALSE;
            return VO_TRUE;
		break;
		case VOCTRL_UPDATE_SCREENINFO:
			if (vo_fs)
			{
				vo_screenwidth = My_Screen->Width;
				vo_screenheight = My_Screen->Height;
			}
			else
			{
				struct Screen *scr = IIntuition->LockPubScreen (NULL);
				if(scr)
				{
					vo_screenwidth = scr->Width;
					vo_screenheight = scr->Height;
					IIntuition->UnlockPubScreen(NULL, scr);
				}
	        }
	        aspect_save_screenres(vo_screenwidth, vo_screenheight);
			return VO_TRUE;
		break;
        case VOCTRL_PAUSE:
			Cgx_ControlBlanker(My_Screen, TRUE);
            return VO_TRUE;
		break;
        case VOCTRL_RESUME:
			Cgx_ControlBlanker(My_Screen, FALSE);
            return VO_TRUE;
		break;
        case VOCTRL_QUERY_FORMAT:
            return query_format(*(ULONG *)data);
		break;
    }

    return VO_NOTIMPL;
}

/******************************** CHECK_EVENTS    ******************************************/
static void check_events(void)
{

	uint32_t oldwidth = window_width, oldheight = window_height;

	if ( Cgx_CheckEvents(My_Screen, My_Window, &window_height, &window_width, &win_left, &win_top) &&
	     (window_width != oldwidth || window_height != oldheight))
	{
		//Update_WinSize();
	}

}

static int query_format(uint32_t format)
{
    switch( format)
    {
	    case IMGFMT_YV12:
	    case IMGFMT_YUY2:
	    case IMGFMT_I420:
    	case IMGFMT_UYVY:
	    case IMGFMT_YVYU:
    	    return  VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD |
        	    	VFCAP_HWSCALE_UP 	| VFCAP_HWSCALE_DOWN 		| VFCAP_ACCEPT_STRIDE;

	    case IMGFMT_RGB15:
    	case IMGFMT_BGR15:
	    case IMGFMT_RGB16:
    	case IMGFMT_BGR16:
	    case IMGFMT_RGB24:
	    case IMGFMT_BGR24:
	    case IMGFMT_RGB32:
	    case IMGFMT_BGR32:
    	    return VFCAP_CSP_SUPPORTED | VFCAP_OSD | VFCAP_FLIP;

        default:
            return VO_FALSE;
    }
}

