<commit_before>// DESCRIPTION:   GenericSLM device adapter
// COPYRIGHT:     2009-2016 Regents of the University of California
//                2016 Open Imaging, Inc.
//
// AUTHOR:        <NAME>, <EMAIL>, 3/17/2009
//                <NAME> (refactor/rewrite), 2016
//
// LICENSE:       This file is distributed under the BSD license.
//                License text is included with the source distribution.
//
//                This file is distributed in the hope that it will be useful,
//                but WITHOUT ANY WARRANTY; without even the implied warranty
//                of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
//                IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//                CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//                INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES.

#include "GenericSLM.h"

#include "Monitors.h"
#include "OffscreenBuffer.h"
#include "SLMWindow.h"
#include "SleepBlocker.h"

#include "ModuleInterface.h"
#include "DeviceUtils.h"

#include <Windows.h>

#include <algorithm>


const char* g_GenericSLMName = "GenericSLM";
const char* g_PropName_GraphicsPort = "GraphicsPort";
const char* g_PropName_Inversion = "Inversion";
const char* g_PropName_MonoColor = "MonochromeColor";


MODULE_API void InitializeModuleData()
{
   RegisterDevice(g_GenericSLMName, MM::SLMDevice,
         "Spatial light modulator controlled through computer graphics output");
}


MODULE_API MM::Device* CreateDevice(const char* deviceName)
{
   if (deviceName == 0)
      return 0;

   if (strcmp(deviceName, g_GenericSLMName) == 0)
   {
      GenericSLM* pGenericSLM = new GenericSLM(g_GenericSLMName);
      return pGenericSLM;
   }

   return 0;
}


MODULE_API void DeleteDevice(MM::Device* pDevice)
{
   delete pDevice;
}


GenericSLM::GenericSLM(const char* name) :
   name_(name),
   window_(0),
   offscreen_(0),
   sleepBlocker_(0),
   shouldBlitInverted_(false),
   invert_(false),
   inversionStr_("Off"),
   monoColor_(SLM_COLOR_WHITE),
   monoColorStr_("White")
{
   SetErrorText(DEVICE_ERR, "An error occurred");
   // TODO We can do better than that

   availableMonitors_ = GetMonitorNames(true, false);

   // Create pre-init properties

   CreateProperty(MM::g_Keyword_Name, name_.c_str(), MM::String, true);
   CreateProperty(MM::g_Keyword_Description, "SLM controlled by computer display adapter output", MM::String, true);

   CreateStringProperty(g_PropName_GraphicsPort, "Undefined", false, 0, true);
   AddAllowedValue(g_PropName_GraphicsPort, "Undefined", 0); // Prevent empty list
   for (unsigned i = 0; i < availableMonitors_.size(); ++i)
   {
      AddAllowedValue(g_PropName_GraphicsPort,
            availableMonitors_[i].c_str(), i + 1);
   }

   CreateStringProperty(g_PropName_Inversion, inversionStr_.c_str(), false,
         new CPropertyAction(this, &GenericSLM::OnInversion), false);
   AddAllowedValue(g_PropName_Inversion, "Off", 0);
   AddAllowedValue(g_PropName_Inversion, "On", 1);

   CreateProperty(g_PropName_MonoColor, monoColorStr_.c_str(), MM::String, false,
         new CPropertyAction(this, &GenericSLM::OnMonochromeColor), false);
   AddAllowedValue(g_PropName_MonoColor, "White", SLM_COLOR_WHITE);
   AddAllowedValue(g_PropName_MonoColor, "Red", SLM_COLOR_RED);
   AddAllowedValue(g_PropName_MonoColor, "Green", SLM_COLOR_GREEN);
   AddAllowedValue(g_PropName_MonoColor, "Blue", SLM_COLOR_BLUE);
   AddAllowedValue(g_PropName_MonoColor, "Cyan", SLM_COLOR_CYAN);
   AddAllowedValue(g_PropName_MonoColor, "Magenta", SLM_COLOR_MAGENTA);
   AddAllowedValue(g_PropName_MonoColor, "Yellow", SLM_COLOR_YELLOW);
}


GenericSLM::~GenericSLM()
{
   Shutdown();
}


void GenericSLM::GetName(char* name) const
{
   CDeviceUtils::CopyLimitedString(name, name_.c_str());
}


int GenericSLM::Initialize()
{
   Shutdown();

   long index;
   int err = GetCurrentPropertyData(g_PropName_GraphicsPort, index);
   if (err != DEVICE_OK)
      return err;
   if (index == 0)
      return DEVICE_ERR; // TODO "Graphics port not selected"
   monitorName_ = availableMonitors_[index - 1];

   if (!DetachMonitorFromDesktop(monitorName_))
   {
      monitorName_ = "";
      return DEVICE_ERR; // TODO "Cannot detach monitor from desktop"
   }

   std::vector<std::string> otherAttachedMonitors(GetMonitorNames(false, true));

   LONG posX, posY;
   GetRightmostMonitorTopRight(otherAttachedMonitors, posX, posY);

   if (!AttachMonitorToDesktop(monitorName_, posX, posY))
   {
      monitorName_ = "";
      return DEVICE_ERR; // TODO "Cannot attach monitor to desktop"
   }

   LONG x, y, w, h;
   GetMonitorRect(monitorName_, x, y, w, h);

   window_ = new SLMWindow("MM_SLM", x, y, w, h);
   window_->Show();

   offscreen_ = new OffscreenBuffer(window_->GetDC(), w, h);

   RECT mouseClipRect;
   if (GetBoundingRect(otherAttachedMonitors, mouseClipRect))
      sleepBlocker_ = new SleepBlocker(mouseClipRect);
   else
      sleepBlocker_ = new SleepBlocker();
   sleepBlocker_->Start();

   return DEVICE_OK;
}


int GenericSLM::Shutdown()
{
   if (sleepBlocker_)
   {
      sleepBlocker_->Stop();<commit_msg>GenericSLM: Add a simple test mode<commit_after>// DESCRIPTION:   GenericSLM device adapter
// COPYRIGHT:     2009-2016 Regents of the University of California
//                2016 Open Imaging, Inc.
//
// AUTHOR:        <NAME>, <EMAIL>, 3/17/2009
//                <NAME> (refactor/rewrite), 2016
//
// LICENSE:       This file is distributed under the BSD license.
//                License text is included with the source distribution.
//
//                This file is distributed in the hope that it will be useful,
//                but WITHOUT ANY WARRANTY; without even the implied warranty
//                of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
//                IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//                CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//                INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES.

#include "GenericSLM.h"

#include "Monitors.h"
#include "OffscreenBuffer.h"
#include "SLMWindow.h"
#include "SleepBlocker.h"

#include "ModuleInterface.h"
#include "DeviceUtils.h"

#include <Windows.h>

#include <algorithm>


const char* g_GenericSLMName = "GenericSLM";
const char* g_PropName_GraphicsPort = "GraphicsPort";
const char* g_PropName_Inversion = "Inversion";
const char* g_PropName_MonoColor = "MonochromeColor";


MODULE_API void InitializeModuleData()
{
   RegisterDevice(g_GenericSLMName, MM::SLMDevice,
         "Spatial light modulator controlled through computer graphics output");
}


MODULE_API MM::Device* CreateDevice(const char* deviceName)
{
   if (deviceName == 0)
      return 0;

   if (strcmp(deviceName, g_GenericSLMName) == 0)
   {
      GenericSLM* pGenericSLM = new GenericSLM(g_GenericSLMName);
      return pGenericSLM;
   }

   return 0;
}


MODULE_API void DeleteDevice(MM::Device* pDevice)
{
   delete pDevice;
}


GenericSLM::GenericSLM(const char* name) :
   name_(name),
   window_(0),
   offscreen_(0),
   sleepBlocker_(0),
   shouldBlitInverted_(false),
   invert_(false),
   inversionStr_("Off"),
   monoColor_(SLM_COLOR_WHITE),
   monoColorStr_("White")
{
   SetErrorText(DEVICE_ERR, "An error occurred");
   // TODO We can do better than that

   availableMonitors_ = GetMonitorNames(true, false);

   // Create pre-init properties

   CreateProperty(MM::g_Keyword_Name, name_.c_str(), MM::String, true);
   CreateProperty(MM::g_Keyword_Description, "SLM controlled by computer display adapter output", MM::String, true);

   CreateStringProperty(g_PropName_GraphicsPort, "Test128x128", false, 0, true);
   AddAllowedValue(g_PropName_GraphicsPort, "Test128x128", 0); // Prevent empty list
   for (unsigned i = 0; i < availableMonitors_.size(); ++i)
   {
      AddAllowedValue(g_PropName_GraphicsPort,
            availableMonitors_[i].c_str(), i + 1);
   }

   CreateStringProperty(g_PropName_Inversion, inversionStr_.c_str(), false,
         new CPropertyAction(this, &GenericSLM::OnInversion), false);
   AddAllowedValue(g_PropName_Inversion, "Off", 0);
   AddAllowedValue(g_PropName_Inversion, "On", 1);

   CreateProperty(g_PropName_MonoColor, monoColorStr_.c_str(), MM::String, false,
         new CPropertyAction(this, &GenericSLM::OnMonochromeColor), false);
   AddAllowedValue(g_PropName_MonoColor, "White", SLM_COLOR_WHITE);
   AddAllowedValue(g_PropName_MonoColor, "Red", SLM_COLOR_RED);
   AddAllowedValue(g_PropName_MonoColor, "Green", SLM_COLOR_GREEN);
   AddAllowedValue(g_PropName_MonoColor, "Blue", SLM_COLOR_BLUE);
   AddAllowedValue(g_PropName_MonoColor, "Cyan", SLM_COLOR_CYAN);
   AddAllowedValue(g_PropName_MonoColor, "Magenta", SLM_COLOR_MAGENTA);
   AddAllowedValue(g_PropName_MonoColor, "Yellow", SLM_COLOR_YELLOW);
}


GenericSLM::~GenericSLM()
{
   Shutdown();
}


void GenericSLM::GetName(char* name) const
{
   CDeviceUtils::CopyLimitedString(name, name_.c_str());
}


int GenericSLM::Initialize()
{
   Shutdown();

   long index;
   int err = GetCurrentPropertyData(g_PropName_GraphicsPort, index);
   if (err != DEVICE_OK)
      return err;
   if (index > 0) // Unless test mode
      monitorName_ = availableMonitors_[index - 1];

   if (!monitorName_.empty() && !DetachMonitorFromDesktop(monitorName_))
   {
      monitorName_ = "";
      return DEVICE_ERR; // TODO "Cannot detach monitor from desktop"
   }

   std::vector<std::string> otherAttachedMonitors(GetMonitorNames(false, true));

   LONG posX, posY;
   GetRightmostMonitorTopRight(otherAttachedMonitors, posX, posY);

   if (!monitorName_.empty() &&
         !AttachMonitorToDesktop(monitorName_, posX, posY))
   {
      monitorName_ = "";
      return DEVICE_ERR; // TODO "Cannot attach monitor to desktop"
   }

   LONG x, y, w, h;
   if (!monitorName_.empty())
   {
      GetMonitorRect(monitorName_, x, y, w, h);
   }
   else // Test mode
   {
      x = y = 0;
      w = h = 128;
   }

   window_ = new SLMWindow("MM_SLM", x, y, w, h);
   window_->Show();

   offscreen_ = new OffscreenBuffer(window_->GetDC(), w, h);

   RECT mouseClipRect;
   if (GetBoundingRect(otherAttachedMonitors, mouseClipRect))
      sleepBlocker_ = new SleepBlocker(mouseClipRect);
   else
      sleepBlocker_ = new SleepBlocker();
   sleepBlocker_->Start();

   return DEVICE_OK;
}


int GenericSLM::Shutdown()
{
   if (sleepBlocker_)
   {
      sleepBlocker_->Stop();
{'fraction_non_alphanumeric': 0.11328200192492782, 'fraction_numerical': 0.008854667949951878, 'mean_word_length': 3.8240482822655526, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7473488', 'n_tokens_mistral': 3490, 'n_tokens_neox': 3327, 'n_words': 785}