/***************************************************************************************/
/*
* File name: RTDisplayMonitor.cpp
* Location: See Matrox Example Launcher in the MIL Control Center
 * 
*
* Synopsis:  This programs displays images grabbed in a real time sub-system.
*            Note that, to display the image while it is being grabbed in a real time 
*            sub-system, this program must start before the grab begins.
*
* Copyright (C) Matrox Electronic Systems Ltd., 1992-2020.
* All Rights Reserved
*/


#include <mil.h>
#include <Windows.h>
#include <Rtapi.h>

#include "RTDisplayMonitor.h"


DWORD WINAPI DisplayThread( LPVOID lpParam );

int MosMain(void)
{
   MIL_ID MilApplication;  /* Application identifier.  */
   MIL_ID MilSystem;       /* System identifier.       */
   MIL_ID MilDisplay;
   MIL_ID ThreadId;
   DISP_THREAD_INFO ThreadInfo;
   HANDLE ShareMemDispAlloc;
   HANDLE AllocDispEvent;
   void *dataLoc = NULL;
   
   /* Allocate a default MIL application, system */
   MappAlloc(M_DEFAULT, &MilApplication);
   MsysAlloc(M_SYSTEM_HOST, M_DEFAULT, M_DEFAULT, &MilSystem);

   AllocDispEvent = RtCreateEvent(NULL, FALSE, FALSE, DISP_EVENT_MIL_NAMED);

   if((ShareMemDispAlloc = RtCreateSharedMemory(PAGE_READWRITE, 0, 1024, DISP_SHARE_MEM_NAMED, &dataLoc)) ==NULL)
      {
      RtCloseHandle(AllocDispEvent);
      ExitProcess(1);
      }

   MosPrintf(MIL_TEXT("MIL RTOS display monitor.\n"));
   MosPrintf(MIL_TEXT("------------------------------\n\n"));

   MosPrintf(MIL_TEXT("This example displays images grabbed with RTDigProcess running under\na RTOS.\n\n"));
   MosPrintf(MIL_TEXT("It must be started before RTDigProcess.\n"));

   MdispAlloc(MilSystem, M_DEFAULT, MIL_TEXT("M_DEFAULT"), M_DEFAULT, &MilDisplay);
   MosPrintf("\n\nPress any key to terminate.");

   ThreadInfo.SystemId  = MilSystem;
   ThreadInfo.MilDisplay= MilDisplay;
   ThreadInfo.DispEvent = AllocDispEvent;
   ThreadInfo.SharePtr  = dataLoc;
   ThreadInfo.Exit      = false;

   MthrAlloc(MilSystem, M_THREAD, M_DEFAULT, &DisplayThread, &ThreadInfo,  &ThreadId);

   MosGetch();

   ThreadInfo.Exit = true;
   RtSetEvent(AllocDispEvent);
   MthrFree(ThreadId);

   RtCloseHandle(AllocDispEvent);
   RtCloseHandle(ShareMemDispAlloc);

   MdispFree(MilDisplay);
   MsysFree(MilSystem);
   MappFree(MilApplication);

   return 0;
}

DWORD WINAPI DisplayThread( LPVOID lpParam )
   {
   DISP_THREAD_INFO *ThreadInfo = (DISP_THREAD_INFO *)lpParam;
   RTX_DISP_BUFFER *DispInfo = NULL;
   MIL_ID MilImageDisp = NULL;

   while(1)
      {
      RtWaitForSingleObject(ThreadInfo->DispEvent, INFINITE);

      if(ThreadInfo->Exit)
         break;

      DispInfo = (RTX_DISP_BUFFER *) ThreadInfo->SharePtr;
      if(DispInfo->Cmd == DISP_ALLOC_CMD)
         {
         if(MilImageDisp)
            MbufFree(MilImageDisp);

         MbufCreateColor(ThreadInfo->SystemId, 
            DispInfo->Band,
            DispInfo->SizeX,
            DispInfo->SizeY,
            8,
            DispInfo->Format + M_DISP,
            M_PHYSICAL_ADDRESS + M_PITCH,
            DispInfo->Pitch,
            (void **)DispInfo->PhysicalAddress,
            &MilImageDisp);

         if(MilImageDisp)
            {
            MdispSelect(ThreadInfo->MilDisplay, MilImageDisp);
            }
         }
      else if (DispInfo->Cmd == DISP_FREE_CMD)
         {
         if(MilImageDisp)
            {
            MbufFree(MilImageDisp);
            MilImageDisp = NULL;
            }
         }
      else if (DispInfo->Cmd == DISP_UPATE_CMD)
         {
         if(MilImageDisp)
            MbufControl(MilImageDisp, M_MODIFIED, M_DEFAULT);
         }

      };

   if(MilImageDisp)
      MbufFree(MilImageDisp);

   return 0;
   }