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.

ovdCArchwayHandlerGUI.cpp 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. #ifdef MENSIA_DISTRIBUTION
  2. #include "ovdCArchwayHandlerGUI.h"
  3. #include <openvibe/ov_directories.h>
  4. #include <fs/Files.h>
  5. #include <sstream>
  6. #include <cassert>
  7. #include <cstdio>
  8. #include <sstream>
  9. #include "../ovdCApplication.h"
  10. #include "ovProcessUtilities.hpp"
  11. #if defined TARGET_OS_Windows
  12. #define pclose _pclose
  13. #endif
  14. namespace OpenViBE {
  15. namespace {
  16. enum EnginePipelinesModelColumn
  17. {
  18. Column_PipelineId = 0,
  19. Column_PipelineHexId,
  20. Column_PipelineDescription,
  21. Column_PipelineIsConfigured
  22. };
  23. enum PipelineConfigurationModelColumn
  24. {
  25. Column_SettingPipelineId = 0,
  26. Column_SettingName = 1,
  27. Column_SettingDefaultValue = 2,
  28. Column_SettingValue = 3
  29. };
  30. void on_button_configure_acquisition_clicked(GtkMenuItem* menuItem, gpointer data)
  31. {
  32. auto gui = static_cast<CArchwayHandlerGUI*>(data);
  33. const std::string configToolLaunchCmd = std::string(Directories::getBinDir().toASCIIString()) + "/mensia-device-configuration";
  34. //std::string configFilePath = std::string(getenv("USERPROFILE")) + "\\lib-mensia-engine.conf";
  35. std::string escapedURL = gui->m_Controller.m_DeviceURL;
  36. size_t startPosition = 0;
  37. while ((startPosition = escapedURL.find('\"', startPosition)) != std::string::npos)
  38. {
  39. escapedURL.replace(startPosition, 1, "\\\"");
  40. startPosition += 2; // Handles case where 'to' is a substring of 'from'
  41. }
  42. #if defined TARGET_OS_Windows
  43. std::string command = "\"\"" + configToolLaunchCmd + "\" --no-file \"" + escapedURL + "\"\"";
  44. for (std::string stringToEscape : { "^", "<", ">", "&", "|", "%" }) // ^ must be escaped first!
  45. {
  46. startPosition = 0;
  47. while ((startPosition = command.find(stringToEscape, startPosition)) != std::string::npos)
  48. {
  49. command.replace(startPosition, stringToEscape.size(), "^" + stringToEscape);
  50. startPosition += 1 + stringToEscape.size();
  51. }
  52. }
  53. #elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
  54. std::string command = configurationToolLaunchCmd + " --no-file \"" + escapedURL + "\"";
  55. #endif
  56. FILE* commandPipe = FS::Files::popen(command.c_str(), "r");
  57. char buffer[512];
  58. std::stringstream urlStream;
  59. while (fgets(buffer, sizeof(buffer), commandPipe) != nullptr) { urlStream << buffer; }
  60. pclose(commandPipe);
  61. auto deviceURL = urlStream.str();
  62. deviceURL = deviceURL.substr(0, deviceURL.length() - 1);
  63. gui->m_Controller.m_DeviceURL = deviceURL;
  64. gui->m_Controller.writeArchwayConfigurationFile();
  65. }
  66. void on_button_reinitialize_archway_clicked(GtkMenuItem*, gpointer data)
  67. {
  68. auto gui = static_cast<CArchwayHandlerGUI*>(data);
  69. const auto engineTypeCombobox = GTK_COMBO_BOX(gtk_builder_get_object(gui->m_Builder, "combobox-engine-connection-type"));
  70. gui->m_Controller.m_EngineType = (gtk_combo_box_get_active(engineTypeCombobox) == 0 ? EEngineType::Local : EEngineType::LAN);
  71. gui->m_Controller.reinitializeArchway();
  72. gui->refreshEnginePipelines();
  73. }
  74. void on_combobox_engine_type_changed(GtkComboBox*, gpointer data)
  75. {
  76. const auto gui = static_cast<CArchwayHandlerGUI*>(data);
  77. if (gtk_combo_box_get_active(gui->m_ComboBoxEngineType) == 0) { gtk_widget_set_sensitive(gui->m_ButtonLaunchEngine, FALSE); }
  78. else { gtk_widget_set_sensitive(gui->m_ButtonLaunchEngine, TRUE); }
  79. on_button_reinitialize_archway_clicked(nullptr, data);
  80. }
  81. gboolean on_dialog_engine_configuration_delete_event(GtkDialog* dialog, GdkEvent*, gpointer data)
  82. {
  83. const auto gui = static_cast<CArchwayHandlerGUI*>(data);
  84. gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(gui->m_ButtonOpenEngineConfigurationDialog), false);
  85. gtk_widget_hide(GTK_WIDGET(dialog));
  86. return TRUE;
  87. }
  88. gboolean on_dialog_pipeline_configuration_delete_event(GtkDialog* pDialog, GdkEvent*, gpointer)
  89. {
  90. gtk_dialog_response(pDialog, GTK_RESPONSE_CANCEL);
  91. gtk_widget_hide(GTK_WIDGET(pDialog));
  92. return TRUE;
  93. }
  94. void view_pipeline_config(CArchwayHandlerGUI* gui)
  95. {
  96. const auto treeModel = gtk_tree_view_get_model(GTK_TREE_VIEW(gui->m_TreeViewEnginePipelines));
  97. guint64 pipelineID;
  98. gtk_tree_model_get(treeModel, &gui->m_SelectedPipelineIter, Column_PipelineId, &pipelineID, -1);
  99. gui->displayPipelineConfigurationDialog(size_t(pipelineID));
  100. auto enginePipelines = gui->m_Controller.getEnginePipelines();
  101. for (const auto& pipeline : enginePipelines)
  102. {
  103. if (pipeline.id != pipelineID) { continue; }
  104. gtk_list_store_set(GTK_LIST_STORE(treeModel), &gui->m_SelectedPipelineIter, Column_PipelineIsConfigured, pipeline.isConfigured, -1);
  105. }
  106. }
  107. void view_popup_menu_onOpenScenario(GtkWidget* menuitem, gpointer data)
  108. {
  109. auto gui = static_cast<CArchwayHandlerGUI*>(data);
  110. const auto treeModel = gtk_tree_view_get_model(GTK_TREE_VIEW(gui->m_TreeViewEnginePipelines));
  111. guint64 pipelineID;
  112. gtk_tree_model_get(treeModel, &gui->m_SelectedPipelineIter, Column_PipelineId, &pipelineID, -1);
  113. if (gui->m_Controller.m_EngineType == EEngineType::Local)
  114. {
  115. const std::string path = gui->m_Controller.getPipelineScenarioPath(size_t(pipelineID));
  116. gui->m_Application->openScenario(path.c_str());
  117. }
  118. }
  119. void view_popup_menu_onConfItem(GtkWidget* menuitem, gpointer data)
  120. {
  121. const auto gui = static_cast<CArchwayHandlerGUI*>(data);
  122. view_pipeline_config(gui);
  123. }
  124. void on_treeview_engine_pipelines_popup_menu(CArchwayHandlerGUI* gui, GdkEventButton* event)
  125. {
  126. GtkWidget* menu = gtk_menu_new();
  127. GtkWidget* openConfItem = gtk_menu_item_new_with_label("Open configuration file");
  128. g_signal_connect(openConfItem, "activate", GCallback(view_popup_menu_onConfItem), gui);
  129. gtk_menu_shell_append(GTK_MENU_SHELL(menu), openConfItem);
  130. if (gui->m_Controller.m_EngineType == EEngineType::Local)
  131. {
  132. GtkWidget* openScenarioItem = gtk_menu_item_new_with_label("Open scenario");
  133. g_signal_connect(openScenarioItem, "activate", GCallback(view_popup_menu_onOpenScenario), gui);
  134. gtk_menu_shell_append(GTK_MENU_SHELL(menu), openScenarioItem);
  135. }
  136. gtk_widget_show_all(menu);
  137. gtk_menu_popup(GTK_MENU(menu), nullptr, nullptr, nullptr, nullptr, event->button, gdk_event_get_time(reinterpret_cast<GdkEvent*>(event)));
  138. }
  139. gboolean on_treeview_engine_pipelines_button_pressed(GtkWidget* treeView, GdkEventButton* event, gpointer userData)
  140. {
  141. // Only acknowledge, if it's a right click, or double click
  142. if (!(event->type == GDK_BUTTON_PRESS && event->button == 3) && !(event->type == GDK_2BUTTON_PRESS && event->button == 1)) { return FALSE; }
  143. auto gui = static_cast<CArchwayHandlerGUI*>(userData);
  144. GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gui->m_TreeViewEnginePipelines));
  145. if (gtk_tree_selection_count_selected_rows(selection) == 1)
  146. {
  147. gtk_tree_selection_get_selected(selection, &gui->m_TreeModelEnginePipelines, &gui->m_SelectedPipelineIter);
  148. // single click with the right mouse button
  149. if (event->type == GDK_BUTTON_PRESS && event->button == 3)
  150. {
  151. on_treeview_engine_pipelines_popup_menu(gui, event);
  152. return TRUE;
  153. }
  154. else if (event->type == GDK_2BUTTON_PRESS && event->button == 1)
  155. {
  156. view_pipeline_config(gui);
  157. return TRUE;
  158. }
  159. }
  160. return FALSE;
  161. }
  162. void startEngine(GtkWidget* widget, gpointer data, bool isFastForward)
  163. {
  164. auto gui = static_cast<CArchwayHandlerGUI*>(data);
  165. // Get the currently selected pipeline in the list
  166. const auto selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gui->m_TreeViewEnginePipelines));
  167. if (gtk_tree_selection_count_selected_rows(selection) == 1)
  168. {
  169. gtk_tree_selection_get_selected(selection, &gui->m_TreeModelEnginePipelines, &gui->m_SelectedPipelineIter);
  170. size_t pipelineID = 0;
  171. gtk_tree_model_get(gui->m_TreeModelEnginePipelines, &gui->m_SelectedPipelineIter, Column_PipelineId, &pipelineID, -1);
  172. const bool shouldAcquireImpedance = (gtk_toggle_tool_button_get_active(gui->m_ToggleAcquireImpedance) == gboolean(true));
  173. if (gui->m_Controller.startEngineWithPipeline(size_t(pipelineID), isFastForward, shouldAcquireImpedance))
  174. {
  175. gtk_widget_set_sensitive(GTK_WIDGET(gui->m_ToggleAcquireImpedance), false);
  176. gtk_widget_set_sensitive(GTK_WIDGET(gui->m_ComboBoxEngineType), false);
  177. gtk_widget_set_sensitive(gui->m_ButtonConfigureAcquisition, false);
  178. gtk_widget_set_sensitive(gui->m_ButtonLaunchEngine, false);
  179. gtk_widget_set_sensitive(gui->m_ButtonStartEngine, false);
  180. gtk_widget_set_sensitive(gui->m_ButtonStartEngineFastFoward, false);
  181. gtk_widget_set_sensitive(gui->m_ButtonStopEngine, true);
  182. gtk_widget_set_sensitive(gui->m_TreeViewEnginePipelines, false);
  183. gtk_spinner_start(gui->m_SpinnerEngineActivity);
  184. gtk_widget_show(GTK_WIDGET(gui->m_SpinnerEngineActivity));
  185. }
  186. }
  187. else
  188. {
  189. const auto alertDialog = gtk_message_dialog_new(nullptr, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Please select a pipeline to run.");
  190. gtk_dialog_run(GTK_DIALOG(alertDialog));
  191. gtk_widget_destroy(alertDialog);
  192. }
  193. }
  194. void on_button_start_engine_clicked(GtkWidget* widget, gpointer data) { startEngine(widget, data, false); }
  195. void on_button_start_engine_fast_forward_clicked(GtkWidget* widget, gpointer data) { startEngine(widget, data, true); }
  196. void on_button_stop_engine_clicked(GtkWidget* widget, gpointer data)
  197. {
  198. auto gui = static_cast<CArchwayHandlerGUI*>(data);
  199. if (gui->m_Controller.stopEngine())
  200. {
  201. gtk_widget_set_sensitive(GTK_WIDGET(gui->m_ToggleAcquireImpedance), true);
  202. gtk_widget_set_sensitive(GTK_WIDGET(gui->m_ComboBoxEngineType), true);
  203. gtk_widget_set_sensitive(gui->m_ButtonConfigureAcquisition, true);
  204. gtk_widget_set_sensitive(gui->m_ButtonLaunchEngine, true);
  205. gtk_widget_set_sensitive(gui->m_ButtonStartEngine, true);
  206. gtk_widget_set_sensitive(gui->m_ButtonStartEngineFastFoward, true);
  207. gtk_widget_set_sensitive(gui->m_ButtonStopEngine, false);
  208. gtk_widget_set_sensitive(gui->m_TreeViewEnginePipelines, true);
  209. gtk_spinner_stop(gui->m_SpinnerEngineActivity);
  210. gtk_widget_hide(GTK_WIDGET(gui->m_SpinnerEngineActivity));
  211. }
  212. }
  213. void on_button_pipeline_configuration_apply_clicked(GtkWidget* widget, gpointer)
  214. {
  215. GtkWidget* dialog = gtk_widget_get_parent(gtk_widget_get_parent((gtk_widget_get_parent(widget))));
  216. gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_APPLY);
  217. gtk_widget_hide(dialog);
  218. }
  219. void on_button_pipeline_configuration_cancel_clicked(GtkWidget* widget, gpointer)
  220. {
  221. GtkWidget* dialog = gtk_widget_get_parent(gtk_widget_get_parent((gtk_widget_get_parent(widget))));
  222. gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
  223. gtk_widget_hide(dialog);
  224. }
  225. void on_pipeline_configuration_cellrenderer_parameter_value_edited(GtkCellRendererText* cell, gchar* path, gchar* newText, gpointer data)
  226. {
  227. auto gui = static_cast<CArchwayHandlerGUI*>(data);
  228. gui->setPipelineParameterValueAtPath(path, newText);
  229. }
  230. gboolean on_pipeline_configuration_cellrenderer_parameter_value_entry_focus_out(GtkWidget* widget, GdkEvent* event, gpointer data)
  231. {
  232. auto gui = static_cast<CArchwayHandlerGUI*>(data);
  233. const auto entry = GTK_ENTRY(widget);
  234. gui->setPipelineParameterValueAtPath(gui->m_CurrentlyEditedCellPath.c_str(), gtk_entry_get_text(entry));
  235. return FALSE;
  236. }
  237. void on_pipeline_configuration_cellrenderer_parameter_value_editing_started(GtkCellRenderer* cell, GtkCellEditable* editable, gchar* path, gpointer data)
  238. {
  239. auto gui = static_cast<CArchwayHandlerGUI*>(data);
  240. // As we are sending data to a callback created within a callback, we really want to avoid
  241. // allocating memory.
  242. gui->m_CurrentlyEditedCellPath = path;
  243. const auto entry = GTK_ENTRY(editable);
  244. g_signal_connect(G_OBJECT(entry),
  245. "focus-out-event",
  246. G_CALLBACK(on_pipeline_configuration_cellrenderer_parameter_value_entry_focus_out), data);
  247. }
  248. void on_button_launch_engine_clicked(GtkWidget* widget, gpointer data)
  249. {
  250. // auto gui = static_cast<CArchwayHandlerGUI*>(data);
  251. if (!ProcessUtilities::doesProcessExist("mensia-engine-server"))
  252. {
  253. #if defined TARGET_OS_Windows
  254. if (FS::Files::fileExists(Directories::getBinDir() + "/mensia-engine-server.exe"))
  255. {
  256. ProcessUtilities::launchCommand(std::string(Directories::getBinDir() + "/mensia-engine-server.exe").c_str());
  257. }
  258. else if (FS::Files::fileExists("C:/Program Files (x86)/NeuroRT/NeuroRT Engine Server/bin/mensia-engine-server.exe"))
  259. {
  260. ProcessUtilities::launchCommand(std::string("C:/Program Files (x86)/NeuroRT/NeuroRT Engine Server/neurort-engine-server.cmd").c_str());
  261. }
  262. #elif defined TARGET_OS_Linux || defined TARGET_OS_MacOS
  263. if (FS::Files::fileExists(Directories::getBinDir() + "/mensia-engine-server"))
  264. {
  265. ProcessUtilities::launchCommand(std::string(Directories::getBinDir() + "/mensia-engine-server").c_str());
  266. }
  267. #endif
  268. }
  269. }
  270. }
  271. CArchwayHandlerGUI::CArchwayHandlerGUI(CArchwayHandler& controller, Designer::CApplication* application)
  272. : m_Controller(controller), m_Application(application)
  273. {
  274. m_Builder = gtk_builder_new();
  275. GError* gtkError = nullptr;
  276. gtk_builder_add_from_file(m_Builder, Directories::getDataDir() + "/applications/designer/interface-archway.ui", &gtkError);
  277. assert(gtkError == nullptr);
  278. // gtk_builder_connect_signals(m_builder, nullptr);
  279. m_ButtonConfigureAcquisition = GTK_WIDGET(gtk_builder_get_object(m_Builder, "button-configure-acquisition"));
  280. g_signal_connect(G_OBJECT(m_ButtonConfigureAcquisition), "clicked", G_CALLBACK(on_button_configure_acquisition_clicked), this);
  281. m_ButtonReinitializeArchway = GTK_WIDGET(gtk_builder_get_object(m_Builder, "button-reinitialize-archway"));
  282. g_signal_connect(G_OBJECT(m_ButtonReinitializeArchway), "clicked", G_CALLBACK(on_button_reinitialize_archway_clicked), this);
  283. g_signal_connect(G_OBJECT(gtk_builder_get_object(m_Builder, "button-pipeline-configuration-apply")),
  284. "clicked", G_CALLBACK(on_button_pipeline_configuration_apply_clicked), this);
  285. g_signal_connect(G_OBJECT(gtk_builder_get_object(m_Builder, "button-pipeline-configuration-cancel")),
  286. "clicked", G_CALLBACK(on_button_pipeline_configuration_cancel_clicked), this);
  287. m_SpinnerEngineActivity = GTK_SPINNER(gtk_builder_get_object(m_Builder, "spinner-engine-activity"));
  288. gtk_widget_hide(GTK_WIDGET(m_SpinnerEngineActivity));
  289. m_ToggleAcquireImpedance = GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(m_Builder, "toggle-acquire-impedance"));
  290. m_ButtonStartEngine = GTK_WIDGET(gtk_builder_get_object(m_Builder, "button-start-engine"));
  291. m_ButtonStartEngineFastFoward = GTK_WIDGET(gtk_builder_get_object(m_Builder, "button-start-engine-fast"));
  292. m_ButtonStopEngine = GTK_WIDGET(gtk_builder_get_object(m_Builder, "button-stop-engine"));
  293. gtk_widget_set_sensitive(m_ButtonStopEngine, false);
  294. g_signal_connect(G_OBJECT(m_ButtonStartEngine), "clicked", G_CALLBACK(on_button_start_engine_clicked), this);
  295. g_signal_connect(G_OBJECT(m_ButtonStartEngineFastFoward), "clicked", G_CALLBACK(on_button_start_engine_fast_forward_clicked), this);
  296. g_signal_connect(G_OBJECT(m_ButtonStopEngine), "clicked", G_CALLBACK(on_button_stop_engine_clicked), this);
  297. g_signal_connect(G_OBJECT(gtk_builder_get_object(m_Builder, "dialog-engine-configuration")),
  298. "delete-event", G_CALLBACK(on_dialog_engine_configuration_delete_event), this);
  299. g_signal_connect(G_OBJECT(gtk_builder_get_object(m_Builder, "dialog-pipeline-configuration")),
  300. "delete-event", G_CALLBACK(on_dialog_pipeline_configuration_delete_event), this);
  301. m_TreeViewEnginePipelines = GTK_WIDGET(gtk_builder_get_object(m_Builder, "treeview-engine-pipelines"));
  302. g_signal_connect(m_TreeViewEnginePipelines, "button-press-event", GCallback(on_treeview_engine_pipelines_button_pressed), this);
  303. g_signal_connect(G_OBJECT(gtk_builder_get_object(m_Builder, "pipeline-configuration-cellrenderer-parameter-value")),
  304. "edited",
  305. G_CALLBACK(on_pipeline_configuration_cellrenderer_parameter_value_edited), this);
  306. g_signal_connect(G_OBJECT(gtk_builder_get_object(m_Builder, "pipeline-configuration-cellrenderer-parameter-value")),
  307. "editing-started",
  308. G_CALLBACK(on_pipeline_configuration_cellrenderer_parameter_value_editing_started), this);
  309. m_TreeModelEnginePipelines = GTK_TREE_MODEL(gtk_builder_get_object(m_Builder, "liststore-pipelines"));
  310. m_Controller.m_GUIBridge.refreshStoppedEngine = [this]()
  311. {
  312. gtk_widget_set_sensitive(GTK_WIDGET(m_ToggleAcquireImpedance), true);
  313. gtk_widget_set_sensitive(GTK_WIDGET(m_ComboBoxEngineType), true);
  314. gtk_widget_set_sensitive(m_ButtonConfigureAcquisition, true);
  315. gtk_widget_set_sensitive(m_ButtonLaunchEngine, true);
  316. gtk_widget_set_sensitive(m_ButtonStartEngine, true);
  317. gtk_widget_set_sensitive(m_ButtonStartEngineFastFoward, true);
  318. gtk_widget_set_sensitive(m_ButtonStopEngine, false);
  319. gtk_widget_set_sensitive(m_TreeViewEnginePipelines, true);
  320. gtk_spinner_stop(m_SpinnerEngineActivity);
  321. gtk_widget_hide(GTK_WIDGET(m_SpinnerEngineActivity));
  322. };
  323. m_ComboBoxEngineType = GTK_COMBO_BOX(gtk_builder_get_object(m_Builder, "combobox-engine-connection-type"));
  324. g_signal_connect(G_OBJECT(m_ComboBoxEngineType), "changed", G_CALLBACK(on_combobox_engine_type_changed), this);
  325. m_ButtonLaunchEngine = GTK_WIDGET(gtk_builder_get_object(m_Builder, "button-launch-engine-server"));
  326. g_signal_connect(G_OBJECT(m_ButtonLaunchEngine), "clicked", G_CALLBACK(on_button_launch_engine_clicked), this);
  327. }
  328. CArchwayHandlerGUI::~CArchwayHandlerGUI() { if (m_Builder) { g_object_unref(G_OBJECT(m_Builder)); } }
  329. void CArchwayHandlerGUI::refreshEnginePipelines()
  330. {
  331. const auto listStorePipelines = GTK_LIST_STORE(m_TreeModelEnginePipelines);
  332. gtk_list_store_clear(listStorePipelines);
  333. auto enginePipelines = m_Controller.getEnginePipelines();
  334. GtkTreeIter iter;
  335. for (auto& pipeline : enginePipelines)
  336. {
  337. std::stringstream pipelineIdInHex;
  338. pipelineIdInHex << std::hex << pipeline.id;
  339. gtk_list_store_append(listStorePipelines, &iter);
  340. gtk_list_store_set(listStorePipelines, &iter, Column_PipelineId, pipeline.id, Column_PipelineHexId, pipelineIdInHex.str().c_str(),
  341. Column_PipelineDescription, pipeline.description.c_str(), Column_PipelineIsConfigured, pipeline.isConfigured, -1);
  342. }
  343. }
  344. void CArchwayHandlerGUI::toggleNeuroRTEngineConfigurationDialog(const bool shouldDisplay)
  345. {
  346. const auto engineConfigurationWidget = GTK_WIDGET(gtk_builder_get_object(m_Builder, "dialog-engine-configuration"));
  347. if (shouldDisplay)
  348. {
  349. gtk_combo_box_set_active(m_ComboBoxEngineType, m_Controller.m_EngineType == EEngineType::Local ? 0 : 1);
  350. this->refreshEnginePipelines();
  351. gtk_widget_show(engineConfigurationWidget);
  352. }
  353. else { gtk_widget_hide(engineConfigurationWidget); }
  354. }
  355. void CArchwayHandlerGUI::displayPipelineConfigurationDialog(const size_t pipelineID)
  356. {
  357. const auto pipelineConfigurationWidget = GTK_WIDGET(gtk_builder_get_object(m_Builder, "dialog-pipeline-configuration"));
  358. const auto pipelineConfigurationListStore = GTK_LIST_STORE(gtk_builder_get_object(m_Builder, "liststore-pipeline-configuration"));
  359. gtk_list_store_clear(pipelineConfigurationListStore);
  360. auto pipelineParameters = m_Controller.getPipelineParameters(pipelineID);
  361. GtkTreeIter iter;
  362. for (auto& parameter : pipelineParameters)
  363. {
  364. gtk_list_store_append(pipelineConfigurationListStore, &iter);
  365. gtk_list_store_set(pipelineConfigurationListStore, &iter,
  366. Column_SettingPipelineId, static_cast<size_t>(pipelineID),
  367. Column_SettingName, parameter.name.c_str(),
  368. Column_SettingDefaultValue, parameter.defaultValue.c_str(),
  369. Column_SettingValue, parameter.value.c_str(),
  370. -1);
  371. }
  372. const auto savedSettings = m_Controller.getPipelineSettings(pipelineID);
  373. const auto response = gtk_dialog_run(GTK_DIALOG(pipelineConfigurationWidget));
  374. if (response == GTK_RESPONSE_CANCEL) { m_Controller.getPipelineSettings(pipelineID) = savedSettings; }
  375. }
  376. bool CArchwayHandlerGUI::setPipelineParameterValueAtPath(gchar const* path, gchar const* value)
  377. {
  378. const auto pipelineConfigurationListStore =
  379. GTK_TREE_MODEL(gtk_builder_get_object(this->m_Builder, "liststore-pipeline-configuration"));
  380. GtkTreeIter iter;
  381. gboolean valid = gtk_tree_model_get_iter_from_string(pipelineConfigurationListStore, &iter, path);
  382. assert(valid);
  383. size_t id = 0;
  384. gchar* name;
  385. gtk_tree_model_get(pipelineConfigurationListStore, &iter, Column_SettingName, &name, -1);
  386. gtk_tree_model_get(pipelineConfigurationListStore, &iter, Column_SettingPipelineId, &id, -1);
  387. gtk_list_store_set(GTK_LIST_STORE(pipelineConfigurationListStore), &iter, Column_SettingValue, value, -1);
  388. this->m_Controller.setPipelineParameterValue(size_t(id), name, value);
  389. g_free(name);
  390. return true;
  391. }
  392. } // namespace OpenViBE
  393. #endif