You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ovdCArchwayHandler.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. #ifdef MENSIA_DISTRIBUTION
  2. #include "ovdCArchwayHandler.h"
  3. #include <openvibe/ov_directories.h>
  4. #include <openvibe/kernel/log/ovILogManager.h>
  5. #include <openvibe/kernel/configuration/ovIConfigurationManager.h>
  6. #include <fs/Files.h>
  7. #include <ios>
  8. #include <cassert>
  9. #include <fstream>
  10. #include <sstream>
  11. #include <regex>
  12. namespace OpenViBE {
  13. const std::string CArchwayHandler::ARCHWAY_CONFIG_FILE = (Directories::getUserDataDir() + "/studio-archway.conf").toASCIIString();
  14. const std::string CArchwayHandler::ARCHWAY_PIPELINES_CONFIG_FILE = (Directories::getUserDataDir() + "/studio-archway-pipeline-configuration.conf").
  15. toASCIIString();
  16. std::string CArchwayHandler::getArchwayErrorString() const
  17. {
  18. assert(m_Archway);
  19. const auto errorCode = m_archway->getLastError();
  20. const auto errorString = m_archway->getErrorString(errorCode);
  21. std::stringstream stream;
  22. stream << std::hex << errorCode;
  23. return "[0x" + stream.str() + "] " + errorString;
  24. }
  25. EEngineInitialisationStatus CArchwayHandler::initialize()
  26. {
  27. #if defined TARGET_OS_Windows
  28. m_archwayModule.loadFromPath("mensia-engine.dll", "initialize");
  29. #elif defined TARGET_OS_Linux
  30. m_archwayModule.loadFromPath("libmensia-engine.so", "initialize");
  31. #elif defined TARGET_OS_MacOS
  32. m_archwayModule.loadFromPath("libmensia-engine.dylib", "initialize");
  33. #endif
  34. if (!m_archwayModule.isLoaded()) { return EEngineInitialisationStatus::NotAvailable; }
  35. m_archway = new struct ArchwayAPI();
  36. bool didLoad = true;
  37. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getLastError", &m_archway->getLastError);
  38. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getErrorString", &m_archway->getErrorString);
  39. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getVersionDescription", &m_archway->getVersionDescription);
  40. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getConfigurationParameterAsString",
  41. &m_archway->getConfigurationParameterAsString);
  42. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getPipelineScenarioPath", &m_archway->getPipelineScenarioPath);
  43. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "initialize", &m_archway->initialize);
  44. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "startAllAcquisitionDevices", &m_archway->startAllAcquisitionDevices);
  45. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "startImpedanceCheckOnAllAcquisitionDevices",
  46. &m_archway->startImpedanceCheckOnAllAcquisitionDevices);
  47. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "startEngine", &m_archway->startEngine);
  48. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "startEngineInFastForward", &m_archway->startEngineInFastForward);
  49. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "stopEngine", &m_archway->stopEngine);
  50. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "stopAllAcquisitionDevices", &m_archway->stopAllAcquisitionDevices);
  51. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "uninitialize", &m_archway->uninitialize);
  52. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "enumerateAvailablePipelines", &m_archway->enumerateAvailablePipelines);
  53. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "createPipeline", &m_archway->createPipeline);
  54. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "releasePipeline", &m_archway->releasePipeline);
  55. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "isPipelineRunning", &m_archway->isPipelineRunning);
  56. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "isPipelineInErrorState", &m_archway->isPipelineInErrorState);
  57. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "enumeratePipelineParameters", &m_archway->enumeratePipelineParameters);
  58. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "setPipelineParameterAsString", &m_archway->setPipelineParameterAsString);
  59. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "mainloop", &m_archway->mainloop);
  60. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getPendingValueCount", &m_archway->getPendingValueCount);
  61. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getPendingValueDimension", &m_archway->getPendingValueDimension);
  62. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getPendingValue", &m_archway->getPendingValue);
  63. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getPendingLogMessageCount", &m_archway->getPendingLogMessageCount);
  64. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "getPendingLogMessage", &m_archway->getPendingLogMessage);
  65. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "dropPendingValues", &m_archway->dropPendingValues);
  66. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "dropPendingEvents", &m_archway->dropPendingEvents);
  67. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "isInitialized", &m_archway->isInitialized);
  68. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "isAcquiring", &m_archway->isAcquiring);
  69. didLoad &= System::CDynamicModuleSymbolLoader::getSymbol<>(m_archwayModule, "isStarted", &m_archway->isStarted);
  70. if (!didLoad)
  71. {
  72. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to load symbols from Archway library [" << m_archwayModule.getErrorDetails() <<
  73. "]\n";
  74. delete m_archway;
  75. m_archway = nullptr;
  76. return EEngineInitialisationStatus::NotAvailable;
  77. }
  78. m_kernelCtx.getLogManager() << Kernel::LogLevel_Trace << "Working with Archway version: " << m_archway->getVersionDescription() << "\n";
  79. // Now initialize the ArchwayBridge structure with closures that bridge to local Archway functions
  80. // this way we do not have to expose the Archway object or the C API
  81. m_ArchwayBridge.isStarted = [this]() { return this->m_archway->isStarted(); };
  82. m_ArchwayBridge.getAvailableValueMatrixCount = [this](size_t valueChannelId)
  83. {
  84. return this->m_archway->getPendingValueCount(m_RunningPipelineId, valueChannelId);
  85. };
  86. // This function returns the last getPendingValue result as a vector
  87. // Such encapsulation enables us to avoid a call to getPendingValueDimension
  88. // from the client plugin.
  89. m_ArchwayBridge.popValueMatrix = [this](const size_t valueChannelId)
  90. {
  91. std::vector<float> valueMatrix;
  92. const auto valueChannelDim = this->m_archway->getPendingValueDimension(m_RunningPipelineId, valueChannelId);
  93. valueMatrix.resize(valueChannelDim);
  94. if (valueChannelDim > 0)
  95. {
  96. if (!this->m_archway->getPendingValue(m_RunningPipelineId, valueChannelId, &valueMatrix[0]))
  97. {
  98. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to get pending value " << this->getArchwayErrorString().c_str() << "\n";
  99. }
  100. }
  101. return valueMatrix;
  102. };
  103. // As archway buffers signals we have to expose this function to the client plugins
  104. m_ArchwayBridge.dropBuffers = [this]()
  105. {
  106. m_archway->dropPendingEvents(0);
  107. m_archway->dropPendingValues(0);
  108. return true;
  109. };
  110. // We save the address of the structure in the heap memory as a string and save it in
  111. // the ConfigurationManager, this is because a box can not communicate directly with the Designer
  112. std::ostringstream archwayBridgeAddress;
  113. archwayBridgeAddress << static_cast<void const*>(&m_ArchwayBridge);
  114. m_kernelCtx.getConfigurationManager().createConfigurationToken("Designer_ArchwayBridgeAddress", archwayBridgeAddress.str().c_str());
  115. if (!this->loadPipelineConfigurations()) { return EEngineInitialisationStatus::Failure; }
  116. m_EngineType = EEngineType::Local;
  117. // Get the starting engine type from configuration
  118. std::ifstream archwayConfigFile;
  119. FS::Files::openIFStream(archwayConfigFile, ARCHWAY_CONFIG_FILE.c_str());
  120. if (archwayConfigFile.good())
  121. {
  122. try
  123. {
  124. std::string line;
  125. while (std::getline(archwayConfigFile, line))
  126. {
  127. std::cmatch cm;
  128. if (std::regex_match(line.c_str(), cm, std::regex("config.server\\s*=\\s*'(lan|local)'")))
  129. {
  130. if (cm[1] == "lan") { m_EngineType = EEngineType::LAN; }
  131. }
  132. else if (std::regex_match(line.c_str(), cm, std::regex("config.device[1]\\s*=\\s*'([^']*)'"))) { m_DeviceURL = cm[1]; }
  133. }
  134. }
  135. catch (...)
  136. {
  137. // An exception will be thrown when using libc++ from ubuntu 14.04
  138. // in that case we do nothing and keep the defaults
  139. }
  140. }
  141. if (!this->initializeArchway())
  142. {
  143. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to initialize the engine " << this->getArchwayErrorString().c_str() << "\n";
  144. return EEngineInitialisationStatus::Failure;
  145. }
  146. char deviceURL[2048];
  147. m_archway->getConfigurationParameterAsString("config.device[1]", deviceURL, sizeof(deviceURL));
  148. m_DeviceURL = deviceURL;
  149. return EEngineInitialisationStatus::Success;
  150. }
  151. bool CArchwayHandler::uninitialize()
  152. {
  153. assert(m_Archway);
  154. if (m_archway->isStarted())
  155. {
  156. if (!m_archway->stopEngine())
  157. {
  158. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to stop Engine " << this->getArchwayErrorString().c_str() << "\n";
  159. }
  160. }
  161. if (m_archway->isAcquiring())
  162. {
  163. if (!m_archway->stopAllAcquisitionDevices())
  164. {
  165. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to stop all acquisition devices " << this->getArchwayErrorString().c_str() <<
  166. "\n";
  167. }
  168. }
  169. if (m_archway->isInitialized())
  170. {
  171. if (!m_archway->uninitialize())
  172. {
  173. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to uninitialize Archway " << this->getArchwayErrorString().c_str() << "\n";
  174. }
  175. }
  176. delete m_archway;
  177. m_archway = nullptr;
  178. if (!this->savePipelineConfigurations()) { return false; }
  179. return true;
  180. }
  181. CArchwayHandler::~CArchwayHandler() { if (m_archway) { this->uninitialize(); } }
  182. bool CArchwayHandler::initializeArchway()
  183. {
  184. assert(m_Archway);
  185. m_kernelCtx.getLogManager() << Kernel::LogLevel_Trace << "Re-initializing engine in [" << (m_EngineType == EEngineType::Local ? "Local" : "LAN") << "]" <<
  186. "\n";
  187. return m_archway->initialize("user", "pass", "neurort-studio", ARCHWAY_CONFIG_FILE.c_str());
  188. }
  189. bool CArchwayHandler::uninitializeArchway()
  190. {
  191. assert(m_Archway);
  192. if (m_archway->isInitialized())
  193. {
  194. if (!m_archway->uninitialize())
  195. {
  196. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to uninitialize Archway " << this->getArchwayErrorString().c_str() << "\n";
  197. return false;
  198. }
  199. }
  200. return true;
  201. }
  202. bool CArchwayHandler::reinitializeArchway()
  203. {
  204. assert(m_Archway);
  205. if (!this->uninitializeArchway())
  206. {
  207. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to uninitialize Engine " << this->getArchwayErrorString().c_str() << "\n";
  208. return false;
  209. }
  210. this->writeArchwayConfigurationFile();
  211. if (!this->initializeArchway())
  212. {
  213. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to initialize Engine " << this->getArchwayErrorString().c_str() << "\n";
  214. return false;
  215. }
  216. m_kernelCtx.getLogManager() << Kernel::LogLevel_Info << "Archway re-initialized \n";
  217. return true;
  218. }
  219. bool CArchwayHandler::startEngineWithPipeline(const size_t pipelineClassID, const bool isFastForward, const bool shouldAcquireImpedance)
  220. {
  221. assert(m_Archway);
  222. if (m_archway->isStarted())
  223. {
  224. m_kernelCtx.getLogManager() << Kernel::LogLevel_Info << "Engine is already started\n";
  225. return true;
  226. }
  227. if (!m_archway->isAcquiring())
  228. {
  229. if (shouldAcquireImpedance)
  230. {
  231. if (!m_archway->startImpedanceCheckOnAllAcquisitionDevices())
  232. {
  233. m_kernelCtx.getLogManager() << Kernel::LogLevel_Error << "Failed to start the impedance acquisition" << this->getArchwayErrorString().c_str() <<
  234. "\n";
  235. return false;
  236. }
  237. }
  238. else if (!m_archway->startAllAcquisitionDevices())
  239. {
  240. m_kernelCtx.getLogManager() << Kernel::LogLevel_Error << "Failed to start the data acquisition" << this->getArchwayErrorString().c_str() << "\n";
  241. return false;
  242. }
  243. }
  244. m_RunningPipelineId = m_archway->createPipeline(pipelineClassID, "");
  245. if (m_RunningPipelineId == 0)
  246. {
  247. m_archway->stopAllAcquisitionDevices();
  248. m_kernelCtx.getLogManager() << Kernel::LogLevel_Error << "Failed to create pipeline " << this->getArchwayErrorString().c_str() << "\n";
  249. return false;
  250. }
  251. if (m_pipelineSettings.count(pipelineClassID) != 0)
  252. {
  253. for (auto& parameter : m_pipelineSettings[pipelineClassID])
  254. {
  255. m_archway->setPipelineParameterAsString(m_RunningPipelineId, parameter.first.c_str(), parameter.second.c_str());
  256. }
  257. }
  258. if (!(isFastForward ? m_archway->startEngineInFastForward() : m_archway->startEngine()))
  259. {
  260. m_kernelCtx.getLogManager() << Kernel::LogLevel_Error << "Engine failed to start " << this->getArchwayErrorString().c_str() << "\n";
  261. const size_t nPendingLogMessage = m_archway->getPendingLogMessageCount(m_RunningPipelineId);
  262. for (size_t i = 0; i < nPendingLogMessage; ++i)
  263. {
  264. size_t logLevel;
  265. char messageBuffer[2048];
  266. std::string logMessages;
  267. m_archway->getPendingLogMessage(m_RunningPipelineId, &logLevel, messageBuffer, sizeof(messageBuffer));
  268. m_kernelCtx.getLogManager() << Kernel::ELogLevel(logLevel) << messageBuffer;
  269. }
  270. if (!m_archway->stopAllAcquisitionDevices())
  271. {
  272. m_kernelCtx.getLogManager() << Kernel::LogLevel_Error << "Failed to stop all acquisition devices " << this->getArchwayErrorString().c_str() << "\n";
  273. }
  274. return false;
  275. }
  276. m_kernelCtx.getLogManager() << Kernel::LogLevel_Info << "Engine Started\n";
  277. return true;
  278. }
  279. bool CArchwayHandler::stopEngine()
  280. {
  281. assert(m_Archway);
  282. bool hasStopSucceeded = true;
  283. if (m_archway->isStarted())
  284. {
  285. if (!m_archway->stopEngine())
  286. {
  287. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to stop Engine " << this->getArchwayErrorString().c_str() << "\n";
  288. hasStopSucceeded = false;
  289. }
  290. }
  291. if (m_archway->isAcquiring())
  292. {
  293. if (!m_archway->stopAllAcquisitionDevices())
  294. {
  295. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to all acquisition devices " << this->getArchwayErrorString().c_str() << "\n";
  296. hasStopSucceeded = false;
  297. }
  298. }
  299. if (m_RunningPipelineId != 0)
  300. {
  301. if (!m_archway->releasePipeline(m_RunningPipelineId))
  302. {
  303. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to release pipeline [" << m_RunningPipelineId << "] " << this->
  304. getArchwayErrorString().c_str() << "\n";
  305. hasStopSucceeded = false;
  306. }
  307. m_RunningPipelineId = 0;
  308. }
  309. m_kernelCtx.getLogManager() << Kernel::LogLevel_Info << "Engine Stopped\n";
  310. return hasStopSucceeded;
  311. }
  312. bool CArchwayHandler::loopEngine()
  313. {
  314. assert(m_Archway);
  315. const bool success = m_archway->mainloop();
  316. const bool isPipelineRunning = m_archway->isPipelineRunning(m_RunningPipelineId);
  317. const bool isPipelineInErrorState = m_archway->isPipelineInErrorState(m_RunningPipelineId);
  318. if (!isPipelineRunning) { m_kernelCtx.getLogManager() << Kernel::LogLevel_Info << "Pipeline [" << m_RunningPipelineId << "] is not running.\n"; }
  319. if (isPipelineInErrorState) { m_kernelCtx.getLogManager() << Kernel::LogLevel_Error << "Pipeline [" << m_RunningPipelineId << "] is in error state.\n"; }
  320. const size_t nPendingLogMessage = m_archway->getPendingLogMessageCount(m_RunningPipelineId);
  321. for (size_t i = 0; i < nPendingLogMessage; ++i)
  322. {
  323. size_t logLevel;
  324. char messageBuffer[2048];
  325. std::string logMessages;
  326. m_archway->getPendingLogMessage(m_RunningPipelineId, &logLevel, messageBuffer, sizeof(messageBuffer));
  327. m_kernelCtx.getLogManager() << Kernel::ELogLevel(logLevel) << messageBuffer;
  328. }
  329. if (!isPipelineRunning || isPipelineInErrorState)
  330. {
  331. if (!this->stopEngine()) { return false; }
  332. m_GUIBridge.refreshStoppedEngine();
  333. return success && !isPipelineInErrorState;
  334. }
  335. return success;
  336. }
  337. bool CArchwayHandler::isEngineStarted()
  338. {
  339. if (!m_archway) { return false; }
  340. return m_archway->isStarted();
  341. }
  342. namespace {
  343. void enumerateEnginePipelinesCallback(const size_t pipelineID, const char* pipelineDescription, void* userData)
  344. {
  345. const auto callbackParameters = static_cast<std::pair<std::vector<SPipeline>*, std::map<size_t, std::map<std::string, std::string>>*>*>(userData);
  346. auto enginePipelines = callbackParameters->first;
  347. const auto pipelineSettings = callbackParameters->second;
  348. enginePipelines->push_back({ pipelineID, pipelineDescription, pipelineSettings->count(pipelineID) != 0 });
  349. }
  350. void enumeratePipelineParametersCallback(size_t/*pipelineID*/, const char* parameterName, const char* parameterValue, void* userData)
  351. {
  352. // This callback will go through the pipeline parameters one by one and push them into the
  353. // vector of SPipelineParameters which is passed as the first element of the data input pair
  354. // This callback receives the parameter's name and default value from Archway, which is why we pass
  355. // it the list of the _currently set_ parameters for the pipeline
  356. const auto parameters = static_cast<std::pair<std::vector<SPipelineParameter>*, std::map<std::string, std::string> const*>*>(userData);
  357. // Our output parameter is the list of pipeline parameters
  358. auto pipelineParameters = parameters->first;
  359. // Our additional input parameter is the map of currently set parameters for the pipeline
  360. // (note that if no parameters are set for the pipeline then this pointer will be null)
  361. const auto pipelineSettings = parameters->second;
  362. // Search for the currently set value of the currently handled parameter
  363. std::string str;
  364. if (pipelineSettings && pipelineSettings->count(parameterName) != 0) { str = pipelineSettings->at(parameterName); }
  365. pipelineParameters->push_back({ parameterName, parameterValue, str });
  366. }
  367. } // namespace
  368. std::vector<SPipeline> CArchwayHandler::getEnginePipelines() const
  369. {
  370. assert(m_Archway);
  371. std::vector<SPipeline> enginePipelines;
  372. auto callbackParameters = make_pair(&enginePipelines, &m_pipelineSettings);
  373. if (!m_archway->enumerateAvailablePipelines(enumerateEnginePipelinesCallback, &callbackParameters))
  374. {
  375. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed enumerate the available pipelines " << this->getArchwayErrorString().c_str() << "\n";
  376. }
  377. return enginePipelines;
  378. }
  379. std::vector<SPipelineParameter> CArchwayHandler::getPipelineParameters(const size_t pipelineClassID) const
  380. {
  381. assert(m_Archway);
  382. std::vector<SPipelineParameter> pipelineParameters;
  383. std::map<std::string, std::string> const* pipelineSettings = nullptr;
  384. if (m_pipelineSettings.count(pipelineClassID) != 0) { pipelineSettings = &m_pipelineSettings.at(pipelineClassID); }
  385. auto callbackParameters = std::make_pair(&pipelineParameters, pipelineSettings);
  386. const size_t pipelineID = m_archway->createPipeline(pipelineClassID, "");
  387. if (!m_archway->enumeratePipelineParameters(pipelineID, enumeratePipelineParametersCallback, &callbackParameters))
  388. {
  389. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed enumerate the pipeline's parameters " << this->getArchwayErrorString().c_str() <<
  390. "\n";
  391. }
  392. if (!m_archway->releasePipeline(pipelineID))
  393. {
  394. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Failed to release pipeline " << this->getArchwayErrorString().c_str() << "\n";
  395. }
  396. return pipelineParameters;
  397. }
  398. std::string CArchwayHandler::getPipelineScenarioPath(size_t pipelineClassID) const
  399. {
  400. assert(m_Archway);
  401. char messageBuffer[2048];
  402. std::string logMessages;
  403. if (!m_archway->getPipelineScenarioPath(pipelineClassID, messageBuffer, sizeof(messageBuffer))) { return ""; }
  404. return std::string(messageBuffer);
  405. }
  406. bool CArchwayHandler::setPipelineParameterValue(const size_t pipelineClassID, std::string const& parameterName, std::string const& parameterValue)
  407. {
  408. if (m_pipelineSettings.find(pipelineClassID) == m_pipelineSettings.end())
  409. {
  410. m_kernelCtx.getLogManager() << Kernel::LogLevel_Error << "Failed to set the value [" << parameterValue << "] to the parameter [" << parameterName <<
  411. "]. The pipeline class id is invalid.\n";
  412. return false;
  413. }
  414. if (parameterValue != "") { m_pipelineSettings[pipelineClassID][parameterName] = parameterValue; }
  415. else
  416. {
  417. if (m_pipelineSettings.count(pipelineClassID) != 0)
  418. {
  419. if (m_pipelineSettings[pipelineClassID].count(parameterName) != 0)
  420. {
  421. m_pipelineSettings[pipelineClassID].erase(m_pipelineSettings[pipelineClassID].find(parameterName));
  422. if (m_pipelineSettings[pipelineClassID].size() == 0) { m_pipelineSettings.erase(m_pipelineSettings.find(pipelineClassID)); }
  423. }
  424. }
  425. }
  426. // m_kernelCtx.getLogManager() << Kernel::LogLevel_Info << "Set [" << uiPipelineClassId << "/" << sParameterName << "] to [" << sParameterValue << "]\n";
  427. return true;
  428. }
  429. bool CArchwayHandler::writeArchwayConfigurationFile()
  430. {
  431. std::ofstream file;
  432. FS::Files::openOFStream(file, ARCHWAY_CONFIG_FILE.c_str());
  433. if (!file.good())
  434. {
  435. file.close();
  436. return false;
  437. }
  438. file << "config.server = '" << (m_EngineType == EEngineType::LAN ? "lan" : "local") << "'\n";
  439. file << "config.device[1] = '" << m_DeviceURL << "'\n";
  440. file.close();
  441. return true;
  442. }
  443. bool CArchwayHandler::savePipelineConfigurations()
  444. {
  445. std::ofstream file;
  446. FS::Files::openOFStream(file, ARCHWAY_PIPELINES_CONFIG_FILE.c_str());
  447. if (!file.good())
  448. {
  449. m_kernelCtx.getLogManager() << Kernel::LogLevel_Warning << "Cannot open file for writing\n";
  450. return false;
  451. }
  452. for (auto& pipeline : m_pipelineSettings)
  453. {
  454. for (auto& setting : pipeline.second) { file << pipeline.first << "\t" << setting.first << "\t" << setting.second << "\n"; }
  455. }
  456. file.close();
  457. return true;
  458. }
  459. bool CArchwayHandler::loadPipelineConfigurations()
  460. {
  461. std::ifstream file;
  462. FS::Files::openIFStream(file, ARCHWAY_PIPELINES_CONFIG_FILE.c_str());
  463. if (!file.good())
  464. {
  465. m_kernelCtx.getLogManager() << Kernel::LogLevel_Trace << "Cannot open Engine Pipeline Configuration file for reading\n";
  466. return false;
  467. }
  468. while (!file.eof())
  469. {
  470. size_t pipelineClassID;
  471. file >> pipelineClassID;
  472. std::string parameterName;
  473. // The first one simply trashes the tab after the pipeline Id
  474. getline(file, parameterName, '\t');
  475. getline(file, parameterName, '\t');
  476. std::string parameterValue;
  477. getline(file, parameterValue, '\n');
  478. if (parameterValue != "")
  479. {
  480. m_pipelineSettings[pipelineClassID];
  481. m_pipelineSettings[pipelineClassID][parameterName] = parameterValue;
  482. }
  483. }
  484. file.close();
  485. return true;
  486. }
  487. } // namespace OpenViBE
  488. #endif