| [89] | 1 | // %pacpus:license{ | 
|---|
|  | 2 | // This file is part of the PACPUS framework distributed under the | 
|---|
|  | 3 | // CECILL-C License, Version 1.0. | 
|---|
|  | 4 | // %pacpus:license} | 
|---|
|  | 5 | /// @file | 
|---|
|  | 6 | /// @author  Gerald Dhermobez <firstname.surname@utc.fr> | 
|---|
|  | 7 | /// @author  Marek Kurdej <firstname.surname@utc.fr> | 
|---|
|  | 8 | /// @author  Samuel Gosselin <firstname.surname@utc.fr> | 
|---|
| [138] | 9 | /// @author  Julien Moras <firstname.surname@utc.fr> | 
|---|
| [89] | 10 | /// @date    February, 2006 | 
|---|
|  | 11 | /// @version $Id: ComponentBase.h 76 2013-01-10 17:05:10Z kurdejma $ | 
|---|
|  | 12 | /// @copyright Copyright (c) UTC/CNRS Heudiasyc 2006 - 2013. All rights reserved. | 
|---|
|  | 13 | /// @brief Generic ComponentBase class. This is an abstract class. | 
|---|
|  | 14 | /// | 
|---|
|  | 15 | /// Detailed description. | 
|---|
|  | 16 | /// @todo        - see if some methods can be private with ComponentManager | 
|---|
|  | 17 | ///              friendship | 
|---|
|  | 18 | ///              - include the copy of Xml node in param here | 
|---|
|  | 19 | ///              - see if there is a possibility to avoid the constraint | 
|---|
|  | 20 | ///              on parameters in the constructor of derived class | 
|---|
|  | 21 |  | 
|---|
|  | 22 | #ifndef DEF_PACPUS_COMPONENTBASE_H | 
|---|
|  | 23 | #define DEF_PACPUS_COMPONENTBASE_H | 
|---|
|  | 24 |  | 
|---|
| [288] | 25 | //#include <Pacpus/kernel/ComponentManager.h> | 
|---|
| [182] | 26 | #include <Pacpus/kernel/InputOutputBase.h> | 
|---|
| [195] | 27 | // InputOutputInterface.h must be included, otherwise we could not use addInput, addOutput template methods | 
|---|
|  | 28 | #include <Pacpus/kernel/InputOutputInterface.h> | 
|---|
| [196] | 29 | #include <Pacpus/kernel/PacpusLibConfig.h> | 
|---|
| [89] | 30 | #include <Pacpus/kernel/XmlComponentConfig.h> | 
|---|
|  | 31 |  | 
|---|
| [286] | 32 | #include <boost/noncopyable.hpp> | 
|---|
| [272] | 33 | #include <boost/program_options/options_description.hpp> | 
|---|
|  | 34 | #include <boost/program_options/value_semantic.hpp> | 
|---|
| [288] | 35 | #include <QMap> | 
|---|
| [89] | 36 | #include <QString> | 
|---|
| [176] | 37 | #include <string> | 
|---|
|  | 38 |  | 
|---|
| [110] | 39 | class QWidget; | 
|---|
|  | 40 |  | 
|---|
| [281] | 41 | namespace boost | 
|---|
|  | 42 | { | 
|---|
|  | 43 | class exception_ptr; | 
|---|
|  | 44 |  | 
|---|
|  | 45 | namespace program_options | 
|---|
|  | 46 | { | 
|---|
| [176] | 47 | class options_description_easy_init; | 
|---|
| [281] | 48 | } // namespace program_options | 
|---|
| [176] | 49 |  | 
|---|
| [281] | 50 | } // namespace boost | 
|---|
|  | 51 |  | 
|---|
| [286] | 52 | namespace pacpus | 
|---|
|  | 53 | { | 
|---|
| [89] | 54 |  | 
|---|
| [288] | 55 | class ComponentBase; | 
|---|
|  | 56 |  | 
|---|
| [89] | 57 | class ComponentManager; | 
|---|
|  | 58 |  | 
|---|
| [184] | 59 | class InputInterfaceBase; | 
|---|
|  | 60 | class OutputInterfaceBase; | 
|---|
|  | 61 |  | 
|---|
| [152] | 62 | template <typename T, class C> | 
|---|
|  | 63 | class InputInterface; | 
|---|
|  | 64 | template <typename T, class C> | 
|---|
|  | 65 | class OutputInterface; | 
|---|
|  | 66 |  | 
|---|
| [286] | 67 | using boost::program_options::value; | 
|---|
| [199] | 68 |  | 
|---|
| [201] | 69 | /// @brief Base class of a Pacpus component. | 
|---|
| [89] | 70 | class PACPUSLIB_API ComponentBase | 
|---|
| [286] | 71 | : boost::noncopyable | 
|---|
| [89] | 72 | { | 
|---|
|  | 73 | friend class ComponentManager; | 
|---|
| [152] | 74 |  | 
|---|
| [89] | 75 | public: | 
|---|
| [201] | 76 | /// Enumeration of the state that can take a component, the three last states suppose | 
|---|
|  | 77 | /// that the component is started. | 
|---|
|  | 78 | enum COMPONENT_STATE { | 
|---|
|  | 79 | STOPPED, | 
|---|
|  | 80 | NOT_MONITORED, | 
|---|
|  | 81 | MONITOR_OK, | 
|---|
|  | 82 | MONITOR_NOK | 
|---|
| [89] | 83 | }; | 
|---|
|  | 84 |  | 
|---|
| [201] | 85 | /// Resulting state of a component after its configuration. | 
|---|
|  | 86 | enum COMPONENT_CONFIGURATION { | 
|---|
|  | 87 | CONFIGURED_OK, | 
|---|
|  | 88 | NOT_CONFIGURED, | 
|---|
|  | 89 | CONFIGURATION_DELAYED, | 
|---|
|  | 90 | CONFIGURED_FAILED | 
|---|
| [89] | 91 | }; | 
|---|
|  | 92 |  | 
|---|
| [201] | 93 | /// Ctor of ComponentBase. | 
|---|
|  | 94 | /// @param name Name of your component. | 
|---|
| [288] | 95 | ComponentBase(QString const& name); | 
|---|
| [89] | 96 |  | 
|---|
| [201] | 97 | /// Dtor of ComponentBase. | 
|---|
| [89] | 98 | virtual ~ComponentBase(); | 
|---|
|  | 99 |  | 
|---|
| [201] | 100 | /// Returns the state of the component. | 
|---|
|  | 101 | /// @return Value of the current state. | 
|---|
| [89] | 102 | COMPONENT_STATE getState(); | 
|---|
| [349] | 103 | COMPONENT_STATE state(); | 
|---|
| [89] | 104 |  | 
|---|
| [201] | 105 | /// Checks whether the component if configurer or not. | 
|---|
|  | 106 | /// @return @b true if the component is configured, otherwise @b false. | 
|---|
| [89] | 107 | bool isConfigured() const; | 
|---|
|  | 108 |  | 
|---|
| [201] | 109 | /// Returns the name of the component. | 
|---|
|  | 110 | /// @return Name of the component. | 
|---|
| [89] | 111 | QString getName() const; | 
|---|
| [349] | 112 | QString name() const; | 
|---|
| [206] | 113 |  | 
|---|
|  | 114 | /// @returns @b true if the component has been started and is active (working) | 
|---|
|  | 115 | bool isActive() const; | 
|---|
| [89] | 116 |  | 
|---|
|  | 117 | protected: | 
|---|
| [201] | 118 | /// Changes the state of the component. | 
|---|
|  | 119 | /// @param state New component state. | 
|---|
| [89] | 120 | void setState(COMPONENT_STATE state); | 
|---|
|  | 121 |  | 
|---|
| [201] | 122 | /// Called when the component starts, you must override this function. | 
|---|
| [89] | 123 | virtual void startActivity() = 0; | 
|---|
|  | 124 |  | 
|---|
| [201] | 125 | /// Called when the component stops, you must override this function. | 
|---|
| [89] | 126 | virtual void stopActivity() = 0; | 
|---|
|  | 127 |  | 
|---|
| [201] | 128 | /// Called by the ComponentManager, it configure the component thanks a XML node. | 
|---|
|  | 129 | /// @param config Component's XML node. | 
|---|
|  | 130 | /// @return State of the configuration. | 
|---|
|  | 131 | /// @todo FIXME: 'config' should be const, but it will be a breaking change | 
|---|
|  | 132 | /// old stuff. | 
|---|
| [89] | 133 | virtual COMPONENT_CONFIGURATION configureComponent(XmlComponentConfig config) = 0; | 
|---|
|  | 134 |  | 
|---|
|  | 135 | // virtual QString getType() = 0; | 
|---|
| [120] | 136 |  | 
|---|
| [201] | 137 | /// @todo FIXME: should be pure virtual, but it will be a breaking change | 
|---|
| [161] | 138 | virtual void addInputs() {} | 
|---|
|  | 139 | virtual void addOutputs() {} | 
|---|
| [120] | 140 |  | 
|---|
| [201] | 141 | /// Returns an object permitting to add component parameters. | 
|---|
| [286] | 142 | boost::program_options::options_description_easy_init addParameters(); | 
|---|
| [312] | 143 | void addParameter(const char* name, const char* description); | 
|---|
|  | 144 | void addParameter(const char* name, const boost::program_options::value_semantic* s); | 
|---|
|  | 145 | void addParameter(const char* name, const boost::program_options::value_semantic* s, const char* description); | 
|---|
|  | 146 |  | 
|---|
| [89] | 147 | protected: | 
|---|
| [290] | 148 | typedef QMap<QString, InputSharedPointer> InputsMap; | 
|---|
|  | 149 | typedef QMap<QString, OutputSharedPointer> OutputsMap; | 
|---|
| [89] | 150 |  | 
|---|
| [152] | 151 | template <typename DataType, class ComponentType, typename Function> | 
|---|
|  | 152 | void addInput(const char * name, Function function) | 
|---|
|  | 153 | { | 
|---|
|  | 154 | typedef InputInterface<DataType, ComponentType> InputType; | 
|---|
| [290] | 155 | InputSharedPointer connection(new InputType(name, dynamic_cast<ComponentType *>(this), function)); | 
|---|
| [152] | 156 | inputs().insert(name, connection); | 
|---|
|  | 157 | } | 
|---|
| [89] | 158 |  | 
|---|
| [152] | 159 | template <typename DataType, class ComponentType> | 
|---|
|  | 160 | void addOutput(const char * name) | 
|---|
|  | 161 | { | 
|---|
|  | 162 | typedef OutputInterface<DataType, ComponentType> OutputType; | 
|---|
| [290] | 163 | OutputSharedPointer connection(new OutputType(name, dynamic_cast<ComponentType *>(this))); | 
|---|
| [152] | 164 | outputs().insert(name, connection); | 
|---|
|  | 165 | } | 
|---|
| [202] | 166 |  | 
|---|
|  | 167 | /// @todo DOC | 
|---|
| [290] | 168 | InputInterfaceBase* getInput(QString name) const; | 
|---|
| [89] | 169 |  | 
|---|
| [202] | 170 | /// @todo DOC | 
|---|
| [290] | 171 | OutputInterfaceBase* getOutput(QString name) const; | 
|---|
| [202] | 172 |  | 
|---|
| [152] | 173 | template <typename DataType, class ComponentType> | 
|---|
| [290] | 174 | InputInterface<DataType, ComponentType>* getTypedInput(const char * name) const | 
|---|
| [152] | 175 | { | 
|---|
| [290] | 176 | //using boost::dynamic_pointer_cast; | 
|---|
|  | 177 | //return dynamic_pointer_cast<InputInterface<DataType, ComponentType> >(getInput(name)); | 
|---|
|  | 178 | return dynamic_cast<InputInterface<DataType, ComponentType>*>(getInput(name)); | 
|---|
| [152] | 179 | } | 
|---|
| [89] | 180 |  | 
|---|
| [152] | 181 | template <typename DataType, class ComponentType> | 
|---|
| [290] | 182 | OutputInterface<DataType, ComponentType>* getTypedOutput(const char * name) const | 
|---|
| [152] | 183 | { | 
|---|
| [290] | 184 | //using boost::dynamic_pointer_cast; | 
|---|
|  | 185 | //return dynamic_pointer_cast<OutputInterface<DataType, ComponentType> >(getOutput(name)); | 
|---|
|  | 186 | return dynamic_cast<OutputInterface<DataType, ComponentType>*>(getOutput(name)); | 
|---|
| [152] | 187 | } | 
|---|
| [89] | 188 |  | 
|---|
| [152] | 189 | void setActive(bool isActive); | 
|---|
|  | 190 | bool isRecording() const; | 
|---|
|  | 191 | void setRecording(bool isRecording); | 
|---|
| [89] | 192 |  | 
|---|
| [152] | 193 | InputsMap & inputs(); | 
|---|
|  | 194 | const InputsMap & inputs() const; | 
|---|
|  | 195 | OutputsMap & outputs(); | 
|---|
|  | 196 | const OutputsMap & outputs() const; | 
|---|
| [89] | 197 |  | 
|---|
| [152] | 198 | COMPONENT_CONFIGURATION configurationState() const; | 
|---|
|  | 199 | void setConfigurationState(COMPONENT_CONFIGURATION state); | 
|---|
| [110] | 200 |  | 
|---|
| [152] | 201 | const XmlComponentConfig xmlParameters() const; | 
|---|
| [176] | 202 |  | 
|---|
|  | 203 | protected: | 
|---|
|  | 204 | std::string mName; | 
|---|
|  | 205 | std::string mTypeName; | 
|---|
| [288] | 206 | //QThread mThread; | 
|---|
|  | 207 |  | 
|---|
| [181] | 208 | /// Whether to display or not the graphical interface (GUI) | 
|---|
|  | 209 | bool hasGui() const; | 
|---|
|  | 210 | bool isOutputVerbose() const; | 
|---|
|  | 211 | int getVerbosityLevel() const; | 
|---|
|  | 212 |  | 
|---|
| [89] | 213 | private: | 
|---|
| [176] | 214 | /// Called by ComponentManager to handle parameters | 
|---|
|  | 215 | /// @throws | 
|---|
|  | 216 | void parseParameters(const XmlComponentConfig & cfg); | 
|---|
|  | 217 |  | 
|---|
| [89] | 218 | /// called by the ComponentManager to start the component | 
|---|
|  | 219 | int startComponent(); | 
|---|
| [281] | 220 | void startComponentInThread(); | 
|---|
|  | 221 | void startComponentWithException(boost::exception_ptr& error); | 
|---|
| [89] | 222 |  | 
|---|
|  | 223 | /// called by the ComponentManager to stop the component | 
|---|
|  | 224 | int stopComponent(); | 
|---|
|  | 225 |  | 
|---|
| [152] | 226 | private: | 
|---|
| [181] | 227 | bool mHasGui; | 
|---|
|  | 228 | bool mVerbose; | 
|---|
|  | 229 | int mVerbosityLevel; | 
|---|
|  | 230 |  | 
|---|
| [176] | 231 | boost::program_options::options_description mOptionsDescription; | 
|---|
|  | 232 |  | 
|---|
| [152] | 233 | /// The XML node that is got in the configureComponent method | 
|---|
|  | 234 | XmlComponentConfig param; | 
|---|
|  | 235 |  | 
|---|
|  | 236 | /// the name of the component. It is this one in the XML config file | 
|---|
|  | 237 | QString m_componentName; | 
|---|
|  | 238 |  | 
|---|
|  | 239 | /// is the component active? | 
|---|
|  | 240 | volatile bool m_isActive; | 
|---|
|  | 241 |  | 
|---|
|  | 242 | /// is the component is recording data? | 
|---|
| [177] | 243 | bool mIsRecording; | 
|---|
| [152] | 244 |  | 
|---|
|  | 245 | /// a pointer to the manager of components | 
|---|
|  | 246 | ComponentManager * m_manager; | 
|---|
|  | 247 |  | 
|---|
|  | 248 | InputsMap m_inputs; | 
|---|
|  | 249 | OutputsMap m_outputs; | 
|---|
|  | 250 |  | 
|---|
|  | 251 | /// a pointer to an optional widget | 
|---|
|  | 252 | QWidget * m_ui; | 
|---|
|  | 253 |  | 
|---|
| [89] | 254 | /// store the state of the component | 
|---|
| [152] | 255 | COMPONENT_STATE m_componentState; | 
|---|
| [89] | 256 |  | 
|---|
|  | 257 | /// is the component configured (ie configureComponent method was called) | 
|---|
| [152] | 258 | COMPONENT_CONFIGURATION m_configurationState; | 
|---|
| [89] | 259 | }; | 
|---|
|  | 260 |  | 
|---|
|  | 261 | } // pacpus | 
|---|
|  | 262 |  | 
|---|
|  | 263 | #endif // DEF_PACPUS_COMPONENTBASE_H | 
|---|