#include <windows.h>
#include <mil.h>
#include <queue>
#include <list>
#include <d3d9.h>
#include "md3ddisplayeffect.h"
#include "mdisplay.h"
#include "mdigitizer.h"
using namespace std;
#define MAX_SYSTEMS 6
typedef struct _AUTODETECT
{
MIL_INT DigDeviceNumber;
MIL_TEXT_PTR DCFName;
} AUTODETECT;
AUTODETECT DCF_SCAN[] = {
{M_DEV0, MIL_TEXT("AutoDetect.dcf") },
{M_DEV1, MIL_TEXT("AutoDetect.dcf") },
{M_DEV2, MIL_TEXT("AutoDetect.dcf") },
{M_DEV3, MIL_TEXT("AutoDetect.dcf") },
};
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId,
void* HookDataPtr);
int MosMain(void)
{
MIL_ID MilApplication;
MIL_ID MilSystem[MAX_SYSTEMS] = { M_NULL, };
MIL_INT SystemIndex = 0;
MIL_INT const NumberOfScanElements = (sizeof(DCF_SCAN) / sizeof(AUTODETECT));
MIL_INT InputCount = 0;
vector<CDigitizer *> DigitizerList;
vector<CDisplay *> DisplayList;
vector<CDisplay *>::iterator pDispIterator;
vector<CDigitizer *>::iterator pDigIterator;
LPDIRECT3D9EX g_pD3D = NULL;
Direct3DCreate9Ex(D3D_SDK_VERSION, &g_pD3D);
MappAlloc(M_DEFAULT, &MilApplication);
MappControl(M_ERROR, M_PRINT_DISABLE);
MgraFont(M_DEFAULT, M_FONT_DEFAULT_MEDIUM);
MgraControl(M_DEFAULT, M_BACKGROUND_MODE, M_TRANSPARENT);
MosPrintf(MIL_TEXT("MdigCrossbar.\n"));
MosPrintf(MIL_TEXT("-------------\n\n"));
InputCount = 0;
for(SystemIndex = 0; SystemIndex < MAX_SYSTEMS; SystemIndex++)
{
MsysAlloc(M_SYSTEM_ORION_HD, SystemIndex, M_DEFAULT, &MilSystem[SystemIndex]);
if(MilSystem[SystemIndex] == M_NULL)
break;
MosPrintf(MIL_TEXT("\n"));
MosPrintf(MIL_TEXT("----------------------------------------------------------\n"));
MosPrintf(MIL_TEXT("Searching for input sources on Matrox OrionHD device %d.\n"), SystemIndex);
MosPrintf(MIL_TEXT("----------------------------------------------------------\n\n"));
for(MIL_INT ScanElement = 0; ScanElement < NumberOfScanElements; ScanElement++)
{
CDigitizer *pDig = new CDigitizer(MilSystem[SystemIndex], DCF_SCAN[ScanElement].DigDeviceNumber, DCF_SCAN[ScanElement].DCFName, InputCount);
if(pDig->Digitizer())
{
InputCount++;
DigitizerList.push_back(pDig);
MosPrintf(MIL_TEXT(" Dig %d: \n"), DCF_SCAN[ScanElement].DigDeviceNumber);
pDig->PrintDigitizerInfo();
}
else
{
delete pDig;
MosPrintf(MIL_TEXT(" Dig %d: No input detected. \n"), DCF_SCAN[ScanElement].DigDeviceNumber);
}
}
}
MappControl(M_ERROR, M_PRINT_ENABLE);
if(DigitizerList.empty())
{
MosPrintf(MIL_TEXT("\n\nNo input(s) detected, exiting.\n"));
goto end;
}
MosPrintf(MIL_TEXT("\n\n"));
MosPrintf(MIL_TEXT("------------------------------------\n"));
MosPrintf(MIL_TEXT("Allocating displays.\n"));
MosPrintf(MIL_TEXT("------------------------------------\n\n"));
for(UINT i = 0; i < 32; i++)
{
CDigitizer *pDig = NULL;
MIL_INT DigSizeX = M_NULL;
MIL_INT DigSizeY = M_NULL;
if(i < DigitizerList.size())
pDig = DigitizerList.at(i);
if(pDig)
{
DigSizeX = pDig->SizeX();
DigSizeY = pDig->SizeY();
}
CDisplay *pDisp = new CDisplay(MilSystem[0], i, g_pD3D);
if(pDisp->IsAllocated())
{
DisplayList.push_back(pDisp);
pDisp->SetDisplaySource((MIL_INT64)pDig, DigSizeX, DigSizeY);
}
else
{
delete pDisp;
}
}
HWND hForegroundWindow = GetForegroundWindow();
::InvalidateRect(hForegroundWindow, NULL, TRUE);
UpdateWindow(hForegroundWindow);
MosPrintf(MIL_TEXT("\nPress enter to start.\n"));
MosGetchar();
if(DigitizerList.size())
{
MosPrintf(MIL_TEXT("\nStart grabbing from detected inputs:\n"));
MosPrintf(MIL_TEXT("------------------------------------\n"));
}
for (pDigIterator = DigitizerList.begin(); pDigIterator!= DigitizerList.end(); pDigIterator++)
{
CDigitizer *pDig = *pDigIterator;
pDig->SetUserData(&DisplayList);
Sleep(100);
pDig->Start(ProcessingFunction);
}
Sleep(1000);
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
MIL_INT Key = 0;
while( Key != 'q' )
{
MIL_INT ProcessFrameCount = 0;
MIL_INT ProcessFrameMissed = 0;
MIL_DOUBLE ProcessFrameRate = 0;
bool FoundDviDigitalSource = false;
Sleep(1000);
system("cls");
MosPrintf(MIL_TEXT("MdigCrossbar.\n"));
MosPrintf(MIL_TEXT("-------------\n\n"));
MosPrintf(MIL_TEXT("Commands:\n"));
MosPrintf(MIL_TEXT("---------\n"));
MosPrintf(MIL_TEXT(" Press:\n"));
MosPrintf(MIL_TEXT(" <0 to %d> to display the selected input on all outputs.\n"), DigitizerList.size()-1);
MosPrintf(MIL_TEXT(" <s> to display a selected input on a selected output.\n"));
MosPrintf(MIL_TEXT(" <o> to overlay a selected input on a selected output.\n"));
MosPrintf(MIL_TEXT(" <h> to display one input per output.\n"));
MosPrintf(MIL_TEXT(" <r> to toggle between 30fps and 60fps.\n"));
MosPrintf(MIL_TEXT(" <d> to enable/disable Direct3D effects.\n"));
MosPrintf(MIL_TEXT(" <m> to enable/disable drawing a moving line.\n"));
MosPrintf(MIL_TEXT(" <l> to calculate the latency between the output and the input.\n"));
MosPrintf(MIL_TEXT(" <q> to quit.\n"));
MosPrintf(MIL_TEXT("\n"));
Key = 0;
if(MosKbhit())
Key = MosGetch();
MosPrintf(MIL_TEXT("Digitizers grabbing:\n"));
MosPrintf(MIL_TEXT("--------------------\n"));
for (pDigIterator = DigitizerList.begin(); pDigIterator!= DigitizerList.end(); pDigIterator++)
{
CDigitizer *pDig = *pDigIterator;
pDig->GetStatistics(&ProcessFrameCount, &ProcessFrameRate, &ProcessFrameMissed);
MosPrintf(MIL_TEXT("%4d (%4d x %4d @ %.1f Hz), Frame: %5d (missed: %2d). "),
pDig->Index(), pDig->SizeX(), pDig->SizeY(), ProcessFrameRate, ProcessFrameCount, ProcessFrameMissed);
CDisplay *pDispLatencySource = (CDisplay *) pDig->GetSourceId();
if(pDispLatencySource && pDispLatencySource->Latency())
{
MIL_DOUBLE Cur, Min, Max, Average;
MIL_INT CurInFrames, Count;
pDispLatencySource->GetLatency(&Cur, &Min, &Max, &Average, &CurInFrames, &Count);
MosPrintf(MIL_TEXT("Latency from disp %d (in ms): Cur:%.1f (%d frames), Min:%.1f, Max:%.1f, Avg:%.1f, Count:%d "), pDispLatencySource->Index(),
Cur*1000.0, CurInFrames, Min*1000.0, Max*1000.0, Average*1000.0, Count);
}
MosPrintf(MIL_TEXT("\n"));
if(Key == 'r')
{
if(pDig->GrabDecimation() == 1)
pDig->GrabDecimation(2);
else
pDig->GrabDecimation(1);
}
if(Key == 'm')
pDig->MovingLine(!pDig->MovingLine());
}
MosPrintf(MIL_TEXT("\n"));
MosPrintf(MIL_TEXT("Displays:\n"));
MosPrintf(MIL_TEXT("---------\n"));
for (pDispIterator = DisplayList.begin(); pDispIterator!= DisplayList.end(); pDispIterator++)
{
MIL_INT DisplayCount, DisplaySkipCount;
MIL_DOUBLE DisplayRefreshRate;
CDisplay *pDisp = *pDispIterator;
pDisp->GetStatistic(&DisplayRefreshRate, &DisplayCount, &DisplaySkipCount);
CDigitizer *pDig = (CDigitizer *) pDisp->GetDisplaySource();
MosPrintf(MIL_TEXT("%4d (%4d x %4d @ %.1f Hz) "), pDisp->Index(), pDisp->SizeX(), pDisp->SizeY(), DisplayRefreshRate);
if(pDig)
{
MosPrintf(MIL_TEXT("displaying from dig %d, Frame: %5d (skip: %3d). "),
pDig->Index(), DisplayCount, DisplaySkipCount);
}
else
MosPrintf(MIL_TEXT("not displaying."));
MosPrintf(MIL_TEXT("\n"));
if(Key >= '0' && Key <= '7')
{
MIL_UINT Index = Key - '0';
if(Index < DigitizerList.size() && Index >= 0)
{
CDigitizer *pDig = DigitizerList.at(Index);
pDisp->SetDisplaySource((MIL_INT64)pDig, pDig->SizeX(), pDig->SizeY());
}
}
if(Key == 'h')
{
if((MIL_UINT)pDisp->Index() < DigitizerList.size())
{
CDigitizer *pDig = DigitizerList.at(pDisp->Index());
pDisp->SetDisplaySource((MIL_INT64)pDig, pDig->SizeX(), pDig->SizeY());
}
else
{
pDisp->SetDisplaySource(0, 0, 0);
}
}
if(Key == 'r')
pDisp->ResetStatistic();
if(Key == 'd')
pDisp->D3DEffect(!pDisp->D3DEffect());
if(Key == 'l')
{
MIL_INT ColorMode;
MIL_INT InputMode;
for (pDigIterator = DigitizerList.begin(); pDigIterator!= DigitizerList.end(); pDigIterator++)
{
CDigitizer *pDig = *pDigIterator;
MdigInquire(pDig->Digitizer(), M_COLOR_MODE, &ColorMode);
MdigInquire(pDig->Digitizer(), M_INPUT_MODE, &InputMode);
if((ColorMode == M_DVI) && (InputMode == M_DIGITAL))
{
FoundDviDigitalSource = true;
break;
}
}
if(FoundDviDigitalSource)
pDisp->Latency(!pDisp->Latency());
}
}
if((Key == 'l') && (FoundDviDigitalSource == false))
MosPrintf(MIL_TEXT("\nCan not calculate the latency, no DVI-D input sources detected."));
if(Key == 's' || Key == 'o')
{
CDigitizer *pDig = NULL;
CDisplay *pDisp = NULL;
bool IsSelect = (Key == 's')? true: false;
MIL_INT DispIndex = 0;
MIL_INT DigIndex = 0;
MosPrintf(MIL_TEXT("\nSelect display number (0 to %d): \n"), (DisplayList.size() ? DisplayList.size() - 1 : 0));
Key = MosGetch();
DispIndex = Key - '0';
if((UINT)DispIndex < DisplayList.size() && DispIndex >= 0)
{
pDisp = DisplayList.at(DispIndex);
MosPrintf(MIL_TEXT("Select digitizer number to be outputed on display %d: (0 to %d): \n"), DispIndex, DigitizerList.size()-1);
Key = MosGetch();
DigIndex = Key - '0';
if((UINT)DigIndex < DigitizerList.size() && DigIndex >= 0)
pDig = DigitizerList.at(DigIndex);
if(IsSelect)
{
if(pDig)
pDisp->SetDisplaySource((MIL_INT64)pDig, pDig->SizeX(), pDig->SizeY());
else
pDisp->SetDisplaySource(0 , 0, 0);
}
else
{
if(pDig)
pDisp->SetDisplayOverlaySource((MIL_INT64)pDig, pDig->SizeX(), pDig->SizeY());
else
pDisp->SetDisplayOverlaySource(0 , 0, 0);
}
MosPrintf(MIL_TEXT("\n"));
}
}
MosPrintf(MIL_TEXT("\n"));
}
end:
MosPrintf(MIL_TEXT("Stopping grabs.\n"));
for(pDigIterator = DigitizerList.begin(); pDigIterator!= DigitizerList.end(); pDigIterator++)
{
CDigitizer *pDig = *pDigIterator;
pDig->Stop();
}
MosPrintf(MIL_TEXT("Freeing displays.\n"));
while(!DisplayList.empty())
{
CDisplay *pDisp = DisplayList.back();
DisplayList.pop_back();
delete pDisp;
}
MosPrintf(MIL_TEXT("Freeing digitizers.\n"));
while(!DigitizerList.empty())
{
CDigitizer *pDig = DigitizerList.back();
DigitizerList.pop_back();
delete pDig;
}
MosPrintf(MIL_TEXT("Freeing systems.\n"));
for(SystemIndex = 0; SystemIndex < MAX_SYSTEMS; SystemIndex++)
{
if(MilSystem[SystemIndex])
MsysFree(MilSystem[SystemIndex]);
}
MappFree(MilApplication);
g_pD3D->Release();
::InvalidateRect(hForegroundWindow, NULL, TRUE);
return 0;
}
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
CDigitizer *pDig = (CDigitizer *)HookDataPtr;
CDisplay *pDisp = NULL;
vector<CDisplay *> *pDisplayList;
MIL_ID ModifiedBufferId;
pDisplayList = (vector<CDisplay *> *)pDig->GetUserData();
if(pDisplayList->empty())
return 0;
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER+M_BUFFER_ID, &ModifiedBufferId);
MIL_ID DestBuffer = pDig->GetWorkBuffer();
MbufCopy(ModifiedBufferId, DestBuffer);
vector<CDisplay *>::iterator pDispit;
for (pDispit = pDisplayList->begin(); pDispit!= pDisplayList->end(); pDispit++)
{
CDisplay *pDisp = *pDispit;
if(pDisp->UpdateLatency(ModifiedBufferId))
pDig->SetSourceId((MIL_INT64)pDisp);
if(pDisp->GetDisplaySource() == (MIL_INT64)pDig)
pDisp->DisplayBuffer(DestBuffer);
if(pDisp->GetDisplayOverlaySource() == (MIL_INT64)pDig)
pDisp->DisplayOverlayBuffer(DestBuffer);
}
return 0;
}