init
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
|
||||
# Add all the subdirs as projects of the named branch
|
||||
OV_ADD_PROJECTS("APPLICATIONS_DEVELOPER-TOOLS")
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
|
||||
IF(OV_DISABLE_GTK)
|
||||
MESSAGE(STATUS "Skipping Plugin Inspector, no GTK")
|
||||
RETURN()
|
||||
ENDIF(OV_DISABLE_GTK)
|
||||
|
||||
PROJECT(openvibe-plugin-inspector)
|
||||
|
||||
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
|
||||
SET(PROJECT_VERSION ${OV_GLOBAL_VERSION_STRING})
|
||||
|
||||
FILE(GLOB_RECURSE SRC_FILES src/*.cpp src/*.h src/*.hpp src/*.inl)
|
||||
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_FILES})
|
||||
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY FOLDER ${APP_FOLDER})
|
||||
|
||||
INCLUDE("FindOpenViBE")
|
||||
INCLUDE("FindOpenViBECommon")
|
||||
INCLUDE("FindOpenViBEToolkit")
|
||||
INCLUDE("FindOpenViBEModuleEBML")
|
||||
INCLUDE("FindOpenViBEModuleSystem")
|
||||
INCLUDE("FindThirdPartyGTK")
|
||||
|
||||
# ----------------------
|
||||
# Generate launch script
|
||||
# ----------------------
|
||||
OV_INSTALL_LAUNCH_SCRIPT(SCRIPT_PREFIX "${PROJECT_NAME}" EXECUTABLE_NAME "${PROJECT_NAME}")
|
||||
|
||||
# -----------------------------
|
||||
# Install files
|
||||
# -----------------------------
|
||||
INSTALL(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
|
||||
INSTALL(DIRECTORY share/ DESTINATION ${DIST_DATADIR}/openvibe/applications/plugin-inspector)
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
#####################################################################################
|
||||
# OpenViBE application plugin inspector configuration
|
||||
#####################################################################################
|
||||
# Note: The PluginInspector variables based on ${Path_Root} only make sense in dev environment and have been disabled for release
|
||||
Path_Root = ..
|
||||
PluginInspector_DumpGlobalDefinesDirectory = ${Path_Root}
|
||||
PluginInspector_DumpAlgorithmSnapshotDirectory = ${Path_Root}/../documentation/src/algorithm-snapshots
|
||||
PluginInspector_DumpAlgorithmDocTemplateDirectory = ${Path_Root}/../documentation/src/algorithm-doc
|
||||
PluginInspector_DumpBoxAlgorithmSnapshotDirectory = ${Path_Root}/../documentation/src/box-algorithm-snapshots
|
||||
PluginInspector_DumpBoxAlgorithmDocTemplateDirectory = ${Path_Root}/../documentation/src/box-algorithm-doc
|
||||
#PluginInspector_DumpGlobalDefinesDirectory =
|
||||
#PluginInspector_DumpAlgorithmSnapshotDirectory =
|
||||
#PluginInspector_DumpAlgorithmDocTemplateDirectory =
|
||||
#PluginInspector_DumpBoxAlgorithmSnapshotDirectory =
|
||||
#PluginInspector_DumpBoxAlgorithmDocTemplateDirectory =
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
#include "CAlgorithmGlobalDefinesGen.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
|
||||
CAlgorithmGlobalDefinesGen::CAlgorithmGlobalDefinesGen(const Kernel::IKernelContext& ctx, const std::string& filename)
|
||||
: CPluginObjectDescEnum(ctx)
|
||||
{
|
||||
m_usedIDs.clear();
|
||||
|
||||
const std::string fullFilename = filename + "/ovp_global_defines.h";
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Info << "Writing global defines to '" << fullFilename << "\n";
|
||||
|
||||
m_file.open(fullFilename.c_str());
|
||||
|
||||
OV_ERROR_UNLESS_K(m_file.good(), "Error opening '" << fullFilename << "for writing.", Kernel::ErrorType::BadFileRead,)
|
||||
; // Please note the ",)" to simulate "return;"
|
||||
|
||||
m_file << "#pragma once\n\n// This file was automatically generated by Plugin Inspector\n\n";
|
||||
}
|
||||
|
||||
CAlgorithmGlobalDefinesGen::~CAlgorithmGlobalDefinesGen()
|
||||
{
|
||||
if (!m_file.good()) { return; }
|
||||
|
||||
m_file << "\n";
|
||||
m_file.close();
|
||||
}
|
||||
|
||||
void CAlgorithmGlobalDefinesGen::addIdentifier(const std::string& objectName, const CIdentifier& candidate, const std::string& spaces)
|
||||
{
|
||||
if (m_usedIDs.find(candidate) == m_usedIDs.end())
|
||||
{
|
||||
m_usedIDs[candidate] = objectName;
|
||||
m_file << "#define " << objectName << spaces << "CIdentifier" << candidate.str() << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
OV_WARNING_K(" Object '" << objectName << "' has duplicate id " << candidate.str() << " with " << m_usedIDs[candidate]) ;
|
||||
m_file << "#define " << objectName << spaces << "CIdentifier" << candidate.str() << " // Duplicate of " << m_usedIDs[candidate] << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool CAlgorithmGlobalDefinesGen::callback(const Plugins::IPluginObjectDesc& pluginObjectDesc)
|
||||
{
|
||||
OV_ERROR_UNLESS_KRF(m_file.good(), "Cannot use file; Was it opened correctly ?", Kernel::ErrorType::BadProcessing);
|
||||
|
||||
int width = 120;
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Info << " Dumping [" << pluginObjectDesc.getName() << "]\n";
|
||||
|
||||
Kernel::IAlgorithmManager& manager = m_kernelCtx.getAlgorithmManager();
|
||||
const CIdentifier algorithmId = manager.createAlgorithm(pluginObjectDesc.getCreatedClass());
|
||||
OV_ERROR_UNLESS_KRF(algorithmId != CIdentifier::undefined(), " Unable to create algorithm", Kernel::ErrorType::BadProcessing);
|
||||
|
||||
Kernel::IAlgorithmProxy& proxy = manager.getAlgorithm(algorithmId);
|
||||
|
||||
m_file << "// -----------------------------------------------------\n";
|
||||
m_file << "// " << pluginObjectDesc.getName().toASCIIString() << "\n";
|
||||
m_file << "// -----------------------------------------------------\n";
|
||||
m_file << "\n";
|
||||
|
||||
proxy.initialize();
|
||||
|
||||
const auto addIdentifierFromParameters = [&width, &pluginObjectDesc, this](const char* nameStart, const char* nameEnd, const CIdentifier& id,
|
||||
const std::string& toAppend)
|
||||
{
|
||||
std::string defName;
|
||||
defName += nameStart;
|
||||
defName += transform(pluginObjectDesc.getName().toASCIIString(), true);
|
||||
defName += nameEnd;
|
||||
if (!toAppend.empty()) { defName += transform(toAppend, true); }
|
||||
|
||||
std::string spaces;
|
||||
spaces.resize(width - defName.length(), ' ');
|
||||
|
||||
addIdentifier(defName.c_str(), id, spaces.c_str());
|
||||
};
|
||||
|
||||
addIdentifierFromParameters("OVP_GD_ClassId_Algorithm_", "", pluginObjectDesc.getCreatedClassIdentifier(), "");
|
||||
addIdentifierFromParameters("OVP_GD_ClassId_Algorithm_", "Desc", pluginObjectDesc.getCreatedClassIdentifier(), "");
|
||||
|
||||
CIdentifier id = CIdentifier::undefined();
|
||||
while ((id = proxy.getNextInputParameterIdentifier(id)) != CIdentifier::undefined())
|
||||
{
|
||||
addIdentifierFromParameters("OVP_GD_Algorithm_", "_InputParameterId_", id, proxy.getInputParameterName(id).toASCIIString());
|
||||
}
|
||||
|
||||
id = CIdentifier::undefined();
|
||||
while ((id = proxy.getNextOutputParameterIdentifier(id)) != CIdentifier::undefined())
|
||||
{
|
||||
addIdentifierFromParameters("OVP_GD_Algorithm_", "_OutputParameterId_", id, proxy.getOutputParameterName(id).toASCIIString());
|
||||
}
|
||||
|
||||
id = CIdentifier::undefined();
|
||||
while ((id = proxy.getNextInputTriggerIdentifier(id)) != CIdentifier::undefined())
|
||||
{
|
||||
addIdentifierFromParameters("OVP_GD_Algorithm_", "_InputTriggerId_", id, proxy.getInputTriggerName(id).toASCIIString());
|
||||
}
|
||||
|
||||
id = CIdentifier::undefined();
|
||||
while ((id = proxy.getNextOutputTriggerIdentifier(id)) != CIdentifier::undefined())
|
||||
{
|
||||
addIdentifierFromParameters("OVP_GD_Algorithm_", "_OutputTriggerId_", id, proxy.getOutputTriggerName(id).toASCIIString());
|
||||
}
|
||||
|
||||
proxy.uninitialize();
|
||||
|
||||
m_file << "\n";
|
||||
|
||||
manager.releaseAlgorithm(proxy);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "CPluginObjectDescEnum.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
class CAlgorithmGlobalDefinesGen final : public CPluginObjectDescEnum
|
||||
{
|
||||
public:
|
||||
|
||||
CAlgorithmGlobalDefinesGen(const Kernel::IKernelContext& ctx, const std::string& filename);
|
||||
~CAlgorithmGlobalDefinesGen() override;
|
||||
bool callback(const Plugins::IPluginObjectDesc& pluginObjectDesc) override;
|
||||
|
||||
protected:
|
||||
|
||||
std::ofstream m_file;
|
||||
|
||||
std::map<CIdentifier, std::string> m_usedIDs;
|
||||
// Adds the define to m_usedIdentifiers and m_File
|
||||
void addIdentifier(const std::string& objectName, const CIdentifier& candidate, const std::string& spaces);
|
||||
};
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+296
@@ -0,0 +1,296 @@
|
||||
#include "CAlgorithmSnapshotGen.hpp"
|
||||
|
||||
#include <system/ovCTime.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <pango/pango.h>
|
||||
#include <array>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
CAlgorithmSnapshotGen::CAlgorithmSnapshotGen(const Kernel::IKernelContext& ctx, const std::string& snapshotDir, const std::string& docTemplateDir)
|
||||
: CPluginObjectDescEnum(ctx), m_snapshotDir(snapshotDir), m_docTemplateDir(docTemplateDir)
|
||||
{
|
||||
#define GDK_COLOR_SET(c, r, g, b) { c.pixel=0; c.red=r; c.green=g; c.blue=b; }
|
||||
GDK_COLOR_SET(m_colors[EColors::BackgroundPlayerStarted], 32767, 32767, 32767);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBackgroundSelected], 65535, 65535, 49151);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBackgroundMissing], 49151, 32767, 32767);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBackgroundObsolete], 32767, 49151, 49151);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBackground], 65535, 65535, 65535);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBorderSelected], 0, 0, 0);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBorder], 0, 0, 0);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxInputBackground], 65535, 49151, 32767);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxInputBorder], 16383, 16383, 16383);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxOutputBackground], 32767, 65535, 49151);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxOutputBorder], 16383, 16383, 16383);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxSettingBackground], 49151, 32767, 65535);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxSettingBorder], 16383, 16383, 16383);
|
||||
GDK_COLOR_SET(m_colors[EColors::Link], 0, 0, 0);
|
||||
GDK_COLOR_SET(m_colors[EColors::LinkSelected], 49151, 16383, 16383);
|
||||
GDK_COLOR_SET(m_colors[EColors::SelectionArea], 0x3f00, 0x3f00, 0x3f00);
|
||||
GDK_COLOR_SET(m_colors[EColors::SelectionAreaBorder], 0, 0, 0);
|
||||
#undef GDK_COLOR_SET
|
||||
|
||||
m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
m_widget = gtk_drawing_area_new();
|
||||
gtk_container_add(GTK_CONTAINER(m_window), m_widget);
|
||||
gtk_widget_set_size_request(m_widget, 512, 128);
|
||||
gtk_widget_show_all(m_window);
|
||||
gdk_flush();
|
||||
System::Time::sleep(1000);
|
||||
}
|
||||
|
||||
CAlgorithmSnapshotGen::~CAlgorithmSnapshotGen()
|
||||
{
|
||||
std::ofstream file;
|
||||
file.open((m_docTemplateDir + "/Doc_Algorithms.dox").c_str());
|
||||
file << "/**\n * \\page Doc_Algorithms Algorithms list\n\n * Available algorithms :\n";
|
||||
|
||||
size_t level = 0;
|
||||
std::string lastCat;
|
||||
std::vector<std::string> lastSplittedCat;
|
||||
std::sort(m_categories.begin(), m_categories.end());
|
||||
for (const auto& category : m_categories)
|
||||
{
|
||||
std::string cat = category.first;
|
||||
std::string name = category.second;
|
||||
|
||||
if (lastCat != cat)
|
||||
{
|
||||
std::vector<std::string> splittedCat;
|
||||
size_t i = size_t(-1);
|
||||
bool finished = false;
|
||||
while (!finished)
|
||||
{
|
||||
size_t j = cat.find('/', i + 1);
|
||||
if (j == std::string::npos)
|
||||
{
|
||||
j = cat.length();
|
||||
finished = true;
|
||||
}
|
||||
if (j != i + 1)
|
||||
{
|
||||
splittedCat.push_back(cat.substr(i + 1, j - i - 1));
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
level = splittedCat.size();
|
||||
|
||||
auto it1 = lastSplittedCat.size() < splittedCat.size()
|
||||
? std::mismatch(lastSplittedCat.begin(), lastSplittedCat.end(), splittedCat.begin()).second
|
||||
: std::mismatch(splittedCat.begin(), splittedCat.end(), lastSplittedCat.begin()).first;
|
||||
|
||||
for (; it1 != splittedCat.end(); ++it1) { file << " * " << std::string((it1 - splittedCat.begin()) * 3, ' ') << " - " << *it1 << " : \n"; }
|
||||
|
||||
lastCat = cat;
|
||||
lastSplittedCat = splittedCat;
|
||||
}
|
||||
|
||||
file << " * " << std::string(3 * (level + 1), ' ') << " - \\subpage Doc_algorithm_" << transform(cat + "/" + name) << " \"" << name << "\"\n";
|
||||
}
|
||||
|
||||
file << " */\n";
|
||||
file.close();
|
||||
}
|
||||
|
||||
bool CAlgorithmSnapshotGen::callback(const Plugins::IPluginObjectDesc& pod)
|
||||
{
|
||||
const std::string fullName = std::string(pod.getCategory().toASCIIString()) + "/" + pod.getName().toASCIIString();
|
||||
const std::string filename = m_snapshotDir + "/Algorithm_" + transform(fullName);
|
||||
CIdentifier id;
|
||||
if ((id = m_kernelCtx.getAlgorithmManager().createAlgorithm(pod.getCreatedClassIdentifier())) == CIdentifier::undefined())
|
||||
{
|
||||
m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Skipped [" << filename << "] (could not create corresponding algorithm)\n";
|
||||
return true;
|
||||
}
|
||||
Kernel::IAlgorithmProxy& algorithm = m_kernelCtx.getAlgorithmManager().getAlgorithm(id);
|
||||
|
||||
m_kernelCtx.getLogManager() << Kernel::LogLevel_Trace << "Working on [" << filename << "]\n";
|
||||
|
||||
PangoContext* ctx = gtk_widget_get_pango_context(m_widget);
|
||||
PangoLayout* layout = pango_layout_new(ctx);
|
||||
PangoRectangle rectangle;
|
||||
|
||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||
pango_layout_set_text(layout, pod.getName(), -1);
|
||||
pango_layout_get_pixel_extents(layout, nullptr, &rectangle);
|
||||
|
||||
const int marginX = 5;
|
||||
const int marginY = 5;
|
||||
const int circleMargin = 5;
|
||||
const int circleSize = 11;
|
||||
const int circleSpace = 4;
|
||||
|
||||
const int w = rectangle.width + marginX * 2;
|
||||
const int h = rectangle.height + marginY * 2;
|
||||
const int x = 16;
|
||||
const int y = 16;
|
||||
|
||||
gdk_window_invalidate_rect(m_widget->window, nullptr, true);
|
||||
|
||||
while (gtk_events_pending()) { gtk_main_iteration(); }
|
||||
|
||||
GdkGC* drawGC = gdk_gc_new(m_widget->window);
|
||||
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &m_colors[EColors::BoxBackground]);
|
||||
gdk_draw_rectangle(m_widget->window, drawGC, TRUE, x, y, w, h);
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &m_colors[EColors::BoxBorder]);
|
||||
gdk_draw_rectangle(m_widget->window, drawGC, FALSE, x, y, w, h);
|
||||
|
||||
size_t i = 0;
|
||||
while ((id = algorithm.getNextInputParameterIdentifier(id)) != CIdentifier::undefined())
|
||||
{
|
||||
GdkColor color = m_colors[EColors(algorithm.getInputParameter(id)->getType())];
|
||||
|
||||
std::array<GdkPoint, 4> points;
|
||||
points[0].x = circleSize >> 1;
|
||||
points[0].y = circleSize;
|
||||
points[1].x = 0;
|
||||
points[1].y = 0;
|
||||
points[2].x = circleSize - 1;
|
||||
points[2].y = 0;
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
points[j].x += gint(x + circleMargin + i * (circleSpace + circleSize));
|
||||
points[j].y += gint(y - (circleSize >> 1));
|
||||
}
|
||||
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &color);
|
||||
gdk_draw_polygon(m_widget->window, drawGC, TRUE, points.data(), 3);
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &m_colors[EColors::BoxInputBorder]);
|
||||
gdk_draw_polygon(m_widget->window, drawGC, FALSE, points.data(), 3);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while ((id = algorithm.getNextOutputParameterIdentifier(id)) != CIdentifier::undefined())
|
||||
{
|
||||
GdkColor color = m_colors[EColors(algorithm.getOutputParameter(id)->getType())];
|
||||
|
||||
std::array<GdkPoint, 4> points;
|
||||
points[0].x = circleSize >> 1;
|
||||
points[0].y = circleSize;
|
||||
points[1].x = 0;
|
||||
points[1].y = 0;
|
||||
points[2].x = circleSize - 1;
|
||||
points[2].y = 0;
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
points[j].x += gint(x + circleMargin + i * (circleSpace + circleSize));
|
||||
points[j].y += gint(y - (circleSize >> 1) + h);
|
||||
}
|
||||
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &color);
|
||||
gdk_draw_polygon(m_widget->window, drawGC, TRUE, points.data(), 3);
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &m_colors[EColors::BoxOutputBorder]);
|
||||
gdk_draw_polygon(m_widget->window, drawGC, FALSE, points.data(), 3);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
gdk_draw_layout(m_widget->window, m_widget->style->text_gc[GTK_WIDGET_STATE(m_widget)], x + marginX, y + marginY, layout);
|
||||
g_object_unref(layout);
|
||||
g_object_unref(drawGC);
|
||||
|
||||
GdkPixbuf* buf = gdk_pixbuf_get_from_drawable(nullptr, m_widget->window, nullptr, 0, 0, 0, 0, w + 32, h + 32);
|
||||
OV_WARNING_UNLESS_K(gdk_pixbuf_save(buf, (filename+".png").c_str(), "png", nullptr, nullptr), "Failed saving " << (filename+".png"));
|
||||
|
||||
g_object_unref(buf);
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
|
||||
m_categories.push_back(pair < string, string >(pod.getCategory().toASCIIString(), pod.getName().toASCIIString()));
|
||||
|
||||
std::ofstream file;
|
||||
file.open((filename+".dox").toASCIIString());
|
||||
|
||||
file << "/**\n"
|
||||
<< " * \\page Doc_" << filename << " " << fullName.toASCIIString() << "\n"
|
||||
<< " * \\section Doc_" << filename << "_summary Summary\n"
|
||||
<< " * \\image html " << filename << ".png\n *\n"
|
||||
<< " * - Plugin name : " << pod.getName() << "\n"
|
||||
<< " * - Version : " << pod.getVersion() << "\n"
|
||||
<< " * - Author : " << pod.getAuthorName() << "\n"
|
||||
<< " * - Company : " << pod.getAuthorCompanyName() << "\n"
|
||||
<< " * - Short description : " << pod.getShortDescription() << "\n"
|
||||
<< " * - Documentation template generation date : " << __DATE__ << "\n *\n"
|
||||
<< " * \\section Doc_" << filename << "_description Description\n"
|
||||
<< " * " << pod.getDetailedDescription() << " TODO\n *\n";
|
||||
|
||||
file << " * \\section Doc_" << filename << "_inputs Inputs\n"
|
||||
<< " * Number of inputs : " << box.getInputCount() << "\n *\n";
|
||||
|
||||
for (i = 0; i < box.getInputCount(); ++i)
|
||||
{
|
||||
CString name;
|
||||
CIdentifier typeID;
|
||||
box.getInputName(i, name);
|
||||
box.getInputType(i, typeID);
|
||||
file << " * - Input " << i+1 << "\n"
|
||||
<< " * - Name : " << name.toASCIIString() << "\n"
|
||||
<< " * - Type identifier : " << m_kernelCtx.getTypeManager().getTypeName(typeID).toASCIIString() << " " << typeID.str() << "\n"
|
||||
<< " * - Description : TODO\n *\n";
|
||||
}
|
||||
|
||||
file << " * \\section Doc_" << filename << "_outputs Outputs\n"
|
||||
<< " * Number of outputs : " << box.getOutputCount() << "\n *\n";
|
||||
|
||||
for (i = 0; i < box.getOutputCount(); ++i)
|
||||
{
|
||||
CString name;
|
||||
CIdentifier typeID;
|
||||
box.getOutputName(i, name);
|
||||
box.getOutputType(i, typeID);
|
||||
file
|
||||
<< " * - Output " << i+1 << "\n"
|
||||
<< " * - Name : " << name.toASCIIString() << "\n"
|
||||
<< " * - Type identifier : " << m_kernelCtx.getTypeManager().getTypeName(typeID).toASCIIString() << " " << typeID.str() << "\n"
|
||||
<< " * - Description : TODO\n"
|
||||
<< " *\n";
|
||||
}
|
||||
|
||||
file << " * \\section Doc_" << filename << "_settings Settings\n"
|
||||
<< " * Number of settings : " << box.getSettingCount() << "\n *\n";
|
||||
|
||||
for (i = 0; i < box.getSettingCount(); ++i)
|
||||
{
|
||||
CString name;
|
||||
CIdentifier typeID;
|
||||
CString defaultValue;
|
||||
box.getSettingName(i, name);
|
||||
box.getSettingType(i, typeID);
|
||||
box.getSettingDefaultValue(i, defaultValue);
|
||||
file
|
||||
<< " * - Setting " << i+1 << "\n"
|
||||
<< " * - Name : " << name.toASCIIString() << "\n"
|
||||
<< " * - Type identifier : " << m_kernelCtx.getTypeManager().getTypeName(typeID).toASCIIString() << " " << typeID.str() << "\n"
|
||||
<< " * - Default value : " << defaultValue.toASCIIString() << "\n"
|
||||
<< " * - Description : TODO\n *\n";
|
||||
}
|
||||
|
||||
file << " * \\section Doc_" << filename << "_examples Examples\n * TODO\n *\n"
|
||||
<< " * \\section Doc_" << filename << "_misc Miscellaneous\n * TODO\n */";
|
||||
|
||||
file.close();
|
||||
|
||||
#endif
|
||||
|
||||
m_kernelCtx.getAlgorithmManager().releaseAlgorithm(algorithm);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "CPluginObjectDescEnum.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
class CAlgorithmSnapshotGen final : public CPluginObjectDescEnum
|
||||
{
|
||||
public:
|
||||
|
||||
CAlgorithmSnapshotGen(const Kernel::IKernelContext& ctx, const std::string& snapshotDir, const std::string& docTemplateDir);
|
||||
~CAlgorithmSnapshotGen() override;
|
||||
bool callback(const Plugins::IPluginObjectDesc& pod) override;
|
||||
|
||||
protected:
|
||||
|
||||
std::string m_snapshotDir;
|
||||
std::string m_docTemplateDir;
|
||||
std::vector<std::pair<std::string, std::string>> m_categories;
|
||||
std::map<EColors, GdkColor> m_colors;
|
||||
GtkWidget* m_window = nullptr;
|
||||
GtkWidget* m_widget = nullptr;
|
||||
};
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#include "CBoxAlgorithmDumper.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
CBoxAlgorithmDumper::CBoxAlgorithmDumper(const Kernel::IKernelContext& ctx, const std::string& outFile)
|
||||
: CPluginObjectDescEnum(ctx)
|
||||
{
|
||||
if (outFile.empty()) { m_writeToFile = false; }
|
||||
if (m_writeToFile) { m_file.open(outFile.c_str()); }
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
bool CBoxAlgorithmDumper::callback(const Plugins::IPluginObjectDesc& pluginObjectDesc)
|
||||
{
|
||||
const CIdentifier boxID = pluginObjectDesc.getCreatedClassIdentifier();
|
||||
(m_writeToFile ? m_file : std::cout) << "BoxAlgorithm " << transform(pluginObjectDesc.getName().toASCIIString()) << " " << boxID.str() << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Dumps all registered box algorithms to a text file or cout. The intended use case
|
||||
// is to check the current scenarios to see if all boxes have at least one
|
||||
// scenario where it is used. n.b. The checking was done by a shell script in
|
||||
//
|
||||
// test/check-scenario-coverage.sh
|
||||
//
|
||||
|
||||
#include "CPluginObjectDescEnum.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
class CBoxAlgorithmDumper final : public CPluginObjectDescEnum
|
||||
{
|
||||
public:
|
||||
|
||||
CBoxAlgorithmDumper(const Kernel::IKernelContext& ctx, const std::string& outFile);
|
||||
~CBoxAlgorithmDumper() override { if (m_writeToFile) { m_file.close(); } }
|
||||
bool callback(const Plugins::IPluginObjectDesc& pluginObjectDesc) override;
|
||||
|
||||
protected:
|
||||
std::ofstream m_file;
|
||||
bool m_writeToFile = true; // if false, to console
|
||||
};
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+426
@@ -0,0 +1,426 @@
|
||||
#include "CBoxAlgorithmSnapshotGen.hpp"
|
||||
|
||||
#include <system/ovCTime.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <pango/pango.h>
|
||||
#include <array>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
|
||||
CBoxAlgorithmSnapshotGen::CBoxAlgorithmSnapshotGen(const Kernel::IKernelContext& ctx, const std::string& snapshotDir, const std::string& docTemplateDir)
|
||||
: CPluginObjectDescEnum(ctx), m_snapshotDir(snapshotDir), m_docTemplateDir(docTemplateDir)
|
||||
{
|
||||
m_kernelCtx.getScenarioManager().createScenario(m_scenarioID);
|
||||
m_scenario = &m_kernelCtx.getScenarioManager().getScenario(m_scenarioID);
|
||||
|
||||
#define GDK_COLOR_SET(c, r, g, b) { c.pixel=0; c.red=r; c.green=g; c.blue=b; }
|
||||
GDK_COLOR_SET(m_colors[EColors::BackgroundPlayerStarted], 32767, 32767, 32767);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBackgroundSelected], 65535, 65535, 49151);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBackgroundMissing], 49151, 32767, 32767);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBackgroundDeprecated], 16383, 24575, 24575);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBackground], 65535, 65535, 65535);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBorderSelected], 0, 0, 0);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxBorder], 0, 0, 0);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxInputBackground], 65535, 49151, 32767);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxInputBorder], 16383, 16383, 16383);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxOutputBackground], 32767, 65535, 49151);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxOutputBorder], 16383, 16383, 16383);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxSettingBackground], 49151, 32767, 65535);
|
||||
GDK_COLOR_SET(m_colors[EColors::BoxSettingBorder], 16383, 16383, 16383);
|
||||
GDK_COLOR_SET(m_colors[EColors::Link], 0, 0, 0);
|
||||
GDK_COLOR_SET(m_colors[EColors::LinkSelected], 49151, 16383, 16383);
|
||||
GDK_COLOR_SET(m_colors[EColors::SelectionArea], 0x3f00, 0x3f00, 0x3f00);
|
||||
GDK_COLOR_SET(m_colors[EColors::SelectionAreaBorder], 0, 0, 0);
|
||||
#undef GDK_COLOR_SET
|
||||
|
||||
m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
m_widget = gtk_drawing_area_new();
|
||||
gtk_container_add(GTK_CONTAINER(m_window), m_widget);
|
||||
gtk_widget_set_size_request(m_widget, 512, 128);
|
||||
gtk_widget_show_all(m_window);
|
||||
gdk_flush();
|
||||
System::Time::sleep(1000);
|
||||
}
|
||||
|
||||
CBoxAlgorithmSnapshotGen::~CBoxAlgorithmSnapshotGen()
|
||||
{
|
||||
m_kernelCtx.getScenarioManager().releaseScenario(m_scenarioID);
|
||||
|
||||
std::ofstream file;
|
||||
file.open((m_docTemplateDir + "/Doc_BoxAlgorithms.dox").c_str());
|
||||
file << "/**\n * \\page Doc_BoxAlgorithms Box algorithms list\n *\n * Available box algorithms :\n";
|
||||
|
||||
size_t level = 0;
|
||||
std::string lastCat;
|
||||
std::vector<std::string> lastSplittedCat;
|
||||
std::sort(m_categories.begin(), m_categories.end());
|
||||
for (const auto& category : m_categories)
|
||||
{
|
||||
std::string cat = category.first;
|
||||
std::string name = category.second;
|
||||
|
||||
if (lastCat != cat)
|
||||
{
|
||||
std::vector<std::string> splittedCat;
|
||||
size_t i = size_t(-1);
|
||||
bool finished = false;
|
||||
while (!finished)
|
||||
{
|
||||
size_t j = cat.find('/', i + 1);
|
||||
if (j == std::string::npos)
|
||||
{
|
||||
j = cat.length();
|
||||
finished = true;
|
||||
}
|
||||
if (j != i + 1)
|
||||
{
|
||||
splittedCat.push_back(cat.substr(i + 1, j - i - 1));
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
level = splittedCat.size();
|
||||
// @FIXME C++14 : auto it1 = std::mismatch(lastSplittedCat.begin(), lastSplittedCat.end(), splittedCat.begin(), splittedCat.end()).second;
|
||||
auto it1 = lastSplittedCat.size() < splittedCat.size()
|
||||
? std::mismatch(lastSplittedCat.begin(), lastSplittedCat.end(), splittedCat.begin()).second
|
||||
: std::mismatch(splittedCat.begin(), splittedCat.end(), lastSplittedCat.begin()).first;
|
||||
|
||||
for (; it1 != splittedCat.end(); ++it1) { file << " * " << std::string((it1 - splittedCat.begin()) * 3, ' ') << " - " << *it1 << " : \n"; }
|
||||
|
||||
lastCat = cat;
|
||||
lastSplittedCat = splittedCat;
|
||||
}
|
||||
|
||||
file << " * " << std::string(3 * level, ' ') << " - \\subpage Doc_BoxAlgorithm_" << transform(name) << " \"" << name << "\"\n";
|
||||
}
|
||||
|
||||
file << " */\n";
|
||||
file.close();
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmSnapshotGen::callback(const Plugins::IPluginObjectDesc& pod)
|
||||
{
|
||||
//string fullName = string(rPluginObjectDesc.getCategory().toASCIIString()) + "/" + string(rPluginObjectDesc.getName().toASCIIString());
|
||||
std::string filename = "BoxAlgorithm_" + transform(pod.getName().toASCIIString());
|
||||
CIdentifier boxID;
|
||||
if (!m_scenario->addBox(boxID, pod.getCreatedClassIdentifier(), CIdentifier::undefined()))
|
||||
{
|
||||
OV_WARNING_K("Skipped [" << filename << "] (could not create corresponding box)");
|
||||
return true;
|
||||
}
|
||||
Kernel::IBox& box = *m_scenario->getBoxDetails(boxID);
|
||||
getLogManager() << Kernel::LogLevel_Trace << "Working on [" << filename << "]\n";
|
||||
|
||||
PangoContext* ctx = gtk_widget_get_pango_context(m_widget);
|
||||
PangoLayout* layout = pango_layout_new(ctx);
|
||||
PangoRectangle rectangle;
|
||||
|
||||
pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
|
||||
pango_layout_set_text(layout, pod.getName(), -1);
|
||||
pango_layout_get_pixel_extents(layout, nullptr, &rectangle);
|
||||
|
||||
const int marginX = 5;
|
||||
const int marginY = 5;
|
||||
const int circleSize = 11;
|
||||
const int circleSpace = 4;
|
||||
|
||||
int w = rectangle.width + marginX * 2;
|
||||
int h = rectangle.height + marginY * 2;
|
||||
int x = 16;
|
||||
int y = 16;
|
||||
|
||||
gdk_window_invalidate_rect(m_widget->window, nullptr, true);
|
||||
|
||||
while (gtk_events_pending()) { gtk_main_iteration(); }
|
||||
|
||||
GdkGC* drawGC = gdk_gc_new(m_widget->window);
|
||||
|
||||
bool deprecated = m_kernelCtx.getPluginManager().isPluginObjectFlaggedAsDeprecated(box.getAlgorithmClassIdentifier());
|
||||
if (deprecated) { gdk_gc_set_rgb_fg_color(drawGC, &m_colors[EColors::BoxBackgroundDeprecated]); }
|
||||
else { gdk_gc_set_rgb_fg_color(drawGC, &m_colors[EColors::BoxBackground]); }
|
||||
|
||||
gdkDrawRoundedRectangle(m_widget->window, drawGC, TRUE, x, y, w, h);
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &m_colors[EColors::BoxBorder]);
|
||||
gdkDrawRoundedRectangle(m_widget->window, drawGC, FALSE, x, y, w, h);
|
||||
|
||||
int offset = int(w - box.getInputCount() * (circleSpace + circleSize) + circleSize / 2) / 2;
|
||||
for (size_t i = 0; i < box.getInputCount(); ++i)
|
||||
{
|
||||
CIdentifier id;
|
||||
box.getInputType(i, id);
|
||||
GdkColor color = colorFromIdentifier(id);
|
||||
|
||||
std::array<GdkPoint, 4> points;
|
||||
points[0].x = circleSize >> 1;
|
||||
points[0].y = circleSize;
|
||||
points[1].x = 0;
|
||||
points[1].y = 0;
|
||||
points[2].x = circleSize - 1;
|
||||
points[2].y = 0;
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
{
|
||||
points[j].x += gint(x + i * (circleSpace + circleSize) + offset);
|
||||
points[j].y += gint(y - (circleSize >> 1));
|
||||
}
|
||||
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &color);
|
||||
gdk_draw_polygon(m_widget->window, drawGC, TRUE, points.data(), 3);
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &m_colors[EColors::BoxInputBorder]);
|
||||
gdk_draw_polygon(m_widget->window, drawGC, FALSE, points.data(), 3);
|
||||
}
|
||||
|
||||
offset = int(w - box.getOutputCount() * (circleSpace + circleSize) + circleSize / 2) / 2;
|
||||
for (size_t i = 0; i < box.getOutputCount(); ++i)
|
||||
{
|
||||
CIdentifier id;
|
||||
box.getOutputType(i, id);
|
||||
GdkColor color = colorFromIdentifier(id);
|
||||
|
||||
std::array<GdkPoint, 4> points;
|
||||
points[0].x = circleSize >> 1;
|
||||
points[0].y = circleSize;
|
||||
points[1].x = 0;
|
||||
points[1].y = 0;
|
||||
points[2].x = circleSize - 1;
|
||||
points[2].y = 0;
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
points[j].x += gint(x + i * (circleSpace + circleSize) + offset);
|
||||
points[j].y += gint(y - (circleSize >> 1) + h);
|
||||
}
|
||||
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &color);
|
||||
gdk_draw_polygon(m_widget->window, drawGC, TRUE, points.data(), 3);
|
||||
gdk_gc_set_rgb_fg_color(drawGC, &m_colors[EColors::BoxOutputBorder]);
|
||||
gdk_draw_polygon(m_widget->window, drawGC, FALSE, points.data(), 3);
|
||||
}
|
||||
|
||||
gdk_draw_layout(m_widget->window, m_widget->style->text_gc[GTK_WIDGET_STATE(m_widget)], x + marginX, y + marginY, layout);
|
||||
g_object_unref(layout);
|
||||
g_object_unref(drawGC);
|
||||
|
||||
GdkPixbuf* buf = gdk_pixbuf_get_from_drawable(nullptr, m_widget->window, nullptr, 0, 0, 0, 0, w + 32, h + 32);
|
||||
gdk_pixbuf_save(buf, (m_snapshotDir + "/Doc_" + filename + ".png").c_str(), "png", nullptr, nullptr);
|
||||
|
||||
g_object_unref(buf);
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
m_categories.push_back(std::pair<std::string, std::string>(pod.getCategory().toASCIIString(), pod.getName().toASCIIString()));
|
||||
|
||||
std::ofstream fileSkeleton;
|
||||
std::ofstream filePart;
|
||||
fileSkeleton.open((m_docTemplateDir + "/Doc_" + filename + ".dox-skeleton").c_str());
|
||||
filePart.open((m_docTemplateDir + "/Doc_" + filename + ".dox-part-skeleton").c_str());
|
||||
|
||||
fileSkeleton << "/**\n"
|
||||
<< " * \\page Doc_" << filename << " " << pod.getName() << "\n"
|
||||
<< " * \\section Doc_" << filename << "_Summary Summary\n"
|
||||
<< " * \\image html Doc_" << filename << ".png\n"
|
||||
<< " *\n"
|
||||
<< " * - Plugin name : " << pod.getName() << "\n"
|
||||
<< " * - Version : " << pod.getVersion() << "\n"
|
||||
<< " * - Author : " << pod.getAuthorName() << "\n"
|
||||
<< " * - Company : " << pod.getAuthorCompanyName() << "\n"
|
||||
<< " * - Short description : " << pod.getShortDescription() << "\n"
|
||||
<< " * - Documentation template generation date : " << __DATE__ << "\n";
|
||||
|
||||
bool deprectated = m_kernelCtx.getPluginManager().isPluginObjectFlaggedAsDeprecated(pod.getCreatedClassIdentifier());
|
||||
if (deprectated)
|
||||
{
|
||||
fileSkeleton << " * - <b>WARNING : this box has been marked as DEPRECATED by the developer.</b>\n"
|
||||
<< " * It will be removed soon or later, so you should consider not using this\n"
|
||||
<< " * box and turn to another \"equivalent\" one.\n";
|
||||
}
|
||||
|
||||
// @FIXME CERT
|
||||
#pragma message("WARNING: 'Unstable' block commented out due to Certivibe")
|
||||
|
||||
/*
|
||||
bool isUnstable=m_kernelCtx.getPluginManager().isPluginObjectFlaggedAsUnstable(rPluginObjectDesc.getCreatedClassIdentifier());
|
||||
if(isUnstable)
|
||||
{
|
||||
fileSkeleton
|
||||
<< " * - <b>WARNING : this box has been marked as UNSTABLE by the developer.\n"
|
||||
<< " * It means that its implementation may be incomplete or that the box can only work\n"
|
||||
<< " * under well known conditions. It may possibly crash or cause data loss.\n"
|
||||
<< " * Use this box at your own risk, you've been warned.</b>\n";
|
||||
}
|
||||
*/
|
||||
|
||||
fileSkeleton << " *\n"
|
||||
<< " * \\section Doc_" << filename << "_Description Description\n"
|
||||
<< " * " << pod.getDetailedDescription() << "\n *\n"
|
||||
<< " * @Doc_" << filename << "_Description_Content@\n *\n";
|
||||
|
||||
filePart << "/**\n"
|
||||
<< " * \\page " << filename << " " << pod.getName() << "\n"
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< "Detailed description\n"
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< " * |OVP_DocBegin_" << filename << "_Description|\n"
|
||||
<< " * |OVP_DocEnd_" << filename << "_Description|\n";
|
||||
|
||||
if (box.getInputCount())
|
||||
{
|
||||
fileSkeleton << " * \\section Doc_" << filename << "_Inputs Inputs\n"
|
||||
// << " * Number of inputs : " << box.getInputCount() << "\n"
|
||||
<< " *\n"
|
||||
<< " * @Doc_" << filename << "_Inputs_Content@\n";
|
||||
|
||||
filePart << "__________________________________________________________________\n\n"
|
||||
<< "Inputs description\n"
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< " * |OVP_DocBegin_" << filename << "_Inputs|\n"
|
||||
<< " * |OVP_DocEnd_" << filename << "_Inputs|\n";
|
||||
|
||||
for (size_t i = 0; i < box.getInputCount(); ++i)
|
||||
{
|
||||
CString name;
|
||||
CIdentifier typeID;
|
||||
CString typeName;
|
||||
box.getInputName(i, name);
|
||||
box.getInputType(i, typeID);
|
||||
typeName = m_kernelCtx.getTypeManager().getTypeName(typeID);
|
||||
|
||||
fileSkeleton << " * \\subsection Doc_" << filename << "_Input_" << i + 1 << " " << i + 1 << ". " << name
|
||||
<< "\n * @Doc_" << filename << "_Input" << i + 1 << "_Content@\n *\n * - Type identifier : \\ref Doc_Streams_"
|
||||
<< transform(typeName.toASCIIString()) << " \"" << typeName << "\" <em>" << typeID.str() << "</em>\n *\n";
|
||||
|
||||
filePart << "\n * |OVP_DocBegin_" << filename << "_Input" << i + 1 << "|\n * |OVP_DocEnd_" << filename << "_Input" << i + 1 <<
|
||||
"|\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (box.getOutputCount())
|
||||
{
|
||||
fileSkeleton << " * \\section Doc_" << filename << "_Outputs Outputs\n"
|
||||
// << " * Number of outputs : " << box.getOutputCount() << "\n"
|
||||
<< " *\n * @Doc_" << filename << "_Outputs_Content@\n";
|
||||
|
||||
filePart << "__________________________________________________________________\n\n"
|
||||
<< "Outputs description\n"
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< " * |OVP_DocBegin_" << filename << "_Outputs|\n * |OVP_DocEnd_" << filename << "_Outputs|\n";
|
||||
|
||||
for (size_t i = 0; i < box.getOutputCount(); ++i)
|
||||
{
|
||||
CString name;
|
||||
CIdentifier typeID;
|
||||
CString typeName;
|
||||
box.getOutputName(i, name);
|
||||
box.getOutputType(i, typeID);
|
||||
typeName = m_kernelCtx.getTypeManager().getTypeName(typeID);
|
||||
|
||||
fileSkeleton
|
||||
<< " * \\subsection Doc_" << filename << "_Output_" << i + 1 << " " << i + 1 << ". " << name << "\n"
|
||||
<< " * @Doc_" << filename << "_Output" << i + 1 << "_Content@\n *\n * - Type identifier : \\ref Doc_Streams_"
|
||||
<< transform(typeName.toASCIIString()) << " \"" << typeName << "\" <em>" << typeID.str() << "</em>\n *\n";
|
||||
|
||||
filePart << "\n * |OVP_DocBegin_" << filename << "_Output" << i + 1 << "|\n * |OVP_DocEnd_" << filename << "_Output" << i + 1 <<
|
||||
"|\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (box.getSettingCount())
|
||||
{
|
||||
fileSkeleton
|
||||
<< " * \\section Doc_" << filename << "_Settings Settings\n"
|
||||
// << " * Number of settings : " << box.getSettingCount() << "\n"
|
||||
<< " *\n * @Doc_" << filename << "_Settings_Content@\n";
|
||||
|
||||
filePart
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< "Settings description\n"
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< " * |OVP_DocBegin_" << filename << "_Settings|\n * |OVP_DocEnd_" << filename << "_Settings|\n";
|
||||
|
||||
for (size_t i = 0; i < box.getSettingCount(); ++i)
|
||||
{
|
||||
CString name;
|
||||
CIdentifier typeID;
|
||||
CString defaultValue;
|
||||
CString typeName;
|
||||
box.getSettingName(i, name);
|
||||
box.getSettingType(i, typeID);
|
||||
box.getSettingDefaultValue(i, defaultValue);
|
||||
typeName = m_kernelCtx.getTypeManager().getTypeName(typeID);
|
||||
|
||||
fileSkeleton
|
||||
<< " * \\subsection Doc_" << filename << "_Setting_" << i + 1 << " " << i + 1 << ". " << name << "\n"
|
||||
<< " * @Doc_" << filename << "_Setting" << i + 1 << "_Content@\n"
|
||||
<< " *\n"
|
||||
// "\\ref Doc_Types_" << transform(typeName.toASCIIString())
|
||||
<< " * - Type identifier : <em> " << typeName << " " << typeID.str() << "</em>\n"
|
||||
<< " *\n"
|
||||
<< " * - Default value : [ <em>" << defaultValue << "</em> ]\n"
|
||||
<< " *\n";
|
||||
|
||||
filePart << "\n * |OVP_DocBegin_" << filename << "_Setting" << i + 1 << "|\n * |OVP_DocEnd_" << filename << "_Setting" << i + 1 << "|\n";
|
||||
}
|
||||
}
|
||||
|
||||
// @FIXME CERT
|
||||
#pragma message("WARNING: PluginFunctionality_Visualization block commented out due to Certivibe")
|
||||
|
||||
/*
|
||||
if(rPluginObjectDesc.hasFunctionality(PluginFunctionality_Visualization))
|
||||
{
|
||||
fileSkeleton
|
||||
<< " * \\section Doc_" << filename << "_OnlineVisualizationSettings Online visualization settings\n"
|
||||
<< " *\n"
|
||||
<< " * @Doc_" << filename << "_OnlineVisualizationSettings_Content@\n";
|
||||
|
||||
filePart
|
||||
<< "__________________________________________________________________\n"
|
||||
<< "\n"
|
||||
<< "Online visualization settings\n"
|
||||
<< "__________________________________________________________________\n"
|
||||
<< "\n"
|
||||
<< " * |OVP_DocBegin_" << filename << "_OnlineVisualizationSettings|\n"
|
||||
<< " * |OVP_DocEnd_" << filename << "_OnlineVisualizationSettings|\n";
|
||||
}
|
||||
*/
|
||||
|
||||
fileSkeleton
|
||||
<< " *\n"
|
||||
<< " * \\section Doc_" << filename << "_Examples Examples\n"
|
||||
<< " * @Doc_" << filename << "_Examples_Content@\n"
|
||||
<< " *\n"
|
||||
<< " * \\section Doc_" << filename << "_Miscellaneous Miscellaneous\n"
|
||||
<< " * @Doc_" << filename << "_Miscellaneous_Content@\n"
|
||||
<< " */\n";
|
||||
|
||||
filePart
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< "Examples description\n"
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< " * |OVP_DocBegin_" << filename << "_Examples|\n"
|
||||
<< " * |OVP_DocEnd_" << filename << "_Examples|\n"
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< "Miscellaneous description\n"
|
||||
<< "__________________________________________________________________\n\n"
|
||||
<< " * |OVP_DocBegin_" << filename << "_Miscellaneous|\n"
|
||||
<< " * |OVP_DocEnd_" << filename << "_Miscellaneous|\n"
|
||||
<< " */\n";
|
||||
|
||||
fileSkeleton.close();
|
||||
filePart.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "CPluginObjectDescEnum.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
// ------------------------------------------------------------------------------------------------------------------------------------
|
||||
class CBoxAlgorithmSnapshotGen final : public CPluginObjectDescEnum
|
||||
{
|
||||
public:
|
||||
|
||||
CBoxAlgorithmSnapshotGen(const Kernel::IKernelContext& ctx, const std::string& snapshotDir, const std::string& docTemplateDir);
|
||||
~CBoxAlgorithmSnapshotGen() override;
|
||||
bool callback(const Plugins::IPluginObjectDesc& pod) override;
|
||||
|
||||
protected:
|
||||
|
||||
std::string m_snapshotDir;
|
||||
std::string m_docTemplateDir;
|
||||
std::vector<std::pair<std::string, std::string>> m_categories;
|
||||
std::map<EColors, GdkColor> m_colors;
|
||||
GtkWidget* m_window = nullptr;
|
||||
GtkWidget* m_widget = nullptr;
|
||||
CIdentifier m_scenarioID = CIdentifier::undefined();
|
||||
Kernel::IScenario* m_scenario = nullptr;
|
||||
};
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
#include "CPluginObjectDescEnum.hpp"
|
||||
|
||||
#include <cctype>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
|
||||
bool CPluginObjectDescEnum::enumeratePluginObjectDesc()
|
||||
{
|
||||
CIdentifier id;
|
||||
while ((id = m_kernelCtx.getPluginManager().getNextPluginObjectDescIdentifier(id)) != CIdentifier::undefined())
|
||||
{
|
||||
this->callback(*m_kernelCtx.getPluginManager().getPluginObjectDesc(id));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPluginObjectDescEnum::enumeratePluginObjectDesc(const CIdentifier& parentClassID)
|
||||
{
|
||||
CIdentifier id;
|
||||
while ((id = m_kernelCtx.getPluginManager().getNextPluginObjectDescIdentifier(id, parentClassID)) !=
|
||||
CIdentifier::undefined()) { this->callback(*m_kernelCtx.getPluginManager().getPluginObjectDesc(id)); }
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CPluginObjectDescEnum::transform(const std::string& in, const bool removeSlash)
|
||||
{
|
||||
std::string tmp(in);
|
||||
std::string out;
|
||||
bool lastWasSeparator = true;
|
||||
|
||||
for (std::string::size_type i = 0; i < tmp.length(); ++i)
|
||||
{
|
||||
if (std::isalpha(tmp[i]) || std::isdigit(tmp[i]) || (!removeSlash && tmp[i] == '/'))
|
||||
{
|
||||
if (tmp[i] == '/') { out += "_"; }
|
||||
else { out += lastWasSeparator ? std::toupper(tmp[i]) : tmp[i]; }
|
||||
lastWasSeparator = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//if(!lastWasSeparator) { dst+="_"; }
|
||||
lastWasSeparator = true;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace PluginInspector {
|
||||
class CPluginObjectDescEnum
|
||||
{
|
||||
public:
|
||||
|
||||
explicit CPluginObjectDescEnum(const Kernel::IKernelContext& ctx): m_kernelCtx(ctx) { }
|
||||
virtual ~CPluginObjectDescEnum() { }
|
||||
|
||||
virtual bool enumeratePluginObjectDesc();
|
||||
virtual bool enumeratePluginObjectDesc(const CIdentifier& parentClassID);
|
||||
|
||||
virtual bool callback(const Plugins::IPluginObjectDesc& pod) = 0;
|
||||
|
||||
static std::string transform(const std::string& in, const bool removeSlash = false);
|
||||
|
||||
protected:
|
||||
enum class EColors
|
||||
{
|
||||
BackgroundPlayerStarted,
|
||||
BoxBackground, BoxBackgroundSelected, BoxBackgroundMissing, BoxBackgroundObsolete, BoxBackgroundDeprecated,
|
||||
BoxBorder, BoxBorderSelected,
|
||||
BoxInputBackground, BoxInputBorder,
|
||||
BoxOutputBackground, BoxOutputBorder,
|
||||
BoxSettingBackground, BoxSettingBorder,
|
||||
Link, LinkSelected,
|
||||
SelectionArea, SelectionAreaBorder
|
||||
};
|
||||
|
||||
virtual Kernel::ILogManager& getLogManager() const { return m_kernelCtx.getLogManager(); }
|
||||
virtual Kernel::IErrorManager& getErrorManager() const { return m_kernelCtx.getErrorManager(); }
|
||||
const Kernel::IKernelContext& m_kernelCtx;
|
||||
|
||||
static GdkColor colorFromIdentifier(const CIdentifier& identifier)
|
||||
{
|
||||
GdkColor color;
|
||||
const uint64_t res = identifier.id();
|
||||
|
||||
color.pixel = guint16(0);
|
||||
color.red = guint16(((res) & 0xffff) | 0x8000);
|
||||
color.green = guint16(((res >> 16) & 0xffff) | 0x8000);
|
||||
color.blue = guint16(((res >> 32) & 0xffff) | 0x8000);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
static void gdkDrawRoundedRectangle(GdkDrawable* drawable, GdkGC* gc, const gboolean fill, const gint x, const gint y, const gint w, const gint h,
|
||||
const gint r = 8)
|
||||
{
|
||||
if (fill)
|
||||
{
|
||||
gdk_draw_rectangle(drawable, gc, TRUE, x + r, y, w - 2 * r, h);
|
||||
gdk_draw_rectangle(drawable, gc, TRUE, x, y + r, w, h - 2 * r);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdk_draw_line(drawable, gc, x + r, y, x + w - r, y);
|
||||
gdk_draw_line(drawable, gc, x + r, y + h, x + w - r, y + h);
|
||||
gdk_draw_line(drawable, gc, x, y + r, x, y + h - r);
|
||||
gdk_draw_line(drawable, gc, x + w, y + r, x + w, y + h - r);
|
||||
}
|
||||
gdk_draw_arc(drawable, gc, fill, x + w - r * 2, y, r * 2, r * 2, 0 * 64, 90 * 64);
|
||||
gdk_draw_arc(drawable, gc, fill, x, y, r * 2, r * 2, 90 * 64, 90 * 64);
|
||||
gdk_draw_arc(drawable, gc, fill, x, y + h - r * 2, r * 2, r * 2, 180 * 64, 90 * 64);
|
||||
gdk_draw_arc(drawable, gc, fill, x + w - r * 2, y + h - r * 2, r * 2, r * 2, 270 * 64, 90 * 64);
|
||||
}
|
||||
};
|
||||
} // namespace PluginInspector
|
||||
} // namespace OpenViBE
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
#include "CAlgorithmGlobalDefinesGen.hpp"
|
||||
#include "CBoxAlgorithmDumper.hpp"
|
||||
#include "CBoxAlgorithmSnapshotGen.hpp"
|
||||
#include "CAlgorithmSnapshotGen.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <clocale> // std::setlocale
|
||||
|
||||
typedef struct SConfiguration
|
||||
{
|
||||
SConfiguration() { }
|
||||
|
||||
bool kernelPathOverload = false;
|
||||
bool loadPluginsFromPaths = false;
|
||||
bool dumpPathOverload = false;
|
||||
bool configPathOverload = false;
|
||||
bool listBoxes = false;
|
||||
std::string kernelPath;
|
||||
std::string dumpPath;
|
||||
std::string configPath;
|
||||
std::string listBoxesFile;
|
||||
std::vector<std::string> pluginPaths;
|
||||
} configuration_t;
|
||||
|
||||
|
||||
bool parse_arguments(int argc, char** argv, configuration_t& config)
|
||||
{
|
||||
std::vector<std::string> argValues;
|
||||
|
||||
for (int i = 1; i < argc; ++i) { argValues.push_back(argv[i]); }
|
||||
|
||||
for (auto it = argValues.begin(); it != argValues.end(); ++it)
|
||||
{
|
||||
if (*it == "-h" || *it == "--help")
|
||||
{
|
||||
std::cout << "Usage: " << argv[0] << " [-p <dir1#dir2...>] [-d <dump_path>] [-l boxListFile]" << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
// get a list of folders to load plugins from
|
||||
if (*it == "-p")
|
||||
{
|
||||
if (it + 1 != argValues.end())
|
||||
{
|
||||
std::string pluginDirectories = *++it;
|
||||
|
||||
// split the argument to separate paths, the delimiter is "#"
|
||||
std::stringstream ss(pluginDirectories);
|
||||
std::string item;
|
||||
while (std::getline(ss, item, '#')) { config.pluginPaths.push_back(item); }
|
||||
config.loadPluginsFromPaths = true;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
// Configuration path
|
||||
else if (*it == "-c")
|
||||
{
|
||||
if (it + 1 != argValues.end())
|
||||
{
|
||||
config.configPathOverload = true;
|
||||
config.configPath = *++it;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
// List path
|
||||
else if (*it == "-l")
|
||||
{
|
||||
config.listBoxes = true;
|
||||
if (it + 1 != argValues.end()) { config.listBoxesFile = *++it; }
|
||||
else { config.listBoxesFile = ""; } // to cout
|
||||
}
|
||||
// Kernel path
|
||||
else if (*it == "-k")
|
||||
{
|
||||
if (it + 1 != argValues.end())
|
||||
{
|
||||
config.kernelPathOverload = true;
|
||||
config.kernelPath = *++it;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
// Dump path
|
||||
else if (*it == "-d")
|
||||
{
|
||||
if (it + 1 != argValues.end())
|
||||
{
|
||||
config.dumpPathOverload = true;
|
||||
config.dumpPath = *++it;
|
||||
}
|
||||
else { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
//___________________________________________________________________//
|
||||
// //
|
||||
configuration_t config;
|
||||
|
||||
if (!parse_arguments(argc, argv, config)) { std::cout << "Error parsing arguments" << std::endl; }
|
||||
|
||||
OpenViBE::CKernelLoader loader;
|
||||
|
||||
std::cout << "[ INF ] Created kernel loader, trying to load kernel module" << std::endl;
|
||||
#if defined TARGET_OS_Windows
|
||||
std::string kernelFile = "/openvibe-kernel.dll";
|
||||
#else
|
||||
std::string kernelFile = "/libopenvibe-kernel.so";
|
||||
#endif
|
||||
|
||||
if (config.kernelPathOverload) { kernelFile = config.kernelPath + kernelFile; }
|
||||
else { kernelFile = std::string(OpenViBE::Directories::getLibDir().toASCIIString()) + kernelFile; }
|
||||
|
||||
OpenViBE::CString error;
|
||||
if (!loader.load(OpenViBE::CString(kernelFile.c_str()), &error))
|
||||
{
|
||||
std::cout << "[ FAILED ] Error loading kernel (" << error << ")" << " from [" << kernelFile << "]\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "[ INF ] Kernel module loaded, trying to get kernel descriptor" << std::endl;
|
||||
OpenViBE::Kernel::IKernelDesc* kernelDesc = nullptr;
|
||||
OpenViBE::Kernel::IKernelContext* kernelCtx = nullptr;
|
||||
loader.initialize();
|
||||
loader.getKernelDesc(kernelDesc);
|
||||
if (!kernelDesc) { std::cout << "[ FAILED ] No kernel descriptor" << std::endl; }
|
||||
else
|
||||
{
|
||||
std::cout << "[ INF ] Got kernel descriptor, trying to create kernel" << std::endl;
|
||||
std::string configPath = std::string(OpenViBE::Directories::getDataDir().toASCIIString()) + "/kernel/openvibe.conf";
|
||||
if (config.configPathOverload) { configPath = config.configPath; }
|
||||
kernelCtx = kernelDesc->createKernel("plugin-inspector", OpenViBE::CString(configPath.c_str()));
|
||||
if (!kernelCtx || !kernelCtx->initialize()) { std::cout << "[ FAILED ] No kernel created by kernel descriptor" << std::endl; }
|
||||
else
|
||||
{
|
||||
kernelCtx->getConfigurationManager().addConfigurationFromFile(OpenViBE::CString(configPath.c_str()));
|
||||
kernelCtx->getConfigurationManager().addConfigurationFromFile(
|
||||
OpenViBE::Directories::getDataDir() + "/applications/plugin-inspector/plugin-inspector.conf");
|
||||
OpenViBE::Toolkit::initialize(*kernelCtx);
|
||||
|
||||
OpenViBE::Kernel::IConfigurationManager& configManager = kernelCtx->getConfigurationManager();
|
||||
|
||||
if (config.loadPluginsFromPaths)
|
||||
{
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Loading plugins from specified folders\n";
|
||||
|
||||
std::string pluginPattern;
|
||||
for (const auto& libpath : config.pluginPaths)
|
||||
{
|
||||
// Choose the right pattern for libraries to load depending on the OS
|
||||
#if defined TARGET_OS_Windows
|
||||
pluginPattern = libpath + "/openvibe-plugins-*.dll;";
|
||||
#elif defined TARGET_OS_Linux
|
||||
pluginPattern = libpath + "/libopenvibe-plugins-*.so;"; // + *it + "/lib???.so"
|
||||
#endif
|
||||
kernelCtx->getPluginManager().addPluginsFromFiles(pluginPattern.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Loading plugins as specified by kernel\n";
|
||||
kernelCtx->getPluginManager().addPluginsFromFiles(configManager.expand("${Kernel_Plugins}"));
|
||||
}
|
||||
|
||||
//initialise Gtk before 3D context
|
||||
gtk_init(&argc, &argv);
|
||||
// gtk_rc_parse(Directories::getDataDir() + "/applications/designer/interface.gtkrc");
|
||||
|
||||
// We rely on this with 64bit/gtk 2.24, to roll back gtk_init() sometimes switching
|
||||
// the locale to one where ',' is needed instead of '.' for separators of floats,
|
||||
// causing issues, for example getConfigurationManager.expandAsFloat("0.05") -> 0;
|
||||
// due to implementation by std::stod().
|
||||
std::setlocale(LC_ALL, "C");
|
||||
|
||||
if (configManager.expandAsBoolean("${Kernel_3DVisualizationEnabled}"))
|
||||
{
|
||||
// kernelCtx->getVisualizationManager().initialize3DContext();
|
||||
}
|
||||
|
||||
std::string globalDefinesDir = "";
|
||||
|
||||
std::string algorithmSnapshotDir = "";
|
||||
std::string algorithmDocTemplateDir = "";
|
||||
std::string boxAlgorithmSnapshotDir = "";
|
||||
std::string boxAlgorithmDocTemplateDir = "";
|
||||
|
||||
if (config.dumpPathOverload)
|
||||
{
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Dumping stuff to [" << config.dumpPath << "]\n";
|
||||
algorithmSnapshotDir = config.dumpPath + "/algorithm-snapshots";
|
||||
algorithmDocTemplateDir = config.dumpPath + "/algorithm-doc";
|
||||
boxAlgorithmSnapshotDir = config.dumpPath + "/box-algorithm-snapshots";
|
||||
boxAlgorithmDocTemplateDir = config.dumpPath + "/box-algorithm-doc";
|
||||
globalDefinesDir = config.dumpPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Loading paths from Kernel configuration\n";
|
||||
algorithmSnapshotDir = configManager.expand("${PluginInspector_DumpAlgorithmSnapshotDirectory}");
|
||||
algorithmDocTemplateDir = configManager.expand("${PluginInspector_DumpAlgorithmDocTemplateDirectory}");
|
||||
boxAlgorithmSnapshotDir = configManager.expand("${PluginInspector_DumpBoxAlgorithmSnapshotDirectory}");
|
||||
boxAlgorithmDocTemplateDir = configManager.expand("${PluginInspector_DumpBoxAlgorithmDocTemplateDirectory}");
|
||||
globalDefinesDir = configManager.expand("${PluginInspector_DumpGlobalDefinesDirectory}");
|
||||
}
|
||||
|
||||
if (config.listBoxes)
|
||||
{
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Dumping box identifiers ...\n";
|
||||
OpenViBE::PluginInspector::CBoxAlgorithmDumper boxIDGenerator(*kernelCtx, config.listBoxesFile);
|
||||
boxIDGenerator.enumeratePluginObjectDesc(OV_ClassId_Plugins_BoxAlgorithmDesc);
|
||||
}
|
||||
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Dumping global defines...\n";
|
||||
if (!globalDefinesDir.empty())
|
||||
{
|
||||
OpenViBE::PluginInspector::CAlgorithmGlobalDefinesGen globalDefinesGenerator(*kernelCtx, globalDefinesDir);
|
||||
globalDefinesGenerator.enumeratePluginObjectDesc(OV_ClassId_Plugins_AlgorithmDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Skipped, related PluginInspector tokens are empty in openvibe.conf\n";
|
||||
}
|
||||
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Dumping algorithm snapshots... to [" << algorithmSnapshotDir << "]\n";
|
||||
if (!algorithmSnapshotDir.empty() && !algorithmDocTemplateDir.empty())
|
||||
{
|
||||
OpenViBE::PluginInspector::CAlgorithmSnapshotGen algorithmSnapshotGenerator(*kernelCtx, algorithmSnapshotDir, algorithmDocTemplateDir);
|
||||
algorithmSnapshotGenerator.enumeratePluginObjectDesc(OV_ClassId_Plugins_AlgorithmDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Skipped, related PluginInspector tokens are empty in openvibe.conf\n";
|
||||
}
|
||||
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Dumping box algorithm snapshots...\n";
|
||||
if (!boxAlgorithmSnapshotDir.empty() && !boxAlgorithmDocTemplateDir.empty())
|
||||
{
|
||||
OpenViBE::PluginInspector::CBoxAlgorithmSnapshotGen generator(*kernelCtx, boxAlgorithmSnapshotDir, boxAlgorithmDocTemplateDir);
|
||||
generator.enumeratePluginObjectDesc(OV_ClassId_Plugins_BoxAlgorithmDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Skipped, related PluginInspector tokens are empty in openvibe.conf\n";
|
||||
}
|
||||
|
||||
kernelCtx->getLogManager() << OpenViBE::Kernel::LogLevel_Info << "Application terminated, releasing allocated objects \n";
|
||||
|
||||
OpenViBE::Toolkit::uninitialize(*kernelCtx);
|
||||
|
||||
kernelDesc->releaseKernel(kernelCtx);
|
||||
}
|
||||
}
|
||||
loader.uninitialize();
|
||||
loader.unload();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
#pragma once
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
|
||||
IF(OV_DISABLE_GTK)
|
||||
MESSAGE(STATUS "Skipping Skeleton Generator, no GTK")
|
||||
RETURN()
|
||||
ENDIF(OV_DISABLE_GTK)
|
||||
|
||||
PROJECT(openvibe-skeleton-generator)
|
||||
|
||||
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
|
||||
SET(PROJECT_VERSION ${OV_GLOBAL_VERSION_STRING})
|
||||
|
||||
FILE(GLOB_RECURSE SRC_FILES src/*.cpp src/*.h src/*.inl)
|
||||
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_FILES})
|
||||
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY FOLDER ${APP_FOLDER})
|
||||
|
||||
# ---------------------------------
|
||||
INCLUDE("FindOpenViBE")
|
||||
INCLUDE("FindOpenViBECommon")
|
||||
INCLUDE("FindOpenViBEToolkit")
|
||||
INCLUDE("FindOpenViBEModuleEBML")
|
||||
INCLUDE("FindOpenViBEModuleFS")
|
||||
INCLUDE("FindThirdPartyGTK")
|
||||
INCLUDE("FindThirdPartyBoost")
|
||||
INCLUDE("FindThirdPartyBoost_Thread")
|
||||
INCLUDE("FindThirdPartyBoost_Regex")
|
||||
|
||||
# ----------------------
|
||||
# Generate launch script
|
||||
# ----------------------
|
||||
OV_INSTALL_LAUNCH_SCRIPT(SCRIPT_PREFIX "${PROJECT_NAME}" EXECUTABLE_NAME "${PROJECT_NAME}")
|
||||
|
||||
# -----------------------------
|
||||
# Install files
|
||||
# -----------------------------
|
||||
INSTALL(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
|
||||
INSTALL(DIRECTORY share/ DESTINATION ${DIST_DATADIR}/openvibe/applications/skeleton-generator)
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
#include "ovpCBoxAlgorithm@@ClassName@@.h"
|
||||
|
||||
using namespace OpenViBE;
|
||||
using namespace /*OpenViBE::*/Kernel;
|
||||
using namespace /*OpenViBE::*/Plugins;
|
||||
using namespace /*OpenViBE::Plugins::*/@@Namespace@@;
|
||||
|
||||
bool CBoxAlgorithm@@ClassName@@::initialize()
|
||||
{
|
||||
@@AlgorithmInitialisation@@
|
||||
// If you need to retrieve setting values, use the FSettingValueAutoCast function.
|
||||
// For example :
|
||||
// - CString setting at index 0 in the setting list :
|
||||
// CString sSettingValue = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
// - unsigned int64 setting at index 1 in the setting list :
|
||||
// uint64_t uiSettingValue = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
// - double setting at index 2 in the setting list :
|
||||
// double doubleSettingValue = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
// ...
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithm@@ClassName@@::uninitialize()
|
||||
{
|
||||
@@AlgorithmUninitialisation@@
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
@@ProcessClockCommentIn@@
|
||||
bool CBoxAlgorithm@@ClassName@@::processClock(Kernel::CMessageClock& msg)
|
||||
{
|
||||
// some pre-processing code if needed...
|
||||
|
||||
// ready to process !
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ProcessClockCommentOut@@
|
||||
/*******************************************************************************/
|
||||
|
||||
@@ProcessClockCommentIn@@
|
||||
uint64_t CBoxAlgorithm@@ClassName@@::getClockFrequency()
|
||||
{
|
||||
// Note that the time is coded on a 64 bits unsigned integer, fixed decimal point (32:32)
|
||||
return @@ClockFrequency@@; // the box clock frequency
|
||||
}
|
||||
@@ProcessClockCommentOut@@
|
||||
/*******************************************************************************/
|
||||
|
||||
@@ProcessInputCommentIn@@
|
||||
bool CBoxAlgorithm@@ClassName@@::processInput(const size_t index)
|
||||
{
|
||||
// some pre-processing code if needed...
|
||||
|
||||
// ready to process !
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ProcessInputCommentOut@@
|
||||
/*******************************************************************************/
|
||||
|
||||
|
||||
bool CBoxAlgorithm@@ClassName@@::process()
|
||||
{
|
||||
|
||||
// the static box context describes the box inputs, outputs, settings structures
|
||||
const IBox& staticBoxContext=this->getStaticBoxContext();
|
||||
// the dynamic box context describes the current state of the box inputs and outputs (i.e. the chunks)
|
||||
IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
// here is some useful functions:
|
||||
// - To get input/output/setting count:
|
||||
// staticBoxContext.getInputCount();
|
||||
// staticBoxContext.getOutputCount();
|
||||
|
||||
// - To get the number of chunks currently available on a particular input :
|
||||
// boxContext.getInputChunkCount(input_index)
|
||||
|
||||
// - To send an output chunk :
|
||||
// boxContext.markOutputAsReadyToSend(output_index, chunk_start_time, chunk_end_time);
|
||||
|
||||
|
||||
// A typical process iteration may look like this.
|
||||
// This example only iterate over the first input of type Signal, and output a modified Signal.
|
||||
// thus, the box uses 1 decoder (m_signalDecoder) and 1 encoder (m_signalEncoder)
|
||||
/*
|
||||
IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
//iterate over all chunk on input 0
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
// decode the chunk i
|
||||
m_signalDecoder.decode(i);
|
||||
// the decoder may have decoded 3 different parts : the header, a buffer or the end of stream.
|
||||
if(m_signalDecoder.isHeaderReceived())
|
||||
{
|
||||
// Header received. This happens only once when pressing "play". For example with a StreamedMatrix input, you now know the dimension count, sizes, and labels of the matrix
|
||||
// ... maybe do some process ...
|
||||
|
||||
// Pass the header to the next boxes, by encoding a header on the output 0:
|
||||
m_signalEncoder.encodeHeader(0);
|
||||
// send the output chunk containing the header. The dates are the same as the input chunk:
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i));
|
||||
}
|
||||
if(m_signalDecoder.isBufferReceived())
|
||||
{
|
||||
// Buffer received. For example the signal values
|
||||
// Access to the buffer can be done thanks to :
|
||||
CMatrix* matrix = m_signalDecoder.getOutputMatrix(); // the StreamedMatrix of samples.
|
||||
uint64_t frequency = m_signalDecoder.getOutputSamplingRate(); // the sampling rate of the signal
|
||||
|
||||
// ... do some process on the matrix ...
|
||||
|
||||
// Encode the output buffer :
|
||||
m_signalEncoder.encodeBuffer(0);
|
||||
// and send it to the next boxes :
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i));
|
||||
|
||||
}
|
||||
if(m_signalDecoder.isEndReceived())
|
||||
{
|
||||
// End of stream received. This happens only once when pressing "stop". Just pass it to the next boxes so they receive the message :
|
||||
m_signalEncoder.encodeEnd(0);
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i));
|
||||
}
|
||||
|
||||
// The current input chunk has been processed, and automaticcaly discarded.
|
||||
// you don't need to call "boxContext.markInputAsDeprecated(0, i);"
|
||||
}
|
||||
*/
|
||||
|
||||
// check the official developer documentation webpage for more example and information :
|
||||
|
||||
// Tutorials:
|
||||
// http://openvibe.inria.fr/documentation/#Developer+Documentation
|
||||
// Codec Toolkit page :
|
||||
// http://openvibe.inria.fr/codec-toolkit-references/
|
||||
|
||||
// Feel free to ask experienced developers on the forum (http://openvibe.inria.fr/forum) and IRC (#openvibe on irc.freenode.net).
|
||||
|
||||
return true;
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
#include "ovpCBoxAlgorithm@@ClassName@@.h"
|
||||
|
||||
using namespace OpenViBE;
|
||||
using namespace /*OpenViBE::*/Kernel;
|
||||
using namespace /*OpenViBE::*/Plugins;
|
||||
using namespace /*OpenViBE::Plugins::*/@@Namespace@@;
|
||||
|
||||
bool CBoxAlgorithm@@ClassName@@::initialize()
|
||||
{
|
||||
@@AlgorithmInitialisation@@
|
||||
// If you need to retrieve setting values, use the FSettingValueAutoCast function.
|
||||
// For example :
|
||||
// - CString setting at index 0 in the setting list :
|
||||
// CString sSettingValue = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
// - unsigned int64 setting at index 1 in the setting list :
|
||||
// uint64_t uiSettingValue = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
// - double setting at index 2 in the setting list :
|
||||
// double doubleSettingValue = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
// ...
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithm@@ClassName@@::uninitialize()
|
||||
{
|
||||
@@AlgorithmUninitialisation@@
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
@@ProcessClockCommentIn@@
|
||||
bool CBoxAlgorithm@@ClassName@@::processClock(Kernel::CMessageClock& msg)
|
||||
{
|
||||
// some pre-processing code if needed...
|
||||
|
||||
// ready to process !
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
@@ProcessClockCommentIn@@
|
||||
uint64_t CBoxAlgorithm@@ClassName@@::getClockFrequency()
|
||||
{
|
||||
// Note that the time is coded on a 64 bits unsigned integer, fixed decimal point (32:32)
|
||||
return @@ClockFrequency@@; // the box clock frequency
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
@@ProcessInputCommentIn@@
|
||||
bool CBoxAlgorithm@@ClassName@@::processInput(const size_t /*index*/)
|
||||
{
|
||||
// some pre-processing code if needed...
|
||||
|
||||
// ready to process !
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
/*******************************************************************************/
|
||||
|
||||
bool CBoxAlgorithm@@ClassName@@::process()
|
||||
{
|
||||
|
||||
// the static box context describes the box inputs, outputs, settings structures
|
||||
const IBox& staticBoxCtx = this->getStaticBoxContext();
|
||||
// the dynamic box context describes the current state of the box inputs and outputs (i.e. the chunks)
|
||||
IBoxIO& boxCtx = this->getDynamicBoxContext();
|
||||
|
||||
// here is some useful functions:
|
||||
// - To get input/output/setting count:
|
||||
// staticBoxCtx.getInputCount();
|
||||
// staticBoxCtx.getOutputCount();
|
||||
// staticBoxCtx.getSettingCount();
|
||||
|
||||
// - To get the chunks currently available on a particular input :
|
||||
// boxCtx.getInputChunkCount(input_index)
|
||||
// boxCtx.getInputChunk(input_index, chunk_index)
|
||||
|
||||
// - To get the chunk available on a particular output :
|
||||
// boxCtx.getOutputChunk(output_index)
|
||||
// - To send an output chunk :
|
||||
// boxCtx.markOutputAsReadyToSend(output_index, chunk_start_time, chunk_end_time);
|
||||
|
||||
|
||||
// A typical process iteration may look like this.
|
||||
// This example only iterate over the first input.
|
||||
/*
|
||||
IBoxIO& boxCtx = this->getDynamicBoxContext();
|
||||
|
||||
//iterate over all chunk on input 0
|
||||
for (size_t i = 0; i < boxCtx.getInputChunkCount(0); ++i)
|
||||
{
|
||||
// fill the decoder input with input chunk
|
||||
ip_bufferToDecode = boxCtx.getInputChunk(0, i);
|
||||
// link the encoder output to box output chunk
|
||||
op_buffer = boxCtx.getOutputChunk(0);
|
||||
|
||||
// decode the input chunk
|
||||
m_decoder->process();
|
||||
// the decoder may have decoded 3 different parts : the header, a buffer or the end of stream.
|
||||
// 3 corresponding output triggers may rise.
|
||||
// the decoded block is now in the decoded output (let's say op_pDecodedMatrix)
|
||||
|
||||
if(m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedHeader))
|
||||
{
|
||||
// Header received. This happens only once when pressing "play". For example with a StreamedMatrix input, you now know the dimension count size, and label of the matrix
|
||||
// ... do some process ...
|
||||
|
||||
// Pass the header to the next boxes, by encoding it :
|
||||
m_encoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeHeader);
|
||||
// send the output chunk containing the header :
|
||||
boxCtx.markOutputAsReadyToSend(0, boxCtx.getInputChunkStartTime(0, i), boxCtx.getInputChunkEndTime(0, i));
|
||||
}
|
||||
if(m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedBuffer))
|
||||
{
|
||||
// Buffer received. For example the matrix values
|
||||
// Access to the matrix buffer can be done thanks to :
|
||||
// op_pDecodedMatrix->getBuffer(), which is a one-dimension vector of value.
|
||||
|
||||
// ... do some process ...
|
||||
|
||||
// Encode the output buffer :
|
||||
m_encoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeBuffer);
|
||||
// and send it to the next boxes :
|
||||
boxCtx.markOutputAsReadyToSend(0, boxCtx.getInputChunkStartTime(0, i), boxCtx.getInputChunkEndTime(0, i));
|
||||
|
||||
}
|
||||
if(m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_SignalDecoder_OutputTriggerId_ReceivedEnd))
|
||||
{
|
||||
// End of stream received. This happens only once when pressing "stop". Just pass it to the next boxes so they receive the message :
|
||||
m_encoder->process(OVP_GD_Algorithm_SignalEncoder_InputTriggerId_EncodeEnd);
|
||||
boxCtx.markOutputAsReadyToSend(0, boxCtx.getInputChunkStartTime(0, i), boxCtx.getInputChunkEndTime(0, i));
|
||||
}
|
||||
|
||||
// The current input chunk has been processed, let's discard it :
|
||||
boxCtx.markInputAsDeprecated(0, i);
|
||||
}
|
||||
*/
|
||||
|
||||
// check the official developer documentation webpage for more example and information :
|
||||
// http://openvibe.inria.fr/documentation/#Developer+Documentation
|
||||
// Feel free to ask experienced developers on the forum (http://openvibe.inria.fr/forum) and IRC (#openvibe on irc.freenode.net).
|
||||
|
||||
return true;
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file CBoxAlgorithm@@ClassName@@.h
|
||||
/// \brief Classes of the Box @@BoxName@@.
|
||||
/// \author @@Author@@ (@@Company@@).
|
||||
/// \version @@Version@@.
|
||||
/// \date @@Date@@.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
//You may have to change this path to match your folder organisation
|
||||
#include "ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
// The unique identifiers for the box and its descriptor.
|
||||
// Identifier are randomly chosen by the skeleton-generator.
|
||||
#define OVP_ClassId_BoxAlgorithm_@@ClassName@@ OpenViBE::CIdentifier@@RandomIdentifierClass@@
|
||||
#define OVP_ClassId_BoxAlgorithm_@@ClassName@@Desc OpenViBE::CIdentifier@@RandomIdentifierDescriptor@@
|
||||
#define OV_AttributeId_Box_FlagIsUnstable OpenViBE::CIdentifier(0x666FFFFF, 0x666FFFFF)
|
||||
|
||||
namespace OpenViBE
|
||||
{
|
||||
namespace Plugins
|
||||
{
|
||||
namespace @@Namespace@@
|
||||
{
|
||||
/// <summary> The class CBoxAlgorithm@@ClassName@@ describes the box @@BoxName@@. </summary>
|
||||
class CBoxAlgorithm@@ClassName@@ final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
|
||||
//Here is the different process callbacks possible
|
||||
// - On clock ticks :
|
||||
@@ProcessClockComment@@bool processClock(Kernel::CMessageClock& msg) override;
|
||||
// - On new input received (the most common behaviour for signal processing) :
|
||||
@@ProcessInputComment@@bool processInput(const size_t index) override;
|
||||
|
||||
// If you want to use processClock, you must provide the clock frequency.
|
||||
@@ProcessClockComment@@uint64_t getClockFrequency() override;
|
||||
|
||||
bool process() override;
|
||||
|
||||
// As we do with any class in openvibe, we use the macro below to associate this box to an unique identifier.
|
||||
// The inheritance information is also made available, as we provide the superclass Toolkit::TBoxAlgorithm < IBoxAlgorithm >
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_@@ClassName@@)
|
||||
|
||||
protected:
|
||||
@@Algorithms@@
|
||||
};
|
||||
|
||||
|
||||
// If you need to implement a box Listener, here is a sekeleton for you.
|
||||
// Use only the callbacks you need.
|
||||
// For example, if your box has a variable number of input, but all of them must be stimulation inputs.
|
||||
// The following listener callback will ensure that any newly added input is stimulations :
|
||||
/*
|
||||
bool onInputAdded(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
box.setInputType(index, OV_TypeId_Stimulations);
|
||||
};
|
||||
*/
|
||||
|
||||
@@BoxListenerCommentIn@@
|
||||
// The box listener can be used to call specific callbacks whenever the box structure changes : input added, name changed, etc.
|
||||
// Please uncomment below the callbacks you want to use.
|
||||
/// <summary> Listener of the box @@BoxName@@. </summary>
|
||||
class CBoxAlgorithm@@ClassName@@Listener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
|
||||
//bool onInitialized(Kernel::IBox& box) override { return true; };
|
||||
//bool onNameChanged(Kernel::IBox& box) override { return true; };
|
||||
@@BoxListenerOnInputConnectedComment@@bool onInputConnected(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnInputDisconnectedComment@@bool onInputDisconnected(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnInputAddedComment@@bool onInputAdded(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnInputRemovedComment@@bool onInputRemoved(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnInputTypeChangedComment@@bool onInputTypeChanged(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnInputNameChangedComment@@bool onInputNameChanged(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnOutputConnectedComment@@bool onOutputConnected(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnOutputDisconnectedComment@@bool onOutputDisconnected(Kernel::IBox& box, const size_t index) { return true; };
|
||||
@@BoxListenerOnOutputAddedComment@@bool onOutputAdded(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnOutputRemovedComment@@bool onOutputRemoved(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnOutputTypeChangedComment@@bool onOutputTypeChanged(Kernel::IBox& box, const size_t index) override override { return true; };
|
||||
@@BoxListenerOnOutputNameChangedComment@@bool onOutputNameChanged(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnSettingAddedComment@@bool onSettingAdded(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnSettingRemovedComment@@bool onSettingRemoved(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnSettingTypeChangedComment@@bool onSettingTypeChanged(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnSettingNameChangedComment@@bool onSettingNameChanged(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnSettingDefaultValueChangedComment@@bool onSettingDefaultValueChanged(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
@@BoxListenerOnSettingValueChangedComment@@bool onSettingValueChanged(Kernel::IBox& box, const size_t index) override { return true; };
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
@@BoxListenerCommentOut@@
|
||||
|
||||
/// <summary> Descriptor of the box @@BoxName@@. </summary>
|
||||
class CBoxAlgorithm@@ClassName@@Desc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("@@BoxName@@"); }
|
||||
CString getAuthorName() const override { return CString("@@Author@@"); }
|
||||
CString getAuthorCompanyName() const override { return CString("@@Company@@"); }
|
||||
CString getShortDescription() const override { return CString("@@ShortDescription@@"); }
|
||||
CString getDetailedDescription() const override { return CString("@@DetailedDescription@@"); }
|
||||
CString getCategory() const override { return CString("@@Category@@"); }
|
||||
CString getVersion() const override { return CString("@@Version@@"); }
|
||||
CString getStockItemName() const override { return CString("@@StockItemName@@"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_@@ClassName@@; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithm@@ClassName@@; }
|
||||
|
||||
@@BoxListenerCommentIn@@
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithm@@ClassName@@Listener; }
|
||||
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
|
||||
@@BoxListenerCommentOut@@
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
@@Inputs@@
|
||||
@@InputFlagCanModify@@
|
||||
@@InputFlagCanAdd@@
|
||||
|
||||
@@Outputs@@
|
||||
@@OutputFlagCanModify@@
|
||||
@@OutputFlagCanAdd@@
|
||||
|
||||
@@Settings@@
|
||||
@@SettingFlagCanModify@@
|
||||
@@SettingFlagCanAdd@@
|
||||
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_@@ClassName@@Desc)
|
||||
};
|
||||
} // namespace @@Namespace@@
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
#include "ovasCConfiguration@@ClassName@@.h"
|
||||
|
||||
using namespace OpenViBE;
|
||||
using namespace /*OpenViBE::*/Kernel;
|
||||
using namespace /*OpenViBE::*/AcquisitionServer;
|
||||
|
||||
/*_________________________________________________
|
||||
|
||||
Insert callback to specific widget here
|
||||
Example with a button that launch a calibration of the device:
|
||||
|
||||
//Callback connected to a dedicated gtk button:
|
||||
static void button_calibrate_pressed_cb(GtkButton* button, void* data)
|
||||
{
|
||||
CConfiguration@@ClassName@@* config = static_cast<CConfiguration@@ClassName@@*>(data);
|
||||
config->buttonCalibratePressedCB();
|
||||
}
|
||||
|
||||
//Callback actually called:
|
||||
void CConfigurationGTecGUSBamp::buttonCalibratePressedCB()
|
||||
{
|
||||
// Connect to the hardware, ask for calibration, verify the return code, etc.
|
||||
}
|
||||
_________________________________________________*/
|
||||
|
||||
// If you added more reference attribute, initialize them here
|
||||
CConfiguration@@ClassName@@::CConfiguration@@ClassName@@(IDriverContext& ctx, const char* gtkBuilderFilename)
|
||||
: CConfigurationBuilder(gtkBuilderFilename), m_driverCtx(ctx) { }
|
||||
|
||||
bool CConfiguration@@ClassName@@::preConfigure()
|
||||
{
|
||||
if(! CConfigurationBuilder::preConfigure()) { return false; }
|
||||
|
||||
// Connect here all callbacks
|
||||
// Example:
|
||||
// g_signal_connect(gtk_builder_get_object(m_builder, "button_calibrate"), "pressed", G_CALLBACK(button_calibrate_pressed_cb), this);
|
||||
|
||||
// Insert here the pre-configure code.
|
||||
// For example, you may want to check if a device is currently connected
|
||||
// and if more than one are connected. Then you can list in a dedicated combo-box
|
||||
// the device currently connected so the user can choose which one he wants to acquire from.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CConfiguration@@ClassName@@::postConfigure()
|
||||
{
|
||||
if(m_applyConfig)
|
||||
{
|
||||
// If the user pressed the "apply" button, you need to save the changes made in the configuration.
|
||||
// For example, you can save the connection ID of the selected device:
|
||||
// m_connectionID = <value-from-gtk-widget>
|
||||
}
|
||||
|
||||
if(!CConfigurationBuilder::postConfigure()) { return false; } // normal header is filled (Subject ID, Age, Gender, channels, sampling frequency), ressources are realesed
|
||||
|
||||
return true;
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovasCConfigurationBuilder.h"
|
||||
#include "ovasIDriver.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
namespace OpenViBE
|
||||
{
|
||||
namespace AcquisitionServer
|
||||
{
|
||||
/**
|
||||
* \class CConfiguration@@ClassName@@
|
||||
* \author @@AuthorName@@ (@@CompanyName@@)
|
||||
* \date @@Date@@
|
||||
* \brief The CConfiguration@@ClassName@@ handles the configuration dialog specific to the @@DriverName@@ device.
|
||||
*
|
||||
* TODO: details
|
||||
*
|
||||
* \sa CDriver@@ClassName@@
|
||||
*/
|
||||
class CConfiguration@@ClassName@@ : public CConfigurationBuilder
|
||||
{
|
||||
public:
|
||||
|
||||
// you may have to add to your constructor some reference parameters
|
||||
// for example, a connection ID:
|
||||
//CConfiguration@@ClassName@@(IDriverContext& ctx, const char* gtkBuilderFilename, size_t& rConnectionId);
|
||||
CConfiguration@@ClassName@@(IDriverContext& ctx, const char* gtkBuilderFilename);
|
||||
|
||||
virtual bool preConfigure();
|
||||
virtual bool postConfigure();
|
||||
|
||||
protected:
|
||||
|
||||
IDriverContext& m_driverCtx;
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
* Insert here all specific attributes, such as a connection ID.
|
||||
* use references to directly modify the corresponding attribute of the driver
|
||||
* Example:
|
||||
*/
|
||||
// size_t& m_connectionID;
|
||||
};
|
||||
} //namespace AcquisitionServer
|
||||
} //namespace OpenViBE
|
||||
|
||||
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
#include "ovasCDriver@@ClassName@@.h"
|
||||
#include "ovasCConfiguration@@ClassName@@.h"
|
||||
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
using namespace OpenViBE;
|
||||
using namespace /*OpenViBE::*/AcquisitionServer;
|
||||
using namespace /*OpenViBE::*/Kernel;
|
||||
|
||||
//___________________________________________________________________//
|
||||
// //
|
||||
|
||||
CDriver@@ClassName@@::CDriver@@ClassName@@(IDriverContext& ctx)
|
||||
:IDriver(ctx),m_settings("AcquisitionServer_Driver_@@ClassName@@", m_driverCtx.getConfigurationManager())
|
||||
{
|
||||
m_header.setSampling(@@Sampling@@);
|
||||
m_header.setChannelCount(@@MaxChannel@@);
|
||||
|
||||
// The following class allows saving and loading driver settings from the acquisition server .conf file
|
||||
m_settings.add("Header", &m_header);
|
||||
// To save your custom driver settings, register each variable to the SettingsHelper
|
||||
//m_settings.add("SettingName", &variable);
|
||||
m_settings.load();
|
||||
}
|
||||
|
||||
CDriver@@ClassName@@::~CDriver@@ClassName@@() { }
|
||||
|
||||
const char* CDriver@@ClassName@@::getName() { return "@@DriverName@@"; }
|
||||
|
||||
//___________________________________________________________________//
|
||||
// //
|
||||
|
||||
bool CDriver@@ClassName@@::initialize(const size_t nSamplePerSentBlock, IDriverCallback& callback)
|
||||
{
|
||||
if(m_driverCtx.isConnected()) { return false; }
|
||||
if(!m_header.isChannelCountSet()||!m_header.isSamplingSet()) { return false; }
|
||||
|
||||
// Builds up a buffer to store
|
||||
// acquired samples. This buffer
|
||||
// will be sent to the acquisition
|
||||
// server later...
|
||||
m_sample=new float[m_header.getChannelCount()*nSamplePerSentBlock];
|
||||
if(!m_sample)
|
||||
{
|
||||
delete [] m_sample;
|
||||
m_sample = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ...
|
||||
// initialize hardware and get
|
||||
// available header information
|
||||
// from it
|
||||
// Using for example the connection ID provided by the configuration (m_connectionID)
|
||||
// ...
|
||||
|
||||
// Saves parameters
|
||||
m_callback = &callback;
|
||||
m_nSamplePerSentBlock = nSamplePerSentBlock;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriver@@ClassName@@::start()
|
||||
{
|
||||
if(!m_driverCtx.isConnected()) { return false; }
|
||||
if(m_driverCtx.isStarted()) { return false; }
|
||||
|
||||
// ...
|
||||
// request hardware to start
|
||||
// sending data
|
||||
// ...
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriver@@ClassName@@::loop()
|
||||
{
|
||||
if(!m_driverCtx.isConnected()) { return false; }
|
||||
if(!m_driverCtx.isStarted()) { return true; }
|
||||
|
||||
CStimulationSet stimSet;
|
||||
|
||||
// ...
|
||||
// receive samples from hardware
|
||||
// put them the correct way in the sample array
|
||||
// whether the buffer is full, send it to the acquisition server
|
||||
//...
|
||||
m_callback->setSamples(m_sample);
|
||||
|
||||
// When your sample buffer is fully loaded,
|
||||
// it is advised to ask the acquisition server
|
||||
// to correct any drift in the acquisition automatically.
|
||||
m_driverCtx.correctDriftSampleCount(m_driverCtx.getSuggestedDriftCorrectionSampleCount());
|
||||
|
||||
// ...
|
||||
// receive events from hardware
|
||||
// and put them the correct way in a CStimulationSet object
|
||||
//...
|
||||
m_callback->setStimulationSet(stimSet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriver@@ClassName@@::stop()
|
||||
{
|
||||
if(!m_driverCtx.isConnected()) return false;
|
||||
if(!m_driverCtx.isStarted()) return false;
|
||||
|
||||
// ...
|
||||
// request the hardware to stop
|
||||
// sending data
|
||||
// ...
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriver@@ClassName@@::uninitialize()
|
||||
{
|
||||
if(!m_driverCtx.isConnected()) return false;
|
||||
if(m_driverCtx.isStarted()) return false;
|
||||
|
||||
// ...
|
||||
// uninitialize hardware here
|
||||
// ...
|
||||
|
||||
delete [] m_sample;
|
||||
m_sample = nullptr;
|
||||
m_callback = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//___________________________________________________________________//
|
||||
// //
|
||||
bool CDriver@@ClassName@@::isConfigurable()
|
||||
{
|
||||
return true; // change to false if your device is not configurable
|
||||
}
|
||||
|
||||
bool CDriver@@ClassName@@::configure()
|
||||
{
|
||||
// Change this line if you need to specify some references to your driver attribute that need configuration, e.g. the connection ID.
|
||||
CConfiguration@@ClassName@@ config(m_driverCtx, Directories::getDataDir() + "/applications/acquisition-server/interface-@@ClassName@@.ui");
|
||||
|
||||
if(!config.configure(m_header)) { return false; }
|
||||
m_settings.save();
|
||||
|
||||
return true;
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovasIDriver.h"
|
||||
#include "../ovasCHeader.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
|
||||
#include "../ovasCSettingsHelper.h"
|
||||
#include "../ovasCSettingsHelperOperators.h"
|
||||
|
||||
namespace OpenViBE
|
||||
{
|
||||
namespace AcquisitionServer
|
||||
{
|
||||
/**
|
||||
* \class CDriver@@ClassName@@
|
||||
* \author @@AuthorName@@ (@@CompanyName@@)
|
||||
* \date @@Date@@
|
||||
* \brief The CDriver@@ClassName@@ allows the acquisition server to acquire data from a @@DriverName@@ device.
|
||||
*
|
||||
* TODO: details
|
||||
*
|
||||
* \sa CConfiguration@@ClassName@@
|
||||
*/
|
||||
class CDriver@@ClassName@@ : public IDriver
|
||||
{
|
||||
public:
|
||||
|
||||
CDriver@@ClassName@@(IDriverContext& ctx);
|
||||
virtual ~CDriver@@ClassName@@();
|
||||
virtual const char* getName();
|
||||
|
||||
virtual bool initialize(const size_t nSamplePerSentBlock, IDriverCallback& callback);
|
||||
virtual bool uninitialize();
|
||||
|
||||
virtual bool start();
|
||||
virtual bool stop();
|
||||
virtual bool loop();
|
||||
|
||||
virtual bool isConfigurable();
|
||||
virtual bool configure();
|
||||
virtual const IHeader* getHeader() { return &m_header; }
|
||||
|
||||
virtual bool isFlagSet(const EDriverFlag flag) const { return flag==EDriverFlag::IsUnstable; }
|
||||
|
||||
protected:
|
||||
|
||||
SettingsHelper m_settings;
|
||||
|
||||
IDriverCallback* m_callback = nullptr;
|
||||
|
||||
// Replace this generic Header with any specific header you might have written
|
||||
CHeader m_header;
|
||||
|
||||
size_t m_nSamplePerSentBlock = 0;
|
||||
float* m_sample = nullptr;
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
* Insert here all specific attributes, such as USB port number or device ID.
|
||||
* Example :
|
||||
*/
|
||||
// size_t m_connectionID = 0;
|
||||
};
|
||||
} //namespace AcquisitionServer
|
||||
} //namespace OpenViBE
|
||||
|
||||
|
||||
+3226
File diff suppressed because it is too large
Load Diff
+323
@@ -0,0 +1,323 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="upper">100</property>
|
||||
<property name="lower">0</property>
|
||||
<property name="page_increment">10</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_size">0</property>
|
||||
<property name="value">18</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment2">
|
||||
<property name="upper">100</property>
|
||||
<property name="lower">0</property>
|
||||
<property name="page_increment">10</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_size">0</property>
|
||||
<property name="value">0</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment3">
|
||||
<property name="upper">@@MaxChannel@@</property>
|
||||
<property name="lower">@@MinChannel@@</property>
|
||||
<property name="page_increment">10</property>
|
||||
<property name="step_increment">1</property>
|
||||
<property name="page_size">0</property>
|
||||
<property name="value">@@MaxChannel@@</property>
|
||||
</object>
|
||||
<object class="GtkListStore" id="model1">
|
||||
<columns>
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0" translatable="yes">unspecified</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">female</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">male</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">unknown</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkListStore" id="model2">
|
||||
<columns>
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0" translatable="yes">@@SamplingFrequencyList@@</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<!-- interface-requires gtk+ 2.6 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkDialog" id="openvibe-acquisition-server-settings">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Device configuration</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="gravity">center</property>
|
||||
<property name="has_separator">False</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkVBox" id="dialog-vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
|
||||
<property name="spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">@@DriverName@@</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="border_width">8</property>
|
||||
<property name="spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">8</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="table2">
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">5</property>
|
||||
<property name="n_columns">2</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_gender">
|
||||
<property name="visible">True</property>
|
||||
<property name="model">model1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="renderer1"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_age">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment1</property>
|
||||
<property name="snap_to_ticks">True</property>
|
||||
<property name="numeric">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_identifier">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment2</property>
|
||||
<property name="snap_to_ticks">True</property>
|
||||
<property name="numeric">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_sampling_frequency">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Sampling frequency :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_number_of_channels">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Number of channels :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_gender">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Gender :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_age">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Age :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_identifier">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Identifier :</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="single_line_mode">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_sampling_frequency">
|
||||
<property name="visible">True</property>
|
||||
<property name="active">0</property>
|
||||
<property name="model">model2</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="renderer2"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinButton" id="spinbutton_number_of_channels">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment3</property>
|
||||
<property name="snap_to_ticks">True</property>
|
||||
<property name="numeric">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_change_channel_names">
|
||||
<property name="label" translatable="yes">Change channel names</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHSeparator" id="hseparator1">
|
||||
<property name="visible">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkHButtonBox" id="dialog-action_area">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_apply">
|
||||
<property name="label">gtk-apply</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_cancel">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-10">button_apply</action-widget>
|
||||
<action-widget response="-6">button_cancel</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
</interface>
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
******************************************************
|
||||
* Thanks for using the OpenViBE Skeleton Generator ! *
|
||||
******************************************************
|
||||
|
||||
File generation completed
|
||||
[@@Date@@]
|
||||
-------------------------
|
||||
|
||||
The generator produced the following files:
|
||||
|
||||
The Box class:
|
||||
- ovpCBoxAlgorithm@@ClassName@@.h
|
||||
- ovpCBoxAlgorithm@@ClassName@@.cpp
|
||||
Please put these files in your local repository, in the project of your choice (e.g. Signal Processing or Classification)
|
||||
[openvibe-repository]/contrib/plugins/[plugin-project]/src/[my-box-folder]
|
||||
|
||||
You may have to change the file ovpCBoxAlgorithm@@ClassName@@.h to make it find the included file ovp_defines.h, whose path is related to the project used.
|
||||
|
||||
Don't forget to declare your box in ovp_main.cpp, in order to make it available in the Designer.
|
||||
Look in one of the ovp_main.cpp file, you will find examples of such declarations (#include the header, then OVP_Declare_New macro).
|
||||
This look something like this:
|
||||
|
||||
#include "[my-box-folder]/ovpCBoxAlgorithm@@ClassName@@.h"
|
||||
|
||||
...
|
||||
|
||||
OVP_Declare_Begin();
|
||||
|
||||
...
|
||||
|
||||
OVP_Declare_New(OpenViBE::Plugins::@@Namespace@@::CBoxAlgorithm@@ClassName@@Desc);
|
||||
...
|
||||
|
||||
OVP_Declare_End()
|
||||
|
||||
|
||||
If your box doesn't appear in the designer, maybe it's because you cannot see Unstable Boxes.
|
||||
Try to set your configuration file (openvibe.conf on windows / .openviberc on Linux) with the following token :
|
||||
>>>>>
|
||||
Designer_ShowUnstable = true
|
||||
>>>>>
|
||||
|
||||
For more information about implementing algorithms and boxes to fill your skeleton, please read the official tutorial:
|
||||
http://openvibe.inria.fr/tutorial-1-implementing-a-signal-processing-box/
|
||||
|
||||
Feel free to propose your contribution on the forum !
|
||||
http://openvibe.inria.fr/forum/
|
||||
|
||||
Enjoy OpenViBE !
|
||||
|
||||
- The development team -
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
******************************************************
|
||||
* Thanks for using the OpenViBE Skeleton Generator ! *
|
||||
******************************************************
|
||||
|
||||
File generation completed
|
||||
[@@Date@@]
|
||||
-------------------------
|
||||
|
||||
WARNING:
|
||||
Writing a new driver for an EEG device is often dependent on hardware specifications, such as OS compatibility
|
||||
or communication protocol. The generator gives you only the basic skeletons for easy integration with OpenViBE,
|
||||
please refer to your device specifications (API, protocol description, etc.) for the next steps...
|
||||
|
||||
The generator produced the following files:
|
||||
|
||||
The Configuration and Driver classes:
|
||||
- ovasCConfiguration@@ClassName@@.h
|
||||
- ovasCConfiguration@@ClassName@@.cpp
|
||||
- ovasCDriver@@ClassName@@.h
|
||||
- ovasCDriver@@ClassName@@.cpp
|
||||
You can put these files here in your local repository:
|
||||
[openvibe-repository]/contrib/plugins/server-drivers/[my-device]/src/
|
||||
|
||||
The glade interface:
|
||||
- interface-@@ClassName@@.glade
|
||||
You can put this file in here in your local repository:
|
||||
[openvibe-repository]/contrib/plugins/server-drivers/[my-device]/share/
|
||||
|
||||
Don't forget to declare your driver to the Acquisition Server application.
|
||||
This happens in "./contrib/common/contribAcquisitionServer.inl", there you
|
||||
will find examples of such declarations. You also need to register the source
|
||||
files to CMake, modifying the corresponding "contribAcquisitionServer.cmake".
|
||||
|
||||
For more information about building a new driver and filling your skeleton, please read the official tutorial:
|
||||
http://openvibe.inria.fr/tutorial-creating-a-new-driver-for-the-acquisition-server/
|
||||
|
||||
Feel free to propose your contribution on the forum !
|
||||
http://openvibe.inria.fr/forum/
|
||||
|
||||
Enjoy OpenViBE !
|
||||
|
||||
- The development team -
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
######################################################################################
|
||||
## OpenViBE configuration file, application specific values
|
||||
##
|
||||
## - The file consists of a list of "token name = token value"
|
||||
## - Whatever space / tabulation at the begining or end of a line is removed
|
||||
## - Comments start with #
|
||||
## - Lines ending with \ continue on the next line (all ending \ are removed)
|
||||
## - On Windows, use / in paths as \ is reserved
|
||||
## - You can use ${token name} in a token value
|
||||
## - You can use $Environment{env name} in a token value to get an environment variable
|
||||
######################################################################################
|
||||
|
||||
CustomConfiguration = ${CustomConfigurationPrefix${OperatingSystem}}${CustomConfigurationSuffix${OperatingSystem}}
|
||||
CustomConfigurationApplication = ${CustomConfigurationPrefix${OperatingSystem}}-${ApplicationName}${CustomConfigurationSuffix${OperatingSystem}}
|
||||
+1570
File diff suppressed because it is too large
Load Diff
+138
@@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovsgCSkeletonGenerator.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SkeletonGenerator {
|
||||
class CBoxAlgorithmSkeletonGenerator final : public CSkeletonGenerator
|
||||
{
|
||||
public:
|
||||
|
||||
CBoxAlgorithmSkeletonGenerator(Kernel::IKernelContext& ctx, GtkBuilder* builder) : CSkeletonGenerator(ctx, builder) { }
|
||||
~CBoxAlgorithmSkeletonGenerator() override { }
|
||||
|
||||
bool initialize() override;
|
||||
bool save(const std::string& filename) override;
|
||||
bool load(const std::string& filename) override;
|
||||
void getCurrentParameters() override;
|
||||
|
||||
// Box Description
|
||||
std::string m_Name, m_Version, m_ClassName, m_Category, m_ShortDesc, m_DetailedDesc;
|
||||
std::string m_GtkStockItemName;
|
||||
int m_GtkStockItemIdx = 0;
|
||||
|
||||
struct SIOS
|
||||
{
|
||||
std::string name, type, typeID, defaultValue;
|
||||
};
|
||||
|
||||
// Inputs
|
||||
bool m_CanModifyInputs = false, m_CanAddInputs = false;
|
||||
std::vector<SIOS> m_Inputs;
|
||||
// Outputs
|
||||
bool m_CanModifyOutputs = false, m_CanAddOutputs = false;
|
||||
std::vector<SIOS> m_Outputs;
|
||||
// Settings
|
||||
bool m_CanModifySettings = false, m_CanAddSettings = false;
|
||||
std::vector<SIOS> m_Settings;
|
||||
|
||||
//Algorithms
|
||||
std::vector<std::string> m_Algorithms; // the algorithm selected by user
|
||||
// Can be made non-const after '= false' produces working code
|
||||
static const bool USE_CODEC_TOOLKIT = true; // use or not the codec toolkit for encoder and decoder algorithms
|
||||
//the map between algorithm and corresponding header declaration (all variables algo/input/output).
|
||||
std::map<std::string, std::string> m_AlgoDeclaration;
|
||||
//the map between algorithm and corresponding initialisation
|
||||
std::map<std::string, std::string> m_AlgoInitialisations;
|
||||
//the map between algorithm and corresponding initialisation of ref targets
|
||||
std::map<std::string, std::string> m_AlgoInitialisationReferenceTargets;
|
||||
//the map between algorithm and corresponding uninitialisation
|
||||
std::map<std::string, std::string> m_AlgoUninitialisations;
|
||||
|
||||
// Box Listener
|
||||
bool m_UseBoxListener = false;
|
||||
// input
|
||||
bool m_HasOnInputAdded = false;
|
||||
bool m_HasOnInputRemoved = false;
|
||||
bool m_HasOnInputTypeChanged = false;
|
||||
bool m_HasOnInputNameChanged = false;
|
||||
bool m_HasOnInputConnected = false;
|
||||
bool m_HasOnInputDisconnected = false;
|
||||
// output
|
||||
bool m_HasOnOutputAdded = false;
|
||||
bool m_HasOnOutputRemoved = false;
|
||||
bool m_HasOnOutputTypeChanged = false;
|
||||
bool m_HasOnOutputNameChanged = false;
|
||||
bool m_HasOnOutputConnected = false;
|
||||
bool m_HasOnOutputDisconnected = false;
|
||||
// setting
|
||||
bool m_HasOnSettingAdded = false;
|
||||
bool m_HasOnSettingRemoved = false;
|
||||
bool m_HasOnSettingTypeChanged = false;
|
||||
bool m_HasOnSettingNameChanged = false;
|
||||
bool m_HasOnSettingDefaultValueChanged = false;
|
||||
bool m_HasOnSettingValueChanged = false;
|
||||
|
||||
bool m_HasProcessInput = false;
|
||||
bool m_HasProcessClock = false;
|
||||
bool m_HasProcessMessage = false;
|
||||
uint32_t m_ClockFrequency = 0;
|
||||
|
||||
void buttonCheckCB();
|
||||
void buttonOkCB();
|
||||
void toggleListenerCheckbuttonsStateCB(bool state) const;
|
||||
void buttonTooltipCB(GtkButton* button);
|
||||
void buttonExitCB();
|
||||
|
||||
void buttonAddInputCB() const;
|
||||
void buttonAddOutputCB() const;
|
||||
void buttonAddSettingCB() const;
|
||||
void buttonAddAlgorithmCB() const;
|
||||
void buttonRemoveGeneric(const char* buttonName) const;
|
||||
|
||||
void algorithmSelectedCB(int index);
|
||||
void setSensitivity(const char* widgetName, bool isActive) const;
|
||||
|
||||
private:
|
||||
|
||||
Kernel::ILogManager& getLogManager() const override { return m_kernelCtx.getLogManager(); }
|
||||
Kernel::IErrorManager& getErrorManager() const override { return m_kernelCtx.getErrorManager(); }
|
||||
|
||||
static std::string getRandomIdentifierString() { return CIdentifier::random().str(); }
|
||||
|
||||
// Sanity checks that a string is not empty or consist of spaces
|
||||
static bool isStringValid(const std::string& str) { return !str.empty() && str.find_first_not_of(' ') != std::string::npos; }
|
||||
|
||||
void clearStore(const char* name) const;
|
||||
void addDialogButttons(const char* name) const;
|
||||
void setEntryToConfigValue(const char* name, const char* token) const;
|
||||
void setActiveFromConf(const char* name, const char* token) const;
|
||||
void setActiveFromConfTog(const char* name, const char* token) const;
|
||||
const gchar* getText(const char* name) const;
|
||||
void addCollectionToTree(const char* treeName, const std::vector<std::string>& collection) const;
|
||||
void fillCollection(const char* treeName, std::vector<SIOS>& collection) const;
|
||||
bool isActive(char* name) const;
|
||||
|
||||
std::map<GtkButton*, std::string> m_tooltips;
|
||||
std::vector<std::string> m_typeCorrespondances;
|
||||
};
|
||||
|
||||
class CDummyAlgoProto final : public Kernel::IAlgorithmProto
|
||||
{
|
||||
public:
|
||||
std::map<std::string, Kernel::EParameterType> m_Inputs, m_Outputs;
|
||||
std::vector<std::string> m_InputTriggers, m_OutputTriggers;
|
||||
|
||||
bool addInputParameter(const CIdentifier& id, const CString& name, Kernel::EParameterType typeID,
|
||||
const CIdentifier& subTypeID = CIdentifier::undefined()) override;
|
||||
bool addOutputParameter(const CIdentifier& id, const CString& name, Kernel::EParameterType typeID,
|
||||
const CIdentifier& subTypeID = CIdentifier::undefined()) override;
|
||||
bool addInputTrigger(const CIdentifier& id, const CString& name) override;
|
||||
bool addOutputTrigger(const CIdentifier& id, const CString& name) override;
|
||||
|
||||
CIdentifier getClassIdentifier() const override { return CIdentifier::undefined(); }
|
||||
};
|
||||
} // namespace SkeletonGenerator
|
||||
} // namespace OpenViBE
|
||||
+504
@@ -0,0 +1,504 @@
|
||||
#include "ovsgCDriverSkeletonGenerator.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SkeletonGenerator {
|
||||
//-----------------------------------------------------------------------
|
||||
static void CheckCB(GtkButton* /*button*/, void* data) { static_cast<CDriverSkeletonGenerator*>(data)->buttonCheckCB(); }
|
||||
static void TooltipCB(GtkButton* button, void* data) { static_cast<CDriverSkeletonGenerator*>(data)->buttonTooltipCB(button); }
|
||||
static void OkCB(GtkButton* /*button*/, void* data) { static_cast<CDriverSkeletonGenerator*>(data)->buttonOkCB(); }
|
||||
|
||||
static void ExitCB(GtkButton* /*button*/, void* data)
|
||||
{
|
||||
static_cast<CDriverSkeletonGenerator*>(data)->buttonExitCB();
|
||||
gtk_exit(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void CDriverSkeletonGenerator::buttonExitCB()
|
||||
{
|
||||
getCommonParameters();
|
||||
getCurrentParameters();
|
||||
if (!cleanConfigurationFile(m_configFile)) { return; }
|
||||
saveCommonParameters(m_configFile);
|
||||
save(m_configFile);
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Info << "All entries saved in [" << m_configFile << "]. Exiting.\n";
|
||||
}
|
||||
|
||||
void CDriverSkeletonGenerator::buttonCheckCB()
|
||||
{
|
||||
//Author and Company
|
||||
getCommonParameters();
|
||||
getCurrentParameters();
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Info << "Checking values... \n";
|
||||
|
||||
bool success = true;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "----- STATUS -----\n";
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
//::GtkWidget * driverName = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_driver_name"));
|
||||
//m_DriverName = gtk_entry_get_text(GTK_ENTRY(driverName));
|
||||
const boost::regex regExpDriverName("([a-z]|[A-Z]|[0-9])+([a-z]|[A-Z]|[0-9]|[ \t\r\n]|[\\.-_\\(\\)])*", boost::regex::perl);
|
||||
if (regex_match(std::string(m_DriverName), regExpDriverName) == false)
|
||||
{
|
||||
OV_WARNING_K("-- Driver Name: INVALID");
|
||||
success = false;
|
||||
ss << "[FAILED] Invalid driver name. Please use only characters (lower or uppercase) and numbers (blanck allowed).\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
getLogManager() << Kernel::LogLevel_Info << "-- Driver Name: VALID (" << m_DriverName << ")\n";
|
||||
ss << "[ OK ] Valid driver name.\n";
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
//::GtkWidget * className = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_class_name"));
|
||||
//m_ClassName = gtk_entry_get_text(GTK_ENTRY(className));
|
||||
const boost::regex regExpClassName("([a-z]|[A-Z]|[0-9])+", boost::regex::perl);
|
||||
if (regex_match(std::string(m_ClassName), regExpClassName) == false)
|
||||
{
|
||||
OV_WARNING_K("-- Class Name: INVALID");
|
||||
success = false;
|
||||
ss << "[FAILED] Invalid class name. Please use only characters (lower or uppercase) and numbers (no blanck allowed).\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
getLogManager() << Kernel::LogLevel_Info << "-- Class Name: VALID (" << m_ClassName << ")\n";
|
||||
ss << "[ OK ] Valid class name.\n";
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
GtkWidget* spinMinChannel = GTK_WIDGET(gtk_builder_get_object(m_builder, "spinbutton_min_channel"));
|
||||
//m_MinChannel = std::to_string(size_t(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinMinChannel)))).c_str();
|
||||
GtkWidget* spinMaxChannel = GTK_WIDGET(gtk_builder_get_object(m_builder, "spinbutton_max_channel"));
|
||||
//m_MaxChannel = std::to_string(size_t(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinMaxChannel)))).c_str();
|
||||
if (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinMinChannel)) > gtk_spin_button_get_value(GTK_SPIN_BUTTON(spinMaxChannel)))
|
||||
{
|
||||
OV_WARNING_K(Kernel::LogLevel_Warning << "-- Channels: INVALID");
|
||||
success = false;
|
||||
ss << "[FAILED] Invalid channel count. Be sure that Min <= Max.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
getLogManager() << Kernel::LogLevel_Info << "-- Channels: VALID (" << m_MinChannel << "/" << m_MaxChannel << ")\n";
|
||||
ss << "[ OK ] Valid channel count.\n";
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
/*::GtkWidget * sf = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_sampling_frequencies"));
|
||||
CString samplings = gtk_entry_get_text(GTK_ENTRY(sf));
|
||||
*/
|
||||
const boost::regex regExpSamplings("(([1-9][0-9]*);)*([1-9][0-9]*)", boost::regex::perl);
|
||||
if (regex_match(m_Samplings, regExpSamplings) == false)
|
||||
{
|
||||
OV_WARNING_K("-- Sampling frequencies: INVALID");
|
||||
success = false;
|
||||
ss << "[FAILED] Invalid sampling frequencies. Please use only whole numbers separated with ';' (no blanck allowed).\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Maximum 16 frequencies
|
||||
size_t nSampling = 0;
|
||||
size_t freq;
|
||||
std::stringstream tmp(m_Samplings);
|
||||
m_SamplingSeparate.clear();
|
||||
while (tmp >> freq && nSampling < 16)
|
||||
{
|
||||
m_SamplingSeparate.push_back(std::to_string(freq));
|
||||
if (tmp.peek() == ';') { tmp.ignore(); }
|
||||
nSampling++;
|
||||
}
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Info << "-- Sampling frequencies: VALID\n";
|
||||
for (const auto& s : m_SamplingSeparate) { std::cout << "- " << s << " Hz\n"; }
|
||||
|
||||
ss << "[ OK ] " << nSampling << " valid sampling frequencie(s).\n";
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
/*::GtkWidget * fileChooser = GTK_WIDGET(gtk_builder_get_object(m_builder, "filechooserbutton_target_directory"));
|
||||
char * directory = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileChooser));
|
||||
m_directory = CString(directory);
|
||||
g_free(directory);*/
|
||||
|
||||
#ifdef TARGET_OS_Windows
|
||||
const std::string space("%20");
|
||||
if (m_directory.rfind(space) != std::string::npos)
|
||||
{
|
||||
ss << "[FAILED] Invalid destination folder :" << m_directory << ".\n";
|
||||
getLogManager() << Kernel::LogLevel_Error << "Invalid destination folder :" << m_directory << ".\n";
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
getLogManager() << Kernel::LogLevel_Info << "-- Target directory: " << m_directory << "\n";
|
||||
ss << "[ OK ] Valid target directory: " << m_directory << "\n";
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
GtkWidget* textview = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-tooltips-textview"));
|
||||
GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
|
||||
if (success)
|
||||
{
|
||||
ss << "----- SUCCESS -----\nPress OK to generate the files. If you want to modify your choice(s), please press the \"Check\" button again.";
|
||||
GtkWidget* buttonOk = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-ok-button"));
|
||||
gtk_widget_set_sensitive(buttonOk, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << "----- PROCESS FAILED -----\nModify your choices and press the \"Check\" button again.";
|
||||
GtkWidget* buttonOk = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-ok-button"));
|
||||
gtk_widget_set_sensitive(buttonOk, false);
|
||||
}
|
||||
|
||||
gtk_text_buffer_set_text(buffer, ss.str().c_str(), -1);
|
||||
}
|
||||
|
||||
void CDriverSkeletonGenerator::buttonOkCB()
|
||||
{
|
||||
getLogManager() << Kernel::LogLevel_Info << "Generating files... \n";
|
||||
std::string log = "Generating files...\n";
|
||||
|
||||
bool success = true;
|
||||
|
||||
const std::string date = getDate();
|
||||
|
||||
// we construct the map of substitutions
|
||||
std::map<std::string, std::string> substitutions;
|
||||
substitutions["@@AuthorName@@"] = m_author;
|
||||
substitutions["@@CompanyName@@"] = m_company;
|
||||
substitutions["@@Date@@"] = date;
|
||||
substitutions["@@ClassName@@"] = m_ClassName;
|
||||
substitutions["@@DriverName@@"] = m_DriverName;
|
||||
substitutions["@@MinChannel@@"] = m_MinChannel;
|
||||
substitutions["@@MaxChannel@@"] = m_MaxChannel;
|
||||
substitutions["@@SamplingFrequency@@"] = m_SamplingSeparate[0];
|
||||
|
||||
GtkWidget* textview = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-tooltips-textview"));
|
||||
GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
// driver.h
|
||||
std::string dst = m_directory + "/ovasCDriver" + m_ClassName + ".h";
|
||||
std::string tmplate = m_kernelCtx.getConfigurationManager().expand("${Path_Data}/applications/skeleton-generator/driver.h-skeleton").toASCIIString();
|
||||
|
||||
if (!this->generate(tmplate, dst, substitutions, log))
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer, log.c_str(), -1);
|
||||
success = false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
// driver.cpp
|
||||
dst = m_directory + "/ovasCDriver" + m_ClassName + ".cpp";
|
||||
tmplate = m_kernelCtx.getConfigurationManager().expand("${Path_Data}/applications/skeleton-generator/driver.cpp-skeleton").toASCIIString();
|
||||
|
||||
if (!this->generate(tmplate, dst, substitutions, log))
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer, log.c_str(), -1);
|
||||
success = false;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
// config.h
|
||||
dst = m_directory + "/ovasCConfiguration" + m_ClassName + ".h";
|
||||
tmplate = m_kernelCtx.getConfigurationManager().expand("${Path_Data}/applications/skeleton-generator/configuration.h-skeleton").toASCIIString();
|
||||
|
||||
if (!this->generate(tmplate, dst, substitutions, log))
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer, log.c_str(), -1);
|
||||
success = false;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
// config.cpp
|
||||
dst = m_directory + "/ovasCConfiguration" + m_ClassName + ".cpp";
|
||||
tmplate = m_kernelCtx.getConfigurationManager().expand("${Path_Data}/applications/skeleton-generator/configuration.cpp-skeleton").toASCIIString();
|
||||
|
||||
if (!this->generate(tmplate, dst, substitutions, log))
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer, log.c_str(), -1);
|
||||
success = false;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
// interface.ui
|
||||
dst = m_directory + "/interface-" + m_ClassName + ".ui";
|
||||
tmplate = m_kernelCtx.getConfigurationManager().expand("${Path_Data}/applications/skeleton-generator/interface.ui-skeleton").toASCIIString();
|
||||
|
||||
if (!this->generate(tmplate, dst, substitutions, log))
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer, log.c_str(), -1);
|
||||
success = false;
|
||||
}
|
||||
// the following substitution is done in a .ui file, and not in a cpp file.
|
||||
// The SED primitive immplemented do not cover that case, and some typo problem happen with the character "
|
||||
const std::string pattern("@@SamplingFrequencyList@@");
|
||||
std::string substitute;
|
||||
for (auto it = m_SamplingSeparate.begin(); it != m_SamplingSeparate.end();)
|
||||
{
|
||||
substitute += (*it++);
|
||||
if (it != m_SamplingSeparate.end()) { substitute += "<\\/col><\\/row><row><col id=\\\"0\\\" translatable=\\\"yes\\\">"; }
|
||||
}
|
||||
success &= regexReplace(dst, pattern, substitute, "");
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
// readme-driver.txt
|
||||
dst = m_directory + "/README.txt";
|
||||
tmplate = m_kernelCtx.getConfigurationManager().expand("${Path_Data}/applications/skeleton-generator/readme-driver.txt-skeleton");
|
||||
|
||||
if (!this->generate(tmplate, dst, substitutions, log))
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer, log.c_str(), -1);
|
||||
success = false;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------------------------------//
|
||||
|
||||
if (success)
|
||||
{
|
||||
success &= cleanConfigurationFile(m_configFile);
|
||||
success &= saveCommonParameters(m_configFile);
|
||||
success &= save(m_configFile);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
log += "Generation process did not completly succeed. Some files may have not been produced.\n";
|
||||
OV_WARNING_K("Generation process did not completly succeed. Some files may have not been produced.");
|
||||
}
|
||||
else
|
||||
{
|
||||
log += "Generation process successful. All information saved in [" + m_configFile + "]\nPlease read the file [README.txt] !\n";
|
||||
getLogManager() << Kernel::LogLevel_Info << "Generation process successful. All information saved in [" << m_configFile << "]\n";
|
||||
}
|
||||
|
||||
// Launch the browser to display the produced files
|
||||
const std::string browser = m_kernelCtx.getConfigurationManager().expand("${Designer_WebBrowserCommand_${OperatingSystem}}").toASCIIString();
|
||||
|
||||
#ifdef TARGET_OS_Windows
|
||||
const std::string browserCmd = browser + " file:///" + m_directory; //otherwise the browser does not find the directory (problem with / and \ char)
|
||||
#else
|
||||
const std::string browserCmd = browser + " \"" + m_directory + "\"";
|
||||
#endif
|
||||
|
||||
if (system(browserCmd.c_str())) { }
|
||||
|
||||
gtk_text_buffer_set_text(buffer, log.c_str(), -1);
|
||||
}
|
||||
|
||||
void CDriverSkeletonGenerator::buttonTooltipCB(GtkButton* button)
|
||||
{
|
||||
const EWidgetName widgetName = m_widgetNames[button];
|
||||
|
||||
GtkWidget* textview = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-tooltips-textview"));
|
||||
GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
|
||||
|
||||
if (widgetName == EWidgetName::DriverName)
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer,
|
||||
"Driver Name: \nThis name will be the one displayed in the Acquisition Server selection combobox.\nUsually, the driver is named according to the EEG device (with precisions such as a version number).\n------\nExample: OpenEEG Modular EEG (P2)\n\n\n",
|
||||
-1);
|
||||
}
|
||||
else if (widgetName == EWidgetName::ClassName)
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer,
|
||||
"Class Name: \nThis name will be used to generate all source and GUI files.\nYou should choose a class name close to the device name (no blank allowed !).\n------\nExample: OpenEEGModularEEG will generate\n - ovasCDriverOpenEEGModularEEG.h/.cpp, the driver skeleton \n - ovasCConfigurationOpenEEGModularEEG.h/.cpp, the configuration class skeleton\n - interface-OpenEEG-ModularEEG.ui, the GUI description file",
|
||||
-1);
|
||||
}
|
||||
else if (widgetName == EWidgetName::ChannelCount)
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer,
|
||||
"Channel count: \nEnter in the two fields the minimum and maximum number of channels the device is capable of.\nOf course you can still change it later in the source code.\n------\nExample: Min(1) Max(16)\n\n\n",
|
||||
-1);
|
||||
}
|
||||
else if (widgetName == EWidgetName::Sampling)
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer,
|
||||
"Sampling frequencies: \nEnter in the text field the sampling frequencies your device is capable of.\nYou can specify a list of defined frequencies (value separator ';').\n------\nExample:\n\"128;256;512\" for three defined frequencies.\n\n",
|
||||
-1);
|
||||
}
|
||||
else if (widgetName == EWidgetName::Directory)
|
||||
{
|
||||
gtk_text_buffer_set_text(buffer,
|
||||
"Target directory: \nEnter the destination directory in which all files will be generated. \nAny existing files will be overwritten.\n------\nExample: ~/skeleton-generator/foobar-driver/\n\n\n",
|
||||
-1);
|
||||
}
|
||||
else { }
|
||||
}
|
||||
|
||||
bool CDriverSkeletonGenerator::initialize()
|
||||
{
|
||||
GtkWidget* driver = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-window"));
|
||||
|
||||
// Buttons and signals
|
||||
GtkWidget* buttonCheck = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-check-button"));
|
||||
GtkWidget* buttonOk = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-ok-button"));
|
||||
|
||||
g_signal_connect(buttonCheck, "pressed", G_CALLBACK(CheckCB), this);
|
||||
g_signal_connect(buttonOk, "pressed", G_CALLBACK(OkCB), this);
|
||||
|
||||
////target directory
|
||||
//::GtkWidget * fileChooser = GTK_WIDGET(gtk_builder_get_object(m_builder, "filechooserbutton_target_directory"));
|
||||
//CString directory = m_kernelContext.getConfigurationManager().expand("${SkeletonGenerator_TargetDirectory}");
|
||||
//if(!gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser), directory.c_str()))
|
||||
//{
|
||||
// gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser),"..");
|
||||
//}
|
||||
|
||||
|
||||
// Tooltips buttons and signal
|
||||
GtkButton* buttonDriverName = GTK_BUTTON(gtk_builder_get_object(m_builder, "sg-driver-driver-name-tooltip-button"));
|
||||
GtkButton* buttonClassName = GTK_BUTTON(gtk_builder_get_object(m_builder, "sg-driver-class-name-tooltip-button"));
|
||||
GtkButton* buttonChannelCount = GTK_BUTTON(gtk_builder_get_object(m_builder, "sg-driver-channel-count-tooltip-button"));
|
||||
GtkButton* buttonSampling = GTK_BUTTON(gtk_builder_get_object(m_builder, "sg-driver-sampling-frequencies-tooltip-button"));
|
||||
GtkButton* buttonDirectory = GTK_BUTTON(gtk_builder_get_object(m_builder, "sg-driver-target-directory-tooltip-button"));
|
||||
|
||||
m_widgetNames[buttonDriverName] = EWidgetName::DriverName;
|
||||
m_widgetNames[buttonClassName] = EWidgetName::ClassName;
|
||||
m_widgetNames[buttonChannelCount] = EWidgetName::ChannelCount;
|
||||
m_widgetNames[buttonSampling] = EWidgetName::Sampling;
|
||||
m_widgetNames[buttonDirectory] = EWidgetName::Directory;
|
||||
|
||||
g_signal_connect(buttonDriverName, "pressed", G_CALLBACK(TooltipCB), this);
|
||||
g_signal_connect(buttonClassName, "pressed", G_CALLBACK(TooltipCB), this);
|
||||
g_signal_connect(buttonChannelCount, "pressed", G_CALLBACK(TooltipCB), this);
|
||||
g_signal_connect(buttonSampling, "pressed", G_CALLBACK(TooltipCB), this);
|
||||
g_signal_connect(buttonDirectory, "pressed", G_CALLBACK(TooltipCB), this);
|
||||
|
||||
//Close with X and "cancel" button
|
||||
g_signal_connect(G_OBJECT(driver), "delete_event", G_CALLBACK(gtk_exit), nullptr);
|
||||
GtkWidget* buttonCancel = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-cancel-button"));
|
||||
g_signal_connect(buttonCancel, "pressed", G_CALLBACK(ExitCB), this);
|
||||
|
||||
//load everything from file
|
||||
load(m_configFile);
|
||||
|
||||
gtk_widget_show_all(driver);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriverSkeletonGenerator::save(const std::string& filename)
|
||||
{
|
||||
std::ofstream file;
|
||||
file.open(filename, std::ios::app | std::ios::binary);
|
||||
OV_ERROR_UNLESS_KRF(file.is_open(), "Saving the driver entries in [" << m_configFile << "] failed !", Kernel::ErrorType::BadFileWrite);
|
||||
|
||||
file << "# ----------------------DRIVER-------------------------\n";
|
||||
std::string directory(m_directory);
|
||||
for (auto it = directory.begin(); it < directory.end(); ++it) { if ((*it) == '\\') { directory.replace(it, it + 1, 1, '/'); } }
|
||||
|
||||
file << "SkeletonGenerator_Driver_DriverName = " << m_DriverName << std::endl;
|
||||
file << "SkeletonGenerator_Driver_ClassName = " << m_ClassName << std::endl;
|
||||
file << "SkeletonGenerator_Driver_MinChannel = " << m_MinChannel << std::endl;
|
||||
file << "SkeletonGenerator_Driver_MaxChannel = " << m_MaxChannel << std::endl;
|
||||
file << "SkeletonGenerator_Driver_SamplingFrequencies = " << m_Samplings << std::endl;
|
||||
file << "SkeletonGenerator_Driver_TargetDirectory = " << directory << std::endl;
|
||||
file << "# -----------------------------------------------------" << std::endl;
|
||||
file.close();
|
||||
getLogManager() << Kernel::LogLevel_Info << "Driver entries saved in [" << m_configFile << "]\n";
|
||||
|
||||
m_configFileLoaded = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDriverSkeletonGenerator::load(const std::string& filename)
|
||||
{
|
||||
if (!m_configFileLoaded && !m_kernelCtx.getConfigurationManager().addConfigurationFromFile(filename.c_str()))
|
||||
{
|
||||
OV_WARNING_K("Driver: Configuration file [" << filename << "] could not be loaded. It will be automatically generated after first use.");
|
||||
return false;
|
||||
}
|
||||
|
||||
GtkWidget* driverName = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_driver_name"));
|
||||
gtk_entry_set_text(GTK_ENTRY(driverName), m_kernelCtx.getConfigurationManager().expand("${SkeletonGenerator_Driver_DriverName}"));
|
||||
|
||||
GtkWidget* className = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_class_name"));
|
||||
gtk_entry_set_text(GTK_ENTRY(className), m_kernelCtx.getConfigurationManager().expand("${SkeletonGenerator_Driver_ClassName}"));
|
||||
|
||||
GtkWidget* minChannel = GTK_WIDGET(gtk_builder_get_object(m_builder, "spinbutton_min_channel"));
|
||||
gtk_spin_button_set_value(
|
||||
GTK_SPIN_BUTTON(minChannel), double(m_kernelCtx.getConfigurationManager().expandAsInteger("${SkeletonGenerator_Driver_MinChannel}")));
|
||||
|
||||
GtkWidget* maxChannel = GTK_WIDGET(gtk_builder_get_object(m_builder, "spinbutton_max_channel"));
|
||||
gtk_spin_button_set_value(
|
||||
GTK_SPIN_BUTTON(maxChannel), double(m_kernelCtx.getConfigurationManager().expandAsInteger("${SkeletonGenerator_Driver_MaxChannel}")));
|
||||
|
||||
GtkWidget* sf = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_sampling_frequencies"));
|
||||
gtk_entry_set_text(GTK_ENTRY(sf), m_kernelCtx.getConfigurationManager().expand("${SkeletonGenerator_Driver_SamplingFrequencies}"));
|
||||
|
||||
GtkWidget* fileChooser = GTK_WIDGET(gtk_builder_get_object(m_builder, "filechooserbutton_target_directory"));
|
||||
|
||||
// if the user specified a target directory, it has full priority
|
||||
std::string directory = m_kernelCtx.getConfigurationManager().expand("${SkeletonGenerator_TargetDirectory}").toASCIIString();
|
||||
#ifdef TARGET_OS_Linux
|
||||
bool needFilePrefix = false;
|
||||
#endif
|
||||
if (!directory.empty())
|
||||
{
|
||||
getLogManager() << Kernel::LogLevel_Debug << "Target dir user [" << directory << "]\n";
|
||||
#ifdef TARGET_OS_Linux
|
||||
needFilePrefix = true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//previous entry
|
||||
directory = m_kernelCtx.getConfigurationManager().expand("${SkeletonGenerator_Driver_TargetDirectory}");
|
||||
if (!directory.empty())
|
||||
{
|
||||
getLogManager() << Kernel::LogLevel_Debug << "Target previous [" << directory << "]\n";
|
||||
#ifdef TARGET_OS_Linux
|
||||
needFilePrefix = true;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
//default path = dist
|
||||
getLogManager() << Kernel::LogLevel_Debug << "Target default [dist]\n";
|
||||
#ifdef TARGET_OS_Linux
|
||||
directory = std::string(gtk_file_chooser_get_current_folder_uri(GTK_FILE_CHOOSER(fileChooser)));
|
||||
directory = directory + "/..";
|
||||
#elif defined TARGET_OS_Windows
|
||||
directory = "..";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef TARGET_OS_Linux
|
||||
if(needFilePrefix) directory = "file://" + directory;
|
||||
gtk_file_chooser_set_current_folder_uri(GTK_FILE_CHOOSER(fileChooser), directory.c_str());
|
||||
#elif defined TARGET_OS_Windows
|
||||
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fileChooser), directory.c_str());
|
||||
#endif
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Info << "Driver entries from [" << filename << "] loaded.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDriverSkeletonGenerator::getCurrentParameters()
|
||||
{
|
||||
GtkWidget* driverName = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_driver_name"));
|
||||
m_DriverName = gtk_entry_get_text(GTK_ENTRY(driverName));
|
||||
GtkWidget* className = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_class_name"));
|
||||
m_ClassName = gtk_entry_get_text(GTK_ENTRY(className));
|
||||
GtkWidget* minChannel = GTK_WIDGET(gtk_builder_get_object(m_builder, "spinbutton_min_channel"));
|
||||
m_MinChannel = std::to_string(size_t(gtk_spin_button_get_value(GTK_SPIN_BUTTON(minChannel))));
|
||||
GtkWidget* maxChannel = GTK_WIDGET(gtk_builder_get_object(m_builder, "spinbutton_max_channel"));
|
||||
m_MaxChannel = std::to_string(size_t(gtk_spin_button_get_value(GTK_SPIN_BUTTON(maxChannel))));
|
||||
GtkWidget* sf = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_sampling_frequencies"));
|
||||
m_Samplings = gtk_entry_get_text(GTK_ENTRY(sf));
|
||||
GtkWidget* fileChooser = GTK_WIDGET(gtk_builder_get_object(m_builder, "filechooserbutton_target_directory"));
|
||||
char* directory = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileChooser));
|
||||
m_directory = CString(directory);
|
||||
g_free(directory);
|
||||
}
|
||||
|
||||
} // namespace SkeletonGenerator
|
||||
} // namespace OpenViBE
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "ovsgCSkeletonGenerator.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SkeletonGenerator {
|
||||
class CDriverSkeletonGenerator final : public CSkeletonGenerator
|
||||
{
|
||||
public:
|
||||
|
||||
CDriverSkeletonGenerator(Kernel::IKernelContext& ctx, GtkBuilder* builder) : CSkeletonGenerator(ctx, builder) { }
|
||||
~CDriverSkeletonGenerator() override { }
|
||||
|
||||
bool initialize() override;
|
||||
bool save(const std::string& filename) override;
|
||||
bool load(const std::string& filename) override;
|
||||
void getCurrentParameters() override;
|
||||
|
||||
std::string m_DriverName;
|
||||
std::string m_ClassName;
|
||||
std::string m_Samplings;
|
||||
std::vector<std::string> m_SamplingSeparate;
|
||||
std::string m_MinChannel;
|
||||
std::string m_MaxChannel;
|
||||
|
||||
void buttonCheckCB();
|
||||
void buttonOkCB();
|
||||
void buttonTooltipCB(GtkButton* button);
|
||||
void buttonExitCB();
|
||||
|
||||
private:
|
||||
|
||||
Kernel::ILogManager& getLogManager() const override { return m_kernelCtx.getLogManager(); }
|
||||
Kernel::IErrorManager& getErrorManager() const override { return m_kernelCtx.getErrorManager(); }
|
||||
|
||||
enum class EWidgetName
|
||||
{
|
||||
DriverName,
|
||||
ClassName,
|
||||
ChannelCount,
|
||||
Sampling,
|
||||
Directory,
|
||||
};
|
||||
|
||||
std::map<GtkButton*, EWidgetName> m_widgetNames;
|
||||
};
|
||||
} // namespace SkeletonGenerator
|
||||
} // namespace OpenViBE
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
#include "ovsgCSkeletonGenerator.h"
|
||||
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SkeletonGenerator {
|
||||
|
||||
CSkeletonGenerator::CSkeletonGenerator(Kernel::IKernelContext& ctx, GtkBuilder* builder)
|
||||
: m_kernelCtx(ctx), m_builder(builder)
|
||||
{
|
||||
m_configFile = m_kernelCtx.getConfigurationManager().expand("${CustomConfigurationApplication}");
|
||||
m_kernelCtx.getLogManager() << Kernel::LogLevel_Trace << "Configuration file [" << m_configFile << "]\n";
|
||||
loadCommonParameters(m_configFile);
|
||||
}
|
||||
|
||||
void CSkeletonGenerator::getCommonParameters()
|
||||
{
|
||||
//Author and Company
|
||||
GtkWidget* company = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_company_name"));
|
||||
m_company = gtk_entry_get_text(GTK_ENTRY(company));
|
||||
|
||||
GtkWidget* author = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_author_name"));
|
||||
m_author = gtk_entry_get_text(GTK_ENTRY(author));
|
||||
}
|
||||
|
||||
bool CSkeletonGenerator::saveCommonParameters(const std::string& filename)
|
||||
{
|
||||
// we get the latest values
|
||||
getCommonParameters();
|
||||
|
||||
std::ofstream file;
|
||||
file.open(filename, std::ios::app | std::ios::binary);
|
||||
OV_ERROR_UNLESS_KRF(file.is_open(), "Saving the common entries in [" << filename << "] failed !", Kernel::ErrorType::BadFileRead);
|
||||
|
||||
|
||||
// generator selected
|
||||
std::string active;
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(m_builder, "sg-driver-selection-radio-button")))) { active = "0"; }
|
||||
else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(m_builder, "sg-algo-selection-radio-button")))) { active = "1"; }
|
||||
else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gtk_builder_get_object(m_builder, "sg-box-selection-radio-button")))) { active = "2"; }
|
||||
|
||||
file << "SkeletonGenerator_GeneratorSelected = " << active << std::endl;
|
||||
file << "SkeletonGenerator_Common_Author = " << m_author << std::endl;
|
||||
file << "SkeletonGenerator_Common_Company = " << m_company << std::endl;
|
||||
file.close();
|
||||
getLogManager() << Kernel::LogLevel_Info << "Common entries saved in [" << filename << "]\n";
|
||||
|
||||
//we can reload the file, it may have changed
|
||||
m_configFileLoaded = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSkeletonGenerator::cleanConfigurationFile(const std::string& filename) const
|
||||
{
|
||||
std::ofstream file;
|
||||
file.open(filename, std::ios::binary);
|
||||
OV_ERROR_UNLESS_KRF(file.is_open(), "Failed to clean [" << filename << "]", Kernel::ErrorType::BadFileRead);
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Info << "Configuration file [" << filename << "] cleaned.\n";
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSkeletonGenerator::loadCommonParameters(const std::string& filename)
|
||||
{
|
||||
OV_ERROR_UNLESS_KRF(m_configFileLoaded || m_kernelCtx.getConfigurationManager().addConfigurationFromFile(filename.c_str()),
|
||||
"Common: Configuration file [" << filename << "] could not be loaded. \n", Kernel::ErrorType::BadFileRead);
|
||||
|
||||
GtkWidget* widget = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-driver-selection-radio-button"));
|
||||
gtk_toggle_button_set_active(
|
||||
GTK_TOGGLE_BUTTON(widget), (m_kernelCtx.getConfigurationManager().expandAsUInteger("${SkeletonGenerator_GeneratorSelected}") == 0));
|
||||
widget = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-algo-selection-radio-button"));
|
||||
gtk_toggle_button_set_active(
|
||||
GTK_TOGGLE_BUTTON(widget), (m_kernelCtx.getConfigurationManager().expandAsUInteger("${SkeletonGenerator_GeneratorSelected}") == 1));
|
||||
widget = GTK_WIDGET(gtk_builder_get_object(m_builder, "sg-box-selection-radio-button"));
|
||||
gtk_toggle_button_set_active(
|
||||
GTK_TOGGLE_BUTTON(widget), (m_kernelCtx.getConfigurationManager().expandAsUInteger("${SkeletonGenerator_GeneratorSelected}") == 2));
|
||||
|
||||
GtkWidget* company = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_company_name"));
|
||||
gtk_entry_set_text(GTK_ENTRY(company), m_kernelCtx.getConfigurationManager().expand("${SkeletonGenerator_Common_Company}"));
|
||||
|
||||
GtkWidget* author = GTK_WIDGET(gtk_builder_get_object(m_builder, "entry_author_name"));
|
||||
gtk_entry_set_text(GTK_ENTRY(author), m_kernelCtx.getConfigurationManager().expand("${SkeletonGenerator_Common_Author}"));
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Info << "Common entries from [" << filename << "] loaded.\n";
|
||||
|
||||
m_configFileLoaded = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CSkeletonGenerator::ensureSedCompliancy(const std::string& expression)
|
||||
{
|
||||
std::string res(expression);
|
||||
auto it = res.begin();
|
||||
while (it < res.end())
|
||||
{
|
||||
if ((*it) == '\\')
|
||||
{
|
||||
it = res.insert(it, '\\');
|
||||
++it;
|
||||
it = res.insert(it, '\\');
|
||||
++it;
|
||||
it = res.insert(it, '\\');
|
||||
++it;
|
||||
#ifdef TARGET_OS_Linux
|
||||
it = res.insert(it,'\\');
|
||||
it = res.insert(it,'\\');
|
||||
it+=2;
|
||||
it = res.insert(it,'\\');
|
||||
it = res.insert(it,'\\');
|
||||
it+=2;
|
||||
#endif
|
||||
}
|
||||
else if ((*it) == '/')
|
||||
{
|
||||
it = res.insert(it, '\\');
|
||||
++it;
|
||||
}
|
||||
else if ((*it) == '"')
|
||||
{
|
||||
it = res.insert(it, '\\');
|
||||
++it;
|
||||
it = res.insert(it, '\\');
|
||||
++it;
|
||||
it = res.insert(it, '\\');
|
||||
++it;
|
||||
it = res.insert(it, '\\');
|
||||
++it;
|
||||
it = res.insert(it, '\\');
|
||||
++it;
|
||||
}
|
||||
else if ((*it) == '\n')
|
||||
{
|
||||
it = res.erase(it);
|
||||
#ifdef TARGET_OS_Linux
|
||||
it = res.insert(it,'\\');
|
||||
it = res.insert(it,'\\');
|
||||
it+=2;
|
||||
#endif
|
||||
it = res.insert(it, '\\');
|
||||
it = res.insert(it, '\\');
|
||||
it += 2;
|
||||
it = res.insert(it, 'n');
|
||||
//++it;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CSkeletonGenerator::regexReplace(const std::string& src, const std::string& regEx, const std::string& substitute, const std::string& dst) const
|
||||
{
|
||||
try
|
||||
{
|
||||
// Read file to memory
|
||||
std::ifstream in(src);
|
||||
std::string buffer((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
|
||||
in.close();
|
||||
|
||||
// Open output stream and set an iterator to it
|
||||
std::string realDst((dst.empty() ? src : dst));
|
||||
std::ofstream out(realDst);
|
||||
const std::ostream_iterator<char> it(out);
|
||||
|
||||
// Do regex magic on the iterator
|
||||
boost::regex exp;
|
||||
exp.assign(regEx);
|
||||
|
||||
regex_replace(it, buffer.begin(), buffer.end(), exp, substitute, boost::match_default | boost::format_sed);
|
||||
|
||||
out.close();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "Error occurred processing " << src << " to " << dst << "\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CSkeletonGenerator::getDate()
|
||||
{
|
||||
time_t raw;
|
||||
time(&raw);
|
||||
struct tm* info = localtime(&raw);
|
||||
std::string res(asctime(info));
|
||||
res = res.substr(0, res.size() - 1); // the ascitime ends with a "\n"
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CSkeletonGenerator::generate(const std::string& src, const std::string& dst, const std::map<std::string, std::string>& substitutions,
|
||||
std::string& log) const
|
||||
{
|
||||
// we check if the template file is in place.
|
||||
if (! g_file_test(src.c_str(), G_FILE_TEST_EXISTS))
|
||||
{
|
||||
log += "[FAILED] the template file '" + src + "' is missing.\n";
|
||||
OV_ERROR_KRF("The template file '" << src << "' is missing.", Kernel::ErrorType::BadInput);
|
||||
}
|
||||
|
||||
// we check the map
|
||||
if (substitutions.empty())
|
||||
{
|
||||
log += "[WARNING] No substitution provided.\n";
|
||||
OV_WARNING_K("No substitution provided.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
|
||||
log += "[ OK ] -- template file '" + src + "' found.\n";
|
||||
getLogManager() << Kernel::LogLevel_Info << " -- template file '" << src << "' found.\n";
|
||||
|
||||
//we need to create the destination file by copying the template file, then do the first substitution
|
||||
auto it = substitutions.cbegin();
|
||||
success &= regexReplace(src, it->first, ensureSedCompliancy(it->second), dst);
|
||||
++it;
|
||||
|
||||
//next substitutions are done on the - incomplete - destination file itself
|
||||
while (it != substitutions.cend() && success)
|
||||
{
|
||||
getLogManager() << Kernel::LogLevel_Trace << "Executing substitution [" << it->first << "] ->[" << it->second << "]\n";
|
||||
success &= regexReplace(dst, it->first, ensureSedCompliancy(it->second));
|
||||
++it;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
log += "[FAILED] -- " + dst + " cannot be written.\n";
|
||||
OV_ERROR_KRF(" -- " << dst << " cannot be written.", Kernel::ErrorType::BadFileWrite);
|
||||
}
|
||||
|
||||
log += "[ OK ] -- " + dst + " written.\n";
|
||||
getLogManager() << Kernel::LogLevel_Info << " -- " << dst << " written.\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace SkeletonGenerator
|
||||
} // namespace OpenViBE
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <openvibe/kernel/ovIKernelObject.h>
|
||||
//#include <configuration/ovkCConfigurationManager.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace SkeletonGenerator {
|
||||
class CSkeletonGenerator
|
||||
{
|
||||
public:
|
||||
|
||||
CSkeletonGenerator(Kernel::IKernelContext& ctx, GtkBuilder* builder);
|
||||
virtual ~CSkeletonGenerator() { }
|
||||
|
||||
protected:
|
||||
Kernel::IKernelContext& m_kernelCtx;
|
||||
|
||||
GtkBuilder* m_builder = nullptr;
|
||||
|
||||
std::string m_author;
|
||||
std::string m_company;
|
||||
std::string m_directory;
|
||||
std::string m_configFile; // basic application config file
|
||||
bool m_configFileLoaded = false;
|
||||
|
||||
virtual bool initialize() = 0;
|
||||
|
||||
void getCommonParameters();
|
||||
bool saveCommonParameters(const std::string& filename);
|
||||
bool loadCommonParameters(const std::string& filename);
|
||||
|
||||
bool cleanConfigurationFile(const std::string& filename) const;
|
||||
|
||||
// returns a sed-compliant expression to be parsed in a substitution command
|
||||
static std::string ensureSedCompliancy(const std::string& expression);
|
||||
// executes a regex replace and builds a new file, by replacing the matching expressions by the substitute. If no destination file is provided, the template file is modified.
|
||||
// Note that the input must be a valid sed format regex pattern, the function does not check.
|
||||
bool regexReplace(const std::string& src, const std::string& regEx, const std::string& substitute, const std::string& dst = std::string("")) const;
|
||||
|
||||
// get the formatted string date
|
||||
static std::string getDate();
|
||||
|
||||
// generate a new file, giving a template file, a destination file, and a map ofsubstitutions (Tag,Substitute)
|
||||
// return false if an error occurred.
|
||||
bool generate(const std::string& src, const std::string& dst, const std::map<std::string, std::string>& substitutions, std::string& log) const;
|
||||
|
||||
virtual void getCurrentParameters() = 0;
|
||||
virtual bool save(const std::string& filename) = 0;
|
||||
virtual bool load(const std::string& filename) = 0;
|
||||
|
||||
virtual Kernel::ILogManager& getLogManager() const { return m_kernelCtx.getLogManager(); }
|
||||
virtual Kernel::IErrorManager& getErrorManager() const { return m_kernelCtx.getErrorManager(); }
|
||||
};
|
||||
} // namespace SkeletonGenerator
|
||||
} // namespace OpenViBE
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <clocale> // std::setlocale
|
||||
|
||||
#include "ovsgCDriverSkeletonGenerator.h"
|
||||
#include "ovsgCBoxAlgorithmSkeletonGenerator.h"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
OpenViBE::CKernelLoader loader;
|
||||
|
||||
std::cout << "[ INF ] Created kernel loader, trying to load kernel module" << std::endl;
|
||||
OpenViBE::CString err;
|
||||
#if defined TARGET_OS_Windows
|
||||
const OpenViBE::CString file = OpenViBE::Directories::getLibDir() + "/openvibe-kernel.dll";
|
||||
#else
|
||||
const OpenViBE::CString file = OpenViBE::Directories::getLibDir() + "/libopenvibe-kernel.so";
|
||||
#endif
|
||||
if (!loader.load(file, &err)) { std::cout << "[ FAILED ] Error loading kernel (" << err << ")" << " from [" << file << "]\n"; }
|
||||
else
|
||||
{
|
||||
std::cout << "[ INF ] Kernel module loaded, trying to get kernel descriptor" << std::endl;
|
||||
OpenViBE::Kernel::IKernelDesc* desc = nullptr;
|
||||
loader.initialize();
|
||||
loader.getKernelDesc(desc);
|
||||
if (!desc) { std::cout << "[ FAILED ] No kernel descriptor" << std::endl; }
|
||||
else
|
||||
{
|
||||
std::cout << "[ INF ] Got kernel descriptor, trying to create kernel" << std::endl;
|
||||
OpenViBE::Kernel::IKernelContext* ctx = desc->createKernel("skeleton-generator", OpenViBE::Directories::getDataDir() + "/kernel/openvibe.conf");
|
||||
if (!ctx || !ctx->initialize()) { std::cout << "[ FAILED ] No kernel created by kernel descriptor" << std::endl; }
|
||||
else
|
||||
{
|
||||
ctx->getConfigurationManager().addConfigurationFromFile(OpenViBE::Directories::getDataDir() + "/kernel/openvibe.conf");
|
||||
ctx->getConfigurationManager().addConfigurationFromFile(
|
||||
OpenViBE::Directories::getDataDir() + "/applications/skeleton-generator/skeleton-generator.conf");
|
||||
OpenViBE::Toolkit::initialize(*ctx);
|
||||
OpenViBE::Kernel::IConfigurationManager& configMgr = ctx->getConfigurationManager();
|
||||
ctx->getPluginManager().addPluginsFromFiles(configMgr.expand("${Kernel_Plugins}"));
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// We rely on this with 64bit/gtk 2.24, to roll back gtk_init() sometimes switching
|
||||
// the locale to one where ',' is needed instead of '.' for separators of floats,
|
||||
// causing issues, for example getConfigurationManager.expandAsFloat("0.05") -> 0;
|
||||
// due to implementation by std::stod().
|
||||
std::setlocale(LC_ALL, "C");
|
||||
|
||||
GtkBuilder* builder = gtk_builder_new();
|
||||
const OpenViBE::CString filename = OpenViBE::Directories::getDataDir() + "/applications/skeleton-generator/generator-interface.ui";
|
||||
|
||||
OV_ERROR_UNLESS(gtk_builder_add_from_file(builder, filename.toASCIIString(), nullptr), "Problem loading [" << filename << "]",
|
||||
OpenViBE::Kernel::ErrorType::BadFileRead, -1, ctx->getErrorManager(), ctx->getLogManager());
|
||||
|
||||
//gtk_builder_connect_signals(builder, nullptr);
|
||||
|
||||
GtkWidget* dialog = GTK_WIDGET(gtk_builder_get_object(builder, "sg-selection-dialog"));
|
||||
|
||||
gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK);
|
||||
gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
|
||||
|
||||
GtkWidget* radioDriver = GTK_WIDGET(gtk_builder_get_object(builder, "sg-driver-selection-radio-button"));
|
||||
GtkWidget* radioAlgo = GTK_WIDGET(gtk_builder_get_object(builder, "sg-algo-selection-radio-button"));
|
||||
GtkWidget* radioBox = GTK_WIDGET(gtk_builder_get_object(builder, "sg-box-selection-radio-button"));
|
||||
|
||||
|
||||
OpenViBE::SkeletonGenerator::CBoxAlgorithmSkeletonGenerator boxGenerator(*ctx, builder);
|
||||
OpenViBE::SkeletonGenerator::CDriverSkeletonGenerator driverGenerator(*ctx, builder);
|
||||
|
||||
const gint resp = gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
|
||||
if (resp == GTK_RESPONSE_OK)
|
||||
{
|
||||
gtk_widget_hide(GTK_WIDGET(dialog));
|
||||
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioDriver))) { driverGenerator.initialize(); }
|
||||
OV_ERROR_UNLESS(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioAlgo)), "NOT YET AVAILABLE.",
|
||||
OpenViBE::Kernel::ErrorType::Internal, 0, ctx->getErrorManager(), ctx->getLogManager());
|
||||
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioBox))) { boxGenerator.initialize(); }
|
||||
gtk_main();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "User cancelled. Exit." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loader.uninitialize();
|
||||
loader.unload();
|
||||
return 0;
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
IF(OV_DISABLE_GTK)
|
||||
MESSAGE(STATUS "Skipping VRPN Simulator, no GTK")
|
||||
RETURN()
|
||||
ENDIF(OV_DISABLE_GTK)
|
||||
|
||||
PROJECT(openvibe-vrpn-simulator)
|
||||
|
||||
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
|
||||
SET(PROJECT_VERSION ${OV_GLOBAL_VERSION_STRING})
|
||||
|
||||
INCLUDE("FindThirdPartyVRPN_Check")
|
||||
IF(NOT PATH_VRPN)
|
||||
MESSAGE(STATUS " --> Not building ${PROJECT_NAME}")
|
||||
RETURN()
|
||||
ENDIF(NOT PATH_VRPN)
|
||||
|
||||
FILE(GLOB_RECURSE SRC_FILES src/*.cpp src/*.h src/*.inl)
|
||||
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_FILES})
|
||||
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY FOLDER ${APP_FOLDER})
|
||||
|
||||
INCLUDE("FindOpenViBE")
|
||||
INCLUDE("FindOpenViBECommon")
|
||||
INCLUDE("FindThirdPartyGTK")
|
||||
INCLUDE("FindThirdPartyVRPN")
|
||||
|
||||
# ---------------------------------
|
||||
# Finds standard library pthread
|
||||
# Adds library to target
|
||||
# Adds include path
|
||||
# ---------------------------------
|
||||
IF(UNIX)
|
||||
FIND_LIBRARY(LIB_STANDARD_MODULE_PTHREAD pthread)
|
||||
IF(LIB_STANDARD_MODULE_PTHREAD)
|
||||
MESSAGE(STATUS " Found pthread...")
|
||||
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIB_STANDARD_MODULE_PTHREAD})
|
||||
ELSE(LIB_STANDARD_MODULE_PTHREAD)
|
||||
MESSAGE(STATUS " FAILED to find pthread...")
|
||||
ENDIF(LIB_STANDARD_MODULE_PTHREAD)
|
||||
ENDIF(UNIX)
|
||||
|
||||
# ---------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
# ---------------------------------
|
||||
|
||||
|
||||
# ----------------------
|
||||
# Generate launch script
|
||||
# ----------------------
|
||||
OV_INSTALL_LAUNCH_SCRIPT(SCRIPT_PREFIX "${PROJECT_NAME}" EXECUTABLE_NAME "${PROJECT_NAME}")
|
||||
|
||||
# -----------------------------
|
||||
# Install files
|
||||
# -----------------------------
|
||||
INSTALL(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
|
||||
INSTALL(DIRECTORY share/ DESTINATION ${DIST_DATADIR}/openvibe/applications/vrpn-simulator)
|
||||
+293
@@ -0,0 +1,293 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.12 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkAdjustment" id="adjustment1">
|
||||
<property name="lower">-100</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">0.01</property>
|
||||
<property name="page_increment">1</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment2">
|
||||
<property name="lower">-100</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">0.01</property>
|
||||
<property name="page_increment">1</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment3">
|
||||
<property name="lower">-100</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">0.01</property>
|
||||
<property name="page_increment">1</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment4">
|
||||
<property name="lower">-100</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">0.01</property>
|
||||
<property name="page_increment">1</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment5">
|
||||
<property name="lower">-100</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">0.01</property>
|
||||
<property name="page_increment">1</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment6">
|
||||
<property name="lower">-100</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">0.01</property>
|
||||
<property name="page_increment">1</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment7">
|
||||
<property name="lower">-100</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">0.01</property>
|
||||
<property name="page_increment">1</property>
|
||||
</object>
|
||||
<object class="GtkAdjustment" id="adjustment8">
|
||||
<property name="lower">-100</property>
|
||||
<property name="upper">100</property>
|
||||
<property name="step_increment">0.01</property>
|
||||
<property name="page_increment">1</property>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<child>
|
||||
<object class="GtkVBox" id="vbox">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox_analog">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkVScale" id="vscale_0">
|
||||
<property name="height_request">256</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment1</property>
|
||||
<property name="inverted">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVScale" id="vscale_1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment2</property>
|
||||
<property name="inverted">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVScale" id="vscale_2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment3</property>
|
||||
<property name="inverted">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVScale" id="vscale_3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment4</property>
|
||||
<property name="inverted">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVScale" id="vscale_4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment5</property>
|
||||
<property name="inverted">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVScale" id="vscale_5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment6</property>
|
||||
<property name="inverted">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVScale" id="vscale_6">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment7</property>
|
||||
<property name="inverted">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkVScale" id="vscale_7">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="adjustment">adjustment8</property>
|
||||
<property name="inverted">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkHBox" id="hbox_button">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="togglebutton_0">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-about</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="togglebutton_1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-about</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="togglebutton_2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image2">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-about</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="togglebutton_3">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image3">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-about</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="togglebutton_4">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image4">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-about</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="togglebutton_5">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image5">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-about</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="togglebutton_6">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image6">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-about</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="togglebutton_7">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<child>
|
||||
<object class="GtkImage" id="image7">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-about</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
#if defined TARGET_HAS_ThirdPartyVRPN
|
||||
|
||||
#include <clocale> // std::setlocale
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include <openvibe/ov_directories.h>
|
||||
#include <openvibe/ovCString.h>
|
||||
|
||||
#include <vrpn_Button.h>
|
||||
#include <vrpn_Analog.h>
|
||||
#include <vrpn_Connection.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#define _vrpn_peripheral_name_ "openvibe-vrpn@localhost"
|
||||
|
||||
// #define _DEBUG
|
||||
|
||||
vrpn_Connection* connection = nullptr;
|
||||
vrpn_Button_Server* buttonServer = nullptr;
|
||||
vrpn_Analog_Server* analogServer = nullptr;
|
||||
long nAnalog = 0;
|
||||
long nButton = 0;
|
||||
|
||||
typedef union
|
||||
{
|
||||
gpointer data;
|
||||
int idx;
|
||||
} user_data_t;
|
||||
|
||||
void fScrollCB(GtkRange* range, gpointer data)
|
||||
{
|
||||
user_data_t userData;
|
||||
userData.data = data;
|
||||
const gdouble value = gtk_range_get_value(range);
|
||||
analogServer->channels()[userData.idx] = value;
|
||||
|
||||
#if defined _DEBUG
|
||||
std::cout << "Channel " << int(data) << " value changed to " << value << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
void fSwitchCB(GtkToggleButton* button, gpointer data)
|
||||
{
|
||||
user_data_t userData;
|
||||
userData.data = data;
|
||||
const gboolean value = gtk_toggle_button_get_active(button);
|
||||
buttonServer->set_button(userData.idx, value);
|
||||
|
||||
#if defined _DEBUG
|
||||
std::cout << "Channel " << userData.idx << " toggled to " << value << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
void fConnectCB(GtkWidget* widget, gpointer /*data*/)
|
||||
{
|
||||
if (GTK_IS_RANGE(widget))
|
||||
{
|
||||
g_signal_connect(G_OBJECT(widget), "value-changed", G_CALLBACK(fScrollCB), gpointer(nAnalog));
|
||||
nAnalog++;
|
||||
}
|
||||
|
||||
if (GTK_IS_TOGGLE_BUTTON(widget))
|
||||
{
|
||||
g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(fSwitchCB), reinterpret_cast<void*>(nButton));
|
||||
nButton++;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean fIdleApplicationLoop(gpointer /*data*/)
|
||||
{
|
||||
buttonServer->mainloop();
|
||||
analogServer->report_changes();
|
||||
analogServer->mainloop();
|
||||
connection->mainloop();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyVRPN
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#if defined TARGET_HAS_ThirdPartyVRPN
|
||||
const int nChannels = 8;
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
// We rely on this with 64bit/gtk 2.24, to roll back gtk_init() sometimes switching
|
||||
// the locale to one where ',' is needed instead of '.' for separators of floats,
|
||||
// causing issues, for example getConfigurationManager.expandAsFloat("0.05") -> 0;
|
||||
// due to implementation by std::stod().
|
||||
std::setlocale(LC_ALL, "C");
|
||||
|
||||
// g_pConnection=new ::vrpn_Connection;
|
||||
connection = vrpn_create_server_connection();
|
||||
buttonServer = new vrpn_Button_Server(_vrpn_peripheral_name_, connection, nChannels);
|
||||
analogServer = new vrpn_Analog_Server(_vrpn_peripheral_name_, connection, nChannels);
|
||||
|
||||
GtkBuilder* builder =
|
||||
gtk_builder_new(); // glade_xml_new(OpenViBE::Directories::getDataDir() + "/applications/vrpn-simulator/interface.ui", "window", nullptr);
|
||||
const OpenViBE::CString filename = OpenViBE::Directories::getDataDir() + "/applications/vrpn-simulator/interface.ui";
|
||||
if (!gtk_builder_add_from_file(builder, filename, nullptr))
|
||||
{
|
||||
std::cout << "Problem loading [" << filename << "]\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
GtkWidget* mainWindow = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
|
||||
GtkWidget* hBoxButton = GTK_WIDGET(gtk_builder_get_object(builder, "hbox_button"));
|
||||
GtkWidget* hBoxAnalog = GTK_WIDGET(gtk_builder_get_object(builder, "hbox_analog"));
|
||||
|
||||
g_signal_connect(G_OBJECT(mainWindow), "destroy", gtk_main_quit, nullptr);
|
||||
gtk_container_foreach(GTK_CONTAINER(hBoxButton), fConnectCB, nullptr);
|
||||
gtk_container_foreach(GTK_CONTAINER(hBoxAnalog), fConnectCB, nullptr);
|
||||
gtk_builder_connect_signals(builder, nullptr);
|
||||
|
||||
std::cout << "VRPN Stimulator\n";
|
||||
std::cout << "Got " << nAnalog << " analogs...\n";
|
||||
std::cout << "Got " << nButton << " buttons...\n";
|
||||
std::cout << "Using " << nChannels << " VRPN channels...\n";
|
||||
std::cout << "Signals will be sent to peripheral [" << _vrpn_peripheral_name_ << "]\n";
|
||||
|
||||
g_idle_add(fIdleApplicationLoop, nullptr);
|
||||
|
||||
gtk_widget_show(mainWindow);
|
||||
gtk_main();
|
||||
|
||||
delete analogServer;
|
||||
delete buttonServer;
|
||||
delete connection;
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyVRPN
|
||||
return 0;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
PROJECT(xml-configuration-comparison)
|
||||
|
||||
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
|
||||
SET(PROJECT_VERSION ${OV_GLOBAL_VERSION_STRING})
|
||||
|
||||
FILE(GLOB_RECURSE SRC_FILES *.cpp *.hpp)
|
||||
ADD_EXECUTABLE(${PROJECT_NAME} ${SRC_FILES})
|
||||
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY FOLDER ${APP_FOLDER})
|
||||
|
||||
# ----------------------
|
||||
# Generate launch script
|
||||
# ----------------------
|
||||
OV_INSTALL_LAUNCH_SCRIPT(SCRIPT_PREFIX "${PROJECT_NAME}" EXECUTABLE_NAME "${PROJECT_NAME}")
|
||||
|
||||
# -----------------------------
|
||||
# Install files
|
||||
# -----------------------------
|
||||
INSTALL(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \brief Classes of the Box Features Selection Trainer.
|
||||
/// \author Thibaut Monseigne (Inria).
|
||||
/// \version 1.0.
|
||||
/// \date 14/02/2020.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "tinyxml2.h"
|
||||
#include <algorithm>
|
||||
|
||||
// validation Test take in the algorithm output file, the expected output file (reference) and a tolerance threshold
|
||||
bool comparison(const char* file1, const char* file2, bool removeSpace)
|
||||
{
|
||||
// Load Files
|
||||
tinyxml2::XMLDocument xmlDoc1, xmlDoc2;
|
||||
if (xmlDoc1.LoadFile(file1) != 0) // Check File 1 Exist and Loading
|
||||
{
|
||||
std::cerr << "Error during loading File." << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (xmlDoc2.LoadFile(file2) != 0) // Check File 2 Exist and Loading
|
||||
{
|
||||
std::cerr << "Error during loading Reference." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load Roots
|
||||
tinyxml2::XMLNode *root1 = xmlDoc1.FirstChild(), *root2 = xmlDoc2.FirstChild(); // Get Root Node
|
||||
if (root1 == nullptr) // Check Root Node Exist
|
||||
{
|
||||
std::cerr << "File format not compatible." << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (root2 == nullptr) // Check Root Node Exist
|
||||
{
|
||||
std::cerr << "Reference format not compatible." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Count Settings
|
||||
size_t n1 = 0, n2 = 0;
|
||||
for (tinyxml2::XMLElement* e = root1->FirstChildElement(); e != nullptr; e = e->NextSiblingElement()) { n1++; }
|
||||
for (tinyxml2::XMLElement* e = root2->FirstChildElement(); e != nullptr; e = e->NextSiblingElement()) { n2++; }
|
||||
if (n1 != n2)
|
||||
{
|
||||
std::cerr << "File and Reference are not same number of features." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load settings
|
||||
tinyxml2::XMLElement *e1 = root1->FirstChildElement(), *e2 = root2->FirstChildElement();
|
||||
for (size_t i = 0; i < n1; ++i, e1 = e1->NextSiblingElement(), e2 = e2->NextSiblingElement())
|
||||
{
|
||||
std::string s1(e1->GetText()), s2(e2->GetText());
|
||||
std::cout << s1 << std::endl << s2 << std::endl;
|
||||
if (removeSpace)
|
||||
{
|
||||
s1.erase(std::remove_if(s1.begin(), s1.end(), [](const unsigned char x) { return std::isspace(x); }), s1.end());
|
||||
s2.erase(std::remove_if(s2.begin(), s2.end(), [](const unsigned char x) { return std::isspace(x); }), s2.end());
|
||||
}
|
||||
std::cout << s1 << std::endl << s2 << std::endl;
|
||||
|
||||
if (s1 != s2)
|
||||
{
|
||||
std::cerr << "Setting number " << i << " is different, For File : \n" << s1 << "\nfor Reference : \n" << s2 << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(const int argc, char* argv[])
|
||||
{
|
||||
if (argc != 4)
|
||||
{
|
||||
std::cout << "Usage: " << argv[0] << " <file> <reference> <remove space (true or false)>\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool remove;
|
||||
if (strcmp(argv[3], "true") == 0) { remove = true; }
|
||||
else if (strcmp(argv[3], "false") == 0) { remove = false; }
|
||||
else
|
||||
{
|
||||
std::cout << "Usage: <remove space> must be true or false not " << argv[3] << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!comparison(argv[1], argv[2], remove))
|
||||
{
|
||||
std::cout << "Algorithm failed validation test \n" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "Test passed\n" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
+2557
File diff suppressed because it is too large
Load Diff
+2063
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user