init
This commit is contained in:
+158
@@ -0,0 +1,158 @@
|
||||
#include "ovpCBoxAlgorithmKeypressEmulator.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tools {
|
||||
|
||||
#if defined(TARGET_OS_Windows)
|
||||
#include <winuser.h>
|
||||
#endif
|
||||
|
||||
bool CBoxAlgorithmKeypressEmulator::initialize()
|
||||
{
|
||||
m_decoder.initialize(*this, 0);
|
||||
|
||||
m_triggerStimulation = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
m_keyToPress = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
|
||||
#if defined(TARGET_OS_Windows)
|
||||
const uint64_t modifier = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
if (modifier == OVP_TypeId_Keypress_Modifier_Shift.id()) { m_modifier = VK_SHIFT; }
|
||||
else if (modifier == OVP_TypeId_Keypress_Modifier_Control.id()) { m_modifier = VK_CONTROL; }
|
||||
else if (modifier == OVP_TypeId_Keypress_Modifier_Alt.id()) { m_modifier = VK_MENU; }
|
||||
#elif defined(TARGET_OS_Linux)
|
||||
// @todo implement the whole linux solution
|
||||
// Handle modifier on linux here
|
||||
getLogManager() << Kernel::LogLevel_Error << "This box is only implemented on Windows for the moment\n";
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmKeypressEmulator::uninitialize()
|
||||
{
|
||||
m_decoder.uninitialize();
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmKeypressEmulator::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmKeypressEmulator::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
m_decoder.decode(i);
|
||||
|
||||
if (m_decoder.isHeaderReceived()) { } // NOP
|
||||
if (m_decoder.isBufferReceived())
|
||||
{
|
||||
const IStimulationSet* set = m_decoder.getOutputStimulationSet();
|
||||
for (size_t s = 0; s < set->getStimulationCount(); ++s)
|
||||
{
|
||||
if (set->getStimulationIdentifier(s) == m_triggerStimulation)
|
||||
{
|
||||
#if defined(TARGET_OS_Windows)
|
||||
getLogManager() << Kernel::LogLevel_Debug << "Received " << m_triggerStimulation << ", pressing Windows virtual key " << m_keyToPress
|
||||
<< " with modifier " << m_modifier << ", delay is at least "
|
||||
<< CTime(this->getPlayerContext().getCurrentTime() - set->getStimulationDate(s)) << "\n";
|
||||
|
||||
// @todo the stimulation time is not necessarily RIGHT NOW. A very
|
||||
// accurate solution would call SendInput exactly when the key needs to be pressed. Unfortunately when
|
||||
// we receive the stim chunk, the keypress is already old, and we can't press keys into the past. In this sense
|
||||
// sending immediately might be the best we can do.
|
||||
// Note that the speccing the "time" field of INPUT as nonzero doesn't send keypresses to the past or future.
|
||||
if (m_modifier != 0)
|
||||
{
|
||||
INPUT keypress[3];
|
||||
memset(keypress, 0, sizeof(INPUT) * 3);
|
||||
keypress[0].type = INPUT_KEYBOARD;
|
||||
keypress[0].ki.wVk = WORD(m_modifier);
|
||||
keypress[1].type = INPUT_KEYBOARD;
|
||||
keypress[1].ki.wVk = WORD(m_keyToPress);
|
||||
keypress[2].type = INPUT_KEYBOARD;
|
||||
keypress[2].ki.wVk = WORD(m_modifier);
|
||||
keypress[2].ki.dwFlags = KEYEVENTF_KEYUP;
|
||||
SendInput(3, keypress, sizeof(INPUT));
|
||||
}
|
||||
else
|
||||
{
|
||||
INPUT keypress;
|
||||
memset(&keypress, 0, sizeof(INPUT));
|
||||
keypress.type = INPUT_KEYBOARD;
|
||||
keypress.ki.wVk = WORD(m_keyToPress);
|
||||
SendInput(1, &keypress, sizeof(INPUT));
|
||||
}
|
||||
#elif defined(TARGET_OS_Linux)
|
||||
// @todo
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_decoder.isEndReceived()) { } // NOP
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBoxAlgorithmKeypressEmulator::registerEnums(const Kernel::IPluginModuleContext& ctx)
|
||||
{
|
||||
ctx.getTypeManager().registerEnumerationType(OVP_TypeId_Keypress_Modifier, "Key modifier");
|
||||
ctx.getTypeManager().registerEnumerationEntry(OVP_TypeId_Keypress_Modifier, "None", OVP_TypeId_Keypress_Modifier_None.id());
|
||||
ctx.getTypeManager().registerEnumerationEntry(OVP_TypeId_Keypress_Modifier, "Shift", OVP_TypeId_Keypress_Modifier_Shift.id());
|
||||
ctx.getTypeManager().registerEnumerationEntry(OVP_TypeId_Keypress_Modifier, "Ctrl", OVP_TypeId_Keypress_Modifier_Control.id());
|
||||
ctx.getTypeManager().registerEnumerationEntry(OVP_TypeId_Keypress_Modifier, "Alt", OVP_TypeId_Keypress_Modifier_Alt.id());
|
||||
|
||||
ctx.getTypeManager().registerEnumerationType(OVP_TypeId_Keypress_Key, "Key");
|
||||
|
||||
#if defined(TARGET_OS_Windows)
|
||||
// @note this solution makes the scenario not portable between win<->linux. The challenge is keys such as F1 etc,
|
||||
// otherwise we could just read ascii char and map it to a key.
|
||||
// @fixme we're also not able to expose all the possible keys to the user this way, but the problem seems to be that
|
||||
// GetKeyNameTextA does not give meaningful & different names to all keys for some reason.
|
||||
// - The current appoarch attempts to expose the usual 'english' keys that can be visualized by pango.
|
||||
// - We do not necessarily get arrow keys listed as these may not have a separate representation from
|
||||
// the corresponding 'numpad' keys with the functions we call here; esp. GetKeyNameTextA seems to
|
||||
// depend on the keyboard in use. This limits the scenario portability across keyboards.
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
const UINT mapped = MapVirtualKeyA(UINT(i), MAPVK_VK_TO_VSC);
|
||||
const LONG scanCode = mapped << 16;
|
||||
|
||||
if (scanCode)
|
||||
{
|
||||
CHAR buffer[512];
|
||||
if (GetKeyNameTextA(scanCode, buffer, 512))
|
||||
{
|
||||
std::string tmp(buffer);
|
||||
|
||||
if (tmp.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_*&$%@^#!-+/\\ :;,.'`~()[]\"=") != std::string::npos)
|
||||
{
|
||||
// Some weird characters here, may be difficult to render for pango, ignore this key
|
||||
continue;
|
||||
}
|
||||
|
||||
// GetKeyNameTextA can return the same name for different keys. Only use the first one.
|
||||
if (ctx.getTypeManager().getEnumerationEntryValueFromName(OVP_TypeId_Keypress_Key, buffer) == CIdentifier::undefined().id())
|
||||
{
|
||||
ctx.getTypeManager().registerEnumerationEntry(OVP_TypeId_Keypress_Key, buffer, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(TARGET_OS_Linux)
|
||||
// @todo register the linux keys to the enum here
|
||||
#endif
|
||||
}
|
||||
} // namespace Tools
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tools {
|
||||
/**
|
||||
* \class CBoxAlgorithmKeypressEmulator
|
||||
* \author Jussi T. Lindgren / Inria
|
||||
* \date 29.Oct.2019
|
||||
* \brief Emulates keypresses on a keyboard based on input stimulations. Based on a request from Fabien Lotte / POTIOC.
|
||||
*
|
||||
*/
|
||||
class CBoxAlgorithmKeypressEmulator final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_KeypressEmulator)
|
||||
|
||||
// Register enums to the kernel used by this box
|
||||
static void registerEnums(const Kernel::IPluginModuleContext& ctx);
|
||||
|
||||
protected:
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmKeypressEmulator> m_decoder;
|
||||
|
||||
// @todo for multiple triggers, use std::map<>
|
||||
uint64_t m_triggerStimulation = 0;
|
||||
uint64_t m_keyToPress = 0;
|
||||
uint64_t m_modifier = 0;
|
||||
};
|
||||
|
||||
class CBoxAlgorithmKeypressEmulatorDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Keypress Emulator"); }
|
||||
CString getAuthorName() const override { return CString("Jussi T. Lindgren"); }
|
||||
CString getAuthorCompanyName() const override { return CString("Inria"); }
|
||||
CString getShortDescription() const override { return CString("Emulates pressing keyboard keys when receiving stimulations"); }
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Tools"); }
|
||||
CString getVersion() const override { return CString("0.1"); }
|
||||
CString getStockItemName() const override { return CString("gtk-index"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_KeypressEmulator; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmKeypressEmulator; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Stimulations",OV_TypeId_Stimulations);
|
||||
|
||||
// @todo add support for multiple keys, e.g. look at VRPN boxes for howto
|
||||
prototype.addSetting("Trigger", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_00");
|
||||
prototype.addSetting("Key to press", OVP_TypeId_Keypress_Key, "A");
|
||||
prototype.addSetting("Key modifier", OVP_TypeId_Keypress_Modifier, OVP_TypeId_Keypress_Modifier_None.toString());
|
||||
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_KeypressEmulatorDesc)
|
||||
};
|
||||
} // namespace Tools
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
#include "ovpCBoxAlgorithmLatencyEvaluation.h"
|
||||
#include <system/ovCTime.h>
|
||||
|
||||
// @note by just repeatedly printing to the console, this box introduces significant latency by itself.
|
||||
// @fixme If it makes sense to enable this box at all, it should be reimplemented as printing to a small GUI widget instead.
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tools {
|
||||
|
||||
bool CBoxAlgorithmLatencyEvaluation::initialize()
|
||||
{
|
||||
CString logLevel;
|
||||
getBoxAlgorithmContext()->getStaticBoxContext()->getSettingValue(0, logLevel);
|
||||
m_LogLevel = Kernel::ELogLevel(getBoxAlgorithmContext()->getPlayerContext()->getTypeManager().getEnumerationEntryValueFromName(OV_TypeId_LogLevel, logLevel));
|
||||
|
||||
m_StartTime = System::Time::zgetTime();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLatencyEvaluation::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLatencyEvaluation::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
const uint64_t time = getPlayerContext().getCurrentTime();
|
||||
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
const uint64_t start = boxContext.getInputChunkStartTime(0, i);
|
||||
const uint64_t end = boxContext.getInputChunkEndTime(0, i);
|
||||
const double startLatency = (double((int64_t(time - start) >> 22) * 1000) / 1024.0);
|
||||
const double endLatency = (double((int64_t(time - end) >> 22) * 1000) / 1024.0);
|
||||
|
||||
// getLogManager() << Kernel::LogLevel_Debug << "Timing values [start:end:current]=[" << tStart << ":" << tEnd << ":" << time << "]\n";
|
||||
getLogManager() << m_LogLevel << "Current latency at chunk " << i << " [start:end]=[" << startLatency << ":" << endLatency << "] ms\n";
|
||||
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
}
|
||||
|
||||
const uint64_t elapsed = System::Time::zgetTime() - m_StartTime;
|
||||
const double latency = (double((int64_t(elapsed - time) >> 22) * 1000) / 1024.0);
|
||||
|
||||
getLogManager() << m_LogLevel << "Inner latency : " << latency << " ms\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Tools
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tools {
|
||||
class CBoxAlgorithmLatencyEvaluation final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override { return true; }
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_LatencyEvaluation)
|
||||
|
||||
uint64_t m_StartTime = 0;
|
||||
Kernel::ELogLevel m_LogLevel = Kernel::ELogLevel::LogLevel_None;
|
||||
};
|
||||
|
||||
class CBoxAlgorithmLatencyEvaluationDesc final : public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Latency evaluation"); }
|
||||
CString getAuthorName() const override { return CString("Yann Renard"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA/IRISA"); }
|
||||
CString getShortDescription() const override { return CString("Evaluates i/o jittering and outputs values to log manager"); }
|
||||
|
||||
CString getDetailedDescription() const override
|
||||
{
|
||||
return CString("This box evaluates i/o jittering comparing input chunk' start and end time against current clock time");
|
||||
}
|
||||
|
||||
CString getCategory() const override { return CString("Tools"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-info"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_LatencyEvaluation; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmLatencyEvaluation; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("input", OV_TypeId_EBMLStream);
|
||||
prototype.addSetting("Log level to use", OV_TypeId_LogLevel, "Trace");
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifyInput);
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_LatencyEvaluationDesc)
|
||||
};
|
||||
} // namespace Tools
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "ovpCBoxAlgorithmMouseTracking.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tools {
|
||||
|
||||
|
||||
void motion_event_handler(GtkWidget* widget, GdkEventMotion* event, gpointer data);
|
||||
|
||||
bool CBoxAlgorithmMouseTracking::initialize()
|
||||
{
|
||||
// Feature vector stream encoder
|
||||
m_algo0SignalEncoder.initialize(*this, 0);
|
||||
// Feature vector stream encoder
|
||||
m_algo1SignalEncoder.initialize(*this, 1);
|
||||
|
||||
m_algo0SignalEncoder.getInputMatrix().setReferenceTarget(m_absoluteCoordinateBuffer);
|
||||
m_algo1SignalEncoder.getInputMatrix().setReferenceTarget(m_relativeCoordinateBuffer);
|
||||
|
||||
// Allocates coordinates Matrix
|
||||
m_absoluteCoordinateBuffer = new CMatrix();
|
||||
m_relativeCoordinateBuffer = new CMatrix();
|
||||
|
||||
// Retrieves settings
|
||||
m_sampling = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
m_nGeneratedEpochSample = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
|
||||
m_nSentSample = 0;
|
||||
m_MouseX = 0;
|
||||
m_MouseY = 0;
|
||||
m_prevX = 0;
|
||||
m_prevY = 0;
|
||||
|
||||
// Creates empty window to get mouse position
|
||||
m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
gtk_widget_add_events(m_window, GDK_POINTER_MOTION_MASK);
|
||||
gtk_window_maximize(GTK_WINDOW(m_window));
|
||||
gtk_widget_show_all(m_window);
|
||||
|
||||
g_signal_connect(m_window, "motion-notify-event", G_CALLBACK(motion_event_handler), this);
|
||||
|
||||
m_headerSent = false;
|
||||
|
||||
m_algo0SignalEncoder.getInputSamplingRate() = m_sampling;
|
||||
m_algo1SignalEncoder.getInputSamplingRate() = m_sampling;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmMouseTracking::uninitialize()
|
||||
{
|
||||
m_algo0SignalEncoder.uninitialize();
|
||||
m_algo1SignalEncoder.uninitialize();
|
||||
|
||||
delete m_absoluteCoordinateBuffer;
|
||||
m_absoluteCoordinateBuffer = nullptr;
|
||||
|
||||
delete m_relativeCoordinateBuffer;
|
||||
m_relativeCoordinateBuffer = nullptr;
|
||||
|
||||
gtk_widget_destroy(m_window);
|
||||
m_window = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
|
||||
bool CBoxAlgorithmMouseTracking::processClock(Kernel::CMessageClock& /*msg*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
|
||||
uint64_t CBoxAlgorithmMouseTracking::getClockFrequency()
|
||||
{
|
||||
// Intentional parameter swap to get the frequency
|
||||
m_clockFrequency = CTime(m_nGeneratedEpochSample, m_sampling).time();
|
||||
|
||||
return m_clockFrequency;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithmMouseTracking::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
//Send header and initialize Matrix
|
||||
if (!m_headerSent)
|
||||
{
|
||||
m_absoluteCoordinateBuffer->resize(2, m_nGeneratedEpochSample);
|
||||
m_absoluteCoordinateBuffer->setDimensionLabel(0, 0, "x");
|
||||
m_absoluteCoordinateBuffer->setDimensionLabel(0, 1, "y");
|
||||
|
||||
m_relativeCoordinateBuffer->resize(2, m_nGeneratedEpochSample);
|
||||
m_relativeCoordinateBuffer->setDimensionLabel(0, 0, "x");
|
||||
m_relativeCoordinateBuffer->setDimensionLabel(0, 1, "y");
|
||||
|
||||
|
||||
m_algo0SignalEncoder.encodeHeader();
|
||||
m_algo1SignalEncoder.encodeHeader();
|
||||
|
||||
m_headerSent = true;
|
||||
|
||||
boxContext.markOutputAsReadyToSend(0, 0, 0);
|
||||
boxContext.markOutputAsReadyToSend(1, 0, 0);
|
||||
}
|
||||
else //Do the process and send coordinates to output
|
||||
{
|
||||
const size_t nSentSample = m_nSentSample;
|
||||
|
||||
|
||||
for (size_t i = 0; i < m_nGeneratedEpochSample; ++i)
|
||||
{
|
||||
m_absoluteCoordinateBuffer->getBuffer()[0 * m_nGeneratedEpochSample + i] = m_MouseX;
|
||||
m_absoluteCoordinateBuffer->getBuffer()[1 * m_nGeneratedEpochSample + i] = m_MouseY;
|
||||
|
||||
m_relativeCoordinateBuffer->getBuffer()[0 * m_nGeneratedEpochSample + i] = m_MouseX - m_prevX;
|
||||
m_relativeCoordinateBuffer->getBuffer()[1 * m_nGeneratedEpochSample + i] = m_MouseY - m_prevY;
|
||||
}
|
||||
|
||||
|
||||
m_prevX = m_MouseX;
|
||||
m_prevY = m_MouseY;
|
||||
|
||||
m_nSentSample += m_nGeneratedEpochSample;
|
||||
|
||||
const uint64_t tStart = CTime(m_sampling, nSentSample).time();
|
||||
const uint64_t tEnd = CTime(m_sampling, m_nSentSample).time();
|
||||
|
||||
m_algo0SignalEncoder.encodeBuffer();
|
||||
m_algo1SignalEncoder.encodeBuffer();
|
||||
|
||||
boxContext.markOutputAsReadyToSend(0, tStart, tEnd);
|
||||
boxContext.markOutputAsReadyToSend(1, tStart, tEnd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// CALLBACK
|
||||
// Get mouse position
|
||||
void motion_event_handler(GtkWidget* /*widget*/, GdkEventMotion* event, gpointer data)
|
||||
{
|
||||
CBoxAlgorithmMouseTracking* box = static_cast<CBoxAlgorithmMouseTracking*>(data);
|
||||
box->m_MouseX = double(event->x);
|
||||
box->m_MouseY = double(event->y);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace Tools
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tools {
|
||||
/**
|
||||
* \class CBoxAlgorithmMouseTracking
|
||||
* \author Alison Cellard (Inria)
|
||||
* \date Mon Mar 10 15:07:21 2014
|
||||
* \brief The class CBoxAlgorithmMouseTracking describes the box Mouse tracking.
|
||||
*
|
||||
*/
|
||||
class CBoxAlgorithmMouseTracking final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
// CBoxAlgorithmMouseTracking();
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
|
||||
bool processClock(Kernel::CMessageClock& msg) override;
|
||||
uint64_t getClockFrequency() override;
|
||||
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_MouseTracking)
|
||||
|
||||
protected:
|
||||
// Feature vector stream encoder
|
||||
Toolkit::TSignalEncoder<CBoxAlgorithmMouseTracking> m_algo0SignalEncoder;
|
||||
// Feature vector stream encoder
|
||||
Toolkit::TSignalEncoder<CBoxAlgorithmMouseTracking> m_algo1SignalEncoder;
|
||||
|
||||
// To check if the header was sent or not
|
||||
bool m_headerSent = false;
|
||||
|
||||
// Requested Sampling frequency
|
||||
size_t m_sampling = 0;
|
||||
// Process clock frequency
|
||||
uint64_t m_clockFrequency = 0;
|
||||
|
||||
// Length of output chunks
|
||||
size_t m_nGeneratedEpochSample = 0;
|
||||
// Absolute coordinates of the mouse pointer, that is, relative to the window in fullscreen
|
||||
CMatrix* m_absoluteCoordinateBuffer = nullptr;
|
||||
// Relative coordinates of the mouse pointer, the coordinates is relative to the previous point
|
||||
CMatrix* m_relativeCoordinateBuffer = nullptr;
|
||||
|
||||
size_t m_nSentSample = 0;
|
||||
|
||||
// Gtk window to track mouse position
|
||||
GtkWidget* m_window = nullptr;
|
||||
|
||||
// X coordinate from the previous position (in pixel, reference is upper left corner of window)
|
||||
double m_prevX = 0;
|
||||
// Y coordinate from the previous position (in pixel, reference is upper left corner of window)
|
||||
double m_prevY = 0;
|
||||
|
||||
|
||||
public:
|
||||
// X coordinate of mouse current position
|
||||
double m_MouseX = 0;
|
||||
// Y coordinate of mouse current position
|
||||
double m_MouseY = 0;
|
||||
};
|
||||
|
||||
|
||||
class CBoxAlgorithmMouseTrackingListener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
bool onSettingValueChanged(Kernel::IBox& /*box*/, const size_t /*index*/) override { return true; }
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \class CBoxAlgorithmMouseTrackingDesc
|
||||
* \author Alison Cellard (Inria)
|
||||
* \date Mon Mar 10 15:07:21 2014
|
||||
* \brief Descriptor of the box Mouse tracking.
|
||||
*
|
||||
*/
|
||||
class CBoxAlgorithmMouseTrackingDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Mouse Tracking"); }
|
||||
CString getAuthorName() const override { return CString("Alison Cellard"); }
|
||||
CString getAuthorCompanyName() const override { return CString("Inria"); }
|
||||
CString getShortDescription() const override { return CString("Track mouse position within the screen"); }
|
||||
|
||||
CString getDetailedDescription() const override { return CString("Return absolute and relative to the previous one mouse position"); }
|
||||
|
||||
CString getCategory() const override { return CString("Tools"); }
|
||||
CString getVersion() const override { return CString("1"); }
|
||||
CString getStockItemName() const override { return CString("gtk-index"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_MouseTracking; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmMouseTracking; }
|
||||
|
||||
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmMouseTrackingListener; }
|
||||
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addOutput("Absolute coordinate",OV_TypeId_Signal);
|
||||
prototype.addOutput("Previous relative coordinate",OV_TypeId_Signal);
|
||||
|
||||
prototype.addSetting("Sampling Frequency",OV_TypeId_Integer, "16");
|
||||
prototype.addSetting("Generated epoch sample count",OV_TypeId_Integer, "1");
|
||||
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_MouseTrackingDesc)
|
||||
};
|
||||
} // namespace Tools
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
|
||||
#endif
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
// Boxes
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#define OVP_ClassId_BoxAlgorithm_LatencyEvaluation OpenViBE::CIdentifier(0x0AD11EC1, 0x7EF3690B)
|
||||
#define OVP_ClassId_BoxAlgorithm_LatencyEvaluationDesc OpenViBE::CIdentifier(0x5DB56A54, 0x5380262B)
|
||||
#define OVP_ClassId_BoxAlgorithm_MouseTracking OpenViBE::CIdentifier(0x1E386EE5, 0x203E13C6)
|
||||
#define OVP_ClassId_BoxAlgorithm_MouseTrackingDesc OpenViBE::CIdentifier(0x7A31C11B, 0xF522262E)
|
||||
#define OVP_ClassId_BoxAlgorithm_KeypressEmulator OpenViBE::CIdentifier(0x38503532, 0x19494145)
|
||||
#define OVP_ClassId_BoxAlgorithm_KeypressEmulatorDesc OpenViBE::CIdentifier(0x59286224, 0x99423852)
|
||||
|
||||
// Global defines
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#ifdef TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
#include "ovp_global_defines.h"
|
||||
#endif // TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
|
||||
#define OV_AttributeId_Box_FlagIsUnstable OpenViBE::CIdentifier(0x666FFFFF, 0x666FFFFF)
|
||||
|
||||
#define OVP_TypeId_Keypress_Key OpenViBE::CIdentifier(0x23E525F9, 0x005F187D)
|
||||
#define OVP_TypeId_Keypress_Modifier OpenViBE::CIdentifier(0x0C4F4585, 0x78B246AC)
|
||||
#define OVP_TypeId_Keypress_Modifier_None OpenViBE::CIdentifier(0x5A70497E, 0x52F57199)
|
||||
#define OVP_TypeId_Keypress_Modifier_Shift OpenViBE::CIdentifier(0x47534AA6, 0x138A1130)
|
||||
#define OVP_TypeId_Keypress_Modifier_Control OpenViBE::CIdentifier(0x67C6455F, 0x08E6134D)
|
||||
#define OVP_TypeId_Keypress_Modifier_Alt OpenViBE::CIdentifier(0x77577AEA, 0x74CD7E3E)
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#include "ovp_defines.h"
|
||||
|
||||
//// #include "box-algorithms/ovpCBoxAlgorithmLatencyEvaluation.h"
|
||||
#include "box-algorithms/ovpCBoxAlgorithmMouseTracking.h"
|
||||
#include "box-algorithms/ovpCBoxAlgorithmKeypressEmulator.h"
|
||||
|
||||
#include "openvibe/CIdentifier.hpp"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Tools {
|
||||
|
||||
OVP_Declare_Begin()
|
||||
context.getTypeManager().registerEnumerationEntry(OV_TypeId_BoxAlgorithmFlag, OV_AttributeId_Box_FlagIsUnstable.toString(),
|
||||
OV_AttributeId_Box_FlagIsUnstable.id());
|
||||
// OVP_Declare_New(Tools::CBoxAlgorithmLatencyEvaluationDesc);
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
OVP_Declare_New(CBoxAlgorithmMouseTrackingDesc);
|
||||
#endif
|
||||
|
||||
OVP_Declare_New(CBoxAlgorithmKeypressEmulatorDesc);
|
||||
// @note the following code is a bit long so we've implemented it inside the class
|
||||
CBoxAlgorithmKeypressEmulator::registerEnums(context);
|
||||
|
||||
OVP_Declare_End()
|
||||
|
||||
} // namespace Tools
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
Reference in New Issue
Block a user