...
 
Commits (7)
......@@ -86,6 +86,10 @@ IF(UNIX)
SET(SKIP_PLUGINS_PROCESSING_MATLAB "1")
ENDIF(UNIX)
# If you don't skip the following, it compiles an example of a Fortran-based box (see under plugins/processing/fortran/).
# The feature needs CMake 3.2 and a Fortran compiler (e.g. Intels on Win or gfortran on Linux). Default is to skip this.
SET(SKIP_PLUGINS_PROCESSING_FORTRAN "1")
# Currently empty module
SET(SKIP_CONTRIB_PLUGINS_PROCESSING_CLASSIFICATION "1")
......
INCLUDE(CheckLanguage)
check_language(Fortran)
if(NOT CMAKE_Fortran_COMPILER)
MESSAGE(STATUS "Fortran not available, skipping Fortran example")
RETURN()
ENDIF(NOT CMAKE_Fortran_COMPILER)
enable_language(Fortran)
# INCLUDE(FortranCInterface)
PROJECT(openvibe-plugins-fortran-bridge CXX C Fortran)
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
SET(PROJECT_VERSION_MINOR ${OV_GLOBAL_VERSION_MINOR})
SET(PROJECT_VERSION_PATCH ${OV_GLOBAL_VERSION_PATCH})
SET(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
IF(WIN32)
INCLUDE("CMakeAddFortranSubdirectory")
cmake_add_fortran_subdirectory("src/box-algorithms/example1"
PROJECT openvibe-plugins-fortran-example1
LINK_LIBRARIES
NO_EXTERNAL_INSTALL)
FILE(GLOB_RECURSE source_files src/*.cpp src/*.h src/*.inl)
ELSE(WIN32)
FILE(GLOB_RECURSE source_files src/*.cpp src/*.h src/*.inl *.f90)
ENDIF(WIN32)
ADD_LIBRARY(${PROJECT_NAME} SHARED ${source_files})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
COMPILE_FLAGS "-DOV_Exports -DOV_Shared")
IF(WIN32)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} openvibe-plugins-fortran-example1)
#MESSAGE(STATUS "lib 1 ${CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES}")
#MESSAGE(STATUS "lib 2 ${CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES}")
ENDIF(WIN32)
INCLUDE("FindOpenViBE")
INCLUDE("FindOpenViBECommon")
INCLUDE("FindOpenViBEToolkit")
INCLUDE("FindOpenViBEModuleEBML")
INCLUDE("FindOpenViBEModuleSystem")
# ---------------------------------
# Target macros
# Defines target operating system
# Defines target architecture
# Defines target compiler
# ---------------------------------
IF(WIN32)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
ADD_DEFINITIONS(-DTARGET_OS_Windows)
ADD_DEFINITIONS(-DTARGET_ARCHITECTURE_i386)
ADD_DEFINITIONS(-DTARGET_COMPILER_VisualStudio)
ENDIF(WIN32)
IF(UNIX)
# ADD_DEFINITIONS(-fvisibility=hidden) # This flag should be present... man gcc
ADD_DEFINITIONS(-g)
ADD_DEFINITIONS(-fnon-call-exceptions)
ADD_DEFINITIONS(-DTARGET_OS_Linux)
ADD_DEFINITIONS(-DTARGET_ARCHITECTURE_i386)
ADD_DEFINITIONS(-DTARGET_COMPILER_GCC)
ENDIF(UNIX)
# -----------------------------
# Install files
# -----------------------------
INSTALL(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_FULL_LIBDIR})
#INSTALL(DIRECTORY src/ DESTINATION ${CMAKE_INSTALL_FULL_INCLUDEDIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "doc" EXCLUDE)
#ENDIF(NOT CMAKE_Fortran_COMPILER)
#ENDIF(UNIX)
PROJECT(openvibe-plugins-fortran-example1 C Fortran)
FILE(GLOB_RECURSE source_files *.f90)
# ADD_LIBRARY(${PROJECT_NAME} SHARED ${source_files})
ADD_LIBRARY(${PROJECT_NAME} STATIC ${source_files})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE C++)
!
! This code illustrates passing a matrix in from OpenViBE, making modifications in-place,
! and sending it back. Actually the changes could be directly made into the input
! matrix but care must be taken that the difference in C/Fortran row/column major order
! of the matrix storage is taken into account.
!
! This example adds the channel number to the channel data (so each channel will have noticable and different effect)
!
! this routine is run once at the beginning of playback. it can be used to precompute/load things needed later.
! set errorCode to 0 on success, a non-zero code otherwise.
subroutine fortran_init(errorCode) bind(C)
use iso_c_binding
INTEGER(C_INT32_T), intent(out) :: errorCode
! in this example, the routine does nothing much
write(*,*) "Init in Fortran"
errorCode = 0
end subroutine fortran_init
! this routine is runs once for each matrix chunk of data. It can modify the matrix in place.
! set errorCode to 0 on success, a non-zero code otherwise.
subroutine fortran_process(mat,rows,cols,errorCode) bind(C)
use iso_c_binding
INTEGER(C_INT32_T), intent(in) :: rows,cols
INTEGER(C_INT32_T), intent(out) :: errorCode
REAL(C_DOUBLE), intent(inout) :: mat(rows*cols)
REAL, DIMENSION(1:rows,1:cols) :: A;
! write(*,*) "Process in Fortran" , rows, " ", cols
! matrix from C/C++ is in row-major order, reshape
A = reshape(mat, (/ rows, cols /), ORDER = (/ 2, 1 /) )
! Add +nChannel to each channel
do i=1,rows
do j=1,cols
A(i,j) = A(i,j) + i;
end do
end do
! print the matrix
!WRITE(*,*)
!DO I = LBOUND(A,1), UBOUND(A,1)
! WRITE(*,*) (A(I,J), J = LBOUND(A,2), UBOUND(A,2))
!END DO
mat = reshape( TRANSPOSE(A), (/ rows * cols /) )
errorCode = 0
end subroutine fortran_process
! this routine is run once at the end of playback. it can be used to deallocate resources (memory, files, ...).
! set errorCode to 0 on success, a non-zero code otherwise.
subroutine fortran_uninit(errorCode) bind(C)
use iso_c_binding
INTEGER(C_INT32_T), intent(out) :: errorCode
! in this example, the routine does nothing much
write(*,*) "Uninit in Fortran"
errorCode = 0
end subroutine fortran_uninit
#include "ovpCFortranExample.h"
#include <system/ovCMemory.h>
#include <iostream>
#include <cstdio>
using namespace OpenViBE;
using namespace OpenViBE::Plugins;
using namespace OpenViBE::Kernel;
using namespace OpenViBEPlugins;
using namespace OpenViBEPlugins::Fortran;
using namespace OpenViBEToolkit;
using namespace std;
// These functions must be provided by the Fortran code
extern "C" void fortran_init(int32 *errorCode);
extern "C" void fortran_process(OpenViBE::float64* mat, int32* m, int32* n, int32 *errorCode);
extern "C" void fortran_uninit(int32 *errorCode);
void dumpMatrix(OpenViBE::Kernel::ILogManager &rMgr, const CMatrix& mat, const CString &desc)
{
rMgr << LogLevel_Info << desc << "\n";
for(uint32 i=0;i<mat.getDimensionSize(0);i++) {
rMgr << LogLevel_Info << "Row " << i << ": ";
for(uint32 j=0;j<mat.getDimensionSize(1);j++) {
rMgr << mat.getBuffer()[i*mat.getDimensionSize(1)+j] << " ";
}
rMgr << "\n";
}
}
namespace OpenViBEPlugins
{
namespace Fortran
{
// This function is called once when user presses play in Designer
OpenViBE::boolean CFortranExample::initialize()
{
this->getLogManager() << LogLevel_Info << "Initializing\n";
m_oDecoder.initialize(*this, 0);
m_oEncoder.initialize(*this, 0);
m_oEncoder.getInputMatrix().setReferenceTarget(m_oDecoder.getOutputMatrix());
// Do some initialization in Fortran
int32 l_i32ErrorCode = 0;
fortran_init(&l_i32ErrorCode);
if(l_i32ErrorCode)
{
this->getLogManager() << LogLevel_Error << "Fortran init() returned error code " << l_i32ErrorCode << "\n";
return false;
}
return true;
}
// This function is called once when user presses Stop in Designer
OpenViBE::boolean CFortranExample::uninitialize()
{
this->getLogManager() << LogLevel_Info << "Uninitializing\n";
// Do some uninitialization in Fortran
int32 l_i32ErrorCode = 0;
fortran_uninit(&l_i32ErrorCode);
m_oEncoder.uninitialize();
m_oDecoder.uninitialize();
if(l_i32ErrorCode)
{
this->getLogManager() << LogLevel_Error << "Fortran uninit() returned error code " << l_i32ErrorCode << "\n";
return false;
}
return true;
}
boolean CFortranExample::processInput(uint32 ui32InputIndex)
{
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
// This function is called for every signal chunk (matrix of N samples [channels x samples]).
OpenViBE::boolean CFortranExample::process()
{
IBoxIO& l_rDynamicBoxContext=this->getDynamicBoxContext();
for(uint32 i=0; i<l_rDynamicBoxContext.getInputChunkCount(0); i++)
{
m_oDecoder.decode(i);
if(m_oDecoder.isHeaderReceived())
{
if(m_oDecoder.getOutputMatrix()->getDimensionCount()!=2)
{
this->getLogManager() << LogLevel_Error << "Only 2 dimensional matrices supported\n";
return false;
}
m_oEncoder.encodeHeader();
l_rDynamicBoxContext.markOutputAsReadyToSend(0, l_rDynamicBoxContext.getInputChunkStartTime(0, i), l_rDynamicBoxContext.getInputChunkEndTime(0, i));
}
if(m_oDecoder.isBufferReceived())
{
IMatrix* l_pMatrix = m_oDecoder.getOutputMatrix();
int32 nRows = l_pMatrix->getDimensionSize(0);
int32 nCols = l_pMatrix->getDimensionSize(1);
// Process the sample chunk in Fortran
int32 l_i32ErrorCode = 0;
fortran_process(l_pMatrix->getBuffer(), &nRows, &nCols, &l_i32ErrorCode);
if(l_i32ErrorCode)
{
this->getLogManager() << LogLevel_Error << "Fortran process() returned error code " << l_i32ErrorCode << "\n";
return false;
}
m_oEncoder.encodeBuffer();
l_rDynamicBoxContext.markOutputAsReadyToSend(0, l_rDynamicBoxContext.getInputChunkStartTime(0, i), l_rDynamicBoxContext.getInputChunkEndTime(0, i));
}
if(m_oDecoder.isEndReceived())
{
m_oEncoder.encodeEnd();
l_rDynamicBoxContext.markOutputAsReadyToSend(0, l_rDynamicBoxContext.getInputChunkStartTime(0, i), l_rDynamicBoxContext.getInputChunkEndTime(0, i));
}
}
return true;
}
};
};
#ifndef __OpenViBEPlugins_Stimulation_CFortranExample_H__
#define __OpenViBEPlugins_Stimulation_CFortranExample_H__
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <string>
#include <vector>
#include <queue>
#include <cstdio>
namespace OpenViBEPlugins
{
namespace Fortran
{
class CFortranExample : public OpenViBEToolkit::TBoxAlgorithm<OpenViBE::Plugins::IBoxAlgorithm>
{
public:
//CFortranExample(void);
virtual void release(void) { delete this; }
virtual OpenViBE::boolean initialize();
virtual OpenViBE::boolean uninitialize();
virtual OpenViBE::boolean processInput(OpenViBE::uint32 ui32InputIndex);
virtual OpenViBE::boolean process();
_IsDerivedFromClass_Final_(OpenViBEToolkit::TBoxAlgorithm<OpenViBE::Plugins::IBoxAlgorithm>, OVP_ClassId_FortranExample)
private:
OpenViBEToolkit::TStreamedMatrixDecoder < CFortranExample > m_oDecoder;
OpenViBEToolkit::TStreamedMatrixEncoder < CFortranExample > m_oEncoder;
};
/**
* Plugin's description
*/
class CFortranExampleDesc : public OpenViBE::Plugins::IBoxAlgorithmDesc
{
public:
virtual OpenViBE::CString getName(void) const { return OpenViBE::CString("Fortran example"); }
virtual OpenViBE::CString getAuthorName(void) const { return OpenViBE::CString("Jussi T. Lindgren"); }
virtual OpenViBE::CString getAuthorCompanyName(void) const { return OpenViBE::CString("Inria"); }
virtual OpenViBE::CString getShortDescription(void) const { return OpenViBE::CString("Process matrix stream in Fortran"); }
virtual OpenViBE::CString getDetailedDescription(void) const { return OpenViBE::CString(""); }
virtual OpenViBE::CString getCategory(void) const { return OpenViBE::CString("Examples"); }
virtual OpenViBE::CString getVersion(void) const { return OpenViBE::CString("0.1"); }
virtual OpenViBE::CString getStockItemName(void) const { return OpenViBE::CString("gtk-convert"); }
virtual void release(void) { }
virtual OpenViBE::CIdentifier getCreatedClass(void) const { return OVP_ClassId_FortranExample; }
virtual OpenViBE::Plugins::IPluginObject* create(void) { return new OpenViBEPlugins::Fortran::CFortranExample(); }
// virtual OpenViBE::Plugins::IBoxListener* createBoxListener(void) const { return new CFortranExampleListener; }
// virtual void releaseBoxListener(OpenViBE::Plugins::IBoxListener* pBoxListener) const { delete pBoxListener; }
virtual OpenViBE::boolean getBoxPrototype(OpenViBE::Kernel::IBoxProto& rPrototype) const
{
rPrototype.addInput("Input",OV_TypeId_StreamedMatrix);
rPrototype.addOutput("Output",OV_TypeId_StreamedMatrix);
return true;
}
_IsDerivedFromClass_Final_(OpenViBE::Plugins::IBoxAlgorithmDesc, OVP_ClassId_FortranExampleDesc)
};
};
};
#endif
#ifndef __OpenViBEPlugins_Defines_H__
#define __OpenViBEPlugins_Defines_H__
//___________________________________________________________________//
// //
// Plugin Object Descriptor Class Identifiers //
//___________________________________________________________________//
// //
#define OVP_ClassId_FortranExampleDesc OpenViBE::CIdentifier(0x2BB7368F, 0x207D6480)
//___________________________________________________________________//
// //
// Plugin Object Class Identifiers //
//___________________________________________________________________//
// //
#define OVP_ClassId_FortranExample OpenViBE::CIdentifier(0x6F837408, 0x35BA030E)
#endif // __OpenViBEPlugins_Defines_H__
#include "ovp_defines.h"
#include "box-algorithms/ovpCFortranExample.h"
OVP_Declare_Begin();
OVP_Declare_New(OpenViBEPlugins::Fortran::CFortranExampleDesc);
OVP_Declare_End();