init
This commit is contained in:
+51
@@ -0,0 +1,51 @@
|
||||
PROJECT(openvibe-plugins-stimulation)
|
||||
|
||||
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_LIBRARY(${PROJECT_NAME} SHARED ${SRC_FILES})
|
||||
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
FOLDER ${PLUGINS_FOLDER}
|
||||
COMPILE_FLAGS "-DOVP_Exports -DOVP_Shared")
|
||||
|
||||
INCLUDE("FindOpenViBE")
|
||||
INCLUDE("FindOpenViBECommon")
|
||||
INCLUDE("FindOpenViBEToolkit")
|
||||
INCLUDE("FindOpenViBEModuleEBML")
|
||||
INCLUDE("FindOpenViBEModuleTCPTagging")
|
||||
INCLUDE("FindThirdPartyGTK")
|
||||
INCLUDE("FindThirdPartyLua")
|
||||
INCLUDE("FindThirdPartyOpenAL")
|
||||
INCLUDE("FindThirdPartyBoost")
|
||||
INCLUDE("FindThirdPartyBoost_Thread")
|
||||
INCLUDE("FindThirdPartyBoost_System")
|
||||
INCLUDE("FindOpenViBEVisualizationToolkit")
|
||||
|
||||
# ---------------------------------
|
||||
# Finds standard library winmm
|
||||
# Adds library to target
|
||||
# Adds include path
|
||||
# ---------------------------------
|
||||
IF(WIN32)
|
||||
FIND_LIBRARY(LIB_STANDARD_MODULE_WINMM winmm)
|
||||
IF(LIB_STANDARD_MODULE_WINMM)
|
||||
MESSAGE(STATUS " Found winmm...")
|
||||
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIB_STANDARD_MODULE_WINMM})
|
||||
ELSE(LIB_STANDARD_MODULE_WINMM)
|
||||
MESSAGE(STATUS " FAILED to find winmm...")
|
||||
ENDIF(LIB_STANDARD_MODULE_WINMM)
|
||||
ENDIF(WIN32)
|
||||
|
||||
# -----------------------------
|
||||
# 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/plugins/stimulation)
|
||||
INSTALL(DIRECTORY box-tutorials DESTINATION ${DIST_DATADIR}/openvibe/scenarios/)
|
||||
+550
@@ -0,0 +1,550 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>1</FormatVersion>
|
||||
<Creator>openvibe</Creator>
|
||||
<CreatorVersion>2.0</CreatorVersion>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x00007851, 0x00004cd4)</Identifier>
|
||||
<Name>Signal display</Name>
|
||||
<AlgorithmClassIdentifier>(0x0055be5f, 0x087bdd12)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Data</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6ab26b81, 0x0f8c02f3)</TypeIdentifier>
|
||||
<Name>Channel Units</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x5de046a6, 0x086340aa)</TypeIdentifier>
|
||||
<Name>Display Mode</Name>
|
||||
<DefaultValue>Scan</DefaultValue>
|
||||
<Value>Scan</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x33a30739, 0x00d5299b)</TypeIdentifier>
|
||||
<Name>Auto vertical scale</Name>
|
||||
<DefaultValue>Per channel</DefaultValue>
|
||||
<Value>Per channel</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Scale refresh interval (secs)</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>1</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Scale</Name>
|
||||
<DefaultValue>100</DefaultValue>
|
||||
<Value>100</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Offset</Name>
|
||||
<DefaultValue>0</DefaultValue>
|
||||
<Value>0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Time Scale</Name>
|
||||
<DefaultValue>10</DefaultValue>
|
||||
<Value>10</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Horizontal ruler</Name>
|
||||
<DefaultValue>true</DefaultValue>
|
||||
<Value>true</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Vertical ruler</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Multiview</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>304.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>38</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>480.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x92c056a7, 0x2dc71aff)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>113</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x00fdd416)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc67a01dc, 0x28ce06c1)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>9</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x0f152388, 0x4bae9e07)</Identifier>
|
||||
<Name>Keyboard stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x00d317b9, 0x6324c3ff)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Outgoing Stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename</Name>
|
||||
<DefaultValue>${Path_Data}/plugins/stimulation/simple-keyboard-to-stimulations.txt</DefaultValue>
|
||||
<Value>${Path_Data}/plugins/stimulation/simple-keyboard-to-stimulations.txt</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>80</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>25</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>640</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x8d89d3b7, 0x8339d210)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>161</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x003bc1b1)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x2b9fd0aa, 0x64525c3a)</Identifier>
|
||||
<Name>Mux + 5s delay</Name>
|
||||
<AlgorithmClassIdentifier>(0x0b5a2787, 0x02750621)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>New input</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>New input</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xb0d0db45, 0x49cbc34a)</TypeIdentifier>
|
||||
<Name>Lua Script</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>${Player_ScenarioDirectory}/scripts/sample-lua-script.lua</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x17ee7c08, 0x94c14893)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>192</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>51</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>528</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xd6e3f48b, 0xbee3523a)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x61d11811, 0x71e65362)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>123</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x05321c99)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf191c1c8, 0xa0123976)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x44d592ef, 0x79906895)</Identifier>
|
||||
<Name>Clock stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x4f756d3f, 0x29ff0b96)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Interstimulation interval (in sec)</Name>
|
||||
<DefaultValue>1.0</DefaultValue>
|
||||
<Value>1.0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>80</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>25</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>480</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27b3ee3c, 0xc50527e6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>130</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x004737e8)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x7f12f9f6, 0x1203d055)</Identifier>
|
||||
<Name>Time signal</Name>
|
||||
<AlgorithmClassIdentifier>(0x28a5e7ff, 0x530095de)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Generated signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Sampling frequency</Name>
|
||||
<DefaultValue>512</DefaultValue>
|
||||
<Value>512</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Generated epoch sample count</Name>
|
||||
<DefaultValue>32</DefaultValue>
|
||||
<Value>32</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>80</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>25</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x9e5ca01e, 0x30a4d8c3)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>94</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x005a4c5f)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x000006db, 0x00007628)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x2b9fd0aa, 0x64525c3a)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00007851, 0x00004cd4)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>224</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>528</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>280</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>480</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00003a74, 0x00007163)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x7f12f9f6, 0x1203d055)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00007851, 0x00004cd4)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>99</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>280</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>465</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x11bc52c7, 0x7d39e76b)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x44d592ef, 0x79906895)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x2b9fd0aa, 0x64525c3a)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>99</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>480</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>162</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>520</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x68865d3e, 0x16e4e1af)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x0f152388, 0x4bae9e07)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x2b9fd0aa, 0x64525c3a)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>99</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>640</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>162</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>535</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x3c41271e, 0x4d42de04)</Identifier>
|
||||
<Text>The <i><b>Lua Stimulator</b></i> box delays muxes the stimulations
|
||||
from the <i>Clock Stimulator</i> and the <i>Keyboard Stimulator</i>
|
||||
boxes. Each muxed stimulation is delayed by 5 seconds.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>752</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>192</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x565ec9d6, 0x448fe34f)</Identifier>
|
||||
<Text>You can browse each box' documentation by selecting the box and pressing <b>F1</b></Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>480</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>368</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0x00007851, 0x00004cd4)","childCount":0,"identifier":"(0x000036ad, 0x00006f70)","index":0,"parentIdentifier":"(0xffffffff, 0xffffffff)","type":3},{"boxIdentifier":"(0x0f152388, 0x4bae9e07)","childCount":0,"identifier":"(0x06ca0825, 0x1209828e)","index":0,"parentIdentifier":"(0xffffffff, 0xffffffff)","type":3},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":400,"identifier":"(0x492edea0, 0x7fcf1a84)","index":0,"name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":400},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x333b0470, 0x69c97194)","index":0,"name":"Default tab","parentIdentifier":"(0x492edea0, 0x7fcf1a84)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x36539222, 0x0801778f)","index":0,"name":"Empty","parentIdentifier":"(0x333b0470, 0x69c97194)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
io.write("initialize has been called\n");
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
-- inspects the box topology
|
||||
io.write(string.format("box has %i input(s)\n", box:get_input_count()))
|
||||
io.write(string.format("box has %i output(s)\n", box:get_output_count()))
|
||||
io.write(string.format("box has %i setting(s)\n", box:get_setting_count()))
|
||||
for i = 1, box:get_setting_count() do
|
||||
io.write(string.format(" - setting %i has value [%s]\n", i, box:get_setting(i)))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
io.write("uninitialize has been called\n")
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
io.write("process has been called\n")
|
||||
|
||||
-- loop until box:keep_processing() returns zero
|
||||
-- cpu will be released with a call to sleep
|
||||
-- at the end of the loop
|
||||
while box:keep_processing() do
|
||||
|
||||
-- gets current simulated time
|
||||
t = box:get_current_time()
|
||||
|
||||
-- loops on all inputs of the box
|
||||
for input = 1, box:get_input_count() do
|
||||
|
||||
-- loops on every received stimulation for a given input
|
||||
for stimulation = 1, box:get_stimulation_count(input) do
|
||||
|
||||
-- gets the received stimulation
|
||||
identifier, date, duration = box:get_stimulation(input, 1)
|
||||
|
||||
-- logs the received stimulation
|
||||
io.write(string.format("At time %f on input %i got stimulation id:%s date:%s duration:%s\n", t, input, identifier, date, duration))
|
||||
|
||||
-- discards it
|
||||
box:remove_stimulation(input, 1)
|
||||
|
||||
-- triggers a new OVTK_StimulationId_Label_00 stimulation five seconds after
|
||||
box:send_stimulation(1, OVTK_StimulationId_Label_00, t+5, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- releases cpu
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>1</FormatVersion>
|
||||
<Creator>openvibe</Creator>
|
||||
<CreatorVersion>2.0</CreatorVersion>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x42f8bf57, 0x71efc888)</Identifier>
|
||||
<Name>Clock stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x4f756d3f, 0x29ff0b96)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Interstimulation interval (in sec)</Name>
|
||||
<DefaultValue>1.0</DefaultValue>
|
||||
<Value>10.000000</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>32</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>24</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>384</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27b3ee3c, 0xc50527e6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>114</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x642d51bb, 0x4df52)</Identifier>
|
||||
<Name>Run Command</Name>
|
||||
<AlgorithmClassIdentifier>(0x48843891, 0x7bfc57f4)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 1</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_01</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 1</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>xdg-open http://openvibe.inria.fr &</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 2</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_02</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 2</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>START iexplore http://openvibe.inria.fr</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>128</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>36</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>384</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xe44a71e7, 0x7964dd76)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x61d11811, 0x71e65362)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>101</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x072a525b, 0x544ef3ed)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x42f8bf57, 0x71efc888)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x642d51bb, 0x4df52)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>50</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>384</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>105</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>384</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x015cb409, 0x03490d65)</Identifier>
|
||||
<Text>You can browse each box' documentation by selecting the box and pressing <b>F1</b></Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>512</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>208</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x44a39962, 0x4b0bfcad)</Identifier>
|
||||
<Text>The <i><b>Run Command</b></i> box
|
||||
launches a web browser each time
|
||||
a stimulation is received. This box
|
||||
can be used to launch whatever
|
||||
command most fits your needs.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>592</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>128</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x4afd0495, 0x0b2b4bf2)</Identifier>
|
||||
<Text>The <i>Clock Stimulator</i> box
|
||||
is configured to trigger a stimulation
|
||||
every 10 seconds.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>592</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>32</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":480,"identifier":"(0x04b1b9ca, 0x49fdacb7)","index":0,"name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":640},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x08218b08, 0x6e0a3371)","index":0,"name":"Default tab","parentIdentifier":"(0x04b1b9ca, 0x49fdacb7)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x15e14689, 0x29e46499)","index":0,"name":"Empty","parentIdentifier":"(0x08218b08, 0x6e0a3371)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+700
@@ -0,0 +1,700 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>1</FormatVersion>
|
||||
<Creator>openvibe</Creator>
|
||||
<CreatorVersion>2.0</CreatorVersion>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x00000058, 0x00001507)</Identifier>
|
||||
<Name>Sign changes as stimulations</Name>
|
||||
<AlgorithmClassIdentifier>(0x0055be5f, 0x087bdd12)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Data</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6ab26b81, 0x0f8c02f3)</TypeIdentifier>
|
||||
<Name>Channel Units</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x5de046a6, 0x086340aa)</TypeIdentifier>
|
||||
<Name>Display Mode</Name>
|
||||
<DefaultValue>Scan</DefaultValue>
|
||||
<Value>Scan</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x33a30739, 0x00d5299b)</TypeIdentifier>
|
||||
<Name>Auto vertical scale</Name>
|
||||
<DefaultValue>Per channel</DefaultValue>
|
||||
<Value>Per channel</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Scale refresh interval (secs)</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>5</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Scale</Name>
|
||||
<DefaultValue>100</DefaultValue>
|
||||
<Value>100</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Offset</Name>
|
||||
<DefaultValue>0</DefaultValue>
|
||||
<Value>0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Time Scale</Name>
|
||||
<DefaultValue>10</DefaultValue>
|
||||
<Value>10</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Horizontal ruler</Name>
|
||||
<DefaultValue>true</DefaultValue>
|
||||
<Value>true</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Vertical ruler</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Multiview</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>448.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>43</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>304.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x92c056a7, 0x2dc71aff)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>198</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x003d2119)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>9</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00000b7d, 0x000021cf)</Identifier>
|
||||
<Name>Sinus oscillator</Name>
|
||||
<AlgorithmClassIdentifier>(0x7e33bdb8, 0x68194a4a)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Generated signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Channel count</Name>
|
||||
<DefaultValue>4</DefaultValue>
|
||||
<Value>2</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Sampling frequency</Name>
|
||||
<DefaultValue>512</DefaultValue>
|
||||
<Value>256</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Generated epoch sample count</Name>
|
||||
<DefaultValue>32</DefaultValue>
|
||||
<Value>32</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>48</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x0b214ed8, 0x1f9ad83a)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>109</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x006b51c4)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00001768, 0x00002032)</Identifier>
|
||||
<Name>Simple DSP</Name>
|
||||
<AlgorithmClassIdentifier>(0x00e26fa1, 0x1dbab1b2)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input - A</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Equation</Name>
|
||||
<DefaultValue>x</DefaultValue>
|
||||
<Value>x-1.5</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>208</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>33</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x21889dc4, 0x1126497e)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>82</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x00317051)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00002bfe, 0x0000718a)</Identifier>
|
||||
<Name>Sign Change Detector</Name>
|
||||
<AlgorithmClassIdentifier>(0x04fa78cd, 0xafe45de7)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Signal</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>On Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_01</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_01</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Off Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Channel Index</Name>
|
||||
<DefaultValue>1</DefaultValue>
|
||||
<Value>1</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>368</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>304</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x13bdcd99, 0x9faeff20)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>150</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002af6e1)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc67a01dc, 0x28ce06c1)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000033a4, 0x0000426b)</Identifier>
|
||||
<Name>Temporal filter</Name>
|
||||
<AlgorithmClassIdentifier>(0xb4f9d042, 0x9d79f2e5)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Input signal</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Filtered signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2f2c606c, 0x8512ed68)</TypeIdentifier>
|
||||
<Name>Filter method</Name>
|
||||
<DefaultValue>Butterworth</DefaultValue>
|
||||
<Value>Butterworth</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xfa20178e, 0x4cba62e9)</TypeIdentifier>
|
||||
<Name>Filter type</Name>
|
||||
<DefaultValue>Band pass</DefaultValue>
|
||||
<Value>Band stop</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Filter order</Name>
|
||||
<DefaultValue>4</DefaultValue>
|
||||
<Value>4</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Low cut frequency (Hz)</Name>
|
||||
<DefaultValue>29</DefaultValue>
|
||||
<Value>8</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>High cut frequency (Hz)</Name>
|
||||
<DefaultValue>40</DefaultValue>
|
||||
<Value>20</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Pass band ripple (dB)</Name>
|
||||
<DefaultValue>0.5</DefaultValue>
|
||||
<Value>0.5</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>128</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27a4ceec, 0x876d6384)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>103</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x0041a8b8)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>6</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x000009dc, 0x00007ae0)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001768, 0x00002032)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00000058, 0x00001507)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>231</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>422</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>289</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x0000173b, 0x00002ff3)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001768, 0x00002032)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00002bfe, 0x0000718a)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>231</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>352</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>304</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x0000225d, 0x00004d7f)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000033a4, 0x0000426b)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00001768, 0x00002032)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>146</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>187</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00003775, 0x0000549c)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00000b7d, 0x000021cf)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000033a4, 0x0000426b)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>66</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>112</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00005e52, 0x00006ce3)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00002bfe, 0x0000718a)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00000058, 0x00001507)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>386</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>304</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>422</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>304</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x00001b49, 0x0000218a)</Identifier>
|
||||
<Text>A <b>DSP</b> box is used in combination with the
|
||||
<b>Sign Change Detector</b> to create a threshold detector.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>624</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>224</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x0000585f, 0x000060ca)</Identifier>
|
||||
<Text>Sinus oscillator generates 2 channels of signal.
|
||||
The signal is filtered for simplification.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>608</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>80</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x00005aa9, 0x00006)</Identifier>
|
||||
<Text>The <b>Sign Change Detector</b> takes sends stimulations
|
||||
when the signal on selected channel (0 in this case) becomes
|
||||
positive or negative.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>656</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>352</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x000063b7, 0x00005d9b)</Identifier>
|
||||
<Text>You can browse each box' documentation by selecting the box and pressing <b>F1</b></Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>512</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0x00000058, 0x00001507)","childCount":0,"identifier":"(0x0000195a, 0x00000135)","index":0,"parentIdentifier":"(0xffffffff, 0xffffffff)","type":3},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":507,"identifier":"(0x00005fc9, 0x00000682)","index":0,"name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":798},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x0000430b, 0x000040ff)","index":0,"name":"Default tab","parentIdentifier":"(0x00005fc9, 0x00000682)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x0000717d, 0x0000035a)","index":0,"name":"Empty","parentIdentifier":"(0x0000430b, 0x000040ff)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x790d75b8, 0x3bb90c33)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x8c1fc55b, 0x7b433dc2)</Identifier>
|
||||
<Value>1.0</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x9f5c4075, 0x4a0d3666)</Identifier>
|
||||
<Value>Sign Change Detector example</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf36a1567, 0xd13c53da)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf6b2e3fa, 0x7bd43926)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf8034a49, 0x8b3f37cc)</Identifier>
|
||||
<Value>Inria</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</OpenViBE-Scenario>
|
||||
+728
@@ -0,0 +1,728 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>1</FormatVersion>
|
||||
<Creator>openvibe</Creator>
|
||||
<CreatorVersion>2.0</CreatorVersion>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x00001596, 0x00001900)</Identifier>
|
||||
<Name>TCP Tagging (recommended)</Name>
|
||||
<AlgorithmClassIdentifier>(0x65731e1d, 0x47de5276)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulation stream 1</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xa88b3667, 0x0871638c)</TypeIdentifier>
|
||||
<Name>Log level to use</Name>
|
||||
<DefaultValue>Debug</DefaultValue>
|
||||
<Value>Information</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>400.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>53</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>1072.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xf451ad91, 0x14c75f86)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>195</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x09c475d6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>true</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x341d3912, 0x1478de86)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000016ad, 0x0000777c)</Identifier>
|
||||
<Name>Sound Player</Name>
|
||||
<AlgorithmClassIdentifier>(0x7ac2396f, 0x7ee52efe)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulation stream</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulation stream</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>PLAY trigger</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_01</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>STOP trigger</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_01</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_02</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>File to play</Name>
|
||||
<DefaultValue>${Path_Data}/plugins/stimulation/ov_beep.wav</DefaultValue>
|
||||
<Value>${Path_Data}/plugins/stimulation/ov_beep.wav</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Loop</Name>
|
||||
<DefaultValue>False</DefaultValue>
|
||||
<Value>true</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>192</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xd327e20a, 0xaae6b1f8)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>94</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x03910c35)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>4</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00001828, 0x00007c53)</Identifier>
|
||||
<Name>Keyboard stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x00d317b9, 0x6324c3ff)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Outgoing Stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename</Name>
|
||||
<DefaultValue>${Path_Data}/plugins/stimulation/simple-keyboard-to-stimulations.txt</DefaultValue>
|
||||
<Value>${Path_Data}/plugins/stimulation/simple-keyboard-to-stimulations.txt</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>64</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x8d89d3b7, 0x8339d210)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>140</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x018383ab)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00003786, 0x000009c4)</Identifier>
|
||||
<Name>Direct (deprecated)</Name>
|
||||
<AlgorithmClassIdentifier>(0x65731e1d, 0x47de5276)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulation stream 1</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xa88b3667, 0x0871638c)</TypeIdentifier>
|
||||
<Name>Log level to use</Name>
|
||||
<DefaultValue>Debug</DefaultValue>
|
||||
<Value>Information</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>43</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xf451ad91, 0x14c75f86)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>135</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x0a3bcd39)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00005760, 0x000043ee)</Identifier>
|
||||
<Name>Acquisition client</Name>
|
||||
<AlgorithmClassIdentifier>(0x35d225cb, 0x3e6e3a5f)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x403488e7, 0x565d70b6)</TypeIdentifier>
|
||||
<Name>Experiment information</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Signal stream</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x013df452, 0xa3a8879a)</TypeIdentifier>
|
||||
<Name>Channel localisation</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6ab26b81, 0x0f8c02f3)</TypeIdentifier>
|
||||
<Name>Channel units</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Acquisition server hostname</Name>
|
||||
<DefaultValue>${AcquisitionServer_HostName}</DefaultValue>
|
||||
<Value>${AcquisitionServer_HostName}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Acquisition server port</Name>
|
||||
<DefaultValue>1024</DefaultValue>
|
||||
<Value>1024</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>272.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>33</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>992.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x0d4656c0, 0xc95b1fa8)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>121</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x017ff9bc)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>true</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x341d3912, 0x1478de86)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>5</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00007bff, 0x00005623)</Identifier>
|
||||
<Name>Signal display</Name>
|
||||
<AlgorithmClassIdentifier>(0x0055be5f, 0x087bdd12)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Data</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6ab26b81, 0x0f8c02f3)</TypeIdentifier>
|
||||
<Name>Channel Units</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x5de046a6, 0x086340aa)</TypeIdentifier>
|
||||
<Name>Display Mode</Name>
|
||||
<DefaultValue>Scan</DefaultValue>
|
||||
<Value>Scan</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x33a30739, 0x00d5299b)</TypeIdentifier>
|
||||
<Name>Auto vertical scale</Name>
|
||||
<DefaultValue>Per channel</DefaultValue>
|
||||
<Value>Per channel</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Scale refresh interval (secs)</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>5</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Scale</Name>
|
||||
<DefaultValue>100</DefaultValue>
|
||||
<Value>100</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Vertical Offset</Name>
|
||||
<DefaultValue>0</DefaultValue>
|
||||
<Value>0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Time Scale</Name>
|
||||
<DefaultValue>10</DefaultValue>
|
||||
<Value>10</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Bottom ruler</Name>
|
||||
<DefaultValue>true</DefaultValue>
|
||||
<Value>true</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Left ruler</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2cdb2f0b, 0x12f231ea)</TypeIdentifier>
|
||||
<Name>Multiview</Name>
|
||||
<DefaultValue>false</DefaultValue>
|
||||
<Value>false</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>336.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>43</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>960.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x92c056a7, 0x2dc71aff)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x527ad68d, 0x16d746a0)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>100</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x01bab220)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>true</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x341d3912, 0x1478de86)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>9</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x000004c8, 0x000021b0)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00005760, 0x000043ee)</BoxIdentifier>
|
||||
<BoxOutputIndex>1</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00007bff, 0x00005623)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>295</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>977</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>310</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>945</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x0000338f, 0x000044d6)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000016ad, 0x0000777c)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00003786, 0x000009c4)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>210</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>294</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x000060db, 0x00003025)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00005760, 0x000043ee)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00007bff, 0x00005623)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>295</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>992</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>310</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>960</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x000063f2, 0x00002eeb)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00005760, 0x000043ee)</BoxIdentifier>
|
||||
<BoxOutputIndex>2</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00001596, 0x00001900)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>295</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>992</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>369</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>1072</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00007693, 0x00003000)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001828, 0x00007c53)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000016ad, 0x0000777c)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>82</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>288</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments>
|
||||
<Comment>
|
||||
<Identifier>(0x00004723, 0x000027e9)</Identifier>
|
||||
<Text>The <i><b>Sound Player</b></i> box
|
||||
plays and stops a sound according to stimulation triggers.
|
||||
The sound can be in OGG or WAV format.
|
||||
|
||||
The triggers are passed on after the change
|
||||
to Acquisition Server using TCP Tagging
|
||||
which is the recommended way to combine
|
||||
the stimulation markers with the signal.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>560.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>208.000000</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x00004e97, 0x000004ca)</Identifier>
|
||||
<Text>You can browse each box' documentation by selecting the box and pressing <b>F1</b></Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>480</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>400</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x00006490, 0x00006724)</Identifier>
|
||||
<Text>The <i>Keyboard Stimulator</i> box
|
||||
sends a specific stimulation when pressing a key.
|
||||
|
||||
In the case of this scenario, key 'a' will start the
|
||||
sound loop playback and 'z' will stop it.
|
||||
|
||||
The <i>Keyboard stimulator</i>
|
||||
window must have focus when the keys are pressed.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>560</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>64</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x000068a8, 0x00000f8c)</Identifier>
|
||||
<Text>Unmuting the chain below will show stimulations
|
||||
as they come back from the Acquisition Server's
|
||||
TCP Tagging module.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>992.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>208.000000</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
<Comment>
|
||||
<Identifier>(0x00007576, 0x0000094b)</Identifier>
|
||||
<Text>The <i>Stimulation Listener</i> box
|
||||
prints the incoming stimulations to the console.</Text>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x473d9a43, 0x97fc0a97)</Identifier>
|
||||
<Value>560</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x7234b86b, 0x2b8651a5)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Comment>
|
||||
</Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0x00007bff, 0x00005623)","childCount":0,"identifier":"(0x00004074, 0x000038c0)","index":0,"parentIdentifier":"(0xffffffff, 0xffffffff)","type":3},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x00007ad7, 0x00002240)","index":0,"name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":480},{"boxIdentifier":"(0x00001828, 0x00007c53)","childCount":0,"identifier":"(0x00007ae2, 0x000042d6)","index":0,"parentIdentifier":"(0xffffffff, 0xffffffff)","type":3},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x00007a1f, 0x000058c9)","index":0,"name":"Default tab","parentIdentifier":"(0x00007ad7, 0x00002240)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x0000596c, 0x0000430e)","index":0,"name":"Empty","parentIdentifier":"(0x00007a1f, 0x000058c9)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+376
@@ -0,0 +1,376 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>2</FormatVersion>
|
||||
<Creator>OpenViBE Designer</Creator>
|
||||
<CreatorVersion>2.2.0</CreatorVersion>
|
||||
<Settings></Settings>
|
||||
<Inputs></Inputs>
|
||||
<Outputs></Outputs>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x0000377e, 0x00004994)</Identifier>
|
||||
<Name>After Validation</Name>
|
||||
<AlgorithmClassIdentifier>(0x65731e1d, 0x47de5276)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulation stream 1</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xa88b3667, 0x0871638c)</TypeIdentifier>
|
||||
<Name>Log level to use</Name>
|
||||
<DefaultValue>Information</DefaultValue>
|
||||
<Value>Information</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>608</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xf451ad91, 0x14c75f86)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x0000377e, 0x00004995)</Identifier>
|
||||
<Name>Before Validation</Name>
|
||||
<AlgorithmClassIdentifier>(0x65731e1d, 0x47de5276)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulation stream 1</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xa88b3667, 0x0871638c)</TypeIdentifier>
|
||||
<Name>Log level to use</Name>
|
||||
<DefaultValue>Information</DefaultValue>
|
||||
<Value>Information</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>768</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xf451ad91, 0x14c75f86)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000046ff, 0x00004b04)</Identifier>
|
||||
<Name>Clock stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x4f756d3f, 0x29ff0b96)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Interstimulation interval (in sec)</Name>
|
||||
<DefaultValue>1.0</DefaultValue>
|
||||
<Value>1.0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>240</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>768</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27b3ee3c, 0xc50527e6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x0000476c, 0x000031e0)</Identifier>
|
||||
<Name>Stimulation Validator</Name>
|
||||
<AlgorithmClassIdentifier>(0x393d15e9, 0x5b6f63b9)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Input</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation to count</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_01</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Number for validation</Name>
|
||||
<DefaultValue>2</DefaultValue>
|
||||
<Value>2</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>608</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x25910892, 0x4228395c)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x666fffff, 0x666fffff)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000050a2, 0x00006fea)</Identifier>
|
||||
<Name>Player Controller</Name>
|
||||
<AlgorithmClassIdentifier>(0x5f426dce, 0x08456e13)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation name</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xcc14d8d6, 0xf27ecb73)</TypeIdentifier>
|
||||
<Name>Action to perform</Name>
|
||||
<DefaultValue>Pause</DefaultValue>
|
||||
<Value>Stop</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>304</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>864</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x568d148e, 0x650792b3)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00006d4d, 0x00002b7a)</Identifier>
|
||||
<Name>Timeout</Name>
|
||||
<AlgorithmClassIdentifier>(0x24fcd292, 0x5c8f6aa8)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Input Stream</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output Stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Timeout delay</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>5</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Output Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>240</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>864</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x1eaee00e, 0xdb05d34e)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x0000304a, 0x00007b3d)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x0000476c, 0x000031e0)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x0000377e, 0x00004994)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00005109, 0x00004361)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00006d4d, 0x00002b7a)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000050a2, 0x00006fea)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00007d7e, 0x00000e5b)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000046ff, 0x00004b04)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x0000476c, 0x000031e0)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00007fe8, 0x000035ac)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000046ff, 0x00004b04)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x0000377e, 0x00004995)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments></Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x00007b44, 0x0000460a)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x000037a7, 0x0000188c)","name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":480},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x00002643, 0x000018a3)","index":0,"name":"Default tab","parentIdentifier":"(0x000037a7, 0x0000188c)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x000028e2, 0x00005438)","index":0,"name":"Empty","parentIdentifier":"(0x00002643, 0x000018a3)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_KeyboardStimulator Keyboard stimulator
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KeyboardStimulator_Description|
|
||||
* This plugin grabs key presses and translates them into OpenViBE stimulations
|
||||
* |OVP_DocEnd_BoxAlgorithm_KeyboardStimulator_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KeyboardStimulator_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_KeyboardStimulator_Outputs|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_KeyboardStimulator_Output1|
|
||||
* A stream of stimulations generated by key presses
|
||||
* |OVP_DocEnd_BoxAlgorithm_KeyboardStimulator_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KeyboardStimulator_Settings|
|
||||
* |OVP_DocEnd_BoxAlgorithm_KeyboardStimulator_Settings|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_KeyboardStimulator_Setting1|
|
||||
* The name of the file containing the associations between keys and stimulations
|
||||
* |OVP_DocEnd_BoxAlgorithm_KeyboardStimulator_Setting1|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_KeyboardStimulator_Setting2|
|
||||
* TCP Tagging host address to send stimuli to (empty string: do not connect)
|
||||
* |OVP_DocEnd_BoxAlgorithm_KeyboardStimulator_Setting2|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_KeyboardStimulator_Setting3|
|
||||
* TCP Tagging host port
|
||||
* |OVP_DocEnd_BoxAlgorithm_KeyboardStimulator_Setting3|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KeyboardStimulator_Examples|
|
||||
*
|
||||
* Here is one example of configuration file :
|
||||
*
|
||||
* \code
|
||||
* Left 0x00000301
|
||||
* Right 0x00000302
|
||||
* Up 0x0000030C
|
||||
* Down 0x00000306
|
||||
* a 0x00000300
|
||||
* r 0x00000312
|
||||
* t 0x00000311
|
||||
* y 0x0000030D
|
||||
* BackSpace 0x00000004
|
||||
* Return 0x00000320
|
||||
* \endcode
|
||||
*
|
||||
* |OVP_DocEnd_BoxAlgorithm_KeyboardStimulator_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KeyboardStimulator_Miscellaneous|
|
||||
*
|
||||
* The configuration file should contain a list where each element is formatted like this :
|
||||
*
|
||||
* \code
|
||||
* Name_of_the_key Stimulation_numeric_identifier
|
||||
* \endcode
|
||||
*
|
||||
* For a complete listing of the key names, please consult GDK's "gdk/gdkkeysyms.h" header file.
|
||||
* The names are the same but without the leading "GDK_"
|
||||
*
|
||||
* If TCP Tagging hostname is specified, the stimulator will send the stimuli
|
||||
* to Acquisition Server in that address for accurate alignment of the stimuli
|
||||
* to the EEG signal. If the keypresses are not wanted to be inserted into the signal,
|
||||
* set host address to an empty string. To send to an Acquisition Server running on the same computer,
|
||||
* use 'localhost' as the address.
|
||||
*
|
||||
* |OVP_DocEnd_BoxAlgorithm_KeyboardStimulator_Miscellaneous|
|
||||
*/
|
||||
+312
@@ -0,0 +1,312 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_LuaStimulator Lua Stimulator
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_LuaStimulator_Description|
|
||||
This box gives a fast control over stimulation streams thanks to Lua scripts.
|
||||
|
||||
Scripts are very simple programming languages. They are usually easy to understand,
|
||||
fast to write and reasonably fast to execute. They are used for high level operations
|
||||
and do not need compilation. There are a number of scripting languages around.
|
||||
Lua is one of those scripting languages. It is know for its execution speed and it's ease
|
||||
of use. It can be used on a large number of platforms. For all those reasons, Lua is widely
|
||||
used in the video game industry. If you want more information about Lua, feel free to visit
|
||||
their website at http://www.lua.org and on their documentation website http://www.lua.org/manual/5.1
|
||||
|
||||
This box has a variable number of inputs and outputs. The author is able to add as many
|
||||
of them as necessary. The box automatically decodes the incoming streams and automatically
|
||||
encodes the outgoing streams, leaving the interesting part to the script : doing something with
|
||||
input stimulations and produce output stimulations.
|
||||
|
||||
The script should be divided in three functions :
|
||||
- \ref LuaScriptAPI_initialize
|
||||
- \ref LuaScriptAPI_uninitialize
|
||||
- \ref LuaScriptAPI_process
|
||||
|
||||
The whole script behavior should be executed in a single execution of the \c process function.
|
||||
Thanks to this, the script code is made a lot more easy to understand than the usual C++ boxes.
|
||||
Of course, in case it is necessary, the script can yield, letting the kernel perform a new step
|
||||
of execution.
|
||||
|
||||
A simple API is proposed allowing the script to :
|
||||
- \ref LuaScriptAPI_get_input_count
|
||||
- \ref LuaScriptAPI_get_output_count
|
||||
- \ref LuaScriptAPI_get_setting_count
|
||||
- \ref LuaScriptAPI_get_setting
|
||||
- \ref LuaScriptAPI_get_config
|
||||
- \ref LuaScriptAPI_log
|
||||
- \ref LuaScriptAPI_set_filter_mode
|
||||
|
||||
During the process function, you can also :
|
||||
- \ref LuaScriptAPI_get_current_time
|
||||
- \ref LuaScriptAPI_get_stimulation_count
|
||||
- \ref LuaScriptAPI_get_stimulation
|
||||
- \ref LuaScriptAPI_remove_stimulation
|
||||
- \ref LuaScriptAPI_send_stimulation
|
||||
- \ref LuaScriptAPI_sleep
|
||||
|
||||
\b NOTE: people using the deprecated \e unstable API would be interested in the \ref LuaScriptAPI_upgrading_from_unstable section.
|
||||
|
||||
\subsection LuaScriptAPI_initialize initialize(box)
|
||||
This function is called by the box at IBox::initialize phase. It is up to the script developer to implement this function.
|
||||
In case you don't want to do anything at initialization phase, just ignore this function.
|
||||
- the \c box parameter enables the script developer to access the API described hereafter.
|
||||
|
||||
\subsection LuaScriptAPI_uninitialize uninitialize(box)
|
||||
This function is called by the box at IBox::uninitialize phase. It is up to the script developer to implement this function.
|
||||
In case you don't want to do anything at uninitialization phase, just ignore this function.
|
||||
- the \c box parameter enables the script developer to access the API described hereafter.
|
||||
|
||||
\subsection LuaScriptAPI_process process(box)
|
||||
This function is called by the box at the first IBox::process phase. It is up to the script developer to implement this function and
|
||||
this function is mandatory. It is executed only once, meaning that if that code must be run on a long duration, it must release some
|
||||
CPU cycles using the \ref box:sleep() function.
|
||||
- the \c box parameter enables the script developer to access the API described hereafter. Among others, it will let
|
||||
the script get some usefull information about the box topology (number of inputs, number of outputs, number of settings etc...)
|
||||
- the \c box parameter also enables the script developer to access all the runtime functions such as receiving stimulations,
|
||||
sending stimulations etc...
|
||||
|
||||
\subsection LuaScriptAPI_get_input_count box:get_input_count()
|
||||
This function returns the number of inputs the box has.
|
||||
|
||||
\subsection LuaScriptAPI_get_output_count box:get_output_count()
|
||||
This function returns the number of outputs the box has.
|
||||
|
||||
\subsection LuaScriptAPI_get_setting_count box:get_setting_count()
|
||||
This function returns the number of settings the box has, including the script filename itself.
|
||||
|
||||
\subsection LuaScriptAPI_get_setting box:get_setting(setting_index)
|
||||
This function returns a string containing the value of a given setting in the box. This
|
||||
setting value may be expanded using the configuration manager thanks to a \ref LuaScriptAPI_get_config call.
|
||||
- \c setting_index can range from 1 to \e n if the box has \e n settings.
|
||||
|
||||
\subsection LuaScriptAPI_log box:log(log_level, line_of_text)
|
||||
This function sends a string to the log manager. This message may be printed in the console
|
||||
for the user or may be popped up to him if this is important enough. In any case, it will appear
|
||||
in the log file.
|
||||
- \c log_level the log level which you want to use to print this line of text. This is represented in
|
||||
string and can take the following values : \c Debug, \c Trace, \c Info, \c Warning, \c ImportantWarning, \c Error and \c Fatal.
|
||||
If you use an invalid value, then \c Debug is used.
|
||||
- \c line_of_text can be any line of text you want to print
|
||||
|
||||
\subsection LuaScriptAPI_set_filter_mode box:set_filter_mode(active)
|
||||
|
||||
By default the Lua scripting box works in a clock-driven mode: it runs with a certain frequency, and each time the process code is run, it outputs a stimulus chunk.
|
||||
When the filter mode is active (=1), the input stimulation stream drives the output chunk generation instead. In filter mode, you can copy input stimulations to the output while keeping their exact timestamps.
|
||||
|
||||
Explanation: Lua box generates a stimulation chunk stream \[t1,t2\[, \[t2,t3\[, \[t3,t4\[, ... , with a high frequency (small chunks). The t are the start and end times of each chunk.
|
||||
However, the input stream may have chunks with a bigger granularity such as \[t1,t3\[, \[t3,t5\[, ..., and so on.
|
||||
Now if the box receives stimulation tagged at time t1 from such a bigger granularity input stream, it will have already sent out the chunk \[t1,t2\] as the current time by then is at least t3 as chunk \[t1,t3\[ was received.
|
||||
Hence the stimulation at t1 must be dropped as OpenViBE stimulation stream guarantees that if a stimuli tagged at time t has not been received by the time a chunk with its beginning timestamp greater than t is received, there will never be a stimuli at t.
|
||||
|
||||
Note that for the filter mode operation it is necessary that the upstream generates a meaningful stimulation stream. If not, the box will not output stimulations when the filter mode is active.
|
||||
|
||||
\subsection LuaScriptAPI_get_config box:get_config(token)
|
||||
This function uses the configuration manager to expand a configuration token. The configuration token
|
||||
are listed in the \c openvibe.conf file and can contain valuable information about the OpenViBE
|
||||
environment.
|
||||
- \c token can be any string containing configuration variables (e.g. <em>${Path_Data}/scenarios/signals/my-experiment</em>).
|
||||
|
||||
\subsection LuaScriptAPI_get_current_time box:get_current_time()
|
||||
This function returns the elapsed time in seconds since the scenario started. The returned value is a float.
|
||||
- \b WARNING: this function should only be called while in the \ref LuaScriptAPI_process callback.
|
||||
|
||||
\subsection LuaScriptAPI_get_stimulation_count box:get_stimulation_count(input_index)
|
||||
This function returns the number of pending stimulation on a specific input given with \c input_index.
|
||||
- \c input_index can range from 1 to \e n if the box has \e n inputs.
|
||||
- \b NOTE: if you call this function on an unexisting input, it returns 0.
|
||||
- \b WARNING: this function should only be called while in the \ref LuaScriptAPI_process callback.
|
||||
|
||||
\subsection LuaScriptAPI_get_stimulation box:get_stimulation(input_index, stimulation_index)
|
||||
This function returns the details of a specific pending stimulation for a specific input given with \c input_index.
|
||||
- \c input_index can range from 1 to \e n if the box has \e n inputs.
|
||||
- \c stimulation_index can range from 1 to \e m if the valid input \c input_index has \e m inputs.
|
||||
|
||||
The result is in the form of a 3-tuple containing :
|
||||
- the stimulation code as an integer
|
||||
- the stimulation date as a float
|
||||
- the stimulation duration as a float
|
||||
|
||||
If you call this function with an \c stimulation_index bigger than what \c get_stimulation_count would have returned for
|
||||
the \c input_index input, then the Lua script sleeps until enough stimulation arrived and this function can return.
|
||||
|
||||
- \b WARNING: if you call this function on an unexisting input, the behavior is undefined
|
||||
- \b WARNING: this function should only be called while in the \ref LuaScriptAPI_process callback.
|
||||
|
||||
\subsection LuaScriptAPI_remove_stimulation box:remove_stimulation(input_index, stimulation_index)
|
||||
Removes a pending stimulation on a specific input given with \c input_index.
|
||||
- \c input_index can range from 1 to \e n if the box has \e n inputs.
|
||||
- \c stimulation_index can range from 1 to \e m if the valid input \c input_index has \e m inputs.
|
||||
|
||||
If you call this function with an \c stimulation_index bigger than what \c get_stimulation_count would have returned for
|
||||
the \c input_index input, then the Lua script sleeps until enough stimulation arrived and this function can return.
|
||||
|
||||
After this call, the pending stimulations order is changed, stimulations \c stimulation_index+1, \c stimulation_index+2, ...
|
||||
being moved to \c stimulation_index, \c stimulation_index+1, ... respectively.
|
||||
|
||||
- \b WARNING: this function should only be called while in the \ref LuaScriptAPI_process callback.
|
||||
|
||||
\subsection LuaScriptAPI_send_stimulation box:send_stimulation(output_index, stimulation_identifier, stimulation_date, opt:stimulation_duration=0)
|
||||
Sends a stimulation with code \c stimulation_identifier, date \c stimulation_date and duration \c stimulation_duration on output
|
||||
- \c output_index.
|
||||
- \c output_index can range from 1 to \e n if the box has \e n outputs.
|
||||
- \c stimulation_identifier is an integer with the identifier of the stimulation to send. See \ref Doc_Stimulations for stimulation codes.
|
||||
- \c stimulation_date is a float (in seconds) with the date of the stimulation. The box will take care of buffering the stimulation if needed before
|
||||
actually sending it. However, you can't send a stimulation in "the past".
|
||||
- \c stimulation_duration is a float (in seconds) with the duration of the stimulation. It is usually unused so if you don't know what to
|
||||
put here, just ignore this parameter, or let it be 0.
|
||||
- \b WARNING: this function should only be called while in the \ref LuaScriptAPI_process callback.
|
||||
|
||||
\subsection LuaScriptAPI_sleep box:sleep()
|
||||
|
||||
Pauses the script execution. The box then continues its execution, so the kernel can perform an additional step. Next time the box
|
||||
is executed, it will restore the script execution so you can eventually continue or sleep again.
|
||||
|
||||
- \b NOTE: The \e current \e time is affected by this call !
|
||||
- \b WARNING: this function should only be called while in the \ref LuaScriptAPI_process callback.
|
||||
|
||||
If you want to wait until a fixed date, just use this simple Lua function :
|
||||
\code
|
||||
function wait_until(box, time)
|
||||
while box:get_current_time() < time do
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
\endcode
|
||||
|
||||
If you want to wait for a fixed duration, just use this simple Lua function :
|
||||
\code
|
||||
function wait_for(box, duration)
|
||||
wait_until(box, box:get_current_time() + duration)
|
||||
end
|
||||
\endcode
|
||||
|
||||
* |OVP_DocEnd_BoxAlgorithm_LuaStimulator_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_LuaStimulator_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_LuaStimulator_Outputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_LuaStimulator_Output1|
|
||||
* |OVP_DocEnd_BoxAlgorithm_LuaStimulator_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_LuaStimulator_Settings|
|
||||
* The box can have a varying number of settings. The first setting is
|
||||
* a fixed but the author can add as many settings as he wants. Those
|
||||
* settings can be retrieved in the Lua script thanks to the \ref LuaScriptAPI_get_setting function
|
||||
* |OVP_DocEnd_BoxAlgorithm_LuaStimulator_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_LuaStimulator_Setting1|
|
||||
* This setting defines what Lua script should be executed.
|
||||
* |OVP_DocEnd_BoxAlgorithm_LuaStimulator_Setting1|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_LuaStimulator_Examples|
|
||||
Here is a sample script
|
||||
\code
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
box:log("Trace", "initialize has been called");
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
-- inspects the box topology
|
||||
box:log("Info", string.format("box has %i input(s)", box:get_input_count()))
|
||||
box:log("Info", string.format("box has %i output(s)", box:get_output_count()))
|
||||
box:log("Info", string.format("box has %i setting(s)", box:get_setting_count()))
|
||||
for i = 1, box:get_setting_count() do
|
||||
box:log("Info", string.format(" - setting %i has value [%s]", i, box:get_setting(i)))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
box:log("Trace", "uninitialize has been called")
|
||||
end
|
||||
|
||||
-- this function is called once by the box
|
||||
function process(box)
|
||||
box:log("Trace", "process has been called")
|
||||
|
||||
-- enters infinite loop
|
||||
-- cpu will be released with a call to sleep
|
||||
-- at the end of the loop
|
||||
while box:keep_processing() do
|
||||
|
||||
-- gets current simulated time
|
||||
t = box:get_current_time()
|
||||
|
||||
-- loops on all inputs of the box
|
||||
for input = 1, box:get_input_count() do
|
||||
|
||||
-- loops on every received stimulation for a given input
|
||||
for stimulation = 1, box:get_stimulation_count(input) do
|
||||
|
||||
-- gets the received stimulation
|
||||
identifier, date, duration = box:get_stimulation(input, 1)
|
||||
|
||||
-- logs the received stimulation
|
||||
box:log("Trace", string.format("At time %f on input %i got stimulation id:%s date:%s duration:%s", t, input, identifier, date, duration))
|
||||
|
||||
-- discards it
|
||||
box:remove_stimulation(input, 1)
|
||||
|
||||
-- triggers a new OVTK_StimulationId_Label_00 stimulation five seconds after
|
||||
box:send_stimulation(1, OVTK_StimulationId_Label_00, t+5, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- releases cpu
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
\endcode
|
||||
* |OVP_DocEnd_BoxAlgorithm_LuaStimulator_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_LuaStimulator_Miscellaneous|
|
||||
*
|
||||
* \subsection LuaScriptAPI_upgrading_from_unstable Upgrading from the unstable API
|
||||
* The Lua box has been flagged as unstable for months for several reasons :
|
||||
* - The API was incomplete.
|
||||
* - There were some potential issues in the chosen names for the API functions.
|
||||
* - The box crashed in some circumstances.
|
||||
*
|
||||
* The box has been stabilized now and this results in some small changes in the API. Basically, the \ref LuaScriptAPI_initialize,
|
||||
* \ref LuaScriptAPI_uninitialize and \ref LuaScriptAPI_process callbacks are passed a \e box parameter which should be used to call
|
||||
* the API functions. Each API function is now prefixed with \e box: as described in the Object-Oriented Access documentation page - http://www.lua.org/pil/28.3.html
|
||||
*
|
||||
* In case you would not like to modify your already existing scripts in depth, I suggest you just include the \em lua-stimulator-legacy.lua script
|
||||
* at the initialization of your existing scripts using the following command
|
||||
* \code
|
||||
* dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-legacy.lua")
|
||||
* \endcode
|
||||
*
|
||||
* \subsection LuaScriptAPI_using_stimulation_codes Using OpenViBE stimulation codes in Lua scripts
|
||||
*
|
||||
* It could be convenient to have the stimulation names available in a Lua script. For this purpose, I suggest you just include the \em lua-stimulator-stim-codes.lua script
|
||||
* at the initialization of your existing scripts using the following command
|
||||
* \code
|
||||
* dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
* \endcode
|
||||
*
|
||||
* |OVP_DocEnd_BoxAlgorithm_LuaStimulator_Miscellaneous|
|
||||
*/
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_P300IdentifierStimulator P300 Identifier Stimulator
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Description|
|
||||
* This box is used to generate P300 stimulation timeline. Depending on its parameters,
|
||||
* it generates all the necessary flagging stimulations for an P300 experiment, such as when
|
||||
* a flash starts, when it stops, when the repetitions are finished etc.
|
||||
*
|
||||
* Imagine a list of image. All image of this list are display consecutively a number of time.
|
||||
* Only the target image is less display than other (see the setting 4).
|
||||
* Then a decision can be made and the user can relax.
|
||||
* Then same process restarts and so on.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Inputs|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Input1|
|
||||
* This input is used to start the generation of the pipeline. As soon as the start stimulation
|
||||
* arrives here, the generation process starts. (see setting 1)
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Input1|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Input2|
|
||||
* A stream of stimulations corresponding to the P300 target.
|
||||
* This stream of stimulation is the P300 target during the current trial time.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Input2|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Outputs|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Output1|
|
||||
* This output contains the stimulations used for P300 based experiments.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Settings|
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Settings|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting1|
|
||||
* This first setting tells which stimulation to use to start the generation process. This stimulation
|
||||
* can be received from a keyboard for example (see \ref Doc_BoxAlgorithm_KeyboardStimulator).
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting1|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting2|
|
||||
* This setting tells what stimulation base to use when displaying the image of the list. When image one should
|
||||
* be flashed, this exact stimulation will be sent. When image two should be flashed, this stimulation + 1
|
||||
* will be sent, and so on.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting2|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting3|
|
||||
* This setting tells how many images the list has.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting3|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting4|
|
||||
* This setting tells the ratio of displaying the target(in percent).
|
||||
* 100% are equivalent to the number of repetition and
|
||||
* the setting value is approximately the percent of repetition containing the target.
|
||||
* Please note that the value must be between 0 and 100%.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting4|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting5|
|
||||
* This setting tells how many times each non target images should be displayed in a trial.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting5|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting6|
|
||||
* This setting tells how many trials should be generated.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting6|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting7|
|
||||
* This setting tells how long an image is displaying.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting7|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting8|
|
||||
* This setting tells how long this stimulator should wait after an image is displaying before sending a new image.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting8|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting9|
|
||||
* This setting tells how long rest is left to the user between the repetitions.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting9|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting10|
|
||||
* This setting tells how much rest is left to the user between the trials.
|
||||
* Please note that the end of a trial is also the end of a repetition. So the rest duration includes both times.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting10|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Setting11|
|
||||
* This setting is not used for now.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Setting11|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Examples|
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300IdentifierStimulator_Miscellaneous|
|
||||
* <b>Note:</b> this box has the same behavior as the box P300SpellerStimulator.
|
||||
* Differents are the number of images are free and it's possible to define a display ratio of the target.
|
||||
* The order display of images is randomly, like the display or not of the target in a repetition.
|
||||
*
|
||||
* The sequence generated by this box is typically something like this :
|
||||
* \verbatim
|
||||
* OVTK_StimulationId_ExperimentStart
|
||||
*
|
||||
* OVTK_StimulationId_RestStart
|
||||
* OVTK_StimulationId_RestStop
|
||||
*
|
||||
* OVTK_StimulationId_TrialStart
|
||||
* OVTK_StimulationId_SegmentStart
|
||||
*
|
||||
* OVTK_StimulationId_Label_0B
|
||||
* OVTK_StimulationId_VisualStimulationStart
|
||||
* OVTK_StimulationId_VisualStimulationStop
|
||||
*
|
||||
* OVTK_StimulationId_Label_03
|
||||
* OVTK_StimulationId_VisualStimulationStart
|
||||
* OVTK_StimulationId_VisualStimulationStop
|
||||
*
|
||||
* ...
|
||||
* ...
|
||||
* ...
|
||||
*
|
||||
* OVTK_StimulationId_Label_04
|
||||
* OVTK_StimulationId_VisualStimulationStart
|
||||
* OVTK_StimulationId_VisualStimulationStop
|
||||
*
|
||||
* OVTK_StimulationId_SegmentStop
|
||||
* OVTK_StimulationId_SegmentStart
|
||||
*
|
||||
* ...
|
||||
* ...
|
||||
* ...
|
||||
*
|
||||
* OVTK_StimulationId_SegmentStop
|
||||
*
|
||||
* ...
|
||||
* ...
|
||||
* ...
|
||||
*
|
||||
* OVTK_StimulationId_TrialStop
|
||||
*
|
||||
* OVTK_StimulationId_RestStart
|
||||
* OVTK_StimulationId_RestStop
|
||||
*
|
||||
* OVTK_StimulationId_TrialStart
|
||||
*
|
||||
* ...
|
||||
* ...
|
||||
* ...
|
||||
*
|
||||
* OVTK_StimulationId_TrialStop
|
||||
*
|
||||
* ...
|
||||
* ...
|
||||
* ...
|
||||
*
|
||||
* OVTK_StimulationId_ExperimentStop\endverbatim
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300IdentifierStimulator_Miscellaneous|
|
||||
*/
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_P300SpellerStimulator P300 Speller Stimulator
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Description|
|
||||
This box is used to generate a 2D P300 stimulation timeline. Depending on its parameters,
|
||||
it generates all the necessary flagging stimulations for an P300 experiment, such as when
|
||||
a flash starts, when it stops, when the repetitions are finished etc.
|
||||
|
||||
Imagine a P300 speller application. Such application is based on a matrix of letters / numbers.
|
||||
The lines and columns of this matrix are flashed consecutively a number of time. Then a decision
|
||||
can be made and the user can relax. Then same process restarts and so one. Such experiment can
|
||||
be driven by this box.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Input1|
|
||||
This input is used to start the generation of the pipeline. As soon as the start stimulation
|
||||
arrives here, the generation process starts. (see setting 1)
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Input1|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Outputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Output1|
|
||||
This output contains the stimulations used for P300 based experiments.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Settings|
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting1|
|
||||
This first setting tells which stimulation to use to start the generation process. This stimulation
|
||||
can be received from a keyboard for example (see \ref Doc_BoxAlgorithm_KeyboardStimulator).
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting2|
|
||||
This setting tells what stimulation base to use when flashing rows of the matrix. When row one should
|
||||
be flashed, this exact stimulation will be sent. When row two should be flashed, this stimulation + 1
|
||||
will be sent, and so on.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting2|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting3|
|
||||
This setting tells what stimulation base to use when flashing columns of the matrix. When column one should
|
||||
be flashed, this exact stimulation will be sent. When column two should be flashed, this stimulation + 1
|
||||
will be sent, and so on.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting3|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting4|
|
||||
This setting tells how many row the matrix has.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting4|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting5|
|
||||
This setting tells how many columns the matrix has.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting5|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting6|
|
||||
This setting tells how many times each row / column should be flashed in a trial.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting6|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting7|
|
||||
This setting tells how many trials should be generated.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting7|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting8|
|
||||
This setting tells how long a flash longs.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting8|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting9|
|
||||
This setting tells how long this stimulator should wait after a flash is finished before sending a new flash.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting9|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting10|
|
||||
This setting tells how much rest is left to the user between the repetitions.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting10|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting11|
|
||||
This setting tells how much rest is left to the user between the trials.
|
||||
Please note that the end of a trial is also the end of a repetition. So the rest duration includes both times.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting11|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Setting12|
|
||||
This setting is not used for now.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Setting12|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Examples|
|
||||
This box is used in the <em>P300 speller</em> and the <em>P300 magic card</em> BCIs. Please see those
|
||||
scenarios in the sample <em>openvibe-scenarios</em>.
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_P300SpellerStimulator_Miscellaneous|
|
||||
<b>Note:</b> Even if this box has been created for flashing matrices, it could be used for flashing 1D things. However, in order
|
||||
to have more efficient results on matrices, this box flashes one line, then one column, then one line etc. It never
|
||||
flashes a line and then another line. Thus in the 1D case, you have to know that the same behavior will occur, resulting
|
||||
on the flashing of the low-part of your 1D set, then high part, then low part etc...
|
||||
|
||||
The sequence generated by this box is typically something like this :
|
||||
\verbatim
|
||||
OVTK_StimulationId_ExperimentStart
|
||||
|
||||
OVTK_StimulationId_RestStart
|
||||
OVTK_StimulationId_RestStop
|
||||
|
||||
OVTK_StimulationId_TrialStart
|
||||
OVTK_StimulationId_SegmentStart
|
||||
|
||||
OVTK_StimulationId_Label_0B
|
||||
OVTK_StimulationId_VisualStimulationStart
|
||||
OVTK_StimulationId_VisualStimulationStop
|
||||
|
||||
OVTK_StimulationId_Label_03
|
||||
OVTK_StimulationId_VisualStimulationStart
|
||||
OVTK_StimulationId_VisualStimulationStop
|
||||
|
||||
...
|
||||
...
|
||||
...
|
||||
|
||||
OVTK_StimulationId_Label_04
|
||||
OVTK_StimulationId_VisualStimulationStart
|
||||
OVTK_StimulationId_VisualStimulationStop
|
||||
|
||||
OVTK_StimulationId_SegmentStop
|
||||
OVTK_StimulationId_SegmentStart
|
||||
|
||||
...
|
||||
...
|
||||
...
|
||||
|
||||
OVTK_StimulationId_SegmentStop
|
||||
|
||||
...
|
||||
...
|
||||
...
|
||||
|
||||
OVTK_StimulationId_TrialStop
|
||||
|
||||
OVTK_StimulationId_RestStart
|
||||
OVTK_StimulationId_RestStop
|
||||
|
||||
OVTK_StimulationId_TrialStart
|
||||
|
||||
...
|
||||
...
|
||||
...
|
||||
|
||||
OVTK_StimulationId_TrialStop
|
||||
|
||||
...
|
||||
...
|
||||
...
|
||||
|
||||
OVTK_StimulationId_ExperimentStop\endverbatim
|
||||
* |OVP_DocEnd_BoxAlgorithm_P300SpellerStimulator_Miscellaneous|
|
||||
*/
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_RunCommand Run Command
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_RunCommand_Description|
|
||||
* This box allows to launch a command on specific stimulation reception.
|
||||
* The goal of this is to trigger an external process on specific events,
|
||||
* for example launch an external process on a given stimulation.
|
||||
* |OVP_DocEnd_BoxAlgorithm_RunCommand_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_RunCommand_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_RunCommand_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_RunCommand_Input1|
|
||||
* The stimulation stream to use. The specified stimulations are looked
|
||||
* for into this stream and as soon as a matching stimulation is found,
|
||||
* the command is launched.
|
||||
* |OVP_DocEnd_BoxAlgorithm_RunCommand_Input1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_RunCommand_Settings|
|
||||
* You can add as many settings as you want so to detect a variable number
|
||||
* of stimulations and launch its associated command. It is always a pair
|
||||
* of settings : stimulation to detect / command tu launch.
|
||||
* |OVP_DocEnd_BoxAlgorithm_RunCommand_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_RunCommand_Setting1|
|
||||
* The first stimulation to detect.
|
||||
* |OVP_DocEnd_BoxAlgorithm_RunCommand_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_RunCommand_Setting2|
|
||||
* The command to launch when first stimulation is detected.
|
||||
* |OVP_DocEnd_BoxAlgorithm_RunCommand_Setting2|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_RunCommand_Examples|
|
||||
* |OVP_DocEnd_BoxAlgorithm_RunCommand_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_RunCommand_Miscellaneous|
|
||||
* The different commandline you write should be accessible in the
|
||||
* configured PATH.
|
||||
*
|
||||
* If you have complex commands to launch, you should
|
||||
* consider writing a script that does the work. This way, you'll keep
|
||||
* the box configuration simple.
|
||||
*
|
||||
* If either the command path or some argument contains spaces, you can
|
||||
* try to enclose each such an item in double quotes.
|
||||
*
|
||||
* \code
|
||||
* "C:/Program Files/program.exe" --open "C:/Temp/data file.dat"
|
||||
* \endcode
|
||||
*
|
||||
* Default behavior is to launch the command synchronously. It means
|
||||
* that the command you launch should not be time consuming. If you want
|
||||
* asynchronous call, then you have to postfix the command with
|
||||
* <em>&</em> under, eg :
|
||||
* \code
|
||||
* xdg-open http://openvibe.inria.fr &
|
||||
* \endcode
|
||||
* For Windows, you have to prefix the command with \e START, eg :
|
||||
* \code
|
||||
* START iexplore http://openvibe.inria.fr
|
||||
* \endcode
|
||||
*
|
||||
* The implementation of this box uses POSIX function \c system
|
||||
* to trigger the command. If you are interested in this command's
|
||||
* behavior, see the manual page at http://linux.die.net/man/3/system
|
||||
* |OVP_DocEnd_BoxAlgorithm_RunCommand_Miscellaneous|
|
||||
*/
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_SignChangeDetector Sign Change Detector
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Description|
|
||||
|
||||
This box detects the changes of the sign of the input. It will work on any matrix of exactly two dimensions, signal in particular. This box operates only on one channel. When the input values change sign a stimulation is sent. You can choose the stimulation to send when the value becomes positive or negative.
|
||||
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Input1|
|
||||
Input values. Must be a streamed matrix of exactly two dimensions. This box works well with signal.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Input1|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Outputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Output1|
|
||||
Output stimulations.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Settings|
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Setting1|
|
||||
Stimulation to send when the value becomes positive.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Setting2|
|
||||
Stimulation to send when the value becomes negative.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Setting2|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Setting3|
|
||||
Index of the channel to operate on.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Setting3|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Examples|
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SignChangeDetector_Miscellaneous|
|
||||
* |OVP_DocEnd_BoxAlgorithm_SignChangeDetector_Miscellaneous|
|
||||
*/
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_SoundPlayer Sound Player
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Description|
|
||||
The Sound Player box can play a sound in WAV or OGG format. It is based on the OpenAL library.
|
||||
The box has to be configured to define the stimulations used as "play" and "stop" triggers.
|
||||
When the playback is stopped, manually or not, the "stop" stimulation is output.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Input1|
|
||||
The stimulations that trigger "play" or "stop".
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Input1|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Outputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Output1|
|
||||
The box outputs the "play" and "stop" triggers when the sound is actually started and stopped (manually or at the end of file). These stimulations are synchronized with the OpenAL engine, which timing may differ slightly with the input triggers. Note that this output is deprecated.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Settings|
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Setting1|
|
||||
The stimulation that triggers the sound play.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Setting2|
|
||||
The stimulation that triggers the sound stop.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Setting2|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Setting3|
|
||||
The sound file, in OGG or WAV format.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Setting3|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Setting4|
|
||||
This setting indicates if the file has to be played in a loop once started.
|
||||
\b note: when enabled the output stimulation is not sent after each loop, but only when a "stop" stimulation is received.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Setting4|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Examples|
|
||||
The box can be used to design auditory BCI scenarios or to launch audio events for Event-Related Potential (ERP) data recording.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_SoundPlayer_Miscellaneous|
|
||||
This box is based on OpenAL (through Alut) and uses the libogg and libvorbis libraries.
|
||||
|
||||
The box sends the recognized stimulations to the Acquisition Server using TCP Tagging after the corresponding play or stop events have triggered. This is the mechanism to replace the deprecated stimulation output of the box.
|
||||
* |OVP_DocEnd_BoxAlgorithm_SoundPlayer_Miscellaneous|
|
||||
*/
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_StimulationFilter Stimulation Filter
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Description|
|
||||
* Filters a stimulation stream in order to select or reject some
|
||||
* specific stimulation ranges. The configuration of the box consists
|
||||
* of a time range in which the filter will be activated, and
|
||||
* a set of rules which will be executed consecutively. The first
|
||||
* rule is the default one, specifying what to do if no other rule
|
||||
* matches. The next rules will specify what to do for their respective
|
||||
* range of stimulations. The last matching rule is chosen so you should
|
||||
* build up your rules from general purpose to specific purpose.
|
||||
* Please note that if no time range is specified (i.e. begin and end are both 0),
|
||||
* The filter will be \b always active.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Input1|
|
||||
The stimulation set to filter.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Input1|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Outputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Output1|
|
||||
* The stimulation set filtered according to the specified set of rules.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Settings|
|
||||
* You can add as many settings as you want. They will be grouped
|
||||
* in order to have one action and two stimulation identifiers per rule.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Setting1|
|
||||
* This is the default action to perform if no rule is matching.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Setting2|
|
||||
* The starting time of the filter.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Setting2|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Setting3|
|
||||
* The ending time of the filter.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Setting3|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Setting4|
|
||||
* This setting contains the action to perform on the specified range of stimulations.
|
||||
* The range of stimulations is specified with next two settings.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Setting4|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Setting5|
|
||||
* The stimulation starting the range.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Setting5|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Setting6|
|
||||
* The stimulation ending the range.
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Setting6|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Examples|
|
||||
* A simple example could be a selection from Label 00 to 0F in a stimulation
|
||||
* stream. For such example, you would have to turn third setting value (default action)
|
||||
* to \c Reject and use one \c Select rule for range Label 00 to Label 0F.
|
||||
*
|
||||
* A complete example could be to select Label 00 to 0F,
|
||||
* and the particular stimulations GDF LEFT and GDF RIGHT. Additionally, for a
|
||||
* reason, you want to avoid the Label 07 and Label 08. In this case, you
|
||||
* will have to turn the default action setting to \c Reject then build up 4 rules :
|
||||
* - rule 1 : \c Select range Label 00 to Label 0F
|
||||
* - rule 2 : \c Select range GDF Left to GDF Left (only 1 stim in this range)
|
||||
* - rule 3 : \c Select range GDF Right to GDF Right (only 1 stim in this range)
|
||||
* - rule 4 : \c Reject range Label 07 to Label 08
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_StimulationFilter_Miscellaneous|
|
||||
* |OVP_DocEnd_BoxAlgorithm_StimulationFilter_Miscellaneous|
|
||||
*/
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_Timeout Timeout
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Description|
|
||||
This box will send a stimulation on its output after it stops receiving an input. The user
|
||||
can set a duration to wait before considering the output inactive.
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Input1|
|
||||
Streamed Matrix input to be monitored.
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Input1|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Outputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Output1|
|
||||
Output stimulation. One stimulation will be sent after the timeout is reached.
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Settings|
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Setting1|
|
||||
Timeout value. Duration (in seconds) to wait after the last received chunk before the input is considered inactive.
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Setting2|
|
||||
Sitmulation ID to send.
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Setting2|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Examples|
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_Timeout_Miscellaneous|
|
||||
* |OVP_DocEnd_BoxAlgorithm_Timeout_Miscellaneous|
|
||||
*/
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
Left 0x00000301 0x00008100
|
||||
Right 0x00000302 0x00008100
|
||||
Up 0x0000030C 0x00008100
|
||||
Down 0x00000306 0x00008100
|
||||
a 0x00000300 0x00008100
|
||||
r 0x00000312 0x00008100
|
||||
t 0x00000311 0x00008100
|
||||
y 0x0000030D 0x00008100
|
||||
BackSpace 0x00000004 0x00008100
|
||||
Return 0x00000320 0x00008100
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<object class="GtkWindow" id="keyboard_stimulator-window">
|
||||
<child>
|
||||
<object class="GtkEventBox" id="keyboard_stimulator-eventbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="has_focus">True</property>
|
||||
<property name="is_focus">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="has_default">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="events">GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="keyboard_stimulator-label">
|
||||
<property name="visible">True</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_CENTER</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
function initialize(box) return initialize() end
|
||||
function uninitialize(box) return uninitialize() end
|
||||
function process(box) return process() end
|
||||
function sleep() return __openvibe_box_context:sleep() end
|
||||
function get_current_time() return __openvibe_box_context:get_current_time() end
|
||||
function get_stimulation_count(input_index) return __openvibe_box_context:get_stimulation_count(input_index) end
|
||||
function get_stimulation(input_index, stimulation_index) return __openvibe_box_context:get_stimulation(input_index, stimulation_index) end
|
||||
function remove_stimulation(input_index, stimulation_index) return __openvibe_box_context:remove_stimulation(input_index, stimulation_index) end
|
||||
function send_stimulation(output_index, stimulation_identifier, stimulation_date) return __openvibe_box_context:send_stimulation(output_index, stimulation_identifier, stimulation_date) end
|
||||
function send_stimulation(output_index, stimulation_identifier, stimulation_date, stimulation_duration) return __openvibe_box_context:send_stimulation(output_index, stimulation_identifier, stimulation_date, stimulation_duration) end
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
-- ___________________________________________________________________ --
|
||||
-- --
|
||||
-- OpenViBE toolkit stimulation identifiers --
|
||||
-- ___________________________________________________________________ --
|
||||
-- --
|
||||
-- Stimulation codes --
|
||||
-- Originally from openvibe-toolkit/ovtk_defines.h --
|
||||
|
||||
OVTK_StimulationId_ExperimentStart = 0x00008001
|
||||
OVTK_StimulationId_ExperimentStop = 0x00008002
|
||||
OVTK_StimulationId_SegmentStart = 0x00008003
|
||||
OVTK_StimulationId_SegmentStop = 0x00008004
|
||||
OVTK_StimulationId_TrialStart = 0x00008005
|
||||
OVTK_StimulationId_TrialStop = 0x00008006
|
||||
OVTK_StimulationId_BaselineStart = 0x00008007
|
||||
OVTK_StimulationId_BaselineStop = 0x00008008
|
||||
OVTK_StimulationId_RestStart = 0x00008009
|
||||
OVTK_StimulationId_RestStop = 0x0000800a
|
||||
OVTK_StimulationId_VisualStimulationStart = 0x0000800b
|
||||
OVTK_StimulationId_VisualStimulationStop = 0x0000800c
|
||||
OVTK_StimulationId_VisualSteadyStateStimulationStart = 0x00008010
|
||||
OVTK_StimulationId_VisualSteadyStateStimulationStop = 0x00008011
|
||||
|
||||
OVTK_StimulationId_RemovedSamples = 0x00008310
|
||||
OVTK_StimulationId_AddedSamplesBegin = 0x00008311
|
||||
OVTK_StimulationId_AddedSamplesEnd = 0x00008312
|
||||
|
||||
OVTK_StimulationId_LabelStart = 0x00008100
|
||||
OVTK_StimulationId_Label_00 = 0x00008100
|
||||
OVTK_StimulationId_Label_01 = 0x00008101
|
||||
OVTK_StimulationId_Label_02 = 0x00008102
|
||||
OVTK_StimulationId_Label_03 = 0x00008103
|
||||
OVTK_StimulationId_Label_04 = 0x00008104
|
||||
OVTK_StimulationId_Label_05 = 0x00008105
|
||||
OVTK_StimulationId_Label_06 = 0x00008106
|
||||
OVTK_StimulationId_Label_07 = 0x00008107
|
||||
OVTK_StimulationId_Label_08 = 0x00008108
|
||||
OVTK_StimulationId_Label_09 = 0x00008109
|
||||
OVTK_StimulationId_Label_0A = 0x0000810a
|
||||
OVTK_StimulationId_Label_0B = 0x0000810b
|
||||
OVTK_StimulationId_Label_0C = 0x0000810c
|
||||
OVTK_StimulationId_Label_0D = 0x0000810d
|
||||
OVTK_StimulationId_Label_0E = 0x0000810e
|
||||
OVTK_StimulationId_Label_0F = 0x0000810f
|
||||
OVTK_StimulationId_Label_10 = 0x00008110
|
||||
OVTK_StimulationId_Label_11 = 0x00008111
|
||||
OVTK_StimulationId_Label_12 = 0x00008112
|
||||
OVTK_StimulationId_Label_13 = 0x00008113
|
||||
OVTK_StimulationId_Label_14 = 0x00008114
|
||||
OVTK_StimulationId_Label_15 = 0x00008115
|
||||
OVTK_StimulationId_Label_16 = 0x00008116
|
||||
OVTK_StimulationId_Label_17 = 0x00008117
|
||||
OVTK_StimulationId_Label_18 = 0x00008118
|
||||
OVTK_StimulationId_Label_19 = 0x00008119
|
||||
OVTK_StimulationId_Label_1A = 0x0000811a
|
||||
OVTK_StimulationId_Label_1B = 0x0000811b
|
||||
OVTK_StimulationId_Label_1C = 0x0000811c
|
||||
OVTK_StimulationId_Label_1D = 0x0000811d
|
||||
OVTK_StimulationId_Label_1E = 0x0000811e
|
||||
OVTK_StimulationId_Label_1F = 0x0000811f
|
||||
OVTK_StimulationId_LabelEnd = 0x000081ff
|
||||
|
||||
OVTK_StimulationId_NumberStart = 0x00000000
|
||||
OVTK_StimulationId_Number_00 = 0x00000000
|
||||
OVTK_StimulationId_Number_01 = 0x00000001
|
||||
OVTK_StimulationId_Number_02 = 0x00000002
|
||||
OVTK_StimulationId_Number_03 = 0x00000003
|
||||
OVTK_StimulationId_Number_04 = 0x00000004
|
||||
OVTK_StimulationId_Number_05 = 0x00000005
|
||||
OVTK_StimulationId_Number_06 = 0x00000006
|
||||
OVTK_StimulationId_Number_07 = 0x00000007
|
||||
OVTK_StimulationId_Number_08 = 0x00000008
|
||||
OVTK_StimulationId_Number_09 = 0x00000009
|
||||
OVTK_StimulationId_Number_0A = 0x0000000a
|
||||
OVTK_StimulationId_Number_0B = 0x0000000b
|
||||
OVTK_StimulationId_Number_0C = 0x0000000c
|
||||
OVTK_StimulationId_Number_0D = 0x0000000d
|
||||
OVTK_StimulationId_Number_0E = 0x0000000e
|
||||
OVTK_StimulationId_Number_0F = 0x0000000f
|
||||
OVTK_StimulationId_Number_10 = 0x00000010
|
||||
OVTK_StimulationId_Number_11 = 0x00000011
|
||||
OVTK_StimulationId_Number_12 = 0x00000012
|
||||
OVTK_StimulationId_Number_13 = 0x00000013
|
||||
OVTK_StimulationId_Number_14 = 0x00000014
|
||||
OVTK_StimulationId_Number_15 = 0x00000015
|
||||
OVTK_StimulationId_Number_16 = 0x00000016
|
||||
OVTK_StimulationId_Number_17 = 0x00000017
|
||||
OVTK_StimulationId_Number_18 = 0x00000018
|
||||
OVTK_StimulationId_Number_19 = 0x00000019
|
||||
OVTK_StimulationId_Number_1A = 0x0000001a
|
||||
OVTK_StimulationId_Number_1B = 0x0000001b
|
||||
OVTK_StimulationId_Number_1C = 0x0000001c
|
||||
OVTK_StimulationId_Number_1D = 0x0000001d
|
||||
OVTK_StimulationId_Number_1E = 0x0000001e
|
||||
OVTK_StimulationId_Number_1F = 0x0000001f
|
||||
OVTK_StimulationId_NumberEnd = 0x000000ff
|
||||
|
||||
OVTK_StimulationId_Train = 0x00008201
|
||||
OVTK_StimulationId_Beep = 0x00008202
|
||||
OVTK_StimulationId_DoubleBeep = 0x00008203
|
||||
OVTK_StimulationId_EndOfFile = 0x00008204
|
||||
OVTK_StimulationId_Target = 0x00008205
|
||||
OVTK_StimulationId_NonTarget = 0x00008206
|
||||
OVTK_StimulationId_TrainCompleted = 0x00008207
|
||||
OVTK_StimulationId_Reset = 0x00008208
|
||||
|
||||
-- ___________________________________________________________________ --
|
||||
-- --
|
||||
-- GDF file format stimulation identifiers --
|
||||
-- ___________________________________________________________________ --
|
||||
-- --
|
||||
|
||||
OVTK_GDF_Artifact_EOG_Large = 0x101
|
||||
OVTK_GDF_Artifact_ECG = 0x102
|
||||
OVTK_GDF_Artifact_EMG = 0x103
|
||||
OVTK_GDF_Artifact_Movement = 0x104
|
||||
OVTK_GDF_Artifact_Failing_Electrode = 0x105
|
||||
OVTK_GDF_Artifact_Sweat = 0x106
|
||||
OVTK_GDF_Artifact_50_60_Hz_Interference = 0x107
|
||||
OVTK_GDF_Artifact_Breathing = 0x108
|
||||
OVTK_GDF_Artifact_Pulse = 0x109
|
||||
OVTK_GDF_Artifact_EOG_Small = 0x10A
|
||||
|
||||
OVTK_GDF_Calibration = 0x10F
|
||||
|
||||
OVTK_GDF_EEG_Sleep_Splindles = 0x111
|
||||
OVTK_GDF_EEG_K_Complexes = 0x112
|
||||
OVTK_GDF_EEG_Saw_Tooth_Waves = 0x113
|
||||
OVTK_GDF_EEG_Idling_EEG_Eyes_Open = 0x114
|
||||
OVTK_GDF_EEG_Idling_EEG_Eyes_Closed = 0x115
|
||||
OVTK_GDF_EEG_Spike = 0x116
|
||||
OVTK_GDF_EEG_Seizure = 0x117
|
||||
|
||||
OVTK_GDF_VEP = 0x121
|
||||
OVTK_GDF_AEP = 0x122
|
||||
OVTK_GDF_SEP = 0x123
|
||||
OVTK_GDF_TMS = 0x12F
|
||||
|
||||
OVTK_GDF_SSVEP = 0x131
|
||||
OVTK_GDF_SSAEP = 0x132
|
||||
OVTK_GDF_SSSEP = 0x133
|
||||
|
||||
OVTK_GDF_Start_Of_Trial = 0x300
|
||||
OVTK_GDF_Left = 0x301
|
||||
OVTK_GDF_Right = 0x302
|
||||
OVTK_GDF_Foot = 0x303
|
||||
OVTK_GDF_Tongue = 0x304
|
||||
OVTK_GDF_class5 = 0x305
|
||||
OVTK_GDF_Down = 0x306
|
||||
OVTK_GDF_class7 = 0x307
|
||||
OVTK_GDF_class8 = 0x308
|
||||
OVTK_GDF_class9 = 0x309
|
||||
OVTK_GDF_class10 = 0x30A
|
||||
OVTK_GDF_class11 = 0x30B
|
||||
OVTK_GDF_Up = 0x30C
|
||||
OVTK_GDF_Feedback_Continuous = 0x30D
|
||||
OVTK_GDF_Feedback_Discrete = 0x30E
|
||||
OVTK_GDF_Cue_Unknown_Undefined = 0x30F
|
||||
OVTK_GDF_Beep = 0x311
|
||||
OVTK_GDF_Cross_On_Screen = 0x312
|
||||
OVTK_GDF_Flashing_Light = 0x313
|
||||
-- SPECIALLY ADDED BY YR
|
||||
OVTK_GDF_End_Of_Trial = 0x320
|
||||
|
||||
OVTK_GDF_Correct = 0x381
|
||||
OVTK_GDF_Incorrect = 0x382
|
||||
-- SPECIALLY ADDED BY YR
|
||||
OVTK_GDF_End_Of_Session = 0x3F2
|
||||
OVTK_GDF_Rejection = 0x3FF
|
||||
|
||||
OVTK_GDF_OAHE = 0x401
|
||||
OVTK_GDF_RERA = 0x402
|
||||
OVTK_GDF_CAHE = 0x403
|
||||
OVTK_GDF_CSB = 0x404
|
||||
OVTK_GDF_Sleep_Hypoventilation = 0x405
|
||||
OVTK_GDF_Maximum_Inspiration = 0x40E
|
||||
OVTK_GDF_Start_Of_Inspiration = 0x40F
|
||||
|
||||
OVTK_GDF_Wake = 0x410
|
||||
OVTK_GDF_Stage_1 = 0x411
|
||||
OVTK_GDF_Stage_2 = 0x412
|
||||
OVTK_GDF_Stage_3 = 0x413
|
||||
OVTK_GDF_Stage_4 = 0x414
|
||||
OVTK_GDF_REM = 0x415
|
||||
|
||||
OVTK_GDF_Lights_On = 0x420
|
||||
OVTK_GDF_Lights_Off = 0x8420
|
||||
|
||||
OVTK_GDF_Eyes_Left = 0x431
|
||||
OVTK_GDF_Eyes_Right = 0x432
|
||||
OVTK_GDF_Eyes_Up = 0x433
|
||||
OVTK_GDF_Eyes_Down = 0x434
|
||||
OVTK_GDF_Horizontal_Eye_Movement = 0x435
|
||||
OVTK_GDF_Vertical_Eye_Movement = 0x436
|
||||
OVTK_GDF_Rotation_Clockwise = 0x437
|
||||
OVTK_GDF_Rotation_Counterclockwise = 0x438
|
||||
OVTK_GDF_Eye_Blink = 0x439
|
||||
|
||||
OVTK_GDF_Left_Hand_Movement = 0x441
|
||||
OVTK_GDF_Right_Hand_Movement = 0x442
|
||||
OVTK_GDF_Head_Movement = 0x443
|
||||
OVTK_GDF_Tongue_Movement = 0x444
|
||||
OVTK_GDF_Swallowing = 0x445
|
||||
OVTK_GDF_Biting = 0x446
|
||||
OVTK_GDF_Foot_Movement = 0x447
|
||||
OVTK_GDF_Foot_Right_Movement = 0x448
|
||||
OVTK_GDF_Arm_Movement = 0x449
|
||||
OVTK_GDF_Arm_Right_Movement = 0x44A
|
||||
|
||||
OVTK_GDF_ECG_Fiducial_Point_QRS_Complex = 0x501
|
||||
OVTK_GDF_ECG_P_Wave = 0x502
|
||||
OVTK_GDF_ECG_QRS_Complex = 0x503
|
||||
OVTK_GDF_ECG_R_Point = 0x504
|
||||
OVTK_GDF_ECG_T_Wave = 0x506
|
||||
OVTK_GDF_ECG_U_Wave = 0x507
|
||||
|
||||
OVTK_GDF_Start = 0x580
|
||||
OVTK_GDF_25_Watt = 0x581
|
||||
OVTK_GDF_50_Watt = 0x582
|
||||
OVTK_GDF_75_Watt = 0x583
|
||||
OVTK_GDF_100_Watt = 0x584
|
||||
OVTK_GDF_125_Watt = 0x585
|
||||
OVTK_GDF_150_Watt = 0x586
|
||||
OVTK_GDF_175_Watt = 0x587
|
||||
OVTK_GDF_200_Watt = 0x588
|
||||
OVTK_GDF_225_Watt = 0x589
|
||||
OVTK_GDF_250_Watt = 0x58A
|
||||
OVTK_GDF_275_Watt = 0x58B
|
||||
OVTK_GDF_300_Watt = 0x58C
|
||||
OVTK_GDF_325_Watt = 0x58D
|
||||
OVTK_GDF_350_Watt = 0x58E
|
||||
|
||||
OVTK_GDF_Start_Of_New_Segment = 0x7FFE
|
||||
OVTK_GDF_Non_Equidistant_Sampling_Value = 0x7FFF
|
||||
Binary file not shown.
+11
@@ -0,0 +1,11 @@
|
||||
a 0x00008101 0x00008100
|
||||
z 0x00008102 0x00008100
|
||||
e 0x00008103 0x00008100
|
||||
r 0x00008104 0x00008100
|
||||
t 0x00008105 0x00008100
|
||||
y 0x00008106 0x00008100
|
||||
u 0x00008107 0x00008100
|
||||
i 0x00008108 0x00008100
|
||||
o 0x00008109 0x00008100
|
||||
p 0x0000810A 0x00008100
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
#include "CBoxAlgorithmStimulationValidator.hpp"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
bool CBoxAlgorithmStimulationValidator::initialize()
|
||||
{
|
||||
m_decoder.initialize(*this, 0);
|
||||
m_iStimulation = m_decoder.getOutputStimulationSet();
|
||||
m_encoder.initialize(*this, 0);
|
||||
m_oStimulation = m_encoder.getInputStimulationSet();
|
||||
|
||||
m_stim = uint64_t(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0));
|
||||
m_limit = size_t(uint64_t(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1)));
|
||||
|
||||
return true;
|
||||
}
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
bool CBoxAlgorithmStimulationValidator::uninitialize()
|
||||
{
|
||||
m_decoder.uninitialize();
|
||||
m_encoder.uninitialize();
|
||||
return true;
|
||||
}
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
bool CBoxAlgorithmStimulationValidator::processInput(const size_t index)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
bool CBoxAlgorithmStimulationValidator::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxCtx = this->getDynamicBoxContext();
|
||||
|
||||
const uint64_t currentTime = getPlayerContext().getCurrentTime();
|
||||
m_oStimulation->setStimulationCount(0); // reset stimulation output
|
||||
//***** Stimulations *****
|
||||
for (size_t i = 0; i < boxCtx.getInputChunkCount(0); ++i)
|
||||
{
|
||||
m_decoder.decode(i); // Decode the chunk
|
||||
if (m_decoder.isBufferReceived()) // Buffer Received
|
||||
{
|
||||
for (size_t j = 0; j < m_iStimulation->getStimulationCount(); ++j)
|
||||
{
|
||||
if (m_iStimulation->getStimulationIdentifier(j) == m_stim.id())
|
||||
{
|
||||
m_count++;
|
||||
if (m_count >= m_limit)
|
||||
{
|
||||
m_count = 0;
|
||||
m_oStimulation->appendStimulation(m_stim.id(), m_iStimulation->getStimulationDate(j), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_lastEndTime == 0) { m_encoder.encodeHeader(); } // First time
|
||||
else { m_encoder.encodeBuffer(); } // Others
|
||||
boxCtx.markOutputAsReadyToSend(0, m_lastEndTime, currentTime); // preserve continuous
|
||||
m_lastEndTime = currentTime; // preserve continuous
|
||||
return true;
|
||||
}
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
///
|
||||
/// \file CBoxAlgorithmStimulationValidator.hpp
|
||||
/// \brief Classes of the Box Stimulation Validator.
|
||||
/// \author Thibaut Monseigne (Inria).
|
||||
/// \version 1.0.
|
||||
/// \date Mon Feb 17 10:42:46 2020.
|
||||
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
|
||||
///
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
namespace OpenViBE
|
||||
{
|
||||
namespace Plugins
|
||||
{
|
||||
namespace Stimulation
|
||||
{
|
||||
/// <summary> The class CBoxAlgorithmStimulationValidator describes the box Stimulation Validator. </summary>
|
||||
class CBoxAlgorithmStimulationValidator 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 :
|
||||
//bool processClock(Kernel::CMessageClock& msg) override;
|
||||
// - On new input received (the most common behaviour for signal processing) :
|
||||
bool processInput(const size_t index) override;
|
||||
|
||||
// If you want to use processClock, you must provide the clock frequency.
|
||||
//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_StimulationValidator)
|
||||
|
||||
protected:
|
||||
//***** Codecs *****
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmStimulationValidator> m_decoder; // Stimulation Decoder
|
||||
Toolkit::TStimulationEncoder<CBoxAlgorithmStimulationValidator> m_encoder; // Stimulation Encoder
|
||||
IStimulationSet *m_iStimulation = nullptr, *m_oStimulation = nullptr; // Stimulation Receiver
|
||||
|
||||
//***** Settings *****
|
||||
CIdentifier m_stim = OVTK_StimulationId_Label_00;
|
||||
size_t m_count = 0, m_limit = 0;
|
||||
uint64_t m_lastEndTime = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// <summary> Descriptor of the box Stimulation Validator. </summary>
|
||||
class CBoxAlgorithmStimulationValidatorDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Stimulation Validator"); }
|
||||
CString getAuthorName() const override { return CString("Thibaut Monseigne"); }
|
||||
CString getAuthorCompanyName() const override { return CString("Inria"); }
|
||||
CString getShortDescription() const override { return CString("Count a stimulation and send this after N occurence."); }
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Stimulation"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-add"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_StimulationValidator; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmStimulationValidator; }
|
||||
|
||||
/*
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmStimulationValidatorListener; }
|
||||
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
|
||||
*/
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Input",OV_TypeId_Stimulations);
|
||||
prototype.addOutput("Output",OV_TypeId_Stimulations);
|
||||
prototype.addSetting("Stimulation to count",OV_TypeId_Stimulation, "OVTK_StimulationId_Label_00");
|
||||
prototype.addSetting("Number for validation",OV_TypeId_Integer, "2");
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_StimulationValidatorDesc)
|
||||
};
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
#include "ovpCBoxAlgorithmStimulationFilter.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
bool CBoxAlgorithmStimulationFilter::initialize()
|
||||
{
|
||||
m_defaultAction = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
m_startTime = uint64_t(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1)) * (1LL << 32));
|
||||
m_endTime = uint64_t(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2)) * (1LL << 32));
|
||||
|
||||
if (m_startTime > m_endTime)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_ImportantWarning << "End time is lower than start time\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// we iterate over all Rules. One rule has 3 settings
|
||||
const size_t nSetting = this->getStaticBoxContext().getSettingCount();
|
||||
for (size_t i = 3; i < nSetting; i += 3)
|
||||
{
|
||||
rule_t rule;
|
||||
rule.action = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i); // the action to perform
|
||||
rule.startStimID = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i + 1); // first stim
|
||||
rule.EndStimID = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i + 2); // last stim in the desired range
|
||||
m_rules.push_back(rule);
|
||||
}
|
||||
|
||||
m_encoder = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationEncoder));
|
||||
m_encoder->initialize();
|
||||
|
||||
m_decoder = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder));
|
||||
m_decoder->initialize();
|
||||
|
||||
ip_buffer.initialize(m_decoder->getInputParameter(OVP_GD_Algorithm_StimulationDecoder_InputParameterId_MemoryBufferToDecode));
|
||||
op_stimSet.initialize(m_decoder->getOutputParameter(OVP_GD_Algorithm_StimulationDecoder_OutputParameterId_StimulationSet));
|
||||
ip_stimSet.initialize(m_encoder->getInputParameter(OVP_GD_Algorithm_StimulationEncoder_InputParameterId_StimulationSet));
|
||||
op_buffer.initialize(m_encoder->getOutputParameter(OVP_GD_Algorithm_StimulationEncoder_OutputParameterId_EncodedMemoryBuffer));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmStimulationFilter::uninitialize()
|
||||
{
|
||||
op_buffer.uninitialize();
|
||||
ip_stimSet.uninitialize();
|
||||
op_stimSet.uninitialize();
|
||||
ip_buffer.uninitialize();
|
||||
|
||||
m_decoder->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_decoder);
|
||||
|
||||
m_encoder->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_encoder);
|
||||
|
||||
m_rules.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmStimulationFilter::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmStimulationFilter::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
ip_buffer = boxContext.getInputChunk(0, i);
|
||||
op_buffer = boxContext.getOutputChunk(0);
|
||||
m_decoder->process();
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedHeader))
|
||||
{
|
||||
m_encoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeHeader);
|
||||
}
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedBuffer))
|
||||
{
|
||||
ip_stimSet->setStimulationCount(0);
|
||||
for (size_t s = 0; s < op_stimSet->getStimulationCount(); ++s)
|
||||
{
|
||||
const uint64_t id = op_stimSet->getStimulationIdentifier(s);
|
||||
const uint64_t date = op_stimSet->getStimulationDate(s);
|
||||
uint64_t action = m_defaultAction;
|
||||
|
||||
if ((m_startTime == m_endTime) || (m_startTime != m_endTime && m_startTime <= date && date <= m_endTime))
|
||||
{
|
||||
for (size_t r = 0; r < m_rules.size(); ++r)
|
||||
{
|
||||
const rule_t& rule = m_rules[r];
|
||||
if (rule.startStimID <= id && id <= rule.EndStimID)
|
||||
{
|
||||
action = rule.action;
|
||||
this->getLogManager() << Kernel::LogLevel_Debug << "Switches to rule " << r << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (action == OVP_TypeId_StimulationFilterAction_Select.id())
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Selects stimulation "
|
||||
<< this->getTypeManager().getEnumerationEntryNameFromValue(OV_TypeId_Stimulation, id) << " !\n";
|
||||
ip_stimSet->appendStimulation(id, date, op_stimSet->getStimulationDuration(s));
|
||||
}
|
||||
if (action == OVP_TypeId_StimulationFilterAction_Reject.id())
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Rejects stimulation "
|
||||
<< this->getTypeManager().getEnumerationEntryNameFromValue(OV_TypeId_Stimulation, id) << " !\n";
|
||||
}
|
||||
}
|
||||
|
||||
m_encoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeBuffer);
|
||||
}
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedEnd))
|
||||
{
|
||||
m_encoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeEnd);
|
||||
}
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
class CBoxAlgorithmStimulationFilter final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_StimulationFilter)
|
||||
|
||||
protected:
|
||||
|
||||
Kernel::IAlgorithmProxy* m_decoder = nullptr;
|
||||
Kernel::IAlgorithmProxy* m_encoder = nullptr;
|
||||
Kernel::TParameterHandler<const IMemoryBuffer*> ip_buffer;
|
||||
Kernel::TParameterHandler<IStimulationSet*> op_stimSet;
|
||||
Kernel::TParameterHandler<IStimulationSet*> ip_stimSet;
|
||||
Kernel::TParameterHandler<IMemoryBuffer*> op_buffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t action;
|
||||
uint64_t startStimID;
|
||||
uint64_t EndStimID;
|
||||
} rule_t;
|
||||
|
||||
uint64_t m_defaultAction = 0;
|
||||
uint64_t m_startTime = 0;
|
||||
uint64_t m_endTime = 0;
|
||||
std::vector<rule_t> m_rules;
|
||||
};
|
||||
|
||||
class CBoxAlgorithmStimulationFilterListener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
bool onSettingAdded(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
box.removeSetting(index);
|
||||
//we had a whole rule (3 settings)
|
||||
box.addSetting("Action to perform", OVP_TypeId_StimulationFilterAction, "Select");
|
||||
box.addSetting("Stimulation range begin", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_00");
|
||||
box.addSetting("Stimulation range end", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_0F");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onSettingRemoved(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
//we must remove the 2 other settings corresponding to the rule
|
||||
const size_t settingGroupIdx = (index - 3) / 3;
|
||||
box.removeSetting(settingGroupIdx * 3 + 3);
|
||||
box.removeSetting(settingGroupIdx * 3 + 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
|
||||
class CBoxAlgorithmStimulationFilterDesc final : public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Stimulation Filter"); }
|
||||
CString getAuthorName() const override { return CString("Yann Renard"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA"); }
|
||||
|
||||
CString getShortDescription() const override { return CString("Filters incoming stimulations selecting or rejecting specific ranges of stimulations"); }
|
||||
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Stimulation/Adaptation"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-missing-image"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_StimulationFilter; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmStimulationFilter; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Stimulations", OV_TypeId_Stimulations);
|
||||
prototype.addOutput("Modified Stimulations", OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addSetting("Default action", OVP_TypeId_StimulationFilterAction, "Reject");
|
||||
prototype.addSetting("Time range begin", OV_TypeId_Float, "0");
|
||||
prototype.addSetting("Time range end", OV_TypeId_Float, "0");
|
||||
prototype.addSetting("Action to perform", OVP_TypeId_StimulationFilterAction, "Select");
|
||||
prototype.addSetting("Stimulation range begin", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_00");
|
||||
prototype.addSetting("Stimulation range end", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_0F");
|
||||
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddSetting);
|
||||
// prototype.addFlag (OV_AttributeId_Box_FlagIsUnstable);
|
||||
return true;
|
||||
}
|
||||
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmStimulationFilterListener; }
|
||||
virtual void releaseBoxListener(IBoxListener* listener) { delete listener; }
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_StimulationFilterDesc)
|
||||
};
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+813
@@ -0,0 +1,813 @@
|
||||
#include "ovpCBoxAlgorithmLuaStimulator.h"
|
||||
|
||||
#if defined TARGET_HAS_ThirdPartyLua
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
#define __CB_Assert__(condition) \
|
||||
if(!(condition)) \
|
||||
{ \
|
||||
lua_pushstring(state, "Assertion failed : ["#condition"]"); \
|
||||
lua_error(state); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
namespace {
|
||||
class CLuaThread
|
||||
{
|
||||
public:
|
||||
CLuaThread(CBoxAlgorithmLuaStimulator* pBox) : m_box(pBox) { }
|
||||
CLuaThread(const CLuaThread& thread) : m_box(thread.m_box) { }
|
||||
void operator()() const { m_box->doThread(); }
|
||||
|
||||
protected:
|
||||
CBoxAlgorithmLuaStimulator* m_box;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static void lua_setcallback(lua_State* state, const char* name, int (*callback)(lua_State*), void* data)
|
||||
{
|
||||
lua_getglobal(state, "__openvibe_box_context");
|
||||
lua_pushlightuserdata(state, data);
|
||||
lua_pushcclosure(state, callback, 1);
|
||||
lua_setfield(state, -2, name);
|
||||
}
|
||||
|
||||
// Returns true on success, i.e. if code is 0 (no failure).
|
||||
static bool lua_report(Kernel::ILogManager& logManager, lua_State* state, const int code)
|
||||
{
|
||||
if (code)
|
||||
{
|
||||
logManager << Kernel::LogLevel_ImportantWarning << "Lua error: " << lua_tostring(state, -1) << "\n";
|
||||
lua_pop(state, 1);
|
||||
}
|
||||
return (code == 0);
|
||||
}
|
||||
|
||||
static bool lua_check_argument_count(lua_State* state, const char* name, const int count1, const int count2 = -1)
|
||||
{
|
||||
if (count2 < 0)
|
||||
{
|
||||
if (lua_gettop(state) != count1 + 1)
|
||||
{
|
||||
const std::string msg = "[" + std::string(name) + "] takes " + std::to_string(count1) + " parameter" + (count1 >= 2 ? "s" : "");
|
||||
lua_pushstring(state, msg.c_str());
|
||||
lua_error(state);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lua_gettop(state) != count1 + 1 && lua_gettop(state) != count2 + 1)
|
||||
{
|
||||
const std::string msg = "[" + std::string(name) + "] takes either " + std::to_string(count1) + " or " + std::to_string(count2) + " parameter"
|
||||
+ (count2 >= 2 ? "s" : "");
|
||||
lua_pushstring(state, msg.c_str());
|
||||
lua_error(state);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool lua_check_box_status(lua_State* state, const char* name, const CBoxAlgorithmLuaStimulator::EStates curState)
|
||||
{
|
||||
if (curState == CBoxAlgorithmLuaStimulator::EStates::Please_Quit)
|
||||
{
|
||||
const std::string msg = "[" + std::string(name) + "] This thread has been requested to quit...";
|
||||
lua_pushstring(state, msg.c_str());
|
||||
lua_error(state);
|
||||
return false;
|
||||
}
|
||||
if (curState != CBoxAlgorithmLuaStimulator::EStates::Processing)
|
||||
{
|
||||
const std::string msg = "[" + std::string(name) + "] should only be called in the [process] callback";
|
||||
lua_pushstring(state, msg.c_str());
|
||||
lua_error(state);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int lua_get_input_count_cb(lua_State* state)
|
||||
{
|
||||
size_t nInput = 0;
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_argument_count(state, "get_input_count", 0)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->getInputCountCB(nInput));
|
||||
lua_pushinteger(state, nInput);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_get_output_count_cb(lua_State* state)
|
||||
{
|
||||
size_t nOutput = 0;
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_argument_count(state, "get_output_count", 0)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->getOutputCountCB(nOutput));
|
||||
lua_pushinteger(state, nOutput);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_get_setting_count_cb(lua_State* state)
|
||||
{
|
||||
size_t nSetting = 0;
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_argument_count(state, "get_setting_count", 0)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->getSettingCountCB(nSetting));
|
||||
lua_pushinteger(state, nSetting);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_get_setting_cb(lua_State* state)
|
||||
{
|
||||
CString setting;
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_argument_count(state, "get_setting", 1)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->getSettingCB(size_t(lua_tointeger(state, 2)-1), setting));
|
||||
lua_pushstring(state, setting.toASCIIString());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_get_config_cb(lua_State* state)
|
||||
{
|
||||
CString config;
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_argument_count(state, "get_config", 1)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->getConfigCB(lua_tostring(state, 2), config));
|
||||
lua_pushstring(state, config.toASCIIString());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_get_current_time_cb(lua_State* state)
|
||||
{
|
||||
uint64_t time = 0;
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_argument_count(state, "get_current_time", 0)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->getCurrentTimeCB(time));
|
||||
lua_pushnumber(state, CTime(time).toSeconds());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_sleep_cb(lua_State* state)
|
||||
{
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_box_status(state, "sleep", pThis->m_State)) { return 0; }
|
||||
if (!lua_check_argument_count(state, "sleep", 0)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->sleepCB());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_get_stimulation_count_cb(lua_State* state)
|
||||
{
|
||||
size_t count = 0;
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_box_status(state, "get_stimulation_count", pThis->m_State)) { return 0; }
|
||||
if (!lua_check_argument_count(state, "get_stimulation_count", 1)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->getStimulationCountCB(size_t(lua_tointeger(state, 2)-1), count));
|
||||
lua_pushinteger(state, count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lua_get_stimulation_cb(lua_State* state)
|
||||
{
|
||||
uint64_t id = uint64_t(-1);
|
||||
uint64_t time = uint64_t(-1);
|
||||
uint64_t duration = uint64_t(-1);
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_box_status(state, "get_stimulation", pThis->m_State)) { return 0; }
|
||||
if (!lua_check_argument_count(state, "get_stimulation", 2)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->getStimulationCB(size_t(lua_tointeger(state, 2)-1), size_t(lua_tointeger(state, 3)-1), id, time, duration));
|
||||
lua_pushinteger(state, lua_Integer(id));
|
||||
lua_pushnumber(state, CTime(time).toSeconds());
|
||||
lua_pushnumber(state, CTime(duration).toSeconds());
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int lua_remove_stimulation_cb(lua_State* state)
|
||||
{
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_box_status(state, "remove_stimulation", pThis->m_State)) { return 0; }
|
||||
if (!lua_check_argument_count(state, "remove_stimulation", 2)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->removeStimulationCB(size_t(lua_tointeger(state, 2)-1), size_t(lua_tointeger(state, 3)-1)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_send_stimulation_cb(lua_State* state)
|
||||
{
|
||||
const int iArguments = lua_gettop(state);
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_box_status(state, "send_stimulation", pThis->m_State)) { return 0; }
|
||||
if (!lua_check_argument_count(state, "send_stimulation", 3, 4)) { return 0; }
|
||||
|
||||
__CB_Assert__(pThis->sendStimulationCB(size_t(lua_tointeger(state, 2)-1), size_t(lua_tointeger(state, 3)),
|
||||
CTime(double(lua_tonumber(state, 4))).time(),
|
||||
(iArguments == 5 ? CTime(double(lua_tonumber(state, 5))).time() : 0)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Has the side effect of setting m_bLuaThreadHadError to true if called with "Error" or "Fatal" loglevels.
|
||||
static int lua_log_cb(lua_State* state)
|
||||
{
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_argument_count(state, "log", 2)) { return 0; }
|
||||
|
||||
Kernel::ELogLevel level = Kernel::LogLevel_Debug;
|
||||
const std::string str(lua_tostring(state, 2));
|
||||
if (str == "Trace") { level = Kernel::LogLevel_Trace; }
|
||||
else if (str == "Info") { level = Kernel::LogLevel_Info; }
|
||||
else if (str == "Warning") { level = Kernel::LogLevel_Warning; }
|
||||
else if (str == "ImportantWarning") { level = Kernel::LogLevel_ImportantWarning; }
|
||||
else if (str == "Error")
|
||||
{
|
||||
level = Kernel::LogLevel_Error;
|
||||
pThis->m_LuaThreadHadError = true;
|
||||
}
|
||||
else if (str == "Fatal")
|
||||
{
|
||||
level = Kernel::LogLevel_Fatal;
|
||||
pThis->m_LuaThreadHadError = true;
|
||||
}
|
||||
__CB_Assert__(pThis->log(level, lua_tostring(state, 3)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lua_keep_processing_cb(lua_State* state)
|
||||
{
|
||||
const auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
if (pThis->m_State == CBoxAlgorithmLuaStimulator::EStates::Processing) { return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int lua_set_filter_mode_cb(lua_State* state)
|
||||
{
|
||||
auto pThis = static_cast<CBoxAlgorithmLuaStimulator*>(lua_touserdata(state, lua_upvalueindex(1)));
|
||||
__CB_Assert__(pThis != nullptr);
|
||||
|
||||
if (!lua_check_argument_count(state, "set_filter_mode", 1)) { return 0; }
|
||||
|
||||
pThis->m_FilterMode = (lua_tointeger(state, 2) == 0 ? false : true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if BOOST_VERSION >= 103500
|
||||
CBoxAlgorithmLuaStimulator::CBoxAlgorithmLuaStimulator()
|
||||
: m_innerLock(m_mutex, boost::defer_lock), m_outerLock(m_mutex, boost::defer_lock), m_exitLock(m_mutex, boost::defer_lock) { }
|
||||
#else
|
||||
CBoxAlgorithmLuaStimulator::CBoxAlgorithmLuaStimulator()
|
||||
: m_innerLock(m_mutex, false), m_outerLock(m_mutex, false), m_exitLock(m_mutex, false) { }
|
||||
#endif
|
||||
|
||||
uint64_t CBoxAlgorithmLuaStimulator::getClockFrequency()
|
||||
{
|
||||
if (m_FilterMode) { return 0; } // Only when input received
|
||||
return 128LL << 32; // the box clock frequency
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::processClock(Kernel::CMessageClock& /*msg*/)
|
||||
{
|
||||
if (!m_FilterMode) { this->getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess(); }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::processInput(const size_t /*index*/)
|
||||
{
|
||||
if (m_FilterMode) { getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess(); }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::initialize()
|
||||
{
|
||||
size_t i;
|
||||
const Kernel::IBox& boxContext = this->getStaticBoxContext();
|
||||
|
||||
CString filename = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
filename = this->getConfigurationManager().expand(filename);
|
||||
|
||||
m_FilterMode = false;
|
||||
|
||||
m_State = EStates::Unstarted;
|
||||
m_luaState = luaL_newstate();
|
||||
|
||||
luaL_openlibs(m_luaState);
|
||||
|
||||
lua_newtable(m_luaState);
|
||||
lua_setglobal(m_luaState, "__openvibe_box_context");
|
||||
|
||||
lua_setcallback(m_luaState, "get_input_count", lua_get_input_count_cb, this);
|
||||
lua_setcallback(m_luaState, "get_output_count", lua_get_output_count_cb, this);
|
||||
lua_setcallback(m_luaState, "get_setting_count", lua_get_setting_count_cb, this);
|
||||
lua_setcallback(m_luaState, "get_setting", lua_get_setting_cb, this);
|
||||
lua_setcallback(m_luaState, "get_config", lua_get_config_cb, this);
|
||||
lua_setcallback(m_luaState, "get_current_time", lua_get_current_time_cb, this);
|
||||
lua_setcallback(m_luaState, "sleep", lua_sleep_cb, this);
|
||||
lua_setcallback(m_luaState, "get_stimulation_count", lua_get_stimulation_count_cb, this);
|
||||
lua_setcallback(m_luaState, "get_stimulation", lua_get_stimulation_cb, this);
|
||||
lua_setcallback(m_luaState, "remove_stimulation", lua_remove_stimulation_cb, this);
|
||||
lua_setcallback(m_luaState, "send_stimulation", lua_send_stimulation_cb, this);
|
||||
lua_setcallback(m_luaState, "log", lua_log_cb, this);
|
||||
lua_setcallback(m_luaState, "keep_processing", lua_keep_processing_cb, this);
|
||||
lua_setcallback(m_luaState, "set_filter_mode", lua_set_filter_mode_cb, this);
|
||||
|
||||
if (!lua_report(this->getLogManager(), m_luaState, luaL_dostring(m_luaState, "function initialize(box) end"))) { return false; }
|
||||
if (!lua_report(this->getLogManager(), m_luaState, luaL_dostring(m_luaState, "function uninitialize(box) end"))) { return false; }
|
||||
if (!lua_report(this->getLogManager(), m_luaState, luaL_dostring(m_luaState, "function process(box) end"))) { return false; }
|
||||
if (!lua_report(this->getLogManager(), m_luaState, luaL_dofile(m_luaState, filename.toASCIIString()))) { return false; }
|
||||
if (!lua_report(this->getLogManager(), m_luaState, luaL_dostring(m_luaState, "initialize(__openvibe_box_context)"))) { return false; }
|
||||
|
||||
m_iStimulations.resize(boxContext.getInputCount());
|
||||
m_oStimulations.resize(boxContext.getOutputCount());
|
||||
|
||||
for (i = 0; i < boxContext.getInputCount(); ++i)
|
||||
{
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmLuaStimulator>* decoder = new Toolkit::TStimulationDecoder<CBoxAlgorithmLuaStimulator>;
|
||||
decoder->initialize(*this, i);
|
||||
|
||||
m_decoders.push_back(decoder);
|
||||
}
|
||||
|
||||
for (i = 0; i < boxContext.getOutputCount(); ++i)
|
||||
{
|
||||
Toolkit::TStimulationEncoder<CBoxAlgorithmLuaStimulator>* encoder = new Toolkit::TStimulationEncoder<CBoxAlgorithmLuaStimulator>;
|
||||
encoder->initialize(*this, i);
|
||||
|
||||
m_encoders.push_back(encoder);
|
||||
}
|
||||
|
||||
m_lastTime = 0;
|
||||
m_luaThread = nullptr;
|
||||
m_LuaThreadHadError = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::uninitialize()
|
||||
{
|
||||
if (m_luaThread)
|
||||
{
|
||||
m_outerLock.lock();
|
||||
|
||||
// If Lua thread is still running, ask it to stop.
|
||||
if (m_State == EStates::Processing || m_State == EStates::Please_Quit)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Debug << "Requesting thread to quit, waiting max 5 secs ...\n";
|
||||
|
||||
m_State = EStates::Please_Quit;
|
||||
m_condition.notify_one();
|
||||
|
||||
m_outerLock.unlock();
|
||||
m_exitLock.lock();
|
||||
|
||||
bool gotLock = false;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
// Wait for the thread to stop (in that case it notifies the lock)
|
||||
boost::system_time timeout = boost::get_system_time() + boost::posix_time::milliseconds(1000);
|
||||
if (m_exitCondition.timed_wait(m_exitLock, timeout))
|
||||
{
|
||||
gotLock = true;
|
||||
break;
|
||||
}
|
||||
this->getLogManager() << Kernel::LogLevel_Info << "Waiting for thread to exit, " << i + 1 << "/5 ...\n";
|
||||
}
|
||||
if (gotLock) { this->getLogManager() << Kernel::LogLevel_Debug << "Ok, thread notified the exit lock\n"; }
|
||||
else { this->getLogManager() << Kernel::LogLevel_Debug << "Bad, thread did not notify the exit lock in 5s\n"; }
|
||||
|
||||
m_exitLock.unlock();
|
||||
m_outerLock.lock();
|
||||
}
|
||||
|
||||
if (m_State == EStates::Finished)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Debug << "Ok, thread reached Finished as expected ...\n";
|
||||
m_luaThread->join();
|
||||
delete m_luaThread;
|
||||
m_luaThread = nullptr;
|
||||
}
|
||||
else { this->getLogManager() << Kernel::LogLevel_Warning << "Bad, thread still in state " << toString(m_State) << ", cannot delete. Memory leak.\n"; }
|
||||
|
||||
m_outerLock.unlock();
|
||||
}
|
||||
|
||||
if (m_luaState)
|
||||
{
|
||||
if (!lua_report(this->getLogManager(), m_luaState, luaL_dostring(m_luaState, "uninitialize(__openvibe_box_context)")))
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "Lua script uninitialize failed\n";
|
||||
// Don't return here on false, still want to free the resources below
|
||||
}
|
||||
lua_close(m_luaState);
|
||||
m_luaState = nullptr;
|
||||
}
|
||||
/* TODO: Remove next comment*/
|
||||
/*IBox& staticBoxContext=*/
|
||||
this->getStaticBoxContext();
|
||||
|
||||
for (size_t i = 0; i < m_decoders.size(); ++i)
|
||||
{
|
||||
m_decoders[i]->uninitialize();
|
||||
delete m_decoders[i];
|
||||
}
|
||||
m_decoders.clear();
|
||||
|
||||
for (size_t i = 0; i < m_encoders.size(); ++i)
|
||||
{
|
||||
m_encoders[i]->uninitialize();
|
||||
delete m_encoders[i];
|
||||
}
|
||||
m_encoders.clear();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
const size_t nInput = this->getStaticBoxContext().getInputCount();
|
||||
const uint64_t time = this->getPlayerContext().getCurrentTime();
|
||||
|
||||
// Default time range for the generated stimulation chunk
|
||||
uint64_t start = (m_FilterMode ? std::numeric_limits<uint64_t>::max() : m_lastTime);
|
||||
uint64_t end = (m_FilterMode ? 0 : time);
|
||||
|
||||
if (time == 0)
|
||||
{
|
||||
// Send all headers
|
||||
for (size_t i = 0; i < m_encoders.size(); ++i)
|
||||
{
|
||||
m_encoders[i]->encodeHeader();
|
||||
boxContext.markOutputAsReadyToSend(size_t(i), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < nInput; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < boxContext.getInputChunkCount(i); ++j)
|
||||
{
|
||||
m_decoders[i]->decode(j);
|
||||
if (m_decoders[i]->isHeaderReceived()) { }
|
||||
if (m_decoders[i]->isBufferReceived())
|
||||
{
|
||||
const IStimulationSet* stimSet = m_decoders[i]->getOutputStimulationSet();
|
||||
|
||||
for (size_t k = 0; k < stimSet->getStimulationCount(); ++k)
|
||||
{
|
||||
m_iStimulations[i].insert(std::make_pair(stimSet->getStimulationDate(k),
|
||||
std::make_pair(stimSet->getStimulationIdentifier(k),
|
||||
stimSet->getStimulationDuration(k))));
|
||||
}
|
||||
|
||||
if (m_FilterMode)
|
||||
{
|
||||
// In this mode, the output chunk time range contains all the current input chunk time ranges
|
||||
start = std::min<uint64_t>(start, boxContext.getInputChunkStartTime(i, j));
|
||||
end = std::max<uint64_t>(end, boxContext.getInputChunkEndTime(i, j));
|
||||
if (start < m_lastTime)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "Earliest current input chunk start time "
|
||||
<< CTime(start) << " is older than the last sent block end time "
|
||||
<< CTime(m_lastTime) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_decoders[i]->isEndReceived()) { }
|
||||
boxContext.markInputAsDeprecated(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
runLuaThread();
|
||||
|
||||
// Send unless endtime=0 (then either we're at header time, or no chunks were received in filter mode)
|
||||
if (end > 0) { sendStimulations(start, end); }
|
||||
|
||||
if (!m_luaThread && m_LuaThreadHadError)
|
||||
{
|
||||
// Lua thread has exit, so it was ok to check m_bLuaThreadHadError without a lock
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::runLuaThread()
|
||||
{
|
||||
m_outerLock.lock();
|
||||
|
||||
// Executes one step of the thread
|
||||
switch (m_State)
|
||||
{
|
||||
case EStates::Unstarted:
|
||||
m_State = EStates::Processing;
|
||||
m_luaThread = new boost::thread(CLuaThread(this));
|
||||
m_condition.wait(m_outerLock);
|
||||
break;
|
||||
|
||||
case EStates::Processing:
|
||||
m_condition.notify_one();
|
||||
m_condition.wait(m_outerLock);
|
||||
break;
|
||||
|
||||
case EStates::Please_Quit:
|
||||
// Shouldn't happen as only uninitialize() sets this
|
||||
break;
|
||||
|
||||
case EStates::Finished:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Executes one step of the box once the thread has finished
|
||||
if (m_luaThread)
|
||||
{
|
||||
switch (m_State)
|
||||
{
|
||||
case EStates::Unstarted:
|
||||
break; // This should never happen
|
||||
|
||||
case EStates::Processing:
|
||||
break;
|
||||
|
||||
case EStates::Please_Quit:
|
||||
// Shouldn't happen as only uninitialize() sets this
|
||||
break;
|
||||
|
||||
case EStates::Finished:
|
||||
if (m_luaThread)
|
||||
{
|
||||
m_luaThread->join();
|
||||
delete m_luaThread;
|
||||
m_luaThread = nullptr;
|
||||
this->getLogManager() << Kernel::LogLevel_Info << "Lua script terminated\n";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_outerLock.unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::sendStimulations(const uint64_t startTime, const uint64_t endTime)
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
const size_t nOutput = this->getStaticBoxContext().getOutputCount();
|
||||
|
||||
for (size_t i = 0; i < nOutput; ++i)
|
||||
{
|
||||
IStimulationSet* stimSet = m_encoders[i]->getInputStimulationSet();
|
||||
stimSet->clear();
|
||||
|
||||
auto it = m_oStimulations[i].begin();
|
||||
while (it != m_oStimulations[i].end() && it->first < endTime)
|
||||
{
|
||||
const auto itStim = it;
|
||||
++it;
|
||||
|
||||
stimSet->appendStimulation(itStim->second.first, itStim->first, itStim->second.second);
|
||||
this->getLogManager() << Kernel::LogLevel_Debug << "On output " << i << " - should send stimulation " << itStim->second.first << " at date "
|
||||
<< CTime(itStim->first) << " with duration " << itStim->second.second << "\n";
|
||||
|
||||
m_oStimulations[i].erase(itStim);
|
||||
}
|
||||
|
||||
m_encoders[i]->encodeBuffer();
|
||||
|
||||
boxContext.markOutputAsReadyToSend(i, startTime, endTime);
|
||||
}
|
||||
|
||||
m_lastTime = endTime;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::waitForStimulation(const size_t inputIdx, const size_t stimIdx)
|
||||
{
|
||||
if (inputIdx >= m_iStimulations.size())
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_ImportantWarning << "Input " << (inputIdx + 1) << " does not exist\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
while (m_iStimulations[inputIdx].size() <= stimIdx)
|
||||
{
|
||||
switch (m_State)
|
||||
{
|
||||
case EStates::Unstarted: return false; // this should never happen
|
||||
case EStates::Finished: return false;
|
||||
case EStates::Please_Quit: return false;
|
||||
case EStates::Processing: this->sleepCB();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::getInputCountCB(size_t& count)
|
||||
{
|
||||
count = this->getStaticBoxContext().getInputCount();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::getOutputCountCB(size_t& count)
|
||||
{
|
||||
count = this->getStaticBoxContext().getOutputCount();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::getSettingCountCB(size_t& count)
|
||||
{
|
||||
count = this->getStaticBoxContext().getSettingCount();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::getSettingCB(const size_t index, CString& setting)
|
||||
{
|
||||
if (index >= this->getStaticBoxContext().getSettingCount())
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "Setting " << (index + 1) << " does not exist\n";
|
||||
setting = CString("");
|
||||
return true;
|
||||
}
|
||||
|
||||
setting = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::getConfigCB(const CString& str, CString& config)
|
||||
{
|
||||
config = this->getConfigurationManager().expand(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::getCurrentTimeCB(uint64_t& time)
|
||||
{
|
||||
time = this->getPlayerContext().getCurrentTime();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::sleepCB()
|
||||
{
|
||||
m_condition.notify_one();
|
||||
m_condition.wait(m_innerLock);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::getStimulationCountCB(const size_t index, size_t& count)
|
||||
{
|
||||
if (index >= m_iStimulations.size())
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "Input " << (index + 1) << " does not exist\n";
|
||||
count = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
count = size_t(m_iStimulations[index].size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::getStimulationCB(const size_t inputIdx, const size_t stimIdx, uint64_t& id, uint64_t& time, uint64_t& duration)
|
||||
{
|
||||
if (!this->waitForStimulation(inputIdx, stimIdx))
|
||||
{
|
||||
id = uint64_t(-1);
|
||||
time = uint64_t(-1);
|
||||
duration = uint64_t(-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto it = m_iStimulations[inputIdx].begin();
|
||||
|
||||
for (size_t i = 0; i < stimIdx; i++, ++it) {}
|
||||
|
||||
id = it->second.first;
|
||||
time = it->first;
|
||||
duration = it->second.second;
|
||||
|
||||
this->getLogManager() << Kernel::LogLevel_Debug << "getStimulationCB " << (inputIdx + 1) << " " << (stimIdx + 1) << " " << id << " " << time << " "
|
||||
<< duration << "\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::removeStimulationCB(const size_t inputIdx, const size_t stimIdx)
|
||||
{
|
||||
if (!this->waitForStimulation(inputIdx, stimIdx)) { return true; }
|
||||
|
||||
auto it = m_iStimulations[inputIdx].begin();
|
||||
|
||||
for (size_t i = 0; i < stimIdx; i++, ++it) {}
|
||||
|
||||
m_iStimulations[inputIdx].erase(it);
|
||||
|
||||
this->getLogManager() << Kernel::LogLevel_Debug << "removeStimulationCB " << (inputIdx + 1) << " " << (stimIdx + 1) << "\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::sendStimulationCB(const size_t outputIdx, uint64_t id, uint64_t time, uint64_t duration)
|
||||
{
|
||||
if (outputIdx < m_oStimulations.size())
|
||||
{
|
||||
if (time >= m_lastTime)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Debug << "sendStimulationCB " << (outputIdx + 1) << " " << id << " " << time << " " << duration << "\n";
|
||||
m_oStimulations[outputIdx].insert(std::make_pair(time, std::make_pair(id, duration)));
|
||||
}
|
||||
else
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_ImportantWarning << "Ignored outdated stimulation " << id << " " << CTime(time) << " " << CTime(duration)
|
||||
<< " sent on output " << (outputIdx + 1) << " - older than last chunk end time " << CTime(m_lastTime) << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_ImportantWarning << "Ignored stimulation " << id << " " << CTime(time) << " " << CTime(duration)
|
||||
<< " sent on unexistant output " << (outputIdx + 1) << "\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmLuaStimulator::log(const Kernel::ELogLevel level, const CString& text)
|
||||
{
|
||||
this->getLogManager() << level << "<" << Kernel::LogColor_PushStateBit << Kernel::LogColor_ForegroundGreen
|
||||
<< "In Script" << Kernel::LogColor_PopStateBit << "> " << text.toASCIIString() << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBoxAlgorithmLuaStimulator::doThread()
|
||||
{
|
||||
m_innerLock.lock();
|
||||
if (!lua_report(this->getLogManager(), m_luaState, luaL_dostring(m_luaState, "process(__openvibe_box_context)"))) { m_LuaThreadHadError = true; }
|
||||
m_State = EStates::Finished;
|
||||
m_innerLock.unlock();
|
||||
|
||||
m_condition.notify_one();
|
||||
m_exitCondition.notify_one();
|
||||
}
|
||||
|
||||
std::string CBoxAlgorithmLuaStimulator::toString(const EStates state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case EStates::Unstarted: return "Unstarted";
|
||||
case EStates::Processing: return "Processing";
|
||||
case EStates::Please_Quit: return "Please_Quit";
|
||||
case EStates::Finished: return "Finished";
|
||||
default: return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyLua
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
#pragma once
|
||||
|
||||
#if defined TARGET_HAS_ThirdPartyLua
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/thread/condition.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <cstdio>
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
}
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
class CBoxAlgorithmLuaStimulator final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>, public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
CBoxAlgorithmLuaStimulator();
|
||||
~CBoxAlgorithmLuaStimulator() override = default;
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
uint64_t getClockFrequency() override;
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processClock(Kernel::CMessageClock& msg) override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_LuaStimulator)
|
||||
|
||||
bool waitForStimulation(size_t inputIdx, size_t stimIdx);
|
||||
|
||||
bool getInputCountCB(size_t& count);
|
||||
bool getOutputCountCB(size_t& count);
|
||||
bool getSettingCountCB(size_t& count);
|
||||
bool getSettingCB(size_t index, CString& setting);
|
||||
bool getConfigCB(const CString& str, CString& config);
|
||||
|
||||
bool getCurrentTimeCB(uint64_t& time);
|
||||
bool sleepCB();
|
||||
bool getStimulationCountCB(size_t index, size_t& count);
|
||||
bool getStimulationCB(size_t inputIdx, size_t stimIdx, uint64_t& id, uint64_t& time, uint64_t& duration);
|
||||
bool removeStimulationCB(size_t inputIdx, size_t stimIdx);
|
||||
bool sendStimulationCB(size_t outputIdx, uint64_t id, uint64_t time, uint64_t duration);
|
||||
bool log(Kernel::ELogLevel level, const CString& text);
|
||||
|
||||
void doThread();
|
||||
|
||||
enum class EStates
|
||||
{
|
||||
Unstarted,
|
||||
Processing,
|
||||
Please_Quit,
|
||||
Finished,
|
||||
};
|
||||
|
||||
static std::string toString(const EStates state);
|
||||
|
||||
EStates m_State = EStates::Unstarted;
|
||||
bool m_LuaThreadHadError = false; // Set to true by the lua thread if there were issues
|
||||
bool m_FilterMode = false; // Output chunk generation driven by inputs (true) or by clock (false)
|
||||
|
||||
protected:
|
||||
|
||||
lua_State* m_luaState = nullptr;
|
||||
|
||||
uint64_t m_lastTime = 0;
|
||||
std::vector<std::multimap<uint64_t, std::pair<uint64_t, uint64_t>>> m_oStimulations;
|
||||
std::vector<std::multimap<uint64_t, std::pair<uint64_t, uint64_t>>> m_iStimulations;
|
||||
|
||||
boost::thread* m_luaThread = nullptr;
|
||||
boost::mutex m_mutex;
|
||||
boost::mutex::scoped_lock m_innerLock;
|
||||
boost::mutex::scoped_lock m_outerLock;
|
||||
boost::mutex::scoped_lock m_exitLock;
|
||||
boost::condition m_condition;
|
||||
boost::condition m_exitCondition;
|
||||
|
||||
std::vector<Toolkit::TStimulationDecoder<CBoxAlgorithmLuaStimulator>*> m_decoders;
|
||||
std::vector<Toolkit::TStimulationEncoder<CBoxAlgorithmLuaStimulator>*> m_encoders;
|
||||
|
||||
private:
|
||||
|
||||
CBoxAlgorithmLuaStimulator(const CBoxAlgorithmLuaStimulator&);
|
||||
|
||||
bool runLuaThread();
|
||||
bool sendStimulations(uint64_t startTime, uint64_t endTime);
|
||||
};
|
||||
|
||||
class CBoxAlgorithmLuaStimulatorListener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
|
||||
bool onInputAdded(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
box.setInputType(index, OV_TypeId_Stimulations);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onOutputAdded(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
box.setOutputType(index, OV_TypeId_Stimulations);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onSettingAdded(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
box.setSettingType(index, OV_TypeId_String);
|
||||
box.setSettingName(index, ("Setting " + std::to_string(index)).c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
|
||||
class CBoxAlgorithmLuaStimulatorDesc final : public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Lua Stimulator"); }
|
||||
CString getAuthorName() const override { return CString("Yann Renard"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA"); }
|
||||
CString getShortDescription() const override { return CString("Generates some stimulations according to an Lua script"); }
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Scripting"); }
|
||||
CString getVersion() const override { return CString("1.1"); }
|
||||
CString getStockItemName() const override { return CString("gtk-missing-image"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_LuaStimulator; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmLuaStimulator; }
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmLuaStimulatorListener; }
|
||||
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addOutput("Stimulations", OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addSetting("Lua Script", OV_TypeId_Script, "");
|
||||
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddOutput);
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddInput);
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddSetting);
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifySetting);
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_LuaStimulatorDesc)
|
||||
};
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyLua
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
#if defined TARGET_HAS_ThirdPartyOpenAL
|
||||
|
||||
#include "ovpCBoxAlgorithmOpenALSoundPlayer.h"
|
||||
#include <tcptagging/IStimulusSender.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
|
||||
#define BUFFER_SIZE 32768
|
||||
#define UNIQUE_SOURCE 1
|
||||
|
||||
bool CBoxAlgorithmOpenALSoundPlayer::initialize()
|
||||
{
|
||||
m_decoder.initialize(*this, 0);
|
||||
m_encoder.initialize(*this, 0);
|
||||
|
||||
m_playTrigger = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
m_stopTrigger = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
m_filename = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
m_loop = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
|
||||
|
||||
m_lastOutputChunkDate = -1;
|
||||
m_startOfSoundSent = false;
|
||||
m_endOfSoundSent = false;
|
||||
|
||||
if (alutInit(nullptr, nullptr) != AL_TRUE)
|
||||
{
|
||||
if (alutGetError() == ALUT_ERROR_INVALID_OPERATION) { this->getLogManager() << Kernel::LogLevel_Trace << "ALUT already initialized.\n"; }
|
||||
else
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "ALUT initialization returned a bad status.\n";
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "ALUT ERROR:\n" << alutGetErrorString(alutGetError()) << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_fileFormat = FILE_FORMAT_UNSUPPORTED;
|
||||
|
||||
const std::string file(m_filename.toASCIIString());
|
||||
if (file.find(".wav") != std::string::npos) { m_fileFormat = FILE_FORMAT_WAV; }
|
||||
if (file.find(".ogg") != std::string::npos) { m_fileFormat = FILE_FORMAT_OGG; }
|
||||
|
||||
m_stimulusSender = TCPTagging::CreateStimulusSender();
|
||||
|
||||
if (!m_stimulusSender->connect("localhost", "15361"))
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "Unable to connect to AS's TCP Tagging plugin, stimuli wont be forwarded.\n";
|
||||
}
|
||||
|
||||
return openSoundFile();
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmOpenALSoundPlayer::uninitialize()
|
||||
{
|
||||
m_decoder.uninitialize();
|
||||
m_encoder.uninitialize();
|
||||
|
||||
const bool status = stopSound(false);
|
||||
|
||||
#if UNIQUE_SOURCE
|
||||
alDeleteSources(1, &m_sourceHandle);
|
||||
#endif
|
||||
alDeleteBuffers(1, &m_soundBufferHandle);
|
||||
|
||||
if (alutExit() != AL_TRUE)
|
||||
{
|
||||
if (alutGetError() == ALUT_ERROR_INVALID_OPERATION) { this->getLogManager() << Kernel::LogLevel_Trace << "ALUT already exited.\n"; }
|
||||
else
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "ALUT uninitialization returned a bad status.\n";
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "ALUT ERROR:\n" << alutGetErrorString(alutGetError()) << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_stimulusSender)
|
||||
{
|
||||
delete m_stimulusSender;
|
||||
m_stimulusSender = nullptr;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmOpenALSoundPlayer::processClock(Kernel::CMessageClock& /*msg*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmOpenALSoundPlayer::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmOpenALSoundPlayer::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
if (m_lastOutputChunkDate == uint64_t(-1))
|
||||
{
|
||||
// Send header on initialize
|
||||
m_encoder.encodeHeader();
|
||||
boxContext.markOutputAsReadyToSend(0, 0, 0);
|
||||
m_lastOutputChunkDate = 0;
|
||||
}
|
||||
|
||||
// Look for command stimulations
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
m_decoder.decode(i);
|
||||
|
||||
if (m_decoder.isHeaderReceived()) { } // NOP
|
||||
if (m_decoder.isBufferReceived())
|
||||
{
|
||||
const IStimulationSet* stimSet = m_decoder.getOutputStimulationSet();
|
||||
|
||||
for (size_t j = 0; j < stimSet->getStimulationCount(); ++j)
|
||||
{
|
||||
const uint64_t stim = stimSet->getStimulationIdentifier(j);
|
||||
if (stim == m_playTrigger)
|
||||
{
|
||||
playSound();
|
||||
m_endOfSoundSent = false;
|
||||
m_startOfSoundSent = false;
|
||||
}
|
||||
else if (stim == m_stopTrigger) { stopSound(true); }
|
||||
else
|
||||
{
|
||||
// Immediate passthrough
|
||||
m_stimulusSender->sendStimulation(stim);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_decoder.isEndReceived())
|
||||
{
|
||||
// @fixme potentially bad behavior: the box may send chunks after sending this end
|
||||
m_encoder.encodeEnd();
|
||||
boxContext.markOutputAsReadyToSend(0, m_lastOutputChunkDate, this->getPlayerContext().getCurrentTime());
|
||||
m_lastOutputChunkDate = this->getPlayerContext().getCurrentTime();
|
||||
}
|
||||
}
|
||||
|
||||
// n.b. TCP Tagging should be used instead of this socket output. This code is kept for backwards compatibility.
|
||||
IStimulationSet* oStimSet = m_encoder.getInputStimulationSet();
|
||||
oStimSet->clear();
|
||||
|
||||
ALint status;
|
||||
alGetSourcei(m_sourceHandle, AL_SOURCE_STATE, &status);
|
||||
// CASE : the sound has stopped, and we need to send the stimulation
|
||||
if (status == AL_STOPPED && !m_endOfSoundSent)
|
||||
{
|
||||
oStimSet->appendStimulation(m_stopTrigger, this->getPlayerContext().getCurrentTime(), 0);
|
||||
m_endOfSoundSent = true;
|
||||
}
|
||||
// CASE : the sound has started playing, and we need to send the stimulation
|
||||
if (status == AL_PLAYING && !m_startOfSoundSent)
|
||||
{
|
||||
oStimSet->appendStimulation(m_playTrigger, this->getPlayerContext().getCurrentTime(), 0);
|
||||
m_startOfSoundSent = true;
|
||||
}
|
||||
|
||||
m_encoder.encodeBuffer();
|
||||
boxContext.markOutputAsReadyToSend(0, m_lastOutputChunkDate, this->getPlayerContext().getCurrentTime());
|
||||
|
||||
m_lastOutputChunkDate = this->getPlayerContext().getCurrentTime();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmOpenALSoundPlayer::openSoundFile()
|
||||
{
|
||||
switch (m_fileFormat)
|
||||
{
|
||||
case FILE_FORMAT_WAV:
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Buffering WAV file (this step may take some times for long files).\n";
|
||||
m_soundBufferHandle = alutCreateBufferFromFile(m_filename);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "WAV file buffered.\n";
|
||||
if (m_soundBufferHandle == AL_NONE)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "ALUT can't create buffer from file " << m_filename << "\n";
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "ALUT ERROR:\n" << alutGetErrorString(alutGetError()) << "\n";
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FILE_FORMAT_OGG:
|
||||
{
|
||||
// On windows using fopen+ov_open can lead to failure, as stated in the vorbis official documentation:
|
||||
//http://xiph.org/vorbis/doc/vorbisfile/ov_open.html
|
||||
// using ov_fopen instead.
|
||||
//m_oggVorbisStream.File = fopen((const char *)m_filename, "rb");
|
||||
//if (m_oggVorbisStream.File == nullptr)
|
||||
//{
|
||||
// this->getLogManager() << Kernel::LogLevel_Error << "Can't open file "<<m_filename<<": IO error\n.";
|
||||
// return false;
|
||||
//}
|
||||
|
||||
#if defined TARGET_OS_Windows
|
||||
if (ov_fopen(const_cast<char*>(m_filename.toASCIIString()), &m_oggVorbisStream.Stream) < 0)
|
||||
#elif defined TARGET_OS_Linux
|
||||
if((m_oggVorbisStream.File = fopen((const char *)m_filename, "rb")) == nullptr)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Can't open file "<<m_filename<<": IO error\n.";
|
||||
return false;
|
||||
}
|
||||
if(ov_open(m_oggVorbisStream.File, &(m_oggVorbisStream.Stream), nullptr, 0) < 0)
|
||||
#else
|
||||
#error "Please port this code"
|
||||
#endif
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Can't open file " << m_filename << ": OGG VORBIS stream error\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
vorbis_info* infos = ov_info(&m_oggVorbisStream.Stream, -1);
|
||||
m_oggVorbisStream.Format = infos->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
||||
m_oggVorbisStream.SampleRate = infos->rate;
|
||||
|
||||
//Now we fill the raw buffer (good for small piece of sound... use buffering for big files)
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Buffering OGG file (this step may take some times for long files).\n";
|
||||
int bytesRead;
|
||||
int bitStream;
|
||||
char buffer[BUFFER_SIZE];
|
||||
do
|
||||
{
|
||||
// Read up to a buffer's worth of decoded sound data
|
||||
bytesRead = ov_read(&m_oggVorbisStream.Stream, buffer, BUFFER_SIZE, 0, 2, 1, &bitStream);
|
||||
// Append to end of buffer
|
||||
m_rawOggBufferFromFile.insert(m_rawOggBufferFromFile.end(), buffer, buffer + bytesRead);
|
||||
} while (bytesRead > 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "OGG file buffered.\n";
|
||||
|
||||
//we have decoded all the file. we drop the decoder (file is closed for us).
|
||||
ov_clear(&m_oggVorbisStream.Stream);
|
||||
|
||||
//create empty buffer
|
||||
alGenBuffers(1, &m_soundBufferHandle);
|
||||
//fill it with raw data
|
||||
alBufferData(m_soundBufferHandle, m_oggVorbisStream.Format, &m_rawOggBufferFromFile[0], ALsizei(m_rawOggBufferFromFile.size()),
|
||||
m_oggVorbisStream.SampleRate);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Unsupported file format. Please use only WAV or OGG files.\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNIQUE_SOURCE
|
||||
alGenSources(1, &m_sourceHandle);
|
||||
alSourcei(m_sourceHandle, AL_BUFFER, m_soundBufferHandle);
|
||||
alSourcei(m_sourceHandle, AL_LOOPING, (m_loop ? AL_TRUE : AL_FALSE));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmOpenALSoundPlayer::playSound()
|
||||
{
|
||||
switch (m_fileFormat)
|
||||
{
|
||||
case FILE_FORMAT_WAV:
|
||||
case FILE_FORMAT_OGG:
|
||||
{
|
||||
#if UNIQUE_SOURCE
|
||||
ALint status;
|
||||
alGetSourcei(m_sourceHandle, AL_SOURCE_STATE, &status);
|
||||
if (status == AL_PLAYING) { alSourceStop(m_sourceHandle); } // we start back again
|
||||
alSourcePlay(m_sourceHandle);
|
||||
#else
|
||||
ALuint src;
|
||||
alGenSources(1, &src);
|
||||
m_sources.push_back(src);
|
||||
alSourcei (src, AL_BUFFER, m_soundBufferHandle);
|
||||
alSourcei (src, AL_LOOPING, (m_loop?AL_TRUE:AL_FALSE));
|
||||
alSourcePlay(src);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Unsupported file format. Please use only WAV or OGG files.\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_stimulusSender->sendStimulation(m_playTrigger);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmOpenALSoundPlayer::stopSound(const bool forwardStim)
|
||||
{
|
||||
switch (m_fileFormat)
|
||||
{
|
||||
case FILE_FORMAT_WAV:
|
||||
case FILE_FORMAT_OGG:
|
||||
{
|
||||
#if UNIQUE_SOURCE
|
||||
alSourceStop(m_sourceHandle);
|
||||
#else
|
||||
for (size_t i = 0;i<m_sources.size();i++)
|
||||
{
|
||||
//stop all sources
|
||||
alSourceStop(m_sources[i]);
|
||||
alDeleteSources(1, &m_sources[i]);
|
||||
}
|
||||
m_sources.clear();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Unsupported file format. Please use only WAV or OGG files.\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (forwardStim) { m_stimulusSender->sendStimulation(m_stopTrigger); }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif //TARGET_HAS_ThirdPartyOpenAL
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
|
||||
#if defined TARGET_HAS_ThirdPartyOpenAL
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <AL/alut.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
namespace TCPTagging {
|
||||
class IStimulusSender; // fwd declare
|
||||
}
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
class CBoxAlgorithmOpenALSoundPlayer final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
struct SOggVorbisStream
|
||||
{
|
||||
OggVorbis_File Stream;
|
||||
FILE* File;
|
||||
ALenum Format;
|
||||
ALsizei SampleRate;
|
||||
};
|
||||
|
||||
enum ESupportedFileFormat
|
||||
{
|
||||
FILE_FORMAT_WAV = 0,
|
||||
FILE_FORMAT_OGG,
|
||||
FILE_FORMAT_UNSUPPORTED
|
||||
};
|
||||
|
||||
CBoxAlgorithmOpenALSoundPlayer() { }
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
uint64_t getClockFrequency() override { return (128LL << 32); }
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processClock(Kernel::CMessageClock& msg) override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
bool openSoundFile();
|
||||
bool playSound();
|
||||
bool stopSound(bool forwardStim);
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_OpenALSoundPlayer)
|
||||
|
||||
protected:
|
||||
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmOpenALSoundPlayer> m_decoder;
|
||||
Toolkit::TStimulationEncoder<CBoxAlgorithmOpenALSoundPlayer> m_encoder;
|
||||
|
||||
uint64_t m_lastOutputChunkDate = 0;
|
||||
bool m_startOfSoundSent = false;
|
||||
bool m_endOfSoundSent = false;
|
||||
bool m_loop = false;
|
||||
uint64_t m_playTrigger = 0;
|
||||
uint64_t m_stopTrigger = 0;
|
||||
CString m_filename;
|
||||
|
||||
std::vector<ALuint> m_sources;
|
||||
ESupportedFileFormat m_fileFormat = FILE_FORMAT_UNSUPPORTED;
|
||||
|
||||
//The handles
|
||||
ALuint m_soundBufferHandle;
|
||||
ALuint m_sourceHandle;
|
||||
//OGG
|
||||
SOggVorbisStream m_oggVorbisStream;
|
||||
std::vector<char> m_rawOggBufferFromFile;
|
||||
|
||||
// For sending stimulations to the TCP Tagging
|
||||
TCPTagging::IStimulusSender* m_stimulusSender = nullptr;
|
||||
};
|
||||
|
||||
class CBoxAlgorithmOpenALSoundPlayerDesc final : public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Sound Player"); }
|
||||
CString getAuthorName() const override { return CString("Laurent Bonnet"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA"); }
|
||||
CString getShortDescription() const override { return CString("Play/Stop a sound, with or without loop."); }
|
||||
|
||||
CString getDetailedDescription() const override
|
||||
{
|
||||
return CString("Available format : WAV / OGG. Play and stop with input stimulations. Box based on OpenAL.");
|
||||
}
|
||||
|
||||
CString getCategory() const override { return CString("Stimulation"); }
|
||||
CString getVersion() const override { return CString("1.1"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_OpenALSoundPlayer; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmOpenALSoundPlayer; }
|
||||
CString getStockItemName() const override { return CString("gtk-media-play"); }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Input triggers", OV_TypeId_Stimulations);
|
||||
prototype.addOutput("Resync triggers (deprecated)", OV_TypeId_Stimulations);
|
||||
prototype.addSetting("PLAY trigger", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_00");
|
||||
prototype.addSetting("STOP trigger", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_01");
|
||||
prototype.addSetting("File to play", OV_TypeId_Filename, "${Path_Data}/plugins/stimulation/ov_beep.wav");
|
||||
prototype.addSetting("Loop", OV_TypeId_Boolean, "false");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_OpenALSoundPlayerDesc)
|
||||
};
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
#endif //TARGET_HAS_ThirdPartyOpenAL
|
||||
+438
@@ -0,0 +1,438 @@
|
||||
#include "ovpCBoxAlgorithmP300IdentifierStimulator.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
bool CBoxAlgorithmP300IdentifierStimulator::initialize()
|
||||
{
|
||||
//get values of the configure windows for all settings
|
||||
|
||||
m_startStimulation = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
m_stimulationBase = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
|
||||
m_nImages = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
|
||||
//the number of images must be different to 0
|
||||
if (m_nImages == 0)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_ImportantWarning << "This stimulator should at least have 1 Image (got " << m_nImages << ")\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_percentRepetitionTarget = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
|
||||
|
||||
//the percent of Repetition contains the target must be between 0% and 100%
|
||||
if (m_percentRepetitionTarget > 100.)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "The percent of repetition contains Target, should not be more than 100% \n";
|
||||
m_percentRepetitionTarget = 100.;
|
||||
}
|
||||
|
||||
if (m_percentRepetitionTarget < 0.)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "The percent of repetition contains Target, should not be less than 0% \n";
|
||||
m_percentRepetitionTarget = 0.;
|
||||
}
|
||||
|
||||
m_repetitionCountInTrial = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
|
||||
m_nTrial = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 5);
|
||||
m_flashDuration = uint64_t(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 6)) * double(1LL << 32));
|
||||
m_noFlashDuration = uint64_t(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 7)) * double(1LL << 32));
|
||||
m_interRepetitionDuration = uint64_t(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 8)) * double(1LL << 32));
|
||||
m_interTrialDuration = uint64_t(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 9)) * double(1LL << 32));
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
m_encoder = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationEncoder));
|
||||
m_encoder->initialize();
|
||||
|
||||
m_decoder = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder));
|
||||
m_decoder->initialize();
|
||||
|
||||
m_targetDecoder = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder));
|
||||
m_targetDecoder->initialize();
|
||||
|
||||
//initialized all variables
|
||||
m_headerSent = false;
|
||||
m_lastState = EStates::None;
|
||||
|
||||
m_nFlashInRepet = m_nImages;
|
||||
m_nFlashInRepetWithoutTarget = m_nFlashInRepet - 1;
|
||||
m_repetDuration = m_nFlashInRepet * (m_flashDuration + m_noFlashDuration);
|
||||
m_repetDurationWithoutTarget = m_nFlashInRepetWithoutTarget * (m_flashDuration + m_noFlashDuration);
|
||||
|
||||
m_repetTarget = new uint64_t[m_repetitionCountInTrial];
|
||||
|
||||
reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300IdentifierStimulator::reset()
|
||||
{
|
||||
m_lastTime = 0;
|
||||
m_startReceived = false;
|
||||
m_trialStartTime = m_interTrialDuration;
|
||||
|
||||
m_targetNum = 0;
|
||||
m_trialIdx = 1;
|
||||
//generate the first trial variables
|
||||
this->generateTrialVars();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300IdentifierStimulator::uninitialize()
|
||||
{
|
||||
m_decoder->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_decoder);
|
||||
|
||||
m_targetDecoder->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_targetDecoder);
|
||||
|
||||
m_encoder->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_encoder);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300IdentifierStimulator::processInput(const size_t /*index*/)
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
if (!m_startReceived)
|
||||
{
|
||||
Kernel::TParameterHandler<const IMemoryBuffer*> ip_buffer(
|
||||
m_decoder->getInputParameter(OVP_GD_Algorithm_StimulationDecoder_InputParameterId_MemoryBufferToDecode));
|
||||
const Kernel::TParameterHandler<IStimulationSet*> op_pStimulationSet(
|
||||
m_decoder->getOutputParameter(OVP_GD_Algorithm_StimulationDecoder_OutputParameterId_StimulationSet));
|
||||
ip_buffer = boxContext.getInputChunk(0, i);
|
||||
m_decoder->process();
|
||||
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedHeader)) { }
|
||||
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedBuffer))
|
||||
{
|
||||
for (size_t j = 0; j < op_pStimulationSet->getStimulationCount(); ++j)
|
||||
{
|
||||
if (op_pStimulationSet->getStimulationIdentifier(j) == m_startStimulation)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Start\n";
|
||||
m_trialStartTime = op_pStimulationSet->getStimulationDate(j) + m_interTrialDuration;
|
||||
m_startReceived = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedEnd)) { }
|
||||
}
|
||||
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(1); ++i)
|
||||
{
|
||||
if (m_startReceived)
|
||||
{
|
||||
Kernel::TParameterHandler<const IMemoryBuffer*> ip_buffer(
|
||||
m_targetDecoder->getInputParameter(OVP_GD_Algorithm_StimulationDecoder_InputParameterId_MemoryBufferToDecode));
|
||||
const Kernel::TParameterHandler<IStimulationSet*> op_stimSet(
|
||||
m_targetDecoder->getOutputParameter(OVP_GD_Algorithm_StimulationDecoder_OutputParameterId_StimulationSet));
|
||||
ip_buffer = boxContext.getInputChunk(1, i);
|
||||
m_targetDecoder->process();
|
||||
|
||||
if (m_targetDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedHeader)) { }
|
||||
|
||||
if (m_targetDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedBuffer))
|
||||
{
|
||||
for (size_t j = 0; j < op_stimSet->getStimulationCount(); ++j)
|
||||
{
|
||||
const uint64_t stimulationIdx = op_stimSet->getStimulationIdentifier(j) - m_stimulationBase;
|
||||
if (stimulationIdx < m_nImages)
|
||||
{
|
||||
m_targetNum = int64_t(stimulationIdx);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Choosen number of the targets " << m_targetNum << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_targetDecoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedEnd)) { }
|
||||
}
|
||||
|
||||
boxContext.markInputAsDeprecated(1, i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300IdentifierStimulator::processClock(Kernel::CMessageClock& /*msg*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300IdentifierStimulator::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
const uint64_t time = this->getPlayerContext().getCurrentTime();
|
||||
CStimulationSet stimSet;
|
||||
|
||||
//if start stimulation is receive
|
||||
if (m_startReceived)
|
||||
{
|
||||
EStates state; // = EStates::NoFlash;
|
||||
uint64_t flashIndex = uint64_t(-1);
|
||||
//case of inter-trial
|
||||
if (time < m_trialStartTime) { state = EStates::TrialRest; }
|
||||
//case of in-trial
|
||||
else
|
||||
{
|
||||
const uint64_t timeInTrial = time - m_trialStartTime;
|
||||
|
||||
//case of the current time is out of the trial time
|
||||
if (timeInTrial >= m_trialDuration)
|
||||
{
|
||||
//has next trial
|
||||
if (m_nTrial == 0 || m_trialIdx < m_nTrial)
|
||||
{
|
||||
m_trialStartTime = time + m_interTrialDuration;
|
||||
state = EStates::TrialRest;
|
||||
flashIndex = uint64_t(-1);
|
||||
m_trialIdx++;
|
||||
generateTrialVars();
|
||||
}
|
||||
//it was the last trial
|
||||
else
|
||||
{
|
||||
state = EStates::None;
|
||||
reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const int64_t timeInRepetition = getCurrentTimeInRepetition(timeInTrial);
|
||||
|
||||
//case of the current time is out of the repetition time
|
||||
if (timeInRepetition < 0 || uint64_t(timeInRepetition) >= (m_repetWithoutTarget ? m_repetDurationWithoutTarget : m_repetDuration))
|
||||
{
|
||||
state = EStates::RepetitionRest;
|
||||
flashIndex = uint64_t(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
flashIndex = timeInRepetition / (m_flashDuration + m_noFlashDuration);
|
||||
|
||||
//case of the current time isn't out of the flash time
|
||||
if (timeInRepetition % (m_flashDuration + m_noFlashDuration) < m_flashDuration) { state = EStates::Flash; }
|
||||
else { state = EStates::NoFlash; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//case of the state changed
|
||||
if (state != m_lastState)
|
||||
{
|
||||
//trigger send about the old state
|
||||
switch (m_lastState)
|
||||
{
|
||||
//case of the older state was a flash
|
||||
case EStates::Flash:
|
||||
stimSet.appendStimulation(OVTK_StimulationId_VisualStimulationStop, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_VisualStimulationStop\n\t; Trial index:" << m_trialIdx
|
||||
<< " Repetition index: " << m_repetIdx << "\n";
|
||||
break;
|
||||
//case of the older state was a no-flash
|
||||
case EStates::NoFlash:
|
||||
break;
|
||||
|
||||
//case of the older state was a inter-repetition
|
||||
case EStates::RepetitionRest:
|
||||
if (state != EStates::TrialRest && state != EStates::None)
|
||||
{
|
||||
stimSet.appendStimulation(OVTK_StimulationId_SegmentStart, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStart\n\t; Trial index:" << m_trialIdx
|
||||
<< " Repetition index: " << m_repetIdx << "\n";
|
||||
}
|
||||
break;
|
||||
//case of the older state was inter-Trial
|
||||
case EStates::TrialRest:
|
||||
stimSet.appendStimulation(OVTK_StimulationId_RestStop, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_RestStop\n\t; Trial index:" << m_trialIdx <<
|
||||
" Repetition index: "
|
||||
<< m_repetIdx << "\n";
|
||||
stimSet.appendStimulation(OVTK_StimulationId_TrialStart, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_TrialStart\n\t; Trial index:" << m_trialIdx <<
|
||||
" Repetition index: "
|
||||
<< m_repetIdx << "\n";
|
||||
stimSet.appendStimulation(OVTK_StimulationId_SegmentStart, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStart\n\t; Trial index:" << m_trialIdx <<
|
||||
" Repetition index: "
|
||||
<< m_repetIdx << "\n";
|
||||
break;
|
||||
//case of the older state was a None state
|
||||
case EStates::None:
|
||||
stimSet.appendStimulation(OVTK_StimulationId_ExperimentStart, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_ExperimentStart\n\t; Trial index:" << m_trialIdx
|
||||
<< " Repetition index: " << m_repetIdx << "\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//trigger and operation about the new state
|
||||
switch (state)
|
||||
{
|
||||
//case of the new state is a flash
|
||||
case EStates::Flash:
|
||||
stimSet.appendStimulation(m_stimulationBase + m_images[flashIndex], time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_LabelId(x)\n\t; Trial index:" << m_trialIdx <<
|
||||
" Repetition index: "
|
||||
<< m_repetIdx << "\n";
|
||||
stimSet.appendStimulation(OVTK_StimulationId_VisualStimulationStart, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_VisualStimulationStart\n\t; Trial index:" << m_trialIdx
|
||||
<< " Repetition index: " << m_repetIdx << "\n";
|
||||
break;
|
||||
//case of the new state is a no-flash
|
||||
case EStates::NoFlash:
|
||||
break;
|
||||
//case of the new state is a inter-repetition
|
||||
case EStates::RepetitionRest:
|
||||
stimSet.appendStimulation(OVTK_StimulationId_SegmentStop, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStop\n\t; Trial index:" << m_trialIdx <<
|
||||
" Repetition index: "
|
||||
<< m_repetIdx << "\n";
|
||||
this->generateSequence();
|
||||
break;
|
||||
//case of the new state is a inter-trial
|
||||
case EStates::TrialRest:
|
||||
m_targetNum = -1;
|
||||
if (m_lastState != EStates::None)
|
||||
{
|
||||
if (m_lastState != EStates::RepetitionRest)
|
||||
{
|
||||
stimSet.appendStimulation(OVTK_StimulationId_SegmentStop, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStop\n\t; Trial index:" << m_trialIdx
|
||||
<< " Repetition index: " << m_repetIdx << "\n";
|
||||
}
|
||||
stimSet.appendStimulation(OVTK_StimulationId_TrialStop, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_TrialStop\n\t; Trial index:" << m_trialIdx <<
|
||||
" Repetition index: "
|
||||
<< m_repetIdx << "\n";
|
||||
}
|
||||
stimSet.appendStimulation(OVTK_StimulationId_RestStart, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_RestStart\n\t; Trial index:" << m_trialIdx <<
|
||||
" Repetition index: "
|
||||
<< m_repetIdx << "\n";
|
||||
break;
|
||||
//case of the new state is a none state
|
||||
case EStates::None:
|
||||
if (m_lastState != EStates::RepetitionRest)
|
||||
{
|
||||
stimSet.appendStimulation(OVTK_StimulationId_SegmentStop, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStop\n\t; Trial index:" << m_trialIdx
|
||||
<< " Repetition index: " << m_repetIdx << "\n";
|
||||
}
|
||||
stimSet.appendStimulation(OVTK_StimulationId_TrialStop, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_TrialStop\n\t; Trial index:" << m_trialIdx <<
|
||||
" Repetition index: "
|
||||
<< m_repetIdx << "\n";
|
||||
stimSet.appendStimulation(OVTK_StimulationId_ExperimentStop, time, 0);
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_ExperimentStop\n\t; Trial index:" << m_trialIdx
|
||||
<< " Repetition index: " << m_repetIdx << "\n";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_lastState = state;
|
||||
}
|
||||
#if 0
|
||||
this->getLogManager() << Kernel::LogLevel_Info << "State:" << state_to_string(state) << " - flash index:" << flashIdx << " - repetition index:" << repetitionIdx << " - trial index:" << m_trialIdx << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
Kernel::TParameterHandler<IStimulationSet*> ip_stimSet(m_encoder->getInputParameter(OVP_GD_Algorithm_StimulationEncoder_InputParameterId_StimulationSet));
|
||||
Kernel::TParameterHandler<IMemoryBuffer*> op_buffer(
|
||||
m_encoder->getOutputParameter(OVP_GD_Algorithm_StimulationEncoder_OutputParameterId_EncodedMemoryBuffer));
|
||||
ip_stimSet = &stimSet;
|
||||
op_buffer = boxContext.getOutputChunk(0);
|
||||
if (!m_headerSent)
|
||||
{
|
||||
m_encoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeHeader);
|
||||
boxContext.markOutputAsReadyToSend(0, m_lastTime, time);
|
||||
}
|
||||
if (m_lastTime != time)
|
||||
{
|
||||
m_encoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeBuffer);
|
||||
boxContext.markOutputAsReadyToSend(0, m_lastTime, time);
|
||||
}
|
||||
m_lastTime = time;
|
||||
m_headerSent = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CBoxAlgorithmP300IdentifierStimulator::generateSequence()
|
||||
{
|
||||
if (m_repetIdx < m_repetitionCountInTrial)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "generate_sequence Repetition: " << m_repetIdx << " Target: " << m_targetNum << "\n";
|
||||
if (m_repetIdx > 0) { m_repetWithoutTarget = m_repetTarget[m_repetIdx] == m_repetTarget[m_repetIdx - 1]; }
|
||||
else { m_repetWithoutTarget = (m_repetTarget[0] == 0); }
|
||||
m_repetIdx++;
|
||||
std::vector<size_t> images;
|
||||
m_images.clear();
|
||||
for (size_t i = 0; i < m_nImages; ++i) { images.push_back(i); }
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Number target: " << " Repetition without target: " << m_repetWithoutTarget << "\n";
|
||||
if (m_repetWithoutTarget && m_targetNum != -1) { images.erase(images.begin() + size_t(m_targetNum)); }
|
||||
while (!images.empty())
|
||||
{
|
||||
const int j = rand() % images.size();
|
||||
m_images.push_back(size_t(images[j]));
|
||||
images.erase(images.begin() + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBoxAlgorithmP300IdentifierStimulator::generateTrialVars()
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "generate_trial_vars " << "\n";
|
||||
uint64_t nTargetInTrial = 0;
|
||||
for (size_t i = 0; i < m_repetitionCountInTrial; ++i)
|
||||
{
|
||||
const size_t random = rand();
|
||||
//increment the chance to display the target. we would'nt like to have no Target display in a trial.
|
||||
double percentRepetitionTargetInc = m_percentRepetitionTarget + (100 - m_percentRepetitionTarget) / (m_repetitionCountInTrial - 1) * i;
|
||||
const double percentRepetitionTarget = (nTargetInTrial < 1) ? percentRepetitionTargetInc : m_percentRepetitionTarget;
|
||||
|
||||
if (random % 100 < percentRepetitionTarget) { nTargetInTrial++; }
|
||||
m_repetTarget[i] = nTargetInTrial;
|
||||
}
|
||||
m_trialDuration = nTargetInTrial * (m_repetDuration + m_interRepetitionDuration)
|
||||
+ (m_repetitionCountInTrial - nTargetInTrial) * (m_repetDurationWithoutTarget + m_interRepetitionDuration);
|
||||
m_repetIdx = 0;
|
||||
m_targetNum = -1;
|
||||
}
|
||||
|
||||
int64_t CBoxAlgorithmP300IdentifierStimulator::getCurrentTimeInRepetition(const uint64_t timeInTrial)
|
||||
{
|
||||
if (m_repetIdx == 0) { return -1; }
|
||||
const int64_t timeInRepetition = timeInTrial - m_repetDuration * m_repetTarget[m_repetIdx - 1]
|
||||
- m_repetDurationWithoutTarget * (m_repetIdx - m_repetTarget[m_repetIdx - 1])
|
||||
- m_interRepetitionDuration * m_repetIdx;
|
||||
//case of the current time in Repetition is out of the current Repetition time
|
||||
if (timeInRepetition > 0)
|
||||
{
|
||||
generateSequence();
|
||||
return getCurrentTimeInRepetition(timeInTrial);
|
||||
}
|
||||
return timeInRepetition + m_interRepetitionDuration + (m_repetWithoutTarget ? m_repetDurationWithoutTarget : m_repetDuration);
|
||||
}
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
class CBoxAlgorithmP300IdentifierStimulator final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
uint64_t getClockFrequency() override { return 128LL << 32; }
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool processClock(Kernel::CMessageClock& msg) override;
|
||||
bool process() override;
|
||||
bool reset();
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_P300IdentifierStimulator)
|
||||
|
||||
protected:
|
||||
enum class EStates { None, Flash, NoFlash, RepetitionRest, TrialRest, ExperimentStop };
|
||||
|
||||
uint64_t m_startStimulation = 0;
|
||||
uint64_t m_stimulationBase = 0;
|
||||
|
||||
size_t m_nImages = 0;
|
||||
|
||||
double m_percentRepetitionTarget = 0;
|
||||
|
||||
size_t m_repetitionCountInTrial = 0;
|
||||
size_t m_nTrial = 0;
|
||||
uint64_t m_flashDuration = 0;
|
||||
uint64_t m_noFlashDuration = 0;
|
||||
uint64_t m_interRepetitionDuration = 0;
|
||||
uint64_t m_interTrialDuration = 0;
|
||||
|
||||
// bool m_avoidNeighborFlashing = false;
|
||||
|
||||
Kernel::IAlgorithmProxy* m_encoder = nullptr;
|
||||
Kernel::IAlgorithmProxy* m_decoder = nullptr;
|
||||
Kernel::IAlgorithmProxy* m_targetDecoder = nullptr;
|
||||
uint64_t m_lastTime = 0;
|
||||
bool m_headerSent = false;
|
||||
bool m_startReceived = false;
|
||||
|
||||
EStates m_lastState = EStates::None;
|
||||
uint64_t m_trialStartTime = 0;
|
||||
|
||||
size_t m_nFlashInRepet = 0;
|
||||
size_t m_nFlashInRepetWithoutTarget = 0;
|
||||
uint64_t m_repetDuration = 0;
|
||||
uint64_t m_repetDurationWithoutTarget = 0;
|
||||
uint64_t m_trialDuration = 0;
|
||||
size_t m_trialIdx = 0;
|
||||
|
||||
bool m_repetWithoutTarget = false; //true if the repetition doesn't contains the target
|
||||
|
||||
uint64_t m_repetIdx = 0;
|
||||
int64_t m_targetNum = 0;
|
||||
|
||||
uint64_t* m_repetTarget = nullptr; //for every Repetition of one trial indicate the number of target should see for the begin of the trial
|
||||
std::vector<size_t> m_images;
|
||||
|
||||
void generateSequence();
|
||||
void generateTrialVars();
|
||||
int64_t getCurrentTimeInRepetition(uint64_t timeInTrial);
|
||||
};
|
||||
|
||||
class CBoxAlgorithmP300IdentifierStimulatorDesc final : public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("P300 Identifier Stimulator"); }
|
||||
CString getAuthorName() const override { return CString("Baptiste Payan"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA"); }
|
||||
CString getShortDescription() const override { return CString("Generates a P300 stimulation sequence"); }
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Stimulation"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-select-font"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_P300IdentifierStimulator; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmP300IdentifierStimulator; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Incoming stimulations", OV_TypeId_Stimulations);
|
||||
prototype.addOutput("Produced stimulations", OV_TypeId_Stimulations);
|
||||
prototype.addInput("Target Stimulations", OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addSetting("Start stimulation", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_00");
|
||||
prototype.addSetting("Stimulation base", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_01");
|
||||
|
||||
prototype.addSetting("Number of identifiable objects", OV_TypeId_Integer, "6");
|
||||
|
||||
prototype.addSetting("Percent of repetitions containing the target", OV_TypeId_Float, "100");
|
||||
|
||||
prototype.addSetting("Number of repetitions", OV_TypeId_Integer, "5");
|
||||
prototype.addSetting("Number of trials", OV_TypeId_Integer, "5");
|
||||
prototype.addSetting("Flash duration (in sec)", OV_TypeId_Float, "0.075");
|
||||
prototype.addSetting("No flash duration (in sec)", OV_TypeId_Float, "0.125");
|
||||
prototype.addSetting("Inter-repetition delay (in sec)", OV_TypeId_Float, "2");
|
||||
prototype.addSetting("Inter-trial delay (in sec)", OV_TypeId_Float, "5");
|
||||
|
||||
// prototype.addSetting("Avoid neighbor flashing", OV_TypeId_Boolean, "false");
|
||||
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_P300IdentifierStimulatorDesc)
|
||||
};
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+378
@@ -0,0 +1,378 @@
|
||||
//
|
||||
// @todo the code logic in process() should be simplified and made more clear, perhaps by adding more states to the machine
|
||||
//
|
||||
#include "ovpCBoxAlgorithmP300SpellerStimulator.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
/*
|
||||
CString toString(const EStates state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case EStates::None: return "None";
|
||||
case EStates::Flash: return "Flash";
|
||||
case EStates::NoFlash: return "NoFlash";
|
||||
case EStates::RepetitionRest: return "RepetitionRest";
|
||||
case EStates::TrialRest: return "TrialRest";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
bool CBoxAlgorithmP300SpellerStimulator::initialize()
|
||||
{
|
||||
m_decoder = nullptr;
|
||||
m_encoder = nullptr;
|
||||
|
||||
m_startStimulation = this->getTypeManager().getEnumerationEntryValueFromName(
|
||||
OV_TypeId_Stimulation, FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0));
|
||||
m_rowStimulationBase = this->getTypeManager().getEnumerationEntryValueFromName(
|
||||
OV_TypeId_Stimulation, FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1));
|
||||
m_columnStimulationBase = this->getTypeManager().getEnumerationEntryValueFromName(
|
||||
OV_TypeId_Stimulation, FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2));
|
||||
|
||||
m_nRow = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 3);
|
||||
m_nCol = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 4);
|
||||
|
||||
if (m_nRow == 0 || m_nCol == 0)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_ImportantWarning << "This stimulator should at least have 1 row and 1 column (got " << m_nRow << " and " <<
|
||||
m_nCol << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_nRow != m_nCol)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_ImportantWarning << "This stimulator should have the same number of row(s) and columns(s) (got " << m_nRow <<
|
||||
" and " << m_nCol << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_nRepetInTrial = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 5);
|
||||
m_nTrial = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 6);
|
||||
m_flashDuration = CTime(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 7))).time();
|
||||
m_noFlashDuration = CTime(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 8))).time();
|
||||
m_interRepetDuration = CTime(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 9))).time();
|
||||
m_interTrialDuration = CTime(double(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 10))).time();
|
||||
|
||||
m_avoidNeighborFlashing = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 11);
|
||||
|
||||
const uint64_t durationThreshold = (10LL << 32) / 1000; // 10ms
|
||||
if (m_interRepetDuration < durationThreshold)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "Inter repetition duration should not be less than 10 ms\n";
|
||||
m_interRepetDuration = durationThreshold;
|
||||
}
|
||||
|
||||
if (m_interTrialDuration < durationThreshold)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "Inter trial duration should not be less than 10 ms\n";
|
||||
m_interTrialDuration = durationThreshold;
|
||||
}
|
||||
|
||||
if (m_avoidNeighborFlashing) { this->getLogManager() << Kernel::LogLevel_ImportantWarning << "Avoid neighbor flashing setting is not considered yet\n"; }
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
m_encoder = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationEncoder));
|
||||
m_encoder->initialize();
|
||||
|
||||
m_decoder = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder));
|
||||
m_decoder->initialize();
|
||||
|
||||
m_lastTime = 0;
|
||||
m_headerSent = false;
|
||||
m_startReceived = false;
|
||||
|
||||
m_lastState = EStates::None;
|
||||
m_trialStartTime = m_interTrialDuration;
|
||||
|
||||
m_nFlashInRepet = m_nRow + m_nCol;
|
||||
m_repetDuration = m_nFlashInRepet * (m_flashDuration + m_noFlashDuration);
|
||||
m_trialDuration = m_nRepetInTrial * (m_repetDuration + m_interRepetDuration);
|
||||
m_trialIdx = 1;
|
||||
|
||||
this->generateSequence();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300SpellerStimulator::uninitialize()
|
||||
{
|
||||
if (m_decoder)
|
||||
{
|
||||
m_decoder->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_decoder);
|
||||
m_decoder = nullptr;
|
||||
}
|
||||
|
||||
if (m_encoder)
|
||||
{
|
||||
m_encoder->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_encoder);
|
||||
m_encoder = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300SpellerStimulator::processInput(const size_t /*index*/)
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
if (!m_startReceived)
|
||||
{
|
||||
Kernel::TParameterHandler<const IMemoryBuffer*> ip_buffer(
|
||||
m_decoder->getInputParameter(OVP_GD_Algorithm_StimulationDecoder_InputParameterId_MemoryBufferToDecode));
|
||||
const Kernel::TParameterHandler<IStimulationSet*> op_stimSet(
|
||||
m_decoder->getOutputParameter(OVP_GD_Algorithm_StimulationDecoder_OutputParameterId_StimulationSet));
|
||||
ip_buffer = boxContext.getInputChunk(0, i);
|
||||
m_decoder->process();
|
||||
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedHeader)) { }
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedBuffer))
|
||||
{
|
||||
for (size_t j = 0; j < op_stimSet->getStimulationCount(); ++j)
|
||||
{
|
||||
if (op_stimSet->getStimulationIdentifier(j) == m_startStimulation)
|
||||
{
|
||||
m_trialStartTime = op_stimSet->getStimulationDate(j) + m_interTrialDuration;
|
||||
m_startReceived = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedEnd)) { }
|
||||
}
|
||||
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300SpellerStimulator::processClock(Kernel::CMessageClock& /*msg*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmP300SpellerStimulator::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
const uint64_t currentTime = this->getPlayerContext().getCurrentTime();
|
||||
CStimulationSet stimulationSet;
|
||||
|
||||
if (m_startReceived)
|
||||
{
|
||||
EStates state = EStates::NoFlash;
|
||||
size_t flashIndex = size_t(-1);
|
||||
if (currentTime < m_trialStartTime) { state = EStates::TrialRest; }
|
||||
else
|
||||
{
|
||||
if ((m_trialIdx > m_nTrial) && (m_nTrial > 0)) { state = EStates::ExperimentStop; }
|
||||
else
|
||||
{
|
||||
const uint64_t curTimeInTrial = currentTime - m_trialStartTime;
|
||||
const uint64_t curTimeInRepet = curTimeInTrial % (m_repetDuration + m_interRepetDuration);
|
||||
|
||||
// FIXME is it necessary to keep next line uncomment ?
|
||||
//size_t repritionIndexInTrial = currentTimeInTrial/(m_repetDuration+m_interRepetDuration);
|
||||
const size_t flashIndexInRepet = curTimeInRepet / (m_flashDuration + m_noFlashDuration);
|
||||
|
||||
flashIndex = flashIndexInRepet;
|
||||
// FIXME is it necessary to keep next line uncomment ?
|
||||
//repetitionIdx = repritionIndexInTrial;
|
||||
|
||||
if (curTimeInTrial >= m_trialDuration)
|
||||
{
|
||||
if (m_nTrial == 0 || m_trialIdx <= m_nTrial)
|
||||
{
|
||||
m_trialStartTime = currentTime + m_interTrialDuration;
|
||||
state = EStates::TrialRest;
|
||||
flashIndex = size_t(-1);
|
||||
// FIXME is it necessary to keep next line uncomment ?
|
||||
//repetitionIdx = size_t(-1);
|
||||
m_trialIdx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_trialStartTime = currentTime + m_interTrialDuration;
|
||||
state = EStates::None;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curTimeInRepet >= m_repetDuration)
|
||||
{
|
||||
state = EStates::RepetitionRest;
|
||||
flashIndex = size_t(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curTimeInRepet % (m_flashDuration + m_noFlashDuration) < m_flashDuration) { state = EStates::Flash; }
|
||||
else { state = EStates::NoFlash; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state != m_lastState)
|
||||
{
|
||||
const bool bRow = ((flashIndex & 1) == 1);
|
||||
const long row = long(bRow ? m_rows[flashIndex >> 1] : -1);
|
||||
const long col = long(bRow ? -1 : m_columns[flashIndex >> 1]);
|
||||
|
||||
switch (m_lastState)
|
||||
{
|
||||
case EStates::Flash:
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_VisualStimulationStop, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_VisualStimulationStop\n";
|
||||
break;
|
||||
|
||||
case EStates::NoFlash:
|
||||
break;
|
||||
|
||||
case EStates::RepetitionRest:
|
||||
if (state != EStates::TrialRest && state != EStates::None)
|
||||
{
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_SegmentStart, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStart\n";
|
||||
}
|
||||
break;
|
||||
|
||||
case EStates::TrialRest:
|
||||
if (m_trialIdx <= m_nTrial)
|
||||
{
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_RestStop, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_RestStop\n";
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_TrialStart, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_TrialStart\n";
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_SegmentStart, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStart\n";
|
||||
}
|
||||
break;
|
||||
|
||||
case EStates::None:
|
||||
if (m_trialIdx <= m_nTrial)
|
||||
{
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_ExperimentStart, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_ExperimentStart\n";
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case EStates::Flash:
|
||||
stimulationSet.appendStimulation(bRow ? m_rowStimulationBase + row : m_columnStimulationBase + col, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_LabelId(x)\n";
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_VisualStimulationStart, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_VisualStimulationStart\n";
|
||||
break;
|
||||
|
||||
case EStates::NoFlash:
|
||||
break;
|
||||
|
||||
case EStates::RepetitionRest:
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_SegmentStop, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStop\n";
|
||||
this->generateSequence();
|
||||
break;
|
||||
|
||||
case EStates::TrialRest:
|
||||
if (m_lastState != EStates::None)
|
||||
{
|
||||
if (m_lastState != EStates::RepetitionRest)
|
||||
{
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_SegmentStop, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStop\n";
|
||||
}
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_TrialStop, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_TrialStop\n";
|
||||
}
|
||||
if (m_trialIdx <= m_nTrial)
|
||||
{
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_RestStart, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_RestStart\n";
|
||||
}
|
||||
break;
|
||||
|
||||
case EStates::None:
|
||||
if (m_lastState != EStates::RepetitionRest)
|
||||
{
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_SegmentStop, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_SegmentStop\n";
|
||||
}
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_TrialStop, currentTime, 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_TrialStop\n";
|
||||
break;
|
||||
case EStates::ExperimentStop:
|
||||
// The experiment stop is sent with some delay to allow the last flash / letter to be processed gracefully by the DSP later
|
||||
stimulationSet.appendStimulation(OVTK_StimulationId_ExperimentStop, currentTime + CTime(3.0).time(), 0);
|
||||
//this->getLogManager() << Kernel::LogLevel_Trace << "sends OVTK_StimulationId_ExperimentStop\n";
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_lastState = state;
|
||||
}
|
||||
}
|
||||
|
||||
Kernel::TParameterHandler<IStimulationSet*> ip_stimSet(m_encoder->getInputParameter(OVP_GD_Algorithm_StimulationEncoder_InputParameterId_StimulationSet));
|
||||
Kernel::TParameterHandler<IMemoryBuffer*> op_buffer(
|
||||
m_encoder->getOutputParameter(OVP_GD_Algorithm_StimulationEncoder_OutputParameterId_EncodedMemoryBuffer));
|
||||
ip_stimSet = &stimulationSet;
|
||||
op_buffer = boxContext.getOutputChunk(0);
|
||||
if (!m_headerSent)
|
||||
{
|
||||
m_encoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeHeader);
|
||||
boxContext.markOutputAsReadyToSend(0, m_lastTime, currentTime);
|
||||
}
|
||||
if (m_lastTime != currentTime)
|
||||
{
|
||||
m_encoder->process(OVP_GD_Algorithm_StimulationEncoder_InputTriggerId_EncodeBuffer);
|
||||
boxContext.markOutputAsReadyToSend(0, m_lastTime, currentTime);
|
||||
}
|
||||
m_lastTime = currentTime;
|
||||
m_headerSent = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBoxAlgorithmP300SpellerStimulator::generateSequence()
|
||||
{
|
||||
std::vector<size_t> rows;
|
||||
m_rows.clear();
|
||||
for (size_t i = 0; i < m_nRow; ++i) { rows.push_back(i); }
|
||||
for (size_t i = 0; i < m_nRow; ++i)
|
||||
{
|
||||
const size_t j = rand() % rows.size();
|
||||
m_rows[i] = rows[j];
|
||||
rows.erase(rows.begin() + j);
|
||||
}
|
||||
|
||||
std::vector<size_t> cols;
|
||||
m_columns.clear();
|
||||
for (size_t i = 0; i < m_nCol; ++i) { cols.push_back(i); }
|
||||
for (size_t i = 0; i < m_nCol; ++i)
|
||||
{
|
||||
const size_t j = rand() % cols.size();
|
||||
m_columns[i] = cols[j];
|
||||
cols.erase(cols.begin() + j);
|
||||
}
|
||||
}
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
class CBoxAlgorithmP300SpellerStimulator final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
uint64_t getClockFrequency() override { return 128LL << 32; }
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool processClock(Kernel::CMessageClock& msg) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_P300SpellerStimulator)
|
||||
|
||||
protected:
|
||||
|
||||
enum class EStates { None, Flash, NoFlash, RepetitionRest, TrialRest, ExperimentStop };
|
||||
|
||||
uint64_t m_startStimulation = 0;
|
||||
uint64_t m_rowStimulationBase = 0;
|
||||
uint64_t m_columnStimulationBase = 0;
|
||||
|
||||
size_t m_nRow = 0;
|
||||
size_t m_nCol = 0;
|
||||
|
||||
size_t m_nRepetInTrial = 0;
|
||||
size_t m_nTrial = 0;
|
||||
uint64_t m_flashDuration = 0;
|
||||
uint64_t m_noFlashDuration = 0;
|
||||
uint64_t m_interRepetDuration = 0;
|
||||
uint64_t m_interTrialDuration = 0;
|
||||
|
||||
bool m_avoidNeighborFlashing = false;
|
||||
|
||||
Kernel::IAlgorithmProxy* m_encoder = nullptr;
|
||||
Kernel::IAlgorithmProxy* m_decoder = nullptr;
|
||||
uint64_t m_lastTime = 0;
|
||||
bool m_headerSent = false;
|
||||
bool m_startReceived = false;
|
||||
|
||||
EStates m_lastState = EStates::None;
|
||||
uint64_t m_trialStartTime = 0;
|
||||
|
||||
size_t m_nFlashInRepet = 0;
|
||||
uint64_t m_repetDuration = 0;
|
||||
uint64_t m_trialDuration = 0;
|
||||
size_t m_trialIdx = 0;
|
||||
|
||||
std::map<size_t, size_t> m_rows;
|
||||
std::map<size_t, size_t> m_columns;
|
||||
|
||||
void generateSequence();
|
||||
};
|
||||
|
||||
class CBoxAlgorithmP300SpellerStimulatorDesc final : public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("P300 Speller Stimulator"); }
|
||||
CString getAuthorName() const override { return CString("Yann Renard"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA"); }
|
||||
CString getShortDescription() const override { return CString("Generates a stimulation sequence suitable for a P300 speller"); }
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Stimulation"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-select-font"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_P300SpellerStimulator; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmP300SpellerStimulator; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Incoming stimulations", OV_TypeId_Stimulations);
|
||||
prototype.addOutput("Produced stimulations", OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addSetting("Start stimulation", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_00");
|
||||
prototype.addSetting("Row stimulation base", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_01");
|
||||
prototype.addSetting("Column stimulation base", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_07");
|
||||
|
||||
prototype.addSetting("Number of rows", OV_TypeId_Integer, "6");
|
||||
prototype.addSetting("Number of columns", OV_TypeId_Integer, "6");
|
||||
|
||||
prototype.addSetting("Number of repetitions", OV_TypeId_Integer, "5");
|
||||
prototype.addSetting("Number of trials", OV_TypeId_Integer, "5");
|
||||
prototype.addSetting("Flash duration (in sec)", OV_TypeId_Float, "0.075");
|
||||
prototype.addSetting("No flash duration (in sec)", OV_TypeId_Float, "0.125");
|
||||
prototype.addSetting("Inter-repetition delay (in sec)", OV_TypeId_Float, "2");
|
||||
prototype.addSetting("Inter-trial delay (in sec)", OV_TypeId_Float, "5");
|
||||
|
||||
prototype.addSetting("Avoid neighbor flashing", OV_TypeId_Boolean, "false");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_P300SpellerStimulatorDesc)
|
||||
};
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
#include "ovpCBoxAlgorithmRunCommand.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
bool CBoxAlgorithmRunCommand::initialize()
|
||||
{
|
||||
m_decoder = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_GD_ClassId_Algorithm_StimulationDecoder));
|
||||
m_decoder->initialize();
|
||||
ip_buffer.initialize(m_decoder->getInputParameter(OVP_GD_Algorithm_StimulationDecoder_InputParameterId_MemoryBufferToDecode));
|
||||
op_stimSet.initialize(m_decoder->getOutputParameter(OVP_GD_Algorithm_StimulationDecoder_OutputParameterId_StimulationSet));
|
||||
|
||||
const size_t nSetting = this->getStaticBoxContext().getSettingCount();
|
||||
for (size_t i = 0; i < nSetting; i += 2)
|
||||
{
|
||||
m_commands[uint64_t(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i))].
|
||||
push_back(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i + 1));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmRunCommand::uninitialize()
|
||||
{
|
||||
op_stimSet.uninitialize();
|
||||
ip_buffer.uninitialize();
|
||||
m_decoder->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_decoder);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmRunCommand::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmRunCommand::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
ip_buffer = boxContext.getInputChunk(0, i);
|
||||
m_decoder->process();
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedHeader)) { }
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedBuffer))
|
||||
{
|
||||
IStimulationSet* stimSet = op_stimSet;
|
||||
for (size_t j = 0; j < stimSet->getStimulationCount(); ++j)
|
||||
{
|
||||
uint64_t stimulationID = stimSet->getStimulationIdentifier(j);
|
||||
if (m_commands.find(stimulationID) != m_commands.end())
|
||||
{
|
||||
std::vector<CString>& command = m_commands[stimulationID];
|
||||
auto it = command.begin();
|
||||
while (it != command.end())
|
||||
{
|
||||
CString str = *it;
|
||||
#if defined(WIN32)
|
||||
// On Windows, we pad the call with quotes. This addresses the situation where both the
|
||||
// command and some of its arguments have spaces, e.g. the call being like
|
||||
//
|
||||
// "C:\Program Files\blah.exe" --something "C:\Program Files\duh.dat"
|
||||
//
|
||||
// Without padding the whole line with quotes, it doesn't seem work.
|
||||
str = CString("\"") + str + CString("\"");
|
||||
#else
|
||||
// On other platforms, we pass the call as-is. We cannot pad the call in the scenario as the
|
||||
// Linux shell - on the other hand - doesn't like calls like ""blah blah" "blah""
|
||||
#endif
|
||||
this->getLogManager() << Kernel::LogLevel_Debug << "Running command [" << str << "]\n";
|
||||
if (system(str.toASCIIString()) < 0) { this->getLogManager() << Kernel::LogLevel_Warning << "Could not run command " << str << "\n"; }
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_decoder->isOutputTriggerActive(OVP_GD_Algorithm_StimulationDecoder_OutputTriggerId_ReceivedEnd)) { }
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <iomanip>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
class CBoxAlgorithmRunCommand final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_RunCommand)
|
||||
|
||||
protected:
|
||||
|
||||
Kernel::IAlgorithmProxy* m_decoder = nullptr;
|
||||
Kernel::TParameterHandler<const IMemoryBuffer*> ip_buffer;
|
||||
Kernel::TParameterHandler<IStimulationSet*> op_stimSet;
|
||||
std::map<uint64_t, std::vector<CString>> m_commands;
|
||||
};
|
||||
|
||||
class CBoxAlgorithmRunCommandListener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
|
||||
bool check(Kernel::IBox& box) const
|
||||
{
|
||||
for (size_t i = 0; i < box.getSettingCount(); i += 2)
|
||||
{
|
||||
box.setSettingName(i, ("Stimulation " + std::to_string(i / 2 + 1)).c_str());
|
||||
box.setSettingType(i, OV_TypeId_Stimulation);
|
||||
box.setSettingName(i + 1, ("Command " + std::to_string(i / 2 + 1)).c_str());
|
||||
box.setSettingType(i + 1, OV_TypeId_String);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onSettingAdded(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss.fill('0');
|
||||
ss << std::setw(2) << size_t(index / 2 + 1);
|
||||
const CString name(ss.str().c_str());
|
||||
box.setSettingDefaultValue(index, name);
|
||||
box.setSettingValue(index, name);
|
||||
box.addSetting("", OV_TypeId_String, "");
|
||||
this->check(box);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onSettingRemoved(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
box.removeSetting((index / 2) * 2);
|
||||
this->check(box);
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
|
||||
class CBoxAlgorithmRunCommandDesc final : public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Run Command"); }
|
||||
CString getAuthorName() const override { return CString("Yann Renard"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA"); }
|
||||
|
||||
CString getShortDescription() const override { return CString("Runs some command using system call depending on provided stimulations"); }
|
||||
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Stimulation"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-execute"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_RunCommand; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmRunCommand; }
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmRunCommandListener; }
|
||||
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Stimulations", OV_TypeId_Stimulations);
|
||||
prototype.addSetting("Stimulation 1", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_01");
|
||||
prototype.addSetting("Command 1", OV_TypeId_String, "");
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddSetting);
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_RunCommandDesc)
|
||||
};
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "ovpCKeyboardStimulator.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <tcptagging/IStimulusSender.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
//! Callback for the close window button
|
||||
//static void keyboard_stimulator_gtk_widget_do_nothing(GtkWidget* widget) { }
|
||||
|
||||
// Called when a key is pressed on the keyboard
|
||||
static gboolean key_press_cb(GtkWidget* /*widget*/, GdkEventKey* thisEvent, gpointer data)
|
||||
{
|
||||
reinterpret_cast<CKeyboardStimulator*>(data)->processKey(thisEvent->keyval, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called when a key is released on the keyboard
|
||||
static gboolean key_release_cb(GtkWidget* /*widget*/, GdkEventKey* thisEvent, gpointer data)
|
||||
{
|
||||
reinterpret_cast<CKeyboardStimulator*>(data)->processKey(thisEvent->keyval, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a key has been pressed.
|
||||
* \param key The gdk value to the pressed key.
|
||||
* \param state state of the pressed key
|
||||
* */
|
||||
void CKeyboardStimulator::processKey(const guint key, const bool state)
|
||||
{
|
||||
//if there is one entry, adds the stimulation to the list of stims to be sent
|
||||
if (m_keyToStimulation.count(key) != 0 && state != m_keyToStimulation[key].status)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
// getLogManager() << Kernel::LogLevel_Trace << "Pressed key code " << (size_t)key << "\n";
|
||||
m_stimulusSender->sendStimulation(m_keyToStimulation[key].press);
|
||||
m_stimulationToSend.push_back(m_keyToStimulation[key].press);
|
||||
}
|
||||
else
|
||||
{
|
||||
// getLogManager() << Kernel::LogLevel_Trace << "Released key code " << (size_t)key << "\n";
|
||||
m_stimulusSender->sendStimulation(m_keyToStimulation[key].release);
|
||||
m_stimulationToSend.push_back(m_keyToStimulation[key].release);
|
||||
}
|
||||
m_keyToStimulation[key].status = state;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this->getLogManager() << Kernel::LogLevel_Warning << "Unhandled key code " << (size_t)key << "\n";
|
||||
m_unknownKeyPressed = true;
|
||||
m_unknownKeyCode = size_t(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the configuration file and creates the Key/Stimulation associations.
|
||||
* \param filename The name of the configuration file.
|
||||
* \return True if the file was correctly parsed.
|
||||
* */
|
||||
bool CKeyboardStimulator::parseConfigurationFile(const char* filename)
|
||||
{
|
||||
std::ifstream file;
|
||||
file.open(filename);
|
||||
|
||||
if (!file) { return false; }
|
||||
|
||||
std::string keyName, stimPress, stimRelease;
|
||||
|
||||
//reads all the couples key name/stim
|
||||
while (!file.eof() && !file.fail())
|
||||
{
|
||||
file >> keyName >> stimPress >> stimRelease;
|
||||
|
||||
key_t key;
|
||||
key.press = 0;
|
||||
key.release = 0;
|
||||
key.status = false;
|
||||
|
||||
// MAY CAUSE ENDIANNESS PROBLEMS !
|
||||
sscanf(stimPress.c_str(), "0x%08llx", &key.press);
|
||||
sscanf(stimRelease.c_str(), "0x%08llx", &key.release);
|
||||
|
||||
m_keyToStimulation[gdk_keyval_from_name(keyName.c_str())] = key;
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKeyboardStimulator::initialize()
|
||||
{
|
||||
// Parses box settings to find input file's name
|
||||
const CString fileName = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
//CString tcpTaggingHostAddress = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
//CString tcpTaggingHostPort = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
const CString tcpTaggingHostAddress("localhost");
|
||||
const CString tcpTaggingHostPort("15361");
|
||||
|
||||
if (!parseConfigurationFile(fileName.toASCIIString()))
|
||||
{
|
||||
getBoxAlgorithmContext()->getPlayerContext()->getLogManager() << Kernel::LogLevel_Warning << "Problem while parsing configuration file!\n";
|
||||
m_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_encoder.initialize(*this, 0);
|
||||
|
||||
//const std::string red("#602020");
|
||||
const std::string green("#206020");
|
||||
const std::string blue("#202060");
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "\nUse your keyboard to send stimulations\nAvailable keys are :\n\n";
|
||||
for (auto i = m_keyToStimulation.begin(); i != m_keyToStimulation.end(); ++i)
|
||||
{
|
||||
ss << "<span size=\"smaller\">\t";
|
||||
ss << "<span style=\"italic\" foreground=\"" << green << "\">" << gdk_keyval_name(i->first) << "</span>";
|
||||
ss << "\t";
|
||||
ss << "Pressed : <span style=\"italic\" foreground=\"" << blue << "\">"
|
||||
<< this->getTypeManager().getEnumerationEntryNameFromValue(OV_TypeId_Stimulation, i->second.press) << "</span>";
|
||||
ss << "\t";
|
||||
ss << "Released : <span style=\"italic\" foreground=\"" << blue << "\">"
|
||||
<< this->getTypeManager().getEnumerationEntryNameFromValue(OV_TypeId_Stimulation, i->second.release) << "</span>";
|
||||
ss << "\t</span>\n";
|
||||
}
|
||||
|
||||
GtkBuilder* builder =
|
||||
gtk_builder_new(); // glade_xml_new(Directories::getDataDir() + "/plugins/stimulation/keyboard-stimulator.ui", nullptr, nullptr);
|
||||
gtk_builder_add_from_file(builder, Directories::getDataDir() + "/plugins/stimulation/keyboard-stimulator.ui", nullptr);
|
||||
gtk_builder_connect_signals(builder, nullptr);
|
||||
|
||||
m_widget = GTK_WIDGET(gtk_builder_get_object(builder, "keyboard_stimulator-eventbox"));
|
||||
|
||||
gtk_label_set_markup(GTK_LABEL(gtk_builder_get_object(builder, "keyboard_stimulator-label")), ss.str().c_str());
|
||||
|
||||
g_signal_connect(m_widget, "key-press-event", G_CALLBACK(key_press_cb), this);
|
||||
g_signal_connect(m_widget, "key-release-event", G_CALLBACK(key_release_cb), this);
|
||||
g_object_unref(builder);
|
||||
|
||||
m_visualizationCtx = dynamic_cast<VisualizationToolkit::IVisualizationContext*>(this->createPluginObject(OVP_ClassId_Plugin_VisualizationCtx));
|
||||
m_visualizationCtx->setWidget(*this, m_widget);
|
||||
|
||||
//TCP TAGGING
|
||||
m_stimulusSender = TCPTagging::CreateStimulusSender();
|
||||
if (!m_stimulusSender->connect(tcpTaggingHostAddress, tcpTaggingHostPort) && tcpTaggingHostAddress.toASCIIString()[0] != 0)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "Unable to connect to AS's TCP Tagging plugin, stimuli wont be forwarded.\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKeyboardStimulator::uninitialize()
|
||||
{
|
||||
if (m_stimulusSender)
|
||||
{
|
||||
delete m_stimulusSender;
|
||||
m_stimulusSender = nullptr;
|
||||
}
|
||||
|
||||
m_encoder.uninitialize();
|
||||
|
||||
if (m_widget)
|
||||
{
|
||||
g_object_unref(m_widget);
|
||||
m_widget = nullptr;
|
||||
}
|
||||
|
||||
if (m_visualizationCtx)
|
||||
{
|
||||
this->releasePluginObject(m_visualizationCtx);
|
||||
m_visualizationCtx = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKeyboardStimulator::processClock(Kernel::CMessageClock& msg)
|
||||
{
|
||||
if (m_error) { return false; }
|
||||
|
||||
if (m_unknownKeyPressed)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "Unhandled key code " << m_unknownKeyCode << "\n";
|
||||
m_unknownKeyPressed = false;
|
||||
}
|
||||
|
||||
const uint64_t currentTime = msg.getTime();
|
||||
|
||||
if (currentTime == 0)
|
||||
{
|
||||
m_encoder.encodeHeader();
|
||||
getBoxAlgorithmContext()->getDynamicBoxContext()->markOutputAsReadyToSend(0, 0, 0);
|
||||
}
|
||||
|
||||
if (currentTime != m_previousActivationTime)
|
||||
{
|
||||
Kernel::IBoxIO* boxIO = getBoxAlgorithmContext()->getDynamicBoxContext();
|
||||
|
||||
IStimulationSet* stimulationSet = m_encoder.getInputStimulationSet();
|
||||
stimulationSet->clear(); // The encoder may retain the buffer from the previous round, clear it
|
||||
|
||||
for (size_t i = 0; i < m_stimulationToSend.size(); ++i) { stimulationSet->appendStimulation(m_stimulationToSend[i], currentTime, 0); }
|
||||
m_stimulationToSend.clear();
|
||||
|
||||
m_encoder.encodeBuffer();
|
||||
|
||||
boxIO->markOutputAsReadyToSend(0, m_previousActivationTime, currentTime);
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
}
|
||||
|
||||
m_previousActivationTime = currentTime;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
#endif
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <visualization-toolkit/ovviz_all.h>
|
||||
|
||||
namespace TCPTagging {
|
||||
class IStimulusSender; // fwd declare
|
||||
}
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
class CKeyboardStimulator final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
CKeyboardStimulator() { }
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
|
||||
uint64_t getClockFrequency() override { return (32LL << 32); }
|
||||
|
||||
bool processClock(Kernel::CMessageClock& msg) override;
|
||||
bool process() override { return true; }
|
||||
|
||||
bool parseConfigurationFile(const char* filename);
|
||||
void processKey(const guint key, const bool state);
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_KeyboardStimulator)
|
||||
|
||||
protected:
|
||||
Toolkit::TStimulationEncoder<CKeyboardStimulator> m_encoder;
|
||||
|
||||
GtkWidget* m_widget = nullptr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t press;
|
||||
uint64_t release;
|
||||
bool status;
|
||||
} key_t;
|
||||
|
||||
//! Stores keyvalue/stimulation couples
|
||||
std::map<guint, key_t> m_keyToStimulation;
|
||||
|
||||
//! Vector of the stimulations to send when possible
|
||||
std::vector<uint64_t> m_stimulationToSend;
|
||||
|
||||
//! Plugin's previous activation date
|
||||
uint64_t m_previousActivationTime = 0;
|
||||
|
||||
bool m_error = false;
|
||||
|
||||
// TCP Tagging
|
||||
TCPTagging::IStimulusSender* m_stimulusSender = nullptr;
|
||||
|
||||
bool m_unknownKeyPressed = false;
|
||||
size_t m_unknownKeyCode = 0;
|
||||
|
||||
VisualizationToolkit::IVisualizationContext* m_visualizationCtx = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Plugin's description
|
||||
*/
|
||||
class CKeyboardStimulatorDesc final : public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
CString getName() const override { return CString("Keyboard stimulator"); }
|
||||
CString getAuthorName() const override { return CString("Bruno Renier"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA/IRISA"); }
|
||||
CString getShortDescription() const override { return CString("Stimulation generator"); }
|
||||
CString getDetailedDescription() const override { return CString("Sends stimulations according to key presses"); }
|
||||
CString getCategory() const override { return CString("Stimulation"); }
|
||||
CString getVersion() const override { return CString("0.2"); }
|
||||
void release() override { }
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_KeyboardStimulator; }
|
||||
IPluginObject* create() override { return new CKeyboardStimulator(); }
|
||||
|
||||
bool hasFunctionality(const EPluginFunctionality functionality) const override { return functionality == EPluginFunctionality::Visualization; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addOutput("Outgoing Stimulations", OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addSetting("Filename", OV_TypeId_Filename, "${Path_Data}/plugins/stimulation/simple-keyboard-to-stimulations.txt");
|
||||
// @note we don't want to expose these to the user as there is no latency correction in tcp tagging; its best to use localhost
|
||||
// prototype.addSetting("TCP Tagging Host address", OV_TypeId_String, "");
|
||||
// prototype.addSetting("TCP Tagging Host port", OV_TypeId_Integer, "15361");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_KeyboardStimulatorDesc)
|
||||
};
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
#endif
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
#include "ovpCSignChangeDetector.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
bool CSignChangeDetector::initialize()
|
||||
{
|
||||
// we read the settings:
|
||||
// The stimulations names:
|
||||
const CString on = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
const CString off = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1);
|
||||
|
||||
m_onStimId = getTypeManager().getEnumerationEntryValueFromName(OV_TypeId_Stimulation, on);
|
||||
m_offStimId = getTypeManager().getEnumerationEntryValueFromName(OV_TypeId_Stimulation, off);
|
||||
|
||||
m_lastSample = 0;
|
||||
m_firstSample = true;
|
||||
|
||||
m_decoder.initialize(*this, 0);
|
||||
m_encoder.initialize(*this, 0);
|
||||
|
||||
m_channelIdx = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 2);
|
||||
if (m_channelIdx == 0)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Info << "Channel Index is 0. The channel indexing convention starts from 1.\n";
|
||||
return false;
|
||||
}
|
||||
m_channelIdx--; // Convert from [1,n] indexing to [0,n-1] indexing used later
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSignChangeDetector::uninitialize()
|
||||
{
|
||||
m_encoder.uninitialize();
|
||||
m_decoder.uninitialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSignChangeDetector::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSignChangeDetector::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
// Get a few convenience handles
|
||||
const CMatrix* matrix = m_decoder.getOutputMatrix();
|
||||
IStimulationSet* stimSet = m_encoder.getInputStimulationSet();
|
||||
|
||||
// We decode the stream matrix
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
const uint64_t start = boxContext.getInputChunkStartTime(0, i);
|
||||
const uint64_t end = boxContext.getInputChunkEndTime(0, i);
|
||||
|
||||
m_decoder.decode(i);
|
||||
|
||||
// if we received the header
|
||||
if (m_decoder.isHeaderReceived())
|
||||
{
|
||||
//we analyse the header (meaning the input matrix size)
|
||||
if (matrix->getDimensionCount() != 2)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_ImportantWarning << "Streamed matrix must have exactly 2 dimensions\n";
|
||||
return false;
|
||||
}
|
||||
if (m_channelIdx >= matrix->getDimensionSize(0))
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Info << "Channel Index out of bounds. Incoming matrix has fewer channels than specified index.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_samplesPerChannel = matrix->getDimensionSize(1);
|
||||
|
||||
// we send a header on the stimulation output:
|
||||
m_encoder.encodeHeader();
|
||||
boxContext.markOutputAsReadyToSend(0, start, end);
|
||||
}
|
||||
|
||||
|
||||
// if we received a buffer
|
||||
if (m_decoder.isBufferReceived())
|
||||
{
|
||||
stimSet->clear();
|
||||
const double* data = matrix->getBuffer();
|
||||
// for each data sample of the buffer we look for sign change
|
||||
|
||||
for (size_t j = 0; j < matrix->getDimensionSize(1); ++j)
|
||||
{
|
||||
const double currentSample = data[(m_channelIdx * m_samplesPerChannel) + j];
|
||||
if (m_firstSample)
|
||||
{
|
||||
m_lastSample = currentSample;
|
||||
m_firstSample = false;
|
||||
}
|
||||
|
||||
// Change from positive to negative
|
||||
if (m_lastSample >= 0 && currentSample < 0)
|
||||
{
|
||||
const uint64_t time = start + (end - start) * j / m_samplesPerChannel;
|
||||
stimSet->appendStimulation(m_offStimId, time, 0);
|
||||
}
|
||||
|
||||
// Change from negative to positive
|
||||
if (m_lastSample < 0 && currentSample >= 0)
|
||||
{
|
||||
const uint64_t time = start + (end - start) * j / m_samplesPerChannel;
|
||||
stimSet->appendStimulation(m_onStimId, time, 0);
|
||||
}
|
||||
|
||||
m_lastSample = currentSample;
|
||||
}
|
||||
|
||||
m_encoder.encodeBuffer();
|
||||
boxContext.markOutputAsReadyToSend(0, start, end);
|
||||
}
|
||||
|
||||
// if we received the End
|
||||
if (m_decoder.isEndReceived())
|
||||
{
|
||||
// we send the End signal to the stimulation output:
|
||||
m_encoder.encodeEnd();
|
||||
boxContext.markOutputAsReadyToSend(0, start, end);
|
||||
}
|
||||
|
||||
// The stream matrix chunk i has been processed
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
class CSignChangeDetector final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_SignChangeDetector)
|
||||
|
||||
protected:
|
||||
|
||||
Toolkit::TStreamedMatrixDecoder<CSignChangeDetector> m_decoder;
|
||||
Toolkit::TStimulationEncoder<CSignChangeDetector> m_encoder;
|
||||
|
||||
uint64_t m_onStimId = 0;
|
||||
uint64_t m_offStimId = 0;
|
||||
uint64_t m_channelIdx = 0;
|
||||
uint64_t m_samplesPerChannel = 0;
|
||||
double m_lastSample = 0;
|
||||
bool m_firstSample = false;
|
||||
};
|
||||
|
||||
class CSignChangeDetectorDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Sign Change Detector"); }
|
||||
CString getAuthorName() const override { return CString("Joan Fruitet and Jozef Legeny"); }
|
||||
CString getAuthorCompanyName() const override { return CString("Inria Sophia"); }
|
||||
CString getShortDescription() const override { return CString("Detects the change of input's sign"); }
|
||||
|
||||
CString getDetailedDescription() const override
|
||||
{
|
||||
return CString("Triggers a stimulation when one of the input's sign changes (input gets positive or negative");
|
||||
}
|
||||
|
||||
CString getCategory() const override { return CString("Stimulation"); }
|
||||
CString getVersion() const override { return CString("1.2"); }
|
||||
CString getStockItemName() const override { return CString("gtk-missing-image"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_SignChangeDetector; }
|
||||
IPluginObject* create() override { return new CSignChangeDetector; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Signal", OV_TypeId_StreamedMatrix);
|
||||
prototype.addOutput("Generated stimulations", OV_TypeId_Stimulations);
|
||||
prototype.addSetting("Sign switch to positive stimulation", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_01");
|
||||
prototype.addSetting("Sign switch to negative stimulation", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_00");
|
||||
prototype.addSetting("Channel Index", OV_TypeId_Integer, "1");
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_SignChangeDetectorDesc)
|
||||
};
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
// Boxes
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#define OVP_ClassId_BoxAlgorithm_StimulationMultiplexer OpenViBE::CIdentifier(0x07DB4EFA, 0x472B0938)
|
||||
#define OVP_ClassId_BoxAlgorithm_StimulationMultiplexerDesc OpenViBE::CIdentifier(0x79EF4E4D, 0x178F09E6)
|
||||
#define OVP_ClassId_BoxAlgorithm_SoundPlayer OpenViBE::CIdentifier(0x18D06E9F, 0x68D43C23)
|
||||
#define OVP_ClassId_BoxAlgorithm_SoundPlayerDesc OpenViBE::CIdentifier(0x246E5EC4, 0x127D21AA)
|
||||
#define OVP_ClassId_BoxAlgorithm_StimulationVoter OpenViBE::CIdentifier(0x2BBD61FC, 0x041A4EDB)
|
||||
#define OVP_ClassId_BoxAlgorithm_StimulationVoterDesc OpenViBE::CIdentifier(0x1C36287C, 0x6F143FBF)
|
||||
#define OVP_ClassId_KeyboardStimulator OpenViBE::CIdentifier(0x00D317B9, 0x6324C3FF)
|
||||
#define OVP_ClassId_KeyboardStimulatorDesc OpenViBE::CIdentifier(0x00E51ACD, 0x284CA2CF)
|
||||
#define OVP_ClassId_BoxAlgorithm_P300IdentifierStimulator OpenViBE::CIdentifier(0x00F27FDB, 0x8203D1A5)
|
||||
#define OVP_ClassId_BoxAlgorithm_P300IdentifierStimulatorDesc OpenViBE::CIdentifier(0x000F20CA, 0x2A4EA9C3)
|
||||
#define OVP_ClassId_SignChangeDetector OpenViBE::CIdentifier(0x04FA78CD, 0xAFE45DE7)
|
||||
#define OVP_ClassId_SignChangeDetectorDesc OpenViBE::CIdentifier(0x798ACD86, 0xEF1287A4)
|
||||
#define OVP_ClassId_BoxAlgorithm_StimulationFilter OpenViBE::CIdentifier(0x02F96101, 0x5E647CB8)
|
||||
#define OVP_ClassId_BoxAlgorithm_StimulationFilterDesc OpenViBE::CIdentifier(0x4D2A23FC, 0x28191E18)
|
||||
#define OVP_ClassId_BoxAlgorithm_LuaStimulator OpenViBE::CIdentifier(0x0B5A2787, 0x02750621)
|
||||
#define OVP_ClassId_BoxAlgorithm_LuaStimulatorDesc OpenViBE::CIdentifier(0x67AF36F3, 0x2B424F46)
|
||||
#define OVP_ClassId_BoxAlgorithm_OpenALSoundPlayer OpenViBE::CIdentifier(0x7AC2396F, 0x7EE52EFE)
|
||||
#define OVP_ClassId_BoxAlgorithm_OpenALSoundPlayerDesc OpenViBE::CIdentifier(0x6FD040EF, 0x7E2F1284)
|
||||
#define OVP_ClassId_BoxAlgorithm_P300SpellerStimulator OpenViBE::CIdentifier(0x88857F9A, 0xF560D3EB)
|
||||
#define OVP_ClassId_BoxAlgorithm_P300SpellerStimulatorDesc OpenViBE::CIdentifier(0xCEAFBB05, 0x5DA19DCB)
|
||||
#define OVP_ClassId_BoxAlgorithm_RunCommand OpenViBE::CIdentifier(0x48843891, 0x7BFC57F4)
|
||||
#define OVP_ClassId_BoxAlgorithm_RunCommandDesc OpenViBE::CIdentifier(0x29D449AE, 0x2CA94942)
|
||||
#define OVP_ClassId_BoxAlgorithm_StimulationValidator OpenViBE::CIdentifier(0x393d15e9, 0x5b6f63b9)
|
||||
#define OVP_ClassId_BoxAlgorithm_StimulationValidatorDesc OpenViBE::CIdentifier(0x553bdcca, 0xe66d09bf)
|
||||
|
||||
// Global defines
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#ifdef TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
#include "ovp_global_defines.h"
|
||||
#endif // TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
|
||||
#define OV_AttributeId_Box_FlagIsUnstable OpenViBE::CIdentifier(0x666FFFFF, 0x666FFFFF)
|
||||
|
||||
#define OVP_TypeId_Voting_ClearVotes OpenViBE::CIdentifier(0x17AE30F8, 0x40B57661)
|
||||
#define OVP_TypeId_Voting_ClearVotes_AfterOutput OpenViBE::CIdentifier(0x7FA81A20, 0x484023F9)
|
||||
#define OVP_TypeId_Voting_ClearVotes_WhenExpires OpenViBE::CIdentifier(0x02766639, 0x00B155B4)
|
||||
#define OVP_TypeId_Voting_OutputTime OpenViBE::CIdentifier(0x48583E8F, 0x47F22462)
|
||||
#define OVP_TypeId_Voting_OutputTime_Vote OpenViBE::CIdentifier(0x2F37507F, 0x00C06761)
|
||||
#define OVP_TypeId_Voting_OutputTime_Winner OpenViBE::CIdentifier(0x72416689, 0x17673658)
|
||||
#define OVP_TypeId_Voting_OutputTime_Last OpenViBE::CIdentifier(0x4F2830DB, 0x716C2930)
|
||||
#define OVP_TypeId_Voting_RejectClass_CanWin OpenViBE::CIdentifier(0x442F2F14, 0x7A17336C)
|
||||
#define OVP_TypeId_Voting_RejectClass_CanWin_Yes OpenViBE::CIdentifier(0x40011974, 0x54BB3C71)
|
||||
#define OVP_TypeId_Voting_RejectClass_CanWin_No OpenViBE::CIdentifier(0x275B746A, 0x480B302C)
|
||||
|
||||
|
||||
#define OVP_TypeId_StimulationFilterAction OpenViBE::CIdentifier(0x09E59E57, 0x8D4A553A)
|
||||
#define OVP_TypeId_StimulationFilterAction_Select OpenViBE::CIdentifier(0xBDBBA98D, 0xC0477399)
|
||||
#define OVP_TypeId_StimulationFilterAction_Reject OpenViBE::CIdentifier(0xB7C594D2, 0x32474226)
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
#include "ovp_defines.h"
|
||||
|
||||
#include "box-algorithms/ovpCKeyboardStimulator.h"
|
||||
#include "box-algorithms/ovpCSignChangeDetector.h"
|
||||
|
||||
#include "box-algorithms/ovpCBoxAlgorithmRunCommand.h"
|
||||
#if defined TARGET_HAS_ThirdPartyLua
|
||||
#include "box-algorithms/ovpCBoxAlgorithmLuaStimulator.h"
|
||||
#endif // TARGET_HAS_ThirdPartyLua
|
||||
#if defined TARGET_HAS_ThirdPartyOpenAL
|
||||
#include "box-algorithms/ovpCBoxAlgorithmOpenALSoundPlayer.h"
|
||||
#endif // TARGET_HAS_ThirdPartyOpenAL
|
||||
|
||||
#include "box-algorithms/adaptation/ovpCBoxAlgorithmStimulationFilter.h"
|
||||
|
||||
#include "box-algorithms/ovpCBoxAlgorithmP300SpellerStimulator.h"
|
||||
#include "box-algorithms/ovpCBoxAlgorithmP300IdentifierStimulator.h"
|
||||
#include "box-algorithms/CBoxAlgorithmStimulationValidator.hpp"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Stimulation {
|
||||
|
||||
OVP_Declare_Begin()
|
||||
context.getTypeManager().registerEnumerationEntry(OV_TypeId_BoxAlgorithmFlag, OV_AttributeId_Box_FlagIsUnstable.toString(),
|
||||
OV_AttributeId_Box_FlagIsUnstable.id());
|
||||
context.getTypeManager().registerEnumerationType(OVP_TypeId_StimulationFilterAction, "Stimulation Filter Action");
|
||||
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_StimulationFilterAction, "Select", OVP_TypeId_StimulationFilterAction_Select.id());
|
||||
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_StimulationFilterAction, "Reject", OVP_TypeId_StimulationFilterAction_Reject.id());
|
||||
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
OVP_Declare_New(CKeyboardStimulatorDesc);
|
||||
#endif
|
||||
|
||||
OVP_Declare_New(CSignChangeDetectorDesc);
|
||||
|
||||
OVP_Declare_New(CBoxAlgorithmRunCommandDesc);
|
||||
#if defined TARGET_HAS_ThirdPartyLua
|
||||
OVP_Declare_New(CBoxAlgorithmLuaStimulatorDesc);
|
||||
#endif // TARGET_HAS_ThirdPartyLua
|
||||
|
||||
#if defined TARGET_HAS_ThirdPartyOpenAL
|
||||
OVP_Declare_New(CBoxAlgorithmOpenALSoundPlayerDesc);
|
||||
#endif // TARGET_HAS_ThirdPartyOpenAL
|
||||
|
||||
OVP_Declare_New(CBoxAlgorithmStimulationFilterDesc);
|
||||
|
||||
OVP_Declare_New(CBoxAlgorithmP300SpellerStimulatorDesc);
|
||||
OVP_Declare_New(CBoxAlgorithmP300IdentifierStimulatorDesc);
|
||||
|
||||
OVP_Declare_New(CBoxAlgorithmStimulationValidatorDesc);
|
||||
|
||||
context.getTypeManager().registerEnumerationType(OVP_TypeId_Voting_ClearVotes, "Clear votes");
|
||||
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_Voting_ClearVotes, "When expires", OVP_TypeId_Voting_ClearVotes_WhenExpires.id());
|
||||
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_Voting_ClearVotes, "After output", OVP_TypeId_Voting_ClearVotes_AfterOutput.id());
|
||||
context.getTypeManager().registerEnumerationType(OVP_TypeId_Voting_OutputTime, "Output time");
|
||||
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_Voting_OutputTime, "Time of voting", OVP_TypeId_Voting_OutputTime_Vote.id());
|
||||
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_Voting_OutputTime, "Time of last winning stimulus", OVP_TypeId_Voting_OutputTime_Winner.id());
|
||||
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_Voting_OutputTime, "Time of last voting stimulus", OVP_TypeId_Voting_OutputTime_Last.id());
|
||||
context.getTypeManager().registerEnumerationType(OVP_TypeId_Voting_RejectClass_CanWin, "Reject can win");
|
||||
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_Voting_RejectClass_CanWin, "Yes", OVP_TypeId_Voting_RejectClass_CanWin_Yes.id());
|
||||
context.getTypeManager().registerEnumerationEntry(OVP_TypeId_Voting_RejectClass_CanWin, "No", OVP_TypeId_Voting_RejectClass_CanWin_No.id());
|
||||
|
||||
OVP_Declare_End()
|
||||
} // namespace Stimulation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
Time:32Hz,Epoch,sinusOsc 1,Event Id,Event Date,Event Duration
|
||||
0.0000000000,0,0.0000000000,,,
|
||||
0.0312500000,1,1.3687341120,,,
|
||||
0.0625000000,2,0.0834505686,,,
|
||||
0.0937500000,3,1.3965074831,,,
|
||||
0.1250000000,4,2.3460347303,,,
|
||||
0.1562500000,5,0.6652579106,,,
|
||||
0.1875000000,6,1.6342771847,,,
|
||||
0.2187500000,7,2.0374036140,,,
|
||||
0.2500000000,8,0.0223674799,,,
|
||||
0.2812500000,9,0.8587778323,,,
|
||||
0.3125000000,10,1.0605198516,,,
|
||||
0.3437500000,11,-0.8527917255,,,
|
||||
0.3750000000,12,0.2862985568,,,
|
||||
0.4062500000,13,0.6745718556,,,
|
||||
0.4375000000,14,-0.8460419110,,,
|
||||
0.4687500000,15,0.7209285523,,,
|
||||
0.5000000000,16,1.2564364343,,,
|
||||
0.5312500000,17,-0.0631007468,,,
|
||||
0.5625000000,18,1.5912609145,,,
|
||||
0.5937500000,19,1.8564555014,,,
|
||||
0.6250000000,20,0.3100244990,,,
|
||||
0.6562500000,21,1.6531536145,,,
|
||||
0.6875000000,22,1.3612667999,,,
|
||||
0.7187500000,23,-0.5404879020,,,
|
||||
0.7500000000,24,0.5189549878,,,
|
||||
0.7812500000,25,-0.1244988728,,,
|
||||
0.8125000000,26,-2.0249997390,,,
|
||||
0.8437500000,27,-0.8135359478,,,
|
||||
0.8750000000,28,-1.3302670931,,,
|
||||
0.9062500000,29,-2.7774418870,,,
|
||||
0.9375000000,30,-1.0731867792,,,
|
||||
0.9687500000,31,-1.2560591950,,,
|
||||
1.0000000000,32,-2.2082337379,,,
|
||||
|
+54
@@ -0,0 +1,54 @@
|
||||
|
||||
#basics definitions needed here
|
||||
IF(WIN32)
|
||||
SET(EXT cmd)
|
||||
SET(OS_FLAGS "--no-pause")
|
||||
SET(OS_SUFFIX "")
|
||||
ELSE()
|
||||
SET(EXT sh)
|
||||
SET(OS_FLAGS "")
|
||||
SET(OS_SUFFIX "-linux")
|
||||
ENDIF()
|
||||
|
||||
|
||||
# Simple Test of run-command box
|
||||
SET(TEST_NAME test-run-command)
|
||||
SET(SCENARIO_TO_TEST "${TEST_NAME}.xml")
|
||||
ADD_TEST(clean_${TEST_NAME} "${CMAKE_COMMAND}" "-E" "remove" "-f" "${TEST_NAME}.txt")
|
||||
ADD_TEST(run_${TEST_NAME} "$ENV{OV_BINARY_PATH}/openvibe-designer.${EXT}" ${OS_FLAGS} "--invisible" "--play" ${SCENARIO_TO_TEST})
|
||||
ADD_TEST(exist_${TEST_NAME} "${CMAKE_COMMAND}" "-E" "md5sum" "${TEST_NAME}.txt")
|
||||
|
||||
## add some properties that help to debug
|
||||
SET_TESTS_PROPERTIES(run_${TEST_NAME} PROPERTIES ATTACHED_FILES_ON_FAIL ${OV_LOGFILE})
|
||||
|
||||
SET_TESTS_PROPERTIES(exist_${TEST_NAME} PROPERTIES DEPENDS run_${TEST_NAME}})
|
||||
SET_TESTS_PROPERTIES(run_${TEST_NAME} PROPERTIES DEPENDS clean_${TEST_NAME}})
|
||||
|
||||
|
||||
# Test run command with spaces
|
||||
#
|
||||
# This construction is intended to test cases where run command box command has spaces
|
||||
# in both executable path and some of the arguments. We use cmake script 'wrap' to get access to the stdout
|
||||
# where the results are printed in this case.
|
||||
SET(TEST_NAME run-command-with-spaces)
|
||||
SET(SCENARIO_TO_TEST "${TEST_NAME}.xml")
|
||||
ADD_TEST(clean_${TEST_NAME} "${CMAKE_COMMAND}" "-E" "remove" "-f" "${TEST_NAME}.txt")
|
||||
ADD_TEST(run_${TEST_NAME} "$ENV{OV_BINARY_PATH}/openvibe-designer.${EXT}" ${OS_FLAGS} "--invisible" "--no-session-management" "-d" "EXT" "${EXT}" "-d" "OUTFILE" "${TEST_NAME}.txt" "--play" ${SCENARIO_TO_TEST})
|
||||
ADD_TEST(compare_${TEST_NAME} "git" "diff" "--no-index" "--ignore-space-at-eol" "${TEST_NAME}${OS_SUFFIX}.ref.txt" "${TEST_NAME}.txt")
|
||||
|
||||
## add some properties that help to debug
|
||||
SET_TESTS_PROPERTIES(run_$ENV{OV_TEST_NAME} PROPERTIES ATTACHED_FILES_ON_FAIL ${OV_LOGFILE})
|
||||
SET_TESTS_PROPERTIES(exist_${TEST_NAME} PROPERTIES DEPENDS run_${TEST_NAME}})
|
||||
SET_TESTS_PROPERTIES(run_${TEST_NAME} PROPERTIES DEPENDS clean_${TEST_NAME}})
|
||||
|
||||
# Simple Test of timeout box
|
||||
SET(TEST_NAME test-timeout)
|
||||
SET(SCENARIO_TO_TEST "${TEST_NAME}.xml")
|
||||
ADD_TEST(clean_${TEST_NAME} "${CMAKE_COMMAND}" "-E" "remove" "-f" "${TEST_NAME}.txt")
|
||||
ADD_TEST(run_${TEST_NAME} "$ENV{OV_BINARY_PATH}/openvibe-designer.${EXT}" ${OS_FLAGS} "--invisible" "--play" ${SCENARIO_TO_TEST})
|
||||
ADD_TEST(exist_${TEST_NAME} "${CMAKE_COMMAND}" "-E" "md5sum" "${TEST_NAME}.txt")
|
||||
|
||||
## add some properties that help to debug
|
||||
SET_TESTS_PROPERTIES(run_${TEST_NAME} PROPERTIES ATTACHED_FILES_ON_FAIL ${OV_LOGFILE})
|
||||
SET_TESTS_PROPERTIES(exist_${TEST_NAME} PROPERTIES DEPENDS run_${TEST_NAME}})
|
||||
SET_TESTS_PROPERTIES(run_${TEST_NAME} PROPERTIES DEPENDS clean_${TEST_NAME}})
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
start
|
||||
TestRunCommand Params: 1=has space 2= 3= 4=
|
||||
TestRunCommand Params: 1=nospace 2= 3= 4=
|
||||
TestRunCommand Params: 1=has space 2=two 3= 4=
|
||||
TestRunCommand Params: 1= 2= 3= 4=
|
||||
TestRunCommand Params: 1=arg1 2=arg2 3=arg3 4=
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
start
|
||||
TestRunCommand Params: 1="has space" 2= 3= 4=
|
||||
TestRunCommand Params: 1=nospace 2= 3= 4=
|
||||
TestRunCommand Params: 1="has space" 2=two 3= 4=
|
||||
TestRunCommand Params: 1= 2= 3= 4=
|
||||
TestRunCommand Params: 1=arg1 2=arg2 3=arg3 4=
|
||||
Executable
+413
@@ -0,0 +1,413 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>1</FormatVersion>
|
||||
<Creator>openvibe</Creator>
|
||||
<CreatorVersion>2.0</CreatorVersion>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x000026b8, 0x00003463)</Identifier>
|
||||
<Name>Run Command</Name>
|
||||
<AlgorithmClassIdentifier>(0x48843891, 0x7bfc57f4)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 1</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_01</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 1</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>echo start > ${OUTFILE}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 2</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_02</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 2</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>"${Player_ScenarioDirectory}/space test/echoparams.${EXT}" "has space" >> ${OUTFILE}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 3</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_03</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 3</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>"${Player_ScenarioDirectory}/space test/echoparams.${EXT}" nospace >> ${OUTFILE}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 4</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_04</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 4</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>"${Player_ScenarioDirectory}/space test/echoparams.${EXT}" "has space" two >> ${OUTFILE}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 5</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_05</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 5</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>"${Player_ScenarioDirectory}/space test/echoparams.${EXT}" >> ${OUTFILE}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 6</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_06</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 6</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>"${Player_ScenarioDirectory}/space test/echoparams.${EXT}" arg1 arg2 arg3 >> ${OUTFILE}</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>272.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>33</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>320.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xe44a71e7, 0x7964dd76)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x61d11811, 0x71e65362)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>101</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x01871d22)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc67a01dc, 0x28ce06c1)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00004b2a, 0x00001be8)</Identifier>
|
||||
<Name>Player Controller</Name>
|
||||
<AlgorithmClassIdentifier>(0x5f426dce, 0x08456e13)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation name</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xcc14d8d6, 0xf27ecb73)</TypeIdentifier>
|
||||
<Name>Action to perform</Name>
|
||||
<DefaultValue>Pause</DefaultValue>
|
||||
<Value>Stop</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>336.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>496.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x568d148e, 0x650792b3)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>118</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x0133a23e)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00006d67, 0x00007b93)</Identifier>
|
||||
<Name>Clock stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x4f756d3f, 0x29ff0b96)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Interstimulation interval (in sec)</Name>
|
||||
<DefaultValue>1.0</DefaultValue>
|
||||
<Value>1</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>193.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>496.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27b3ee3c, 0xc50527e6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>114</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x0155437c)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x000078f5, 0x000049f4)</Identifier>
|
||||
<Name>Clock stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x4f756d3f, 0x29ff0b96)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Interstimulation interval (in sec)</Name>
|
||||
<DefaultValue>1.0</DefaultValue>
|
||||
<Value>1.0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>160.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>320.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27b3ee3c, 0xc50527e6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>114</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x0186214f)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x00004df8, 0x00001737)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00006d67, 0x00007b93)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x00004b2a, 0x00001be8)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>211</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>496</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>496</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00005fbf, 0x0000288c)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x000078f5, 0x000049f4)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x000026b8, 0x00003463)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>178</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>251</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments></Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x000037ad, 0x00007f7d)","index":0,"name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":480},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x00005418, 0x00006015)","index":0,"name":"Default tab","parentIdentifier":"(0x000037ad, 0x00007f7d)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x000034e0, 0x000049ae)","index":0,"name":"Empty","parentIdentifier":"(0x00005418, 0x00006015)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
@ECHO OFF
|
||||
|
||||
echo TestRunCommand Params: 1=%1 2=%2 3=%3 4=%4
|
||||
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
|
||||
echo TestRunCommand Params: 1=$1 2=$2 3=$3 4=$4
|
||||
|
||||
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>1</FormatVersion>
|
||||
<Creator>openvibe</Creator>
|
||||
<CreatorVersion>2.0</CreatorVersion>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x19fa74c1, 0x160aee69)</Identifier>
|
||||
<Name>Clock stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x4f756d3f, 0x29ff0b96)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Interstimulation interval (in sec)</Name>
|
||||
<DefaultValue>1.0</DefaultValue>
|
||||
<Value>2.0</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_01</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>192</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>27</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>624</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27b3ee3c, 0xc50527e6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>129</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x231b81fc, 0x445bffb6)</Identifier>
|
||||
<Name>Run Command</Name>
|
||||
<AlgorithmClassIdentifier>(0x48843891, 0x7bfc57f4)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 1</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_01</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 1</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>echo "" > test-run-command.txt</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>256</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>42</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xe44a71e7, 0x7964dd76)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x61d11811, 0x71e65362)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>113</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc67a01dc, 0x28ce06c1)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x28da66fe, 0x38162acc)</Identifier>
|
||||
<Name>Player Controller</Name>
|
||||
<AlgorithmClassIdentifier>(0x5f426dce, 0x08456e13)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation name</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_01</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xcc14d8d6, 0xf27ecb73)</TypeIdentifier>
|
||||
<Name>Action to perform</Name>
|
||||
<DefaultValue>Pause</DefaultValue>
|
||||
<Value>Stop</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>256</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>27</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>624</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x568d148e, 0x650792b3)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>134</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x3901841f, 0x09225d88)</Identifier>
|
||||
<Name>Clock stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x4f756d3f, 0x29ff0b96)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Interstimulation interval (in sec)</Name>
|
||||
<DefaultValue>1.0</DefaultValue>
|
||||
<Value>1.7</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>192</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>27</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27b3ee3c, 0xc50527e6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>129</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x2034b137, 0x1bcbbbed)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x3901841f, 0x09225d88)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x231b81fc, 0x445bffb6)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>212</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>416</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>230</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>416</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x49f08097, 0x6d1380fd)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x19fa74c1, 0x160aee69)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x28da66fe, 0x38162acc)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>212</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>624</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>238</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>624</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments></Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":480,"identifier":"(0x340bed7a, 0x471c8a14)","index":0,"name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":640},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x5898b888, 0x060a830d)","index":0,"name":"Default tab","parentIdentifier":"(0x340bed7a, 0x471c8a14)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x32c26df5, 0x73834e6c)","index":0,"name":"Empty","parentIdentifier":"(0x5898b888, 0x060a830d)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+313
@@ -0,0 +1,313 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>2</FormatVersion>
|
||||
<Creator>OpenViBE Designer</Creator>
|
||||
<CreatorVersion>2.2.0</CreatorVersion>
|
||||
<Settings></Settings>
|
||||
<Inputs></Inputs>
|
||||
<Outputs></Outputs>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x0000043c, 0x00007a2d)</Identifier>
|
||||
<Name>CSV File Reader</Name>
|
||||
<AlgorithmClassIdentifier>(0x336a3d9a, 0x753f1ba4)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Output stream</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output stimulation</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>${Player_ScenarioDirectory}/1secSinusOscillator.csv</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>112</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xa9cdc629, 0xb153eb33)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x0b41bcb4, 0x0c439291)</Identifier>
|
||||
<Name>Timeout</Name>
|
||||
<AlgorithmClassIdentifier>(0x24fcd292, 0x5c8f6aa8)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Input Stream</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output Stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Timeout delay</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>1</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Output Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x1eaee00e, 0xdb05d34e)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x20cd295d, 0x2db9393b)</Identifier>
|
||||
<Name>Run Command</Name>
|
||||
<AlgorithmClassIdentifier>(0x48843891, 0x7bfc57f4)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation 1</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_01</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x79a9edeb, 0x245d83fc)</TypeIdentifier>
|
||||
<Name>Command 1</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>echo "" > test-timeout.txt</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>256</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>176</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xe44a71e7, 0x7964dd76)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x61d11811, 0x71e65362)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x2ebb6127, 0x59237986)</Identifier>
|
||||
<Name>Clock stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x4f756d3f, 0x29ff0b96)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Interstimulation interval (in sec)</Name>
|
||||
<DefaultValue>1.0</DefaultValue>
|
||||
<Value>3</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_01</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>144</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27b3ee3c, 0xc50527e6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x72172d53, 0x4b1d2595)</Identifier>
|
||||
<Name>Player Controller</Name>
|
||||
<AlgorithmClassIdentifier>(0x5f426dce, 0x08456e13)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation name</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_01</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xcc14d8d6, 0xf27ecb73)</TypeIdentifier>
|
||||
<Name>Action to perform</Name>
|
||||
<DefaultValue>Pause</DefaultValue>
|
||||
<Value>Stop</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>208</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>320</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x568d148e, 0x650792b3)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x0000079e, 0x000057cc)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x0000043c, 0x00007a2d)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x0b41bcb4, 0x0c439291)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x03ccb08e, 0x02bf8b78)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x0b41bcb4, 0x0c439291)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x20cd295d, 0x2db9393b)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x585d2eff, 0x5d05ee38)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x2ebb6127, 0x59237986)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x72172d53, 0x4b1d2595)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments></Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x6f314ae7, 0x32974c0d)","name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":480},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x53a9b4d7, 0x32eb1e3e)","index":0,"name":"Default tab","parentIdentifier":"(0x6f314ae7, 0x32974c0d)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x68454761, 0x4049650d)","index":0,"name":"Empty","parentIdentifier":"(0x53a9b4d7, 0x32eb1e3e)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
Reference in New Issue
Block a user